1 /* $NetBSD: hxtool.c,v 1.1.1.2 2014/04/24 12:45:42 pettai Exp $ */
4 * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the Institute nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 #include <hxtool-commands.h>
40 #include <krb5/rtbl.h>
41 #include <krb5/parse_time.h>
43 static hx509_context context
;
45 static char *stat_file_string
;
46 static int version_flag
;
49 struct getargs args
[] = {
50 { "statistic-file", 0, arg_string
, &stat_file_string
, NULL
, NULL
},
51 { "version", 0, arg_flag
, &version_flag
, NULL
, NULL
},
52 { "help", 0, arg_flag
, &help_flag
, NULL
, NULL
}
54 int num_args
= sizeof(args
) / sizeof(args
[0]);
59 arg_printusage(args
, num_args
, NULL
, "command");
60 printf("Use \"%s help\" to get more help\n", getprogname());
69 lock_strings(hx509_lock lock
, getarg_strings
*pass
)
72 for (i
= 0; i
< pass
->num_strings
; i
++) {
73 int ret
= hx509_lock_command_string(lock
, pass
->strings
[i
]);
75 errx(1, "hx509_lock_command_string: %s: %d",
76 pass
->strings
[i
], ret
);
85 certs_strings(hx509_context contextp
, const char *type
, hx509_certs certs
,
86 hx509_lock lock
, const getarg_strings
*s
)
90 for (i
= 0; i
< s
->num_strings
; i
++) {
91 ret
= hx509_certs_append(contextp
, certs
, lock
, s
->strings
[i
]);
93 hx509_err(contextp
, 1, ret
,
94 "hx509_certs_append: %s %s", type
, s
->strings
[i
]);
103 parse_oid(const char *str
, const heim_oid
*def
, heim_oid
*oid
)
107 ret
= der_parse_heim_oid (str
, " .", oid
);
109 ret
= der_copy_oid(def
, oid
);
111 errx(1, "parse_oid failed for: %s", str
? str
: "default oid");
119 peer_strings(hx509_context contextp
,
120 hx509_peer_info
*peer
,
121 const getarg_strings
*s
)
123 AlgorithmIdentifier
*val
;
126 ret
= hx509_peer_info_alloc(contextp
, peer
);
128 hx509_err(contextp
, 1, ret
, "hx509_peer_info_alloc");
130 val
= calloc(s
->num_strings
, sizeof(*val
));
134 for (i
= 0; i
< s
->num_strings
; i
++)
135 parse_oid(s
->strings
[i
], NULL
, &val
[i
].algorithm
);
137 ret
= hx509_peer_info_set_cms_algs(contextp
, *peer
, val
, s
->num_strings
);
139 hx509_err(contextp
, 1, ret
, "hx509_peer_info_set_cms_algs");
141 for (i
= 0; i
< s
->num_strings
; i
++)
142 free_AlgorithmIdentifier(&val
[i
]);
151 heim_octet_string
*os
;
156 pem_reader(hx509_context contextp
, const char *type
,
157 const hx509_pem_header
*headers
,
158 const void *data
, size_t length
, void *ctx
)
160 struct pem_data
*p
= (struct pem_data
*)ctx
;
163 p
->os
->data
= malloc(length
);
164 if (p
->os
->data
== NULL
)
166 memcpy(p
->os
->data
, data
, length
);
167 p
->os
->length
= length
;
169 h
= hx509_pem_find_header(headers
, "Content-disposition");
170 if (h
&& strcasecmp(h
, "detached") == 0)
171 p
->detached_data
= 1;
181 cms_verify_sd(struct cms_verify_sd_options
*opt
, int argc
, char **argv
)
183 hx509_verify_ctx ctx
= NULL
;
185 heim_octet_string c
, co
, signeddata
, *sd
= NULL
;
186 hx509_certs store
= NULL
;
187 hx509_certs signers
= NULL
;
188 hx509_certs anchors
= NULL
;
195 if (opt
->missing_revoke_flag
)
196 hx509_context_set_missing_revoke(context
, 1);
198 hx509_lock_init(context
, &lock
);
199 lock_strings(lock
, &opt
->pass_strings
);
201 ret
= hx509_verify_init_ctx(context
, &ctx
);
203 hx509_err(context
, 1, ret
, "hx509_verify_init_ctx");
205 ret
= hx509_certs_init(context
, "MEMORY:cms-anchors", 0, NULL
, &anchors
);
207 hx509_err(context
, 1, ret
, "hx509_certs_init: MEMORY");
208 ret
= hx509_certs_init(context
, "MEMORY:cert-store", 0, NULL
, &store
);
210 hx509_err(context
, 1, ret
, "hx509_certs_init: MEMORY");
212 certs_strings(context
, "anchors", anchors
, lock
, &opt
->anchors_strings
);
213 certs_strings(context
, "store", store
, lock
, &opt
->certificate_strings
);
220 pd
.detached_data
= 0;
222 f
= fopen(argv
[0], "r");
224 err(1, "Failed to open file %s", argv
[0]);
226 ret
= hx509_pem_read(context
, f
, pem_reader
, &pd
);
229 errx(1, "PEM reader failed: %d", ret
);
231 if (pd
.detached_data
&& opt
->signed_content_string
== NULL
) {
232 char *r
= strrchr(argv
[0], '.');
233 if (r
&& strcasecmp(r
, ".pem") == 0) {
234 char *s
= strdup(argv
[0]);
236 errx(1, "malloc: out of memory");
237 s
[r
- argv
[0]] = '\0';
238 ret
= _hx509_map_file_os(s
, &signeddata
);
240 errx(1, "map_file: %s: %d", s
, ret
);
247 ret
= rk_undumpdata(argv
[0], &p
, &sz
);
249 err(1, "map_file: %s: %d", argv
[0], ret
);
255 if (opt
->signed_content_string
) {
256 ret
= _hx509_map_file_os(opt
->signed_content_string
, &signeddata
);
258 errx(1, "map_file: %s: %d", opt
->signed_content_string
, ret
);
262 if (opt
->content_info_flag
) {
263 heim_octet_string uwco
;
266 ret
= hx509_cms_unwrap_ContentInfo(&co
, &oid
, &uwco
, NULL
);
268 errx(1, "hx509_cms_unwrap_ContentInfo: %d", ret
);
270 if (der_heim_oid_cmp(&oid
, &asn1_oid_id_pkcs7_signedData
) != 0)
271 errx(1, "Content is not SignedData");
275 der_free_octet_string(&co
);
283 hx509_verify_attach_anchors(ctx
, anchors
);
285 if (!opt
->signer_allowed_flag
)
286 flags
|= HX509_CMS_VS_ALLOW_ZERO_SIGNER
;
287 if (opt
->allow_wrong_oid_flag
)
288 flags
|= HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH
;
290 ret
= hx509_cms_verify_signed(context
, ctx
, flags
, co
.data
, co
.length
, sd
,
291 store
, &type
, &c
, &signers
);
293 der_free_octet_string(&co
);
297 hx509_err(context
, 1, ret
, "hx509_cms_verify_signed");
301 der_print_heim_oid(&type
, '.', &str
);
302 printf("type: %s\n", str
);
306 if (signers
== NULL
) {
307 printf("unsigned\n");
309 printf("signers:\n");
310 hx509_certs_iter_f(context
, signers
, hx509_ci_print_names
, stdout
);
313 hx509_verify_destroy_ctx(ctx
);
315 hx509_certs_free(&store
);
316 hx509_certs_free(&signers
);
317 hx509_certs_free(&anchors
);
319 hx509_lock_free(lock
);
322 ret
= _hx509_write_file(argv
[1], c
.data
, c
.length
);
324 errx(1, "hx509_write_file: %d", ret
);
327 der_free_octet_string(&c
);
330 _hx509_unmap_file_os(sd
);
336 print_signer(hx509_context contextp
, void *ctx
, hx509_cert cert
)
338 hx509_pem_header
**header
= ctx
;
339 char *signer_name
= NULL
;
343 ret
= hx509_cert_get_subject(cert
, &name
);
345 errx(1, "hx509_cert_get_subject");
347 ret
= hx509_name_to_string(name
, &signer_name
);
348 hx509_name_free(&name
);
350 errx(1, "hx509_name_to_string");
352 hx509_pem_add_header(header
, "Signer", signer_name
);
359 cms_create_sd(struct cms_create_sd_options
*opt
, int argc
, char **argv
)
361 heim_oid contentType
;
362 hx509_peer_info peer
= NULL
;
366 hx509_certs store
, pool
, anchors
, signer
= NULL
;
370 char *infile
, *outfile
= NULL
;
372 memset(&contentType
, 0, sizeof(contentType
));
377 asprintf(&outfile
, "%s.%s", infile
,
378 opt
->pem_flag
? "pem" : "cms-signeddata");
380 errx(1, "out of memory");
384 hx509_lock_init(context
, &lock
);
385 lock_strings(lock
, &opt
->pass_strings
);
387 ret
= hx509_certs_init(context
, "MEMORY:cert-store", 0, NULL
, &store
);
388 if (ret
) hx509_err(context
, 1, ret
, "hx509_certs_init: MEMORY");
389 ret
= hx509_certs_init(context
, "MEMORY:cert-pool", 0, NULL
, &pool
);
390 if (ret
) hx509_err(context
, 1, ret
, "hx509_certs_init: MEMORY");
392 certs_strings(context
, "store", store
, lock
, &opt
->certificate_strings
);
393 certs_strings(context
, "pool", pool
, lock
, &opt
->pool_strings
);
395 if (opt
->anchors_strings
.num_strings
) {
396 ret
= hx509_certs_init(context
, "MEMORY:cert-anchors",
398 if (ret
) hx509_err(context
, 1, ret
, "hx509_certs_init: MEMORY");
399 certs_strings(context
, "anchors", anchors
, lock
, &opt
->anchors_strings
);
403 if (opt
->detached_signature_flag
)
404 flags
|= HX509_CMS_SIGNATURE_DETACHED
;
405 if (opt
->id_by_name_flag
)
406 flags
|= HX509_CMS_SIGNATURE_ID_NAME
;
407 if (!opt
->signer_flag
) {
408 flags
|= HX509_CMS_SIGNATURE_NO_SIGNER
;
412 if (opt
->signer_flag
) {
413 ret
= hx509_query_alloc(context
, &q
);
415 errx(1, "hx509_query_alloc: %d", ret
);
417 hx509_query_match_option(q
, HX509_QUERY_OPTION_PRIVATE_KEY
);
418 hx509_query_match_option(q
, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE
);
420 if (opt
->signer_string
)
421 hx509_query_match_friendly_name(q
, opt
->signer_string
);
423 ret
= hx509_certs_filter(context
, store
, q
, &signer
);
424 hx509_query_free(context
, q
);
426 hx509_err(context
, 1, ret
, "hx509_certs_find");
428 if (!opt
->embedded_certs_flag
)
429 flags
|= HX509_CMS_SIGNATURE_NO_CERTS
;
430 if (opt
->embed_leaf_only_flag
)
431 flags
|= HX509_CMS_SIGNATURE_LEAF_ONLY
;
433 ret
= rk_undumpdata(infile
, &p
, &sz
);
435 err(1, "map_file: %s: %d", infile
, ret
);
437 if (opt
->peer_alg_strings
.num_strings
)
438 peer_strings(context
, &peer
, &opt
->peer_alg_strings
);
440 parse_oid(opt
->content_type_string
, &asn1_oid_id_pkcs7_data
, &contentType
);
442 ret
= hx509_cms_create_signed(context
,
454 hx509_err(context
, 1, ret
, "hx509_cms_create_signed: %d", ret
);
456 hx509_certs_free(&anchors
);
457 hx509_certs_free(&pool
);
458 hx509_certs_free(&store
);
460 hx509_lock_free(lock
);
461 hx509_peer_info_free(peer
);
462 der_free_oid(&contentType
);
464 if (opt
->content_info_flag
) {
465 heim_octet_string wo
;
467 ret
= hx509_cms_wrap_ContentInfo(&asn1_oid_id_pkcs7_signedData
, &o
, &wo
);
469 errx(1, "hx509_cms_wrap_ContentInfo: %d", ret
);
471 der_free_octet_string(&o
);
476 hx509_pem_header
*header
= NULL
;
479 hx509_pem_add_header(&header
, "Content-disposition",
480 opt
->detached_signature_flag
?
481 "detached" : "inline");
483 ret
= hx509_certs_iter_f(context
, signer
, print_signer
, header
);
485 hx509_err(context
, 1, ret
, "print signer");
488 f
= fopen(outfile
, "w");
490 err(1, "open %s", outfile
);
492 ret
= hx509_pem_write(context
, "CMS SIGNEDDATA", header
, f
,
495 hx509_pem_free_header(header
);
497 errx(1, "hx509_pem_write: %d", ret
);
500 ret
= _hx509_write_file(outfile
, o
.data
, o
.length
);
502 errx(1, "hx509_write_file: %d", ret
);
505 hx509_certs_free(&signer
);
512 cms_unenvelope(struct cms_unenvelope_options
*opt
, int argc
, char **argv
)
514 heim_oid contentType
= { 0, NULL
};
515 heim_octet_string o
, co
;
523 hx509_lock_init(context
, &lock
);
524 lock_strings(lock
, &opt
->pass_strings
);
526 ret
= rk_undumpdata(argv
[0], &p
, &sz
);
528 err(1, "map_file: %s: %d", argv
[0], ret
);
533 if (opt
->content_info_flag
) {
534 heim_octet_string uwco
;
537 ret
= hx509_cms_unwrap_ContentInfo(&co
, &oid
, &uwco
, NULL
);
539 errx(1, "hx509_cms_unwrap_ContentInfo: %d", ret
);
541 if (der_heim_oid_cmp(&oid
, &asn1_oid_id_pkcs7_envelopedData
) != 0)
542 errx(1, "Content is not SignedData");
548 ret
= hx509_certs_init(context
, "MEMORY:cert-store", 0, NULL
, &certs
);
550 errx(1, "hx509_certs_init: MEMORY: %d", ret
);
552 certs_strings(context
, "store", certs
, lock
, &opt
->certificate_strings
);
554 if (opt
->allow_weak_crypto_flag
)
555 flags
|= HX509_CMS_UE_ALLOW_WEAK
;
557 ret
= hx509_cms_unenvelope(context
, certs
, flags
, co
.data
, co
.length
,
558 NULL
, 0, &contentType
, &o
);
560 der_free_octet_string(&co
);
562 hx509_err(context
, 1, ret
, "hx509_cms_unenvelope");
565 hx509_lock_free(lock
);
566 hx509_certs_free(&certs
);
567 der_free_oid(&contentType
);
569 ret
= _hx509_write_file(argv
[1], o
.data
, o
.length
);
571 errx(1, "hx509_write_file: %d", ret
);
573 der_free_octet_string(&o
);
579 cms_create_enveloped(struct cms_envelope_options
*opt
, int argc
, char **argv
)
581 heim_oid contentType
;
583 const heim_oid
*enctype
= NULL
;
593 memset(&contentType
, 0, sizeof(contentType
));
595 hx509_lock_init(context
, &lock
);
596 lock_strings(lock
, &opt
->pass_strings
);
598 ret
= rk_undumpdata(argv
[0], &p
, &sz
);
600 err(1, "map_file: %s: %d", argv
[0], ret
);
602 ret
= hx509_certs_init(context
, "MEMORY:cert-store", 0, NULL
, &certs
);
603 if (ret
) hx509_err(context
, 1, ret
, "hx509_certs_init: MEMORY");
605 certs_strings(context
, "store", certs
, lock
, &opt
->certificate_strings
);
607 if (opt
->allow_weak_crypto_flag
)
608 flags
|= HX509_CMS_EV_ALLOW_WEAK
;
610 if (opt
->encryption_type_string
) {
611 enctype
= hx509_crypto_enctype_by_name(opt
->encryption_type_string
);
613 errx(1, "encryption type: %s no found",
614 opt
->encryption_type_string
);
617 ret
= hx509_query_alloc(context
, &q
);
619 errx(1, "hx509_query_alloc: %d", ret
);
621 hx509_query_match_option(q
, HX509_QUERY_OPTION_KU_ENCIPHERMENT
);
623 ret
= hx509_certs_find(context
, certs
, q
, &cert
);
624 hx509_query_free(context
, q
);
626 errx(1, "hx509_certs_find: %d", ret
);
628 parse_oid(opt
->content_type_string
, &asn1_oid_id_pkcs7_data
, &contentType
);
630 ret
= hx509_cms_envelope_1(context
, flags
, cert
, p
, sz
, enctype
,
633 errx(1, "hx509_cms_envelope_1: %d", ret
);
635 hx509_cert_free(cert
);
636 hx509_certs_free(&certs
);
638 der_free_oid(&contentType
);
640 if (opt
->content_info_flag
) {
641 heim_octet_string wo
;
643 ret
= hx509_cms_wrap_ContentInfo(&asn1_oid_id_pkcs7_envelopedData
, &o
, &wo
);
645 errx(1, "hx509_cms_wrap_ContentInfo: %d", ret
);
647 der_free_octet_string(&o
);
651 hx509_lock_free(lock
);
653 ret
= _hx509_write_file(argv
[1], o
.data
, o
.length
);
655 errx(1, "hx509_write_file: %d", ret
);
657 der_free_octet_string(&o
);
663 print_certificate(hx509_context hxcontext
, hx509_cert cert
, int verbose
)
668 fn
= hx509_cert_get_friendly_name(cert
);
670 printf(" friendly name: %s\n", fn
);
671 printf(" private key: %s\n",
672 _hx509_cert_private_key(cert
) ? "yes" : "no");
674 ret
= hx509_print_cert(hxcontext
, cert
, NULL
);
676 errx(1, "failed to print cert");
679 hx509_validate_ctx vctx
;
681 hx509_validate_ctx_init(hxcontext
, &vctx
);
682 hx509_validate_ctx_set_print(vctx
, hx509_print_stdout
, stdout
);
683 hx509_validate_ctx_add_flags(vctx
, HX509_VALIDATE_F_VALIDATE
);
684 hx509_validate_ctx_add_flags(vctx
, HX509_VALIDATE_F_VERBOSE
);
686 hx509_validate_cert(hxcontext
, vctx
, cert
);
688 hx509_validate_ctx_free(vctx
);
699 print_f(hx509_context hxcontext
, void *ctx
, hx509_cert cert
)
701 struct print_s
*s
= ctx
;
703 printf("cert: %d\n", s
->counter
++);
704 print_certificate(context
, cert
, s
->verbose
);
710 pcert_print(struct print_options
*opt
, int argc
, char **argv
)
717 s
.verbose
= opt
->content_flag
;
719 hx509_lock_init(context
, &lock
);
720 lock_strings(lock
, &opt
->pass_strings
);
724 ret
= hx509_certs_init(context
, argv
[0], 0, lock
, &certs
);
726 if (opt
->never_fail_flag
) {
727 printf("ignoreing failure: %d\n", ret
);
730 hx509_err(context
, 1, ret
, "hx509_certs_init");
733 hx509_certs_info(context
, certs
, NULL
, NULL
);
734 hx509_certs_iter_f(context
, certs
, print_f
, &s
);
735 hx509_certs_free(&certs
);
739 hx509_lock_free(lock
);
746 validate_f(hx509_context hxcontext
, void *ctx
, hx509_cert c
)
748 hx509_validate_cert(hxcontext
, ctx
, c
);
753 pcert_validate(struct validate_options
*opt
, int argc
, char **argv
)
755 hx509_validate_ctx ctx
;
759 hx509_lock_init(context
, &lock
);
760 lock_strings(lock
, &opt
->pass_strings
);
762 hx509_validate_ctx_init(context
, &ctx
);
763 hx509_validate_ctx_set_print(ctx
, hx509_print_stdout
, stdout
);
764 hx509_validate_ctx_add_flags(ctx
, HX509_VALIDATE_F_VALIDATE
);
768 ret
= hx509_certs_init(context
, argv
[0], 0, lock
, &certs
);
770 errx(1, "hx509_certs_init: %d", ret
);
771 hx509_certs_iter_f(context
, certs
, validate_f
, ctx
);
772 hx509_certs_free(&certs
);
775 hx509_validate_ctx_free(ctx
);
777 hx509_lock_free(lock
);
783 certificate_copy(struct certificate_copy_options
*opt
, int argc
, char **argv
)
786 hx509_lock inlock
, outlock
= NULL
;
789 hx509_lock_init(context
, &inlock
);
790 lock_strings(inlock
, &opt
->in_pass_strings
);
792 if (opt
->out_pass_string
) {
793 hx509_lock_init(context
, &outlock
);
794 ret
= hx509_lock_command_string(outlock
, opt
->out_pass_string
);
796 errx(1, "hx509_lock_command_string: %s: %d",
797 opt
->out_pass_string
, ret
);
800 ret
= hx509_certs_init(context
, argv
[argc
- 1],
801 HX509_CERTS_CREATE
, inlock
, &certs
);
803 hx509_err(context
, 1, ret
, "hx509_certs_init");
807 retx
= hx509_certs_append(context
, certs
, inlock
, argv
[0]);
809 hx509_err(context
, 1, retx
, "hx509_certs_append");
813 ret
= hx509_certs_store(context
, certs
, 0, outlock
);
815 hx509_err(context
, 1, ret
, "hx509_certs_store");
817 hx509_certs_free(&certs
);
818 hx509_lock_free(inlock
);
819 hx509_lock_free(outlock
);
825 hx509_verify_ctx ctx
;
827 const char *hostname
;
833 verify_f(hx509_context hxcontext
, void *ctx
, hx509_cert c
)
835 struct verify
*v
= ctx
;
838 ret
= hx509_verify_path(hxcontext
, v
->ctx
, c
, v
->chain
);
840 char *s
= hx509_get_error_string(hxcontext
, ret
);
841 printf("verify_path: %s: %d\n", s
, ret
);
842 hx509_free_error_string(s
);
850 ret
= hx509_verify_hostname(hxcontext
, c
, 0, HX509_HN_HOSTNAME
,
851 v
->hostname
, NULL
, 0);
853 printf("verify_hostname: %d\n", ret
);
862 pcert_verify(struct verify_options
*opt
, int argc
, char **argv
)
864 hx509_certs anchors
, chain
, certs
;
865 hx509_revoke_ctx revoke_ctx
;
866 hx509_verify_ctx ctx
;
870 memset(&v
, 0, sizeof(v
));
872 if (opt
->missing_revoke_flag
)
873 hx509_context_set_missing_revoke(context
, 1);
875 ret
= hx509_verify_init_ctx(context
, &ctx
);
877 hx509_err(context
, 1, ret
, "hx509_verify_init_ctx");
878 ret
= hx509_certs_init(context
, "MEMORY:anchors", 0, NULL
, &anchors
);
880 hx509_err(context
, 1, ret
, "hx509_certs_init: MEMORY");
881 ret
= hx509_certs_init(context
, "MEMORY:chain", 0, NULL
, &chain
);
883 hx509_err(context
, 1, ret
, "hx509_certs_init: MEMORY");
884 ret
= hx509_certs_init(context
, "MEMORY:certs", 0, NULL
, &certs
);
886 hx509_err(context
, 1, ret
, "hx509_certs_init: MEMORY");
888 if (opt
->allow_proxy_certificate_flag
)
889 hx509_verify_set_proxy_certificate(ctx
, 1);
891 if (opt
->time_string
) {
896 memset(&tm
, 0, sizeof(tm
));
898 p
= strptime (opt
->time_string
, "%Y-%m-%d", &tm
);
900 errx(1, "Failed to parse time %s, need to be on format %%Y-%%m-%%d",
905 hx509_verify_set_time(ctx
, t
);
908 if (opt
->hostname_string
)
909 v
.hostname
= opt
->hostname_string
;
910 if (opt
->max_depth_integer
)
911 hx509_verify_set_max_depth(ctx
, opt
->max_depth_integer
);
913 ret
= hx509_revoke_init(context
, &revoke_ctx
);
915 errx(1, "hx509_revoke_init: %d", ret
);
920 if (strncmp(s
, "chain:", 6) == 0) {
923 ret
= hx509_certs_append(context
, chain
, NULL
, s
);
925 hx509_err(context
, 1, ret
, "hx509_certs_append: chain: %s: %d", s
, ret
);
927 } else if (strncmp(s
, "anchor:", 7) == 0) {
930 ret
= hx509_certs_append(context
, anchors
, NULL
, s
);
932 hx509_err(context
, 1, ret
, "hx509_certs_append: anchor: %s: %d", s
, ret
);
934 } else if (strncmp(s
, "cert:", 5) == 0) {
937 ret
= hx509_certs_append(context
, certs
, NULL
, s
);
939 hx509_err(context
, 1, ret
, "hx509_certs_append: certs: %s: %d",
942 } else if (strncmp(s
, "crl:", 4) == 0) {
945 ret
= hx509_revoke_add_crl(context
, revoke_ctx
, s
);
947 errx(1, "hx509_revoke_add_crl: %s: %d", s
, ret
);
949 } else if (strncmp(s
, "ocsp:", 4) == 0) {
952 ret
= hx509_revoke_add_ocsp(context
, revoke_ctx
, s
);
954 errx(1, "hx509_revoke_add_ocsp: %s: %d", s
, ret
);
957 errx(1, "unknown option to verify: `%s'\n", s
);
961 hx509_verify_attach_anchors(ctx
, anchors
);
962 hx509_verify_attach_revoke(ctx
, revoke_ctx
);
967 hx509_certs_iter_f(context
, certs
, verify_f
, &v
);
969 hx509_verify_destroy_ctx(ctx
);
971 hx509_certs_free(&certs
);
972 hx509_certs_free(&chain
);
973 hx509_certs_free(&anchors
);
975 hx509_revoke_free(&revoke_ctx
);
979 printf("no certs verify at all\n");
984 printf("failed verifing %d checks\n", v
.errors
);
992 query(struct query_options
*opt
, int argc
, char **argv
)
1000 ret
= hx509_query_alloc(context
, &q
);
1002 errx(1, "hx509_query_alloc: %d", ret
);
1004 hx509_lock_init(context
, &lock
);
1005 lock_strings(lock
, &opt
->pass_strings
);
1007 ret
= hx509_certs_init(context
, "MEMORY:cert-store", 0, NULL
, &certs
);
1008 if (ret
) hx509_err(context
, 1, ret
, "hx509_certs_init: MEMORY");
1012 ret
= hx509_certs_append(context
, certs
, lock
, argv
[0]);
1014 errx(1, "hx509_certs_append: %s: %d", argv
[0], ret
);
1020 if (opt
->friendlyname_string
)
1021 hx509_query_match_friendly_name(q
, opt
->friendlyname_string
);
1023 if (opt
->eku_string
) {
1026 parse_oid(opt
->eku_string
, NULL
, &oid
);
1028 ret
= hx509_query_match_eku(q
, &oid
);
1030 errx(1, "hx509_query_match_eku: %d", ret
);
1034 if (opt
->private_key_flag
)
1035 hx509_query_match_option(q
, HX509_QUERY_OPTION_PRIVATE_KEY
);
1037 if (opt
->keyEncipherment_flag
)
1038 hx509_query_match_option(q
, HX509_QUERY_OPTION_KU_ENCIPHERMENT
);
1040 if (opt
->digitalSignature_flag
)
1041 hx509_query_match_option(q
, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE
);
1043 if (opt
->expr_string
)
1044 hx509_query_match_expr(context
, q
, opt
->expr_string
);
1046 ret
= hx509_certs_find(context
, certs
, q
, &c
);
1047 hx509_query_free(context
, q
);
1049 printf("no match found (%d)\n", ret
);
1051 printf("match found\n");
1052 if (opt
->print_flag
)
1053 print_certificate(context
, c
, 0);
1057 hx509_certs_free(&certs
);
1059 hx509_lock_free(lock
);
1065 ocsp_fetch(struct ocsp_fetch_options
*opt
, int argc
, char **argv
)
1067 hx509_certs reqcerts
, pool
;
1068 heim_octet_string req
, nonce_data
, *nonce
= &nonce_data
;
1072 const char *url
= "/";
1074 memset(&nonce
, 0, sizeof(nonce
));
1076 hx509_lock_init(context
, &lock
);
1077 lock_strings(lock
, &opt
->pass_strings
);
1080 if (!opt
->nonce_flag
)
1083 if (opt
->url_path_string
)
1084 url
= opt
->url_path_string
;
1086 ret
= hx509_certs_init(context
, "MEMORY:ocsp-pool", 0, NULL
, &pool
);
1087 if (ret
) hx509_err(context
, 1, ret
, "hx509_certs_init: MEMORY");
1089 certs_strings(context
, "ocsp-pool", pool
, lock
, &opt
->pool_strings
);
1093 ret
= hx509_certs_init(context
, "MEMORY:ocsp-req", 0, NULL
, &reqcerts
);
1094 if (ret
) hx509_err(context
, 1, ret
, "hx509_certs_init: MEMORY");
1096 for (i
= 1; i
< argc
; i
++) {
1097 ret
= hx509_certs_append(context
, reqcerts
, lock
, argv
[i
]);
1099 errx(1, "hx509_certs_append: req: %s: %d", argv
[i
], ret
);
1102 ret
= hx509_ocsp_request(context
, reqcerts
, pool
, NULL
, NULL
, &req
, nonce
);
1104 errx(1, "hx509_ocsp_request: req: %d", ret
);
1109 f
= fopen(file
, "w");
1114 "POST %s HTTP/1.0\r\n"
1115 "Content-Type: application/ocsp-request\r\n"
1116 "Content-Length: %ld\r\n"
1119 (unsigned long)req
.length
);
1120 fwrite(req
.data
, req
.length
, 1, f
);
1125 der_free_octet_string(nonce
);
1127 hx509_certs_free(&reqcerts
);
1128 hx509_certs_free(&pool
);
1134 ocsp_print(struct ocsp_print_options
*opt
, int argc
, char **argv
)
1136 hx509_revoke_ocsp_print(context
, argv
[0], stdout
);
1145 verify_o(hx509_context hxcontext
, void *ctx
, hx509_cert c
)
1147 heim_octet_string
*os
= ctx
;
1151 ret
= hx509_ocsp_verify(context
, 0, c
, 0,
1152 os
->data
, os
->length
, &expiration
);
1154 char *s
= hx509_get_error_string(hxcontext
, ret
);
1155 printf("ocsp_verify: %s: %d\n", s
, ret
);
1156 hx509_free_error_string(s
);
1158 printf("expire: %d\n", (int)expiration
);
1165 ocsp_verify(struct ocsp_verify_options
*opt
, int argc
, char **argv
)
1170 heim_octet_string os
;
1172 hx509_lock_init(context
, &lock
);
1174 if (opt
->ocsp_file_string
== NULL
)
1175 errx(1, "no ocsp file given");
1177 ret
= _hx509_map_file_os(opt
->ocsp_file_string
, &os
);
1179 err(1, "map_file: %s: %d", argv
[0], ret
);
1181 ret
= hx509_certs_init(context
, "MEMORY:test-certs", 0, NULL
, &certs
);
1182 if (ret
) hx509_err(context
, 1, ret
, "hx509_certs_init: MEMORY");
1184 for (i
= 0; i
< argc
; i
++) {
1185 ret
= hx509_certs_append(context
, certs
, lock
, argv
[i
]);
1187 hx509_err(context
, 1, ret
, "hx509_certs_append: %s", argv
[i
]);
1190 ret
= hx509_certs_iter_f(context
, certs
, verify_o
, &os
);
1192 hx509_certs_free(&certs
);
1193 _hx509_unmap_file_os(&os
);
1194 hx509_lock_free(lock
);
1200 read_private_key(const char *fn
, hx509_private_key
*key
)
1202 hx509_private_key
*keys
;
1208 ret
= hx509_certs_init(context
, fn
, 0, NULL
, &certs
);
1210 hx509_err(context
, 1, ret
, "hx509_certs_init: %s", fn
);
1212 ret
= _hx509_certs_keys_get(context
, certs
, &keys
);
1213 hx509_certs_free(&certs
);
1215 hx509_err(context
, 1, ret
, "hx509_certs_keys_get");
1216 if (keys
[0] == NULL
)
1217 errx(1, "no keys in key store: %s", fn
);
1219 *key
= _hx509_private_key_ref(keys
[0]);
1220 _hx509_certs_keys_free(context
, keys
);
1226 get_key(const char *fn
, const char *type
, int optbits
,
1227 hx509_private_key
*signer
)
1234 unsigned char *p0
, *p
;
1239 errx(1, "no key argument, don't know here to store key");
1241 if (strcasecmp(type
, "rsa") != 0)
1242 errx(1, "can only handle rsa keys for now");
1245 BN_set_word(e
, 0x10001);
1252 errx(1, "RSA_new failed");
1254 ret
= RSA_generate_key_ex(rsa
, bits
, e
, NULL
);
1256 errx(1, "RSA_new failed");
1260 len
= i2d_RSAPrivateKey(rsa
, NULL
);
1262 p0
= p
= malloc(len
);
1264 errx(1, "out of memory");
1266 i2d_RSAPrivateKey(rsa
, &p
);
1268 rk_dumpdata(fn
, p0
, len
);
1274 } else if (fn
== NULL
)
1275 err(1, "no private key");
1277 ret
= read_private_key(fn
, signer
);
1279 err(1, "read_private_key");
1283 request_create(struct request_create_options
*opt
, int argc
, char **argv
)
1285 heim_octet_string request
;
1288 hx509_private_key signer
;
1289 SubjectPublicKeyInfo key
;
1290 const char *outfile
= argv
[0];
1292 memset(&key
, 0, sizeof(key
));
1294 get_key(opt
->key_string
,
1295 opt
->generate_key_string
,
1296 opt
->key_bits_integer
,
1299 hx509_request_init(context
, &req
);
1301 if (opt
->subject_string
) {
1302 hx509_name name
= NULL
;
1304 ret
= hx509_parse_name(context
, opt
->subject_string
, &name
);
1306 errx(1, "hx509_parse_name: %d\n", ret
);
1307 hx509_request_set_name(context
, req
, name
);
1309 if (opt
->verbose_flag
) {
1311 hx509_name_to_string(name
, &s
);
1314 hx509_name_free(&name
);
1317 for (i
= 0; i
< opt
->email_strings
.num_strings
; i
++) {
1318 ret
= _hx509_request_add_email(context
, req
,
1319 opt
->email_strings
.strings
[i
]);
1321 hx509_err(context
, 1, ret
, "hx509_request_add_email");
1324 for (i
= 0; i
< opt
->dnsname_strings
.num_strings
; i
++) {
1325 ret
= _hx509_request_add_dns_name(context
, req
,
1326 opt
->dnsname_strings
.strings
[i
]);
1328 hx509_err(context
, 1, ret
, "hx509_request_add_dns_name");
1332 ret
= hx509_private_key2SPKI(context
, signer
, &key
);
1334 errx(1, "hx509_private_key2SPKI: %d\n", ret
);
1336 ret
= hx509_request_set_SubjectPublicKeyInfo(context
,
1339 free_SubjectPublicKeyInfo(&key
);
1341 hx509_err(context
, 1, ret
, "hx509_request_set_SubjectPublicKeyInfo");
1343 ret
= _hx509_request_to_pkcs10(context
,
1348 hx509_err(context
, 1, ret
, "_hx509_request_to_pkcs10");
1350 hx509_private_key_free(&signer
);
1351 hx509_request_free(&req
);
1354 rk_dumpdata(outfile
, request
.data
, request
.length
);
1355 der_free_octet_string(&request
);
1361 request_print(struct request_print_options
*opt
, int argc
, char **argv
)
1365 printf("request print\n");
1367 for (i
= 0; i
< argc
; i
++) {
1370 ret
= _hx509_request_parse(context
, argv
[i
], &req
);
1372 hx509_err(context
, 1, ret
, "parse_request: %s", argv
[i
]);
1374 ret
= _hx509_request_print(context
, req
, stdout
);
1375 hx509_request_free(&req
);
1377 hx509_err(context
, 1, ret
, "Failed to print file %s", argv
[i
]);
1384 info(void *opt
, int argc
, char **argv
)
1387 ENGINE_add_conf_module();
1390 const RSA_METHOD
*m
= RSA_get_default_method();
1392 printf("rsa: %s\n", m
->name
);
1395 const DH_METHOD
*m
= DH_get_default_method();
1397 printf("dh: %s\n", m
->name
);
1401 printf("ecdsa: ECDSA_METHOD-not-export\n");
1405 printf("ecdsa: hcrypto null\n");
1409 int ret
= RAND_status();
1410 printf("rand: %s\n", ret
== 1 ? "ok" : "not available");
1417 random_data(void *opt
, int argc
, char **argv
)
1422 len
= parse_bytes(argv
[0], "byte");
1424 fprintf(stderr
, "bad argument to random-data\n");
1430 fprintf(stderr
, "out of memory\n");
1434 ret
= RAND_bytes(ptr
, len
);
1437 fprintf(stderr
, "did not get cryptographic strong random\n");
1441 fwrite(ptr
, len
, 1, stdout
);
1450 crypto_available(struct crypto_available_options
*opt
, int argc
, char **argv
)
1452 AlgorithmIdentifier
*val
;
1453 unsigned int len
, i
;
1454 int ret
, type
= HX509_SELECT_ALL
;
1456 if (opt
->type_string
) {
1457 if (strcmp(opt
->type_string
, "all") == 0)
1458 type
= HX509_SELECT_ALL
;
1459 else if (strcmp(opt
->type_string
, "digest") == 0)
1460 type
= HX509_SELECT_DIGEST
;
1461 else if (strcmp(opt
->type_string
, "public-sig") == 0)
1462 type
= HX509_SELECT_PUBLIC_SIG
;
1463 else if (strcmp(opt
->type_string
, "secret") == 0)
1464 type
= HX509_SELECT_SECRET_ENC
;
1466 errx(1, "unknown type: %s", opt
->type_string
);
1469 ret
= hx509_crypto_available(context
, type
, NULL
, &val
, &len
);
1471 errx(1, "hx509_crypto_available");
1473 for (i
= 0; i
< len
; i
++) {
1475 der_print_heim_oid (&val
[i
].algorithm
, '.', &s
);
1480 hx509_crypto_free_algs(val
, len
);
1486 crypto_select(struct crypto_select_options
*opt
, int argc
, char **argv
)
1488 hx509_peer_info peer
= NULL
;
1489 AlgorithmIdentifier selected
;
1490 int ret
, type
= HX509_SELECT_DIGEST
;
1493 if (opt
->type_string
) {
1494 if (strcmp(opt
->type_string
, "digest") == 0)
1495 type
= HX509_SELECT_DIGEST
;
1496 else if (strcmp(opt
->type_string
, "public-sig") == 0)
1497 type
= HX509_SELECT_PUBLIC_SIG
;
1498 else if (strcmp(opt
->type_string
, "secret") == 0)
1499 type
= HX509_SELECT_SECRET_ENC
;
1501 errx(1, "unknown type: %s", opt
->type_string
);
1504 if (opt
->peer_cmstype_strings
.num_strings
)
1505 peer_strings(context
, &peer
, &opt
->peer_cmstype_strings
);
1507 ret
= hx509_crypto_select(context
, type
, NULL
, peer
, &selected
);
1509 errx(1, "hx509_crypto_available");
1511 der_print_heim_oid (&selected
.algorithm
, '.', &s
);
1514 free_AlgorithmIdentifier(&selected
);
1516 hx509_peer_info_free(peer
);
1522 hxtool_hex(struct hex_options
*opt
, int argc
, char **argv
)
1525 if (opt
->decode_flag
) {
1526 char buf
[1024], buf2
[1024], *p
;
1529 while(fgets(buf
, sizeof(buf
), stdin
) != NULL
) {
1530 buf
[strcspn(buf
, "\r\n")] = '\0';
1532 while(isspace(*(unsigned char *)p
))
1534 len
= hex_decode(p
, buf2
, strlen(p
));
1536 errx(1, "hex_decode failed");
1537 if (fwrite(buf2
, 1, len
, stdout
) != (size_t)len
)
1538 errx(1, "fwrite failed");
1544 while((len
= fread(buf
, 1, sizeof(buf
), stdin
)) != 0) {
1545 len
= hex_encode(buf
, len
, &p
);
1548 fprintf(stdout
, "%s\n", p
);
1555 struct cert_type_opt
{
1561 https_server(hx509_context contextp
, hx509_ca_tbs tbs
, struct cert_type_opt
*opt
)
1563 return hx509_ca_tbs_add_eku(contextp
, tbs
, &asn1_oid_id_pkix_kp_serverAuth
);
1567 https_client(hx509_context contextp
, hx509_ca_tbs tbs
, struct cert_type_opt
*opt
)
1569 return hx509_ca_tbs_add_eku(contextp
, tbs
, &asn1_oid_id_pkix_kp_clientAuth
);
1573 peap_server(hx509_context contextp
, hx509_ca_tbs tbs
, struct cert_type_opt
*opt
)
1575 return hx509_ca_tbs_add_eku(contextp
, tbs
, &asn1_oid_id_pkix_kp_serverAuth
);
1579 pkinit_kdc(hx509_context contextp
, hx509_ca_tbs tbs
, struct cert_type_opt
*opt
)
1582 return hx509_ca_tbs_add_eku(contextp
, tbs
, &asn1_oid_id_pkkdcekuoid
);
1586 pkinit_client(hx509_context contextp
, hx509_ca_tbs tbs
, struct cert_type_opt
*opt
)
1592 ret
= hx509_ca_tbs_add_eku(contextp
, tbs
, &asn1_oid_id_pkekuoid
);
1596 ret
= hx509_ca_tbs_add_eku(context
, tbs
, &asn1_oid_id_ms_client_authentication
);
1600 return hx509_ca_tbs_add_eku(context
, tbs
, &asn1_oid_id_pkinit_ms_eku
);
1604 email_client(hx509_context contextp
, hx509_ca_tbs tbs
, struct cert_type_opt
*opt
)
1606 return hx509_ca_tbs_add_eku(contextp
, tbs
, &asn1_oid_id_pkix_kp_emailProtection
);
1612 int (*eval
)(hx509_context
, hx509_ca_tbs
, struct cert_type_opt
*);
1616 "Used for HTTPS server and many other TLS server certificate types",
1621 "Used for HTTPS client certificates",
1626 "Certificate will be use for email",
1631 "Certificate used for Kerberos PK-INIT client certificates",
1636 "Certificates used for Kerberos PK-INIT KDC certificates",
1641 "Certificate used for Radius PEAP (Protected EAP)",
1647 print_eval_types(FILE *out
)
1652 table
= rtbl_create();
1653 rtbl_add_column_by_id (table
, 0, "Name", 0);
1654 rtbl_add_column_by_id (table
, 1, "Description", 0);
1656 for (i
= 0; i
< sizeof(certtypes
)/sizeof(certtypes
[0]); i
++) {
1657 rtbl_add_column_entry_by_id(table
, 0, certtypes
[i
].type
);
1658 rtbl_add_column_entry_by_id(table
, 1, certtypes
[i
].desc
);
1661 rtbl_format (table
, out
);
1662 rtbl_destroy (table
);
1666 eval_types(hx509_context contextp
,
1668 const struct certificate_sign_options
*opt
)
1670 struct cert_type_opt ctopt
;
1675 memset(&ctopt
, 0, sizeof(ctopt
));
1677 for (i
= 0; i
< opt
->type_strings
.num_strings
; i
++) {
1678 const char *type
= opt
->type_strings
.strings
[i
];
1680 for (j
= 0; j
< sizeof(certtypes
)/sizeof(certtypes
[0]); j
++) {
1681 if (strcasecmp(type
, certtypes
[j
].type
) == 0) {
1682 ret
= (*certtypes
[j
].eval
)(contextp
, tbs
, &ctopt
);
1684 hx509_err(contextp
, 1, ret
,
1685 "Failed to evaluate cert type %s", type
);
1689 if (j
>= sizeof(certtypes
)/sizeof(certtypes
[0])) {
1690 fprintf(stderr
, "Unknown certificate type %s\n\n", type
);
1691 fprintf(stderr
, "Available types:\n");
1692 print_eval_types(stderr
);
1697 if (opt
->pk_init_principal_string
) {
1699 errx(1, "pk-init principal given but no pk-init oid");
1701 ret
= hx509_ca_tbs_add_san_pkinit(contextp
, tbs
,
1702 opt
->pk_init_principal_string
);
1704 hx509_err(contextp
, 1, ret
, "hx509_ca_tbs_add_san_pkinit");
1707 if (opt
->ms_upn_string
) {
1709 errx(1, "MS upn given but no pk-init oid");
1711 ret
= hx509_ca_tbs_add_san_ms_upn(contextp
, tbs
, opt
->ms_upn_string
);
1713 hx509_err(contextp
, 1, ret
, "hx509_ca_tbs_add_san_ms_upn");
1717 for (i
= 0; i
< opt
->hostname_strings
.num_strings
; i
++) {
1718 const char *hostname
= opt
->hostname_strings
.strings
[i
];
1720 ret
= hx509_ca_tbs_add_san_hostname(contextp
, tbs
, hostname
);
1722 hx509_err(contextp
, 1, ret
, "hx509_ca_tbs_add_san_hostname");
1725 for (i
= 0; i
< opt
->email_strings
.num_strings
; i
++) {
1726 const char *email
= opt
->email_strings
.strings
[i
];
1728 ret
= hx509_ca_tbs_add_san_rfc822name(contextp
, tbs
, email
);
1730 hx509_err(contextp
, 1, ret
, "hx509_ca_tbs_add_san_hostname");
1732 ret
= hx509_ca_tbs_add_eku(contextp
, tbs
,
1733 &asn1_oid_id_pkix_kp_emailProtection
);
1735 hx509_err(contextp
, 1, ret
, "hx509_ca_tbs_add_eku");
1738 if (opt
->jid_string
) {
1739 ret
= hx509_ca_tbs_add_san_jid(contextp
, tbs
, opt
->jid_string
);
1741 hx509_err(contextp
, 1, ret
, "hx509_ca_tbs_add_san_jid");
1748 hxtool_ca(struct certificate_sign_options
*opt
, int argc
, char **argv
)
1752 hx509_cert signer
= NULL
, cert
= NULL
;
1753 hx509_private_key private_key
= NULL
;
1754 hx509_private_key cert_key
= NULL
;
1755 hx509_name subject
= NULL
;
1756 SubjectPublicKeyInfo spki
;
1759 memset(&spki
, 0, sizeof(spki
));
1761 if (opt
->ca_certificate_string
== NULL
&& !opt
->self_signed_flag
)
1762 errx(1, "--ca-certificate argument missing (not using --self-signed)");
1763 if (opt
->ca_private_key_string
== NULL
&& opt
->generate_key_string
== NULL
&& opt
->self_signed_flag
)
1764 errx(1, "--ca-private-key argument missing (using --self-signed)");
1765 if (opt
->certificate_string
== NULL
)
1766 errx(1, "--certificate argument missing");
1768 if (opt
->template_certificate_string
) {
1769 if (opt
->template_fields_string
== NULL
)
1770 errx(1, "--template-certificate not no --template-fields");
1773 if (opt
->lifetime_string
) {
1774 delta
= parse_time(opt
->lifetime_string
, "day");
1776 errx(1, "Invalid lifetime: %s", opt
->lifetime_string
);
1779 if (opt
->ca_certificate_string
) {
1780 hx509_certs cacerts
= NULL
;
1783 ret
= hx509_certs_init(context
, opt
->ca_certificate_string
, 0,
1786 hx509_err(context
, 1, ret
,
1787 "hx509_certs_init: %s", opt
->ca_certificate_string
);
1789 ret
= hx509_query_alloc(context
, &q
);
1791 errx(1, "hx509_query_alloc: %d", ret
);
1793 hx509_query_match_option(q
, HX509_QUERY_OPTION_PRIVATE_KEY
);
1794 if (!opt
->issue_proxy_flag
)
1795 hx509_query_match_option(q
, HX509_QUERY_OPTION_KU_KEYCERTSIGN
);
1797 ret
= hx509_certs_find(context
, cacerts
, q
, &signer
);
1798 hx509_query_free(context
, q
);
1799 hx509_certs_free(&cacerts
);
1801 hx509_err(context
, 1, ret
, "no CA certificate found");
1802 } else if (opt
->self_signed_flag
) {
1803 if (opt
->generate_key_string
== NULL
1804 && opt
->ca_private_key_string
== NULL
)
1805 errx(1, "no signing private key");
1807 if (opt
->req_string
)
1808 errx(1, "can't be self-signing and have a request at the same time");
1810 errx(1, "missing ca key");
1812 if (opt
->ca_private_key_string
) {
1814 ret
= read_private_key(opt
->ca_private_key_string
, &private_key
);
1816 err(1, "read_private_key");
1818 ret
= hx509_private_key2SPKI(context
, private_key
, &spki
);
1820 errx(1, "hx509_private_key2SPKI: %d\n", ret
);
1822 if (opt
->self_signed_flag
)
1823 cert_key
= private_key
;
1826 if (opt
->req_string
) {
1829 ret
= _hx509_request_parse(context
, opt
->req_string
, &req
);
1831 hx509_err(context
, 1, ret
, "parse_request: %s", opt
->req_string
);
1832 ret
= hx509_request_get_name(context
, req
, &subject
);
1834 hx509_err(context
, 1, ret
, "get name");
1835 ret
= hx509_request_get_SubjectPublicKeyInfo(context
, req
, &spki
);
1837 hx509_err(context
, 1, ret
, "get spki");
1838 hx509_request_free(&req
);
1841 if (opt
->generate_key_string
) {
1842 struct hx509_generate_private_context
*keyctx
;
1844 ret
= _hx509_generate_private_key_init(context
,
1845 &asn1_oid_id_pkcs1_rsaEncryption
,
1848 hx509_err(context
, 1, ret
, "generate private key");
1850 if (opt
->issue_ca_flag
)
1851 _hx509_generate_private_key_is_ca(context
, keyctx
);
1853 if (opt
->key_bits_integer
)
1854 _hx509_generate_private_key_bits(context
, keyctx
,
1855 opt
->key_bits_integer
);
1857 ret
= _hx509_generate_private_key(context
, keyctx
,
1859 _hx509_generate_private_key_free(&keyctx
);
1861 hx509_err(context
, 1, ret
, "generate private key");
1863 ret
= hx509_private_key2SPKI(context
, cert_key
, &spki
);
1865 errx(1, "hx509_private_key2SPKI: %d\n", ret
);
1867 if (opt
->self_signed_flag
)
1868 private_key
= cert_key
;
1871 if (opt
->certificate_private_key_string
) {
1872 ret
= read_private_key(opt
->certificate_private_key_string
, &cert_key
);
1874 err(1, "read_private_key for certificate");
1877 if (opt
->subject_string
) {
1879 hx509_name_free(&subject
);
1880 ret
= hx509_parse_name(context
, opt
->subject_string
, &subject
);
1882 hx509_err(context
, 1, ret
, "hx509_parse_name");
1889 ret
= hx509_ca_tbs_init(context
, &tbs
);
1891 hx509_err(context
, 1, ret
, "hx509_ca_tbs_init");
1893 if (opt
->template_certificate_string
) {
1894 hx509_cert
template;
1898 ret
= hx509_certs_init(context
, opt
->template_certificate_string
, 0,
1901 hx509_err(context
, 1, ret
,
1902 "hx509_certs_init: %s", opt
->template_certificate_string
);
1904 ret
= hx509_get_one_cert(context
, tcerts
, &template);
1906 hx509_certs_free(&tcerts
);
1908 hx509_err(context
, 1, ret
, "no template certificate found");
1910 flags
= parse_units(opt
->template_fields_string
,
1911 hx509_ca_tbs_template_units(), "");
1913 ret
= hx509_ca_tbs_set_template(context
, tbs
, flags
, template);
1915 hx509_err(context
, 1, ret
, "hx509_ca_tbs_set_template");
1917 hx509_cert_free(template);
1920 if (opt
->serial_number_string
) {
1921 heim_integer serialNumber
;
1923 ret
= der_parse_hex_heim_integer(opt
->serial_number_string
,
1926 err(1, "der_parse_hex_heim_integer");
1927 ret
= hx509_ca_tbs_set_serialnumber(context
, tbs
, &serialNumber
);
1929 hx509_err(context
, 1, ret
, "hx509_ca_tbs_init");
1930 der_free_heim_integer(&serialNumber
);
1933 if (spki
.subjectPublicKey
.length
) {
1934 ret
= hx509_ca_tbs_set_spki(context
, tbs
, &spki
);
1936 hx509_err(context
, 1, ret
, "hx509_ca_tbs_set_spki");
1940 ret
= hx509_ca_tbs_set_subject(context
, tbs
, subject
);
1942 hx509_err(context
, 1, ret
, "hx509_ca_tbs_set_subject");
1945 if (opt
->crl_uri_string
) {
1946 ret
= hx509_ca_tbs_add_crl_dp_uri(context
, tbs
,
1947 opt
->crl_uri_string
, NULL
);
1949 hx509_err(context
, 1, ret
, "hx509_ca_tbs_add_crl_dp_uri");
1952 eval_types(context
, tbs
, opt
);
1954 if (opt
->issue_ca_flag
) {
1955 ret
= hx509_ca_tbs_set_ca(context
, tbs
, opt
->path_length_integer
);
1957 hx509_err(context
, 1, ret
, "hx509_ca_tbs_set_ca");
1959 if (opt
->issue_proxy_flag
) {
1960 ret
= hx509_ca_tbs_set_proxy(context
, tbs
, opt
->path_length_integer
);
1962 hx509_err(context
, 1, ret
, "hx509_ca_tbs_set_proxy");
1964 if (opt
->domain_controller_flag
) {
1965 hx509_ca_tbs_set_domaincontroller(context
, tbs
);
1967 hx509_err(context
, 1, ret
, "hx509_ca_tbs_set_domaincontroller");
1971 ret
= hx509_ca_tbs_set_notAfter_lifetime(context
, tbs
, delta
);
1973 hx509_err(context
, 1, ret
, "hx509_ca_tbs_set_notAfter_lifetime");
1976 if (opt
->self_signed_flag
) {
1977 ret
= hx509_ca_sign_self(context
, tbs
, private_key
, &cert
);
1979 hx509_err(context
, 1, ret
, "hx509_ca_sign_self");
1981 ret
= hx509_ca_sign(context
, tbs
, signer
, &cert
);
1983 hx509_err(context
, 1, ret
, "hx509_ca_sign");
1987 ret
= _hx509_cert_assign_key(cert
, cert_key
);
1989 hx509_err(context
, 1, ret
, "_hx509_cert_assign_key");
1995 ret
= hx509_certs_init(context
, opt
->certificate_string
,
1996 HX509_CERTS_CREATE
, NULL
, &certs
);
1998 hx509_err(context
, 1, ret
, "hx509_certs_init");
2000 ret
= hx509_certs_add(context
, certs
, cert
);
2002 hx509_err(context
, 1, ret
, "hx509_certs_add");
2004 ret
= hx509_certs_store(context
, certs
, 0, NULL
);
2006 hx509_err(context
, 1, ret
, "hx509_certs_store");
2008 hx509_certs_free(&certs
);
2012 hx509_name_free(&subject
);
2014 hx509_cert_free(signer
);
2015 hx509_cert_free(cert
);
2016 free_SubjectPublicKeyInfo(&spki
);
2018 if (private_key
!= cert_key
)
2019 hx509_private_key_free(&private_key
);
2020 hx509_private_key_free(&cert_key
);
2022 hx509_ca_tbs_free(&tbs
);
2028 test_one_cert(hx509_context hxcontext
, void *ctx
, hx509_cert cert
)
2030 heim_octet_string sd
, c
;
2031 hx509_verify_ctx vctx
= ctx
;
2032 hx509_certs signer
= NULL
;
2036 if (_hx509_cert_private_key(cert
) == NULL
)
2039 ret
= hx509_cms_create_signed_1(context
, 0, NULL
, NULL
, 0,
2040 NULL
, cert
, NULL
, NULL
, NULL
, &sd
);
2042 errx(1, "hx509_cms_create_signed_1");
2044 ret
= hx509_cms_verify_signed(context
, vctx
, 0, sd
.data
, sd
.length
,
2045 NULL
, NULL
, &type
, &c
, &signer
);
2048 hx509_err(context
, 1, ret
, "hx509_cms_verify_signed");
2050 printf("create-signature verify-sigature done\n");
2058 test_crypto(struct test_crypto_options
*opt
, int argc
, char ** argv
)
2060 hx509_verify_ctx vctx
;
2065 hx509_lock_init(context
, &lock
);
2066 lock_strings(lock
, &opt
->pass_strings
);
2068 ret
= hx509_certs_init(context
, "MEMORY:test-crypto", 0, NULL
, &certs
);
2069 if (ret
) hx509_err(context
, 1, ret
, "hx509_certs_init: MEMORY");
2071 for (i
= 0; i
< argc
; i
++) {
2072 ret
= hx509_certs_append(context
, certs
, lock
, argv
[i
]);
2074 hx509_err(context
, 1, ret
, "hx509_certs_append");
2077 ret
= hx509_verify_init_ctx(context
, &vctx
);
2079 hx509_err(context
, 1, ret
, "hx509_verify_init_ctx");
2081 hx509_verify_attach_anchors(vctx
, certs
);
2083 ret
= hx509_certs_iter_f(context
, certs
, test_one_cert
, vctx
);
2085 hx509_err(context
, 1, ret
, "hx509_cert_iter");
2087 hx509_certs_free(&certs
);
2093 statistic_print(struct statistic_print_options
*opt
, int argc
, char **argv
)
2097 if (stat_file_string
== NULL
)
2098 errx(1, "no stat file");
2100 if (opt
->type_integer
)
2101 type
= opt
->type_integer
;
2103 hx509_query_unparse_stats(context
, type
, stdout
);
2112 crl_sign(struct crl_sign_options
*opt
, int argc
, char **argv
)
2115 heim_octet_string os
;
2116 hx509_cert signer
= NULL
;
2120 hx509_lock_init(context
, &lock
);
2121 lock_strings(lock
, &opt
->pass_strings
);
2123 ret
= hx509_crl_alloc(context
, &crl
);
2125 errx(1, "crl alloc");
2127 if (opt
->signer_string
== NULL
)
2128 errx(1, "signer missing");
2131 hx509_certs certs
= NULL
;
2134 ret
= hx509_certs_init(context
, opt
->signer_string
, 0,
2137 hx509_err(context
, 1, ret
,
2138 "hx509_certs_init: %s", opt
->signer_string
);
2140 ret
= hx509_query_alloc(context
, &q
);
2142 hx509_err(context
, 1, ret
, "hx509_query_alloc: %d", ret
);
2144 hx509_query_match_option(q
, HX509_QUERY_OPTION_PRIVATE_KEY
);
2146 ret
= hx509_certs_find(context
, certs
, q
, &signer
);
2147 hx509_query_free(context
, q
);
2148 hx509_certs_free(&certs
);
2150 hx509_err(context
, 1, ret
, "no signer certificate found");
2153 if (opt
->lifetime_string
) {
2156 delta
= parse_time(opt
->lifetime_string
, "day");
2158 errx(1, "Invalid lifetime: %s", opt
->lifetime_string
);
2160 hx509_crl_lifetime(context
, crl
, delta
);
2164 hx509_certs revoked
= NULL
;
2167 ret
= hx509_certs_init(context
, "MEMORY:revoked-certs", 0,
2170 hx509_err(context
, 1, ret
,
2171 "hx509_certs_init: MEMORY cert");
2173 for (i
= 0; i
< argc
; i
++) {
2174 ret
= hx509_certs_append(context
, revoked
, lock
, argv
[i
]);
2176 hx509_err(context
, 1, ret
, "hx509_certs_append: %s", argv
[i
]);
2179 hx509_crl_add_revoked_certs(context
, crl
, revoked
);
2180 hx509_certs_free(&revoked
);
2183 hx509_crl_sign(context
, signer
, crl
, &os
);
2185 if (opt
->crl_file_string
)
2186 rk_dumpdata(opt
->crl_file_string
, os
.data
, os
.length
);
2190 hx509_crl_free(context
, &crl
);
2191 hx509_cert_free(signer
);
2192 hx509_lock_free(lock
);
2202 help(void *opt
, int argc
, char **argv
)
2204 sl_slc_help(commands
, argc
, argv
);
2209 main(int argc
, char **argv
)
2211 int ret
, optidx
= 0;
2213 setprogname (argv
[0]);
2215 if(getarg(args
, num_args
, argc
, argv
, &optidx
))
2220 print_version(NULL
);
2229 ret
= hx509_context_init(&context
);
2231 errx(1, "hx509_context_init failed with %d", ret
);
2233 if (stat_file_string
)
2234 hx509_query_statistic_file(context
, stat_file_string
);
2236 ret
= sl_command(commands
, argc
, argv
);
2238 warnx ("unrecognized command: %s", argv
[0]);
2240 hx509_context_free(&context
);