2 * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #include <hxtool-commands.h>
39 #include <parse_time.h>
41 static hx509_context context
;
43 static char *stat_file_string
;
44 static int version_flag
;
47 struct getargs args
[] = {
48 { "statistic-file", 0, arg_string
, &stat_file_string
},
49 { "version", 0, arg_flag
, &version_flag
},
50 { "help", 0, arg_flag
, &help_flag
}
52 int num_args
= sizeof(args
) / sizeof(args
[0]);
57 arg_printusage(args
, num_args
, NULL
, "command");
58 printf("Use \"%s help\" to get more help\n", getprogname());
67 lock_strings(hx509_lock lock
, getarg_strings
*pass
)
70 for (i
= 0; i
< pass
->num_strings
; i
++) {
71 int ret
= hx509_lock_command_string(lock
, pass
->strings
[i
]);
73 errx(1, "hx509_lock_command_string: %s: %d",
74 pass
->strings
[i
], ret
);
83 certs_strings(hx509_context context
, const char *type
, hx509_certs certs
,
84 hx509_lock lock
, const getarg_strings
*s
)
88 for (i
= 0; i
< s
->num_strings
; i
++) {
89 ret
= hx509_certs_append(context
, certs
, lock
, s
->strings
[i
]);
91 hx509_err(context
, 1, ret
,
92 "hx509_certs_append: %s %s", type
, s
->strings
[i
]);
101 parse_oid(const char *str
, const heim_oid
*def
, heim_oid
*oid
)
105 ret
= der_parse_heim_oid (str
, " .", oid
);
107 ret
= der_copy_oid(def
, oid
);
109 errx(1, "parse_oid failed for: %s", str
? str
: "default oid");
117 peer_strings(hx509_context context
,
118 hx509_peer_info
*peer
,
119 const getarg_strings
*s
)
121 AlgorithmIdentifier
*val
;
124 ret
= hx509_peer_info_alloc(context
, peer
);
126 hx509_err(context
, 1, ret
, "hx509_peer_info_alloc");
128 val
= calloc(s
->num_strings
, sizeof(*val
));
132 for (i
= 0; i
< s
->num_strings
; i
++)
133 parse_oid(s
->strings
[i
], NULL
, &val
[i
].algorithm
);
135 ret
= hx509_peer_info_set_cms_algs(context
, *peer
, val
, s
->num_strings
);
137 hx509_err(context
, 1, ret
, "hx509_peer_info_set_cms_algs");
139 for (i
= 0; i
< s
->num_strings
; i
++)
140 free_AlgorithmIdentifier(&val
[i
]);
149 heim_octet_string
*os
;
154 pem_reader(hx509_context context
, const char *type
,
155 const hx509_pem_header
*headers
,
156 const void *data
, size_t length
, void *ctx
)
158 struct pem_data
*p
= (struct pem_data
*)ctx
;
161 p
->os
->data
= malloc(length
);
162 if (p
->os
->data
== NULL
)
164 memcpy(p
->os
->data
, data
, length
);
165 p
->os
->length
= length
;
167 h
= hx509_pem_find_header(headers
, "Content-disposition");
168 if (h
&& strcasecmp(h
, "detached") == 0)
169 p
->detached_data
= 1;
179 cms_verify_sd(struct cms_verify_sd_options
*opt
, int argc
, char **argv
)
181 hx509_verify_ctx ctx
= NULL
;
183 heim_octet_string c
, co
, signeddata
, *sd
= NULL
;
184 hx509_certs store
= NULL
;
185 hx509_certs signers
= NULL
;
186 hx509_certs anchors
= NULL
;
193 if (opt
->missing_revoke_flag
)
194 hx509_context_set_missing_revoke(context
, 1);
196 hx509_lock_init(context
, &lock
);
197 lock_strings(lock
, &opt
->pass_strings
);
199 ret
= hx509_verify_init_ctx(context
, &ctx
);
201 hx509_err(context
, 1, ret
, "hx509_verify_init_ctx");
203 ret
= hx509_certs_init(context
, "MEMORY:cms-anchors", 0, NULL
, &anchors
);
205 hx509_err(context
, 1, ret
, "hx509_certs_init: MEMORY");
206 ret
= hx509_certs_init(context
, "MEMORY:cert-store", 0, NULL
, &store
);
208 hx509_err(context
, 1, ret
, "hx509_certs_init: MEMORY");
210 certs_strings(context
, "anchors", anchors
, lock
, &opt
->anchors_strings
);
211 certs_strings(context
, "store", store
, lock
, &opt
->certificate_strings
);
220 f
= fopen(argv
[0], "r");
222 err(1, "Failed to open file %s", argv
[0]);
224 ret
= hx509_pem_read(context
, f
, pem_reader
, &p
);
227 errx(1, "PEM reader failed: %d", ret
);
229 if (p
.detached_data
&& opt
->signed_content_string
== NULL
) {
230 char *r
= strrchr(argv
[0], '.');
231 if (r
&& strcasecmp(r
, ".pem") == 0) {
232 char *s
= strdup(argv
[0]);
234 errx(1, "malloc: out of memory");
235 s
[r
- argv
[0]] = '\0';
236 ret
= _hx509_map_file_os(s
, &signeddata
);
238 errx(1, "map_file: %s: %d", s
, ret
);
245 ret
= rk_undumpdata(argv
[0], &p
, &sz
);
247 err(1, "map_file: %s: %d", argv
[0], ret
);
253 if (opt
->signed_content_string
) {
254 ret
= _hx509_map_file_os(opt
->signed_content_string
, &signeddata
);
256 errx(1, "map_file: %s: %d", opt
->signed_content_string
, ret
);
260 if (opt
->content_info_flag
) {
261 heim_octet_string uwco
;
264 ret
= hx509_cms_unwrap_ContentInfo(&co
, &oid
, &uwco
, NULL
);
266 errx(1, "hx509_cms_unwrap_ContentInfo: %d", ret
);
268 if (der_heim_oid_cmp(&oid
, &asn1_oid_id_pkcs7_signedData
) != 0)
269 errx(1, "Content is not SignedData");
273 der_free_octet_string(&co
);
281 hx509_verify_attach_anchors(ctx
, anchors
);
283 if (!opt
->signer_allowed_flag
)
284 flags
|= HX509_CMS_VS_ALLOW_ZERO_SIGNER
;
285 if (opt
->allow_wrong_oid_flag
)
286 flags
|= HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH
;
288 ret
= hx509_cms_verify_signed(context
, ctx
, flags
, co
.data
, co
.length
, sd
,
289 store
, &type
, &c
, &signers
);
291 der_free_octet_string(&co
);
295 hx509_err(context
, 1, ret
, "hx509_cms_verify_signed");
299 der_print_heim_oid(&type
, '.', &str
);
300 printf("type: %s\n", str
);
304 if (signers
== NULL
) {
305 printf("unsigned\n");
307 printf("signers:\n");
308 hx509_certs_iter_f(context
, signers
, hx509_ci_print_names
, stdout
);
311 hx509_verify_destroy_ctx(ctx
);
313 hx509_certs_free(&store
);
314 hx509_certs_free(&signers
);
315 hx509_certs_free(&anchors
);
317 hx509_lock_free(lock
);
320 ret
= _hx509_write_file(argv
[1], c
.data
, c
.length
);
322 errx(1, "hx509_write_file: %d", ret
);
325 der_free_octet_string(&c
);
328 _hx509_unmap_file_os(sd
);
334 print_signer(hx509_context context
, void *ctx
, hx509_cert cert
)
336 hx509_pem_header
**header
= ctx
;
337 char *signer_name
= NULL
;
341 ret
= hx509_cert_get_subject(cert
, &name
);
343 errx(1, "hx509_cert_get_subject");
345 ret
= hx509_name_to_string(name
, &signer_name
);
346 hx509_name_free(&name
);
348 errx(1, "hx509_name_to_string");
350 hx509_pem_add_header(header
, "Signer", signer_name
);
357 cms_create_sd(struct cms_create_sd_options
*opt
, int argc
, char **argv
)
359 heim_oid contentType
;
360 hx509_peer_info peer
= NULL
;
364 hx509_certs store
, pool
, anchors
, signer
= NULL
;
368 char *infile
, *outfile
= NULL
;
370 memset(&contentType
, 0, sizeof(contentType
));
375 asprintf(&outfile
, "%s.%s", infile
,
376 opt
->pem_flag
? "pem" : "cms-signeddata");
378 errx(1, "out of memory");
382 hx509_lock_init(context
, &lock
);
383 lock_strings(lock
, &opt
->pass_strings
);
385 ret
= hx509_certs_init(context
, "MEMORY:cert-store", 0, NULL
, &store
);
386 if (ret
) hx509_err(context
, 1, ret
, "hx509_certs_init: MEMORY");
387 ret
= hx509_certs_init(context
, "MEMORY:cert-pool", 0, NULL
, &pool
);
388 if (ret
) hx509_err(context
, 1, ret
, "hx509_certs_init: MEMORY");
390 certs_strings(context
, "store", store
, lock
, &opt
->certificate_strings
);
391 certs_strings(context
, "pool", pool
, lock
, &opt
->pool_strings
);
393 if (opt
->anchors_strings
.num_strings
) {
394 ret
= hx509_certs_init(context
, "MEMORY:cert-anchors",
396 if (ret
) hx509_err(context
, 1, ret
, "hx509_certs_init: MEMORY");
397 certs_strings(context
, "anchors", anchors
, lock
, &opt
->anchors_strings
);
401 if (opt
->detached_signature_flag
)
402 flags
|= HX509_CMS_SIGNATURE_DETACHED
;
403 if (opt
->id_by_name_flag
)
404 flags
|= HX509_CMS_SIGNATURE_ID_NAME
;
405 if (!opt
->signer_flag
) {
406 flags
|= HX509_CMS_SIGNATURE_NO_SIGNER
;
410 if (opt
->signer_flag
) {
411 ret
= hx509_query_alloc(context
, &q
);
413 errx(1, "hx509_query_alloc: %d", ret
);
415 hx509_query_match_option(q
, HX509_QUERY_OPTION_PRIVATE_KEY
);
416 hx509_query_match_option(q
, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE
);
418 if (opt
->signer_string
)
419 hx509_query_match_friendly_name(q
, opt
->signer_string
);
421 ret
= hx509_certs_filter(context
, store
, q
, &signer
);
422 hx509_query_free(context
, q
);
424 hx509_err(context
, 1, ret
, "hx509_certs_find");
426 if (!opt
->embedded_certs_flag
)
427 flags
|= HX509_CMS_SIGNATURE_NO_CERTS
;
428 if (opt
->embed_leaf_only_flag
)
429 flags
|= HX509_CMS_SIGNATURE_LEAF_ONLY
;
431 ret
= rk_undumpdata(infile
, &p
, &sz
);
433 err(1, "map_file: %s: %d", infile
, ret
);
435 if (opt
->peer_alg_strings
.num_strings
)
436 peer_strings(context
, &peer
, &opt
->peer_alg_strings
);
438 parse_oid(opt
->content_type_string
, &asn1_oid_id_pkcs7_data
, &contentType
);
440 ret
= hx509_cms_create_signed(context
,
452 hx509_err(context
, 1, ret
, "hx509_cms_create_signed: %d", ret
);
454 hx509_certs_free(&anchors
);
455 hx509_certs_free(&pool
);
456 hx509_certs_free(&store
);
458 hx509_lock_free(lock
);
459 hx509_peer_info_free(peer
);
460 der_free_oid(&contentType
);
462 if (opt
->content_info_flag
) {
463 heim_octet_string wo
;
465 ret
= hx509_cms_wrap_ContentInfo(&asn1_oid_id_pkcs7_signedData
, &o
, &wo
);
467 errx(1, "hx509_cms_wrap_ContentInfo: %d", ret
);
469 der_free_octet_string(&o
);
474 hx509_pem_header
*header
= NULL
;
477 hx509_pem_add_header(&header
, "Content-disposition",
478 opt
->detached_signature_flag
?
479 "detached" : "inline");
481 ret
= hx509_certs_iter_f(context
, signer
, print_signer
, header
);
483 hx509_err(context
, 1, ret
, "print signer");
486 f
= fopen(outfile
, "w");
488 err(1, "open %s", outfile
);
490 ret
= hx509_pem_write(context
, "CMS SIGNEDDATA", header
, f
,
493 hx509_pem_free_header(header
);
495 errx(1, "hx509_pem_write: %d", ret
);
498 ret
= _hx509_write_file(outfile
, o
.data
, o
.length
);
500 errx(1, "hx509_write_file: %d", ret
);
503 hx509_certs_free(&signer
);
510 cms_unenvelope(struct cms_unenvelope_options
*opt
, int argc
, char **argv
)
512 heim_oid contentType
= { 0, NULL
};
513 heim_octet_string o
, co
;
521 hx509_lock_init(context
, &lock
);
522 lock_strings(lock
, &opt
->pass_strings
);
524 ret
= rk_undumpdata(argv
[0], &p
, &sz
);
526 err(1, "map_file: %s: %d", argv
[0], ret
);
531 if (opt
->content_info_flag
) {
532 heim_octet_string uwco
;
535 ret
= hx509_cms_unwrap_ContentInfo(&co
, &oid
, &uwco
, NULL
);
537 errx(1, "hx509_cms_unwrap_ContentInfo: %d", ret
);
539 if (der_heim_oid_cmp(&oid
, &asn1_oid_id_pkcs7_envelopedData
) != 0)
540 errx(1, "Content is not SignedData");
546 ret
= hx509_certs_init(context
, "MEMORY:cert-store", 0, NULL
, &certs
);
548 errx(1, "hx509_certs_init: MEMORY: %d", ret
);
550 certs_strings(context
, "store", certs
, lock
, &opt
->certificate_strings
);
552 if (opt
->allow_weak_crypto_flag
)
553 flags
|= HX509_CMS_UE_ALLOW_WEAK
;
555 ret
= hx509_cms_unenvelope(context
, certs
, flags
, co
.data
, co
.length
,
556 NULL
, 0, &contentType
, &o
);
558 der_free_octet_string(&co
);
560 hx509_err(context
, 1, ret
, "hx509_cms_unenvelope");
563 hx509_lock_free(lock
);
564 hx509_certs_free(&certs
);
565 der_free_oid(&contentType
);
567 ret
= _hx509_write_file(argv
[1], o
.data
, o
.length
);
569 errx(1, "hx509_write_file: %d", ret
);
571 der_free_octet_string(&o
);
577 cms_create_enveloped(struct cms_envelope_options
*opt
, int argc
, char **argv
)
579 heim_oid contentType
;
581 const heim_oid
*enctype
= NULL
;
591 memset(&contentType
, 0, sizeof(contentType
));
593 hx509_lock_init(context
, &lock
);
594 lock_strings(lock
, &opt
->pass_strings
);
596 ret
= rk_undumpdata(argv
[0], &p
, &sz
);
598 err(1, "map_file: %s: %d", argv
[0], ret
);
600 ret
= hx509_certs_init(context
, "MEMORY:cert-store", 0, NULL
, &certs
);
601 if (ret
) hx509_err(context
, 1, ret
, "hx509_certs_init: MEMORY");
603 certs_strings(context
, "store", certs
, lock
, &opt
->certificate_strings
);
605 if (opt
->allow_weak_crypto_flag
)
606 flags
|= HX509_CMS_EV_ALLOW_WEAK
;
608 if (opt
->encryption_type_string
) {
609 enctype
= hx509_crypto_enctype_by_name(opt
->encryption_type_string
);
611 errx(1, "encryption type: %s no found",
612 opt
->encryption_type_string
);
615 ret
= hx509_query_alloc(context
, &q
);
617 errx(1, "hx509_query_alloc: %d", ret
);
619 hx509_query_match_option(q
, HX509_QUERY_OPTION_KU_ENCIPHERMENT
);
621 ret
= hx509_certs_find(context
, certs
, q
, &cert
);
622 hx509_query_free(context
, q
);
624 errx(1, "hx509_certs_find: %d", ret
);
626 parse_oid(opt
->content_type_string
, &asn1_oid_id_pkcs7_data
, &contentType
);
628 ret
= hx509_cms_envelope_1(context
, flags
, cert
, p
, sz
, enctype
,
631 errx(1, "hx509_cms_envelope_1: %d", ret
);
633 hx509_cert_free(cert
);
634 hx509_certs_free(&certs
);
636 der_free_oid(&contentType
);
638 if (opt
->content_info_flag
) {
639 heim_octet_string wo
;
641 ret
= hx509_cms_wrap_ContentInfo(&asn1_oid_id_pkcs7_envelopedData
, &o
, &wo
);
643 errx(1, "hx509_cms_wrap_ContentInfo: %d", ret
);
645 der_free_octet_string(&o
);
649 hx509_lock_free(lock
);
651 ret
= _hx509_write_file(argv
[1], o
.data
, o
.length
);
653 errx(1, "hx509_write_file: %d", ret
);
655 der_free_octet_string(&o
);
661 print_certificate(hx509_context hxcontext
, hx509_cert cert
, int verbose
)
666 fn
= hx509_cert_get_friendly_name(cert
);
668 printf(" friendly name: %s\n", fn
);
669 printf(" private key: %s\n",
670 _hx509_cert_private_key(cert
) ? "yes" : "no");
672 ret
= hx509_print_cert(hxcontext
, cert
, NULL
);
674 errx(1, "failed to print cert");
677 hx509_validate_ctx vctx
;
679 hx509_validate_ctx_init(hxcontext
, &vctx
);
680 hx509_validate_ctx_set_print(vctx
, hx509_print_stdout
, stdout
);
681 hx509_validate_ctx_add_flags(vctx
, HX509_VALIDATE_F_VALIDATE
);
682 hx509_validate_ctx_add_flags(vctx
, HX509_VALIDATE_F_VERBOSE
);
684 hx509_validate_cert(hxcontext
, vctx
, cert
);
686 hx509_validate_ctx_free(vctx
);
697 print_f(hx509_context hxcontext
, void *ctx
, hx509_cert cert
)
699 struct print_s
*s
= ctx
;
701 printf("cert: %d\n", s
->counter
++);
702 print_certificate(context
, cert
, s
->verbose
);
708 pcert_print(struct print_options
*opt
, int argc
, char **argv
)
715 s
.verbose
= opt
->content_flag
;
717 hx509_lock_init(context
, &lock
);
718 lock_strings(lock
, &opt
->pass_strings
);
722 ret
= hx509_certs_init(context
, argv
[0], 0, lock
, &certs
);
724 if (opt
->never_fail_flag
) {
725 printf("ignoreing failure: %d\n", ret
);
728 hx509_err(context
, 1, ret
, "hx509_certs_init");
731 hx509_certs_info(context
, certs
, NULL
, NULL
);
732 hx509_certs_iter_f(context
, certs
, print_f
, &s
);
733 hx509_certs_free(&certs
);
737 hx509_lock_free(lock
);
744 validate_f(hx509_context hxcontext
, void *ctx
, hx509_cert c
)
746 hx509_validate_cert(hxcontext
, ctx
, c
);
751 pcert_validate(struct validate_options
*opt
, int argc
, char **argv
)
753 hx509_validate_ctx ctx
;
757 hx509_lock_init(context
, &lock
);
758 lock_strings(lock
, &opt
->pass_strings
);
760 hx509_validate_ctx_init(context
, &ctx
);
761 hx509_validate_ctx_set_print(ctx
, hx509_print_stdout
, stdout
);
762 hx509_validate_ctx_add_flags(ctx
, HX509_VALIDATE_F_VALIDATE
);
766 ret
= hx509_certs_init(context
, argv
[0], 0, lock
, &certs
);
768 errx(1, "hx509_certs_init: %d", ret
);
769 hx509_certs_iter_f(context
, certs
, validate_f
, ctx
);
770 hx509_certs_free(&certs
);
773 hx509_validate_ctx_free(ctx
);
775 hx509_lock_free(lock
);
781 certificate_copy(struct certificate_copy_options
*opt
, int argc
, char **argv
)
784 hx509_lock inlock
, outlock
= NULL
;
787 hx509_lock_init(context
, &inlock
);
788 lock_strings(inlock
, &opt
->in_pass_strings
);
790 if (opt
->out_pass_string
) {
791 hx509_lock_init(context
, &outlock
);
792 ret
= hx509_lock_command_string(outlock
, opt
->out_pass_string
);
794 errx(1, "hx509_lock_command_string: %s: %d",
795 opt
->out_pass_string
, ret
);
798 ret
= hx509_certs_init(context
, argv
[argc
- 1],
799 HX509_CERTS_CREATE
, inlock
, &certs
);
801 hx509_err(context
, 1, ret
, "hx509_certs_init");
805 ret
= hx509_certs_append(context
, certs
, inlock
, argv
[0]);
807 hx509_err(context
, 1, ret
, "hx509_certs_append");
811 ret
= hx509_certs_store(context
, certs
, 0, outlock
);
813 hx509_err(context
, 1, ret
, "hx509_certs_store");
815 hx509_certs_free(&certs
);
816 hx509_lock_free(inlock
);
817 hx509_lock_free(outlock
);
823 hx509_verify_ctx ctx
;
825 const char *hostname
;
831 verify_f(hx509_context hxcontext
, void *ctx
, hx509_cert c
)
833 struct verify
*v
= ctx
;
836 ret
= hx509_verify_path(hxcontext
, v
->ctx
, c
, v
->chain
);
838 char *s
= hx509_get_error_string(hxcontext
, ret
);
839 printf("verify_path: %s: %d\n", s
, ret
);
840 hx509_free_error_string(s
);
848 ret
= hx509_verify_hostname(hxcontext
, c
, 0, HX509_HN_HOSTNAME
,
849 v
->hostname
, NULL
, 0);
851 printf("verify_hostname: %d\n", ret
);
860 pcert_verify(struct verify_options
*opt
, int argc
, char **argv
)
862 hx509_certs anchors
, chain
, certs
;
863 hx509_revoke_ctx revoke_ctx
;
864 hx509_verify_ctx ctx
;
868 memset(&v
, 0, sizeof(v
));
870 if (opt
->missing_revoke_flag
)
871 hx509_context_set_missing_revoke(context
, 1);
873 ret
= hx509_verify_init_ctx(context
, &ctx
);
875 hx509_err(context
, 1, ret
, "hx509_verify_init_ctx");
876 ret
= hx509_certs_init(context
, "MEMORY:anchors", 0, NULL
, &anchors
);
878 hx509_err(context
, 1, ret
, "hx509_certs_init: MEMORY");
879 ret
= hx509_certs_init(context
, "MEMORY:chain", 0, NULL
, &chain
);
881 hx509_err(context
, 1, ret
, "hx509_certs_init: MEMORY");
882 ret
= hx509_certs_init(context
, "MEMORY:certs", 0, NULL
, &certs
);
884 hx509_err(context
, 1, ret
, "hx509_certs_init: MEMORY");
886 if (opt
->allow_proxy_certificate_flag
)
887 hx509_verify_set_proxy_certificate(ctx
, 1);
889 if (opt
->time_string
) {
894 memset(&tm
, 0, sizeof(tm
));
896 p
= strptime (opt
->time_string
, "%Y-%m-%d", &tm
);
898 errx(1, "Failed to parse time %s, need to be on format %%Y-%%m-%%d",
903 hx509_verify_set_time(ctx
, t
);
906 if (opt
->hostname_string
)
907 v
.hostname
= opt
->hostname_string
;
908 if (opt
->max_depth_integer
)
909 hx509_verify_set_max_depth(ctx
, opt
->max_depth_integer
);
911 ret
= hx509_revoke_init(context
, &revoke_ctx
);
913 errx(1, "hx509_revoke_init: %d", ret
);
918 if (strncmp(s
, "chain:", 6) == 0) {
921 ret
= hx509_certs_append(context
, chain
, NULL
, s
);
923 hx509_err(context
, 1, ret
, "hx509_certs_append: chain: %s: %d", s
, ret
);
925 } else if (strncmp(s
, "anchor:", 7) == 0) {
928 ret
= hx509_certs_append(context
, anchors
, NULL
, s
);
930 hx509_err(context
, 1, ret
, "hx509_certs_append: anchor: %s: %d", s
, ret
);
932 } else if (strncmp(s
, "cert:", 5) == 0) {
935 ret
= hx509_certs_append(context
, certs
, NULL
, s
);
937 hx509_err(context
, 1, ret
, "hx509_certs_append: certs: %s: %d",
940 } else if (strncmp(s
, "crl:", 4) == 0) {
943 ret
= hx509_revoke_add_crl(context
, revoke_ctx
, s
);
945 errx(1, "hx509_revoke_add_crl: %s: %d", s
, ret
);
947 } else if (strncmp(s
, "ocsp:", 4) == 0) {
950 ret
= hx509_revoke_add_ocsp(context
, revoke_ctx
, s
);
952 errx(1, "hx509_revoke_add_ocsp: %s: %d", s
, ret
);
955 errx(1, "unknown option to verify: `%s'\n", s
);
959 hx509_verify_attach_anchors(ctx
, anchors
);
960 hx509_verify_attach_revoke(ctx
, revoke_ctx
);
965 hx509_certs_iter_f(context
, certs
, verify_f
, &v
);
967 hx509_verify_destroy_ctx(ctx
);
969 hx509_certs_free(&certs
);
970 hx509_certs_free(&chain
);
971 hx509_certs_free(&anchors
);
973 hx509_revoke_free(&revoke_ctx
);
977 printf("no certs verify at all\n");
982 printf("failed verifing %d checks\n", v
.errors
);
990 query(struct query_options
*opt
, int argc
, char **argv
)
998 ret
= hx509_query_alloc(context
, &q
);
1000 errx(1, "hx509_query_alloc: %d", ret
);
1002 hx509_lock_init(context
, &lock
);
1003 lock_strings(lock
, &opt
->pass_strings
);
1005 ret
= hx509_certs_init(context
, "MEMORY:cert-store", 0, NULL
, &certs
);
1006 if (ret
) hx509_err(context
, 1, ret
, "hx509_certs_init: MEMORY");
1010 ret
= hx509_certs_append(context
, certs
, lock
, argv
[0]);
1012 errx(1, "hx509_certs_append: %s: %d", argv
[0], ret
);
1018 if (opt
->friendlyname_string
)
1019 hx509_query_match_friendly_name(q
, opt
->friendlyname_string
);
1021 if (opt
->eku_string
) {
1024 parse_oid(opt
->eku_string
, NULL
, &oid
);
1026 ret
= hx509_query_match_eku(q
, &oid
);
1028 errx(1, "hx509_query_match_eku: %d", ret
);
1032 if (opt
->private_key_flag
)
1033 hx509_query_match_option(q
, HX509_QUERY_OPTION_PRIVATE_KEY
);
1035 if (opt
->keyEncipherment_flag
)
1036 hx509_query_match_option(q
, HX509_QUERY_OPTION_KU_ENCIPHERMENT
);
1038 if (opt
->digitalSignature_flag
)
1039 hx509_query_match_option(q
, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE
);
1041 if (opt
->expr_string
)
1042 hx509_query_match_expr(context
, q
, opt
->expr_string
);
1044 ret
= hx509_certs_find(context
, certs
, q
, &c
);
1045 hx509_query_free(context
, q
);
1047 printf("no match found (%d)\n", ret
);
1049 printf("match found\n");
1050 if (opt
->print_flag
)
1051 print_certificate(context
, c
, 0);
1055 hx509_certs_free(&certs
);
1057 hx509_lock_free(lock
);
1063 ocsp_fetch(struct ocsp_fetch_options
*opt
, int argc
, char **argv
)
1065 hx509_certs reqcerts
, pool
;
1066 heim_octet_string req
, nonce_data
, *nonce
= &nonce_data
;
1070 const char *url
= "/";
1072 memset(&nonce
, 0, sizeof(nonce
));
1074 hx509_lock_init(context
, &lock
);
1075 lock_strings(lock
, &opt
->pass_strings
);
1078 if (!opt
->nonce_flag
)
1081 if (opt
->url_path_string
)
1082 url
= opt
->url_path_string
;
1084 ret
= hx509_certs_init(context
, "MEMORY:ocsp-pool", 0, NULL
, &pool
);
1085 if (ret
) hx509_err(context
, 1, ret
, "hx509_certs_init: MEMORY");
1087 certs_strings(context
, "ocsp-pool", pool
, lock
, &opt
->pool_strings
);
1091 ret
= hx509_certs_init(context
, "MEMORY:ocsp-req", 0, NULL
, &reqcerts
);
1092 if (ret
) hx509_err(context
, 1, ret
, "hx509_certs_init: MEMORY");
1094 for (i
= 1; i
< argc
; i
++) {
1095 ret
= hx509_certs_append(context
, reqcerts
, lock
, argv
[i
]);
1097 errx(1, "hx509_certs_append: req: %s: %d", argv
[i
], ret
);
1100 ret
= hx509_ocsp_request(context
, reqcerts
, pool
, NULL
, NULL
, &req
, nonce
);
1102 errx(1, "hx509_ocsp_request: req: %d", ret
);
1107 f
= fopen(file
, "w");
1112 "POST %s HTTP/1.0\r\n"
1113 "Content-Type: application/ocsp-request\r\n"
1114 "Content-Length: %ld\r\n"
1117 (unsigned long)req
.length
);
1118 fwrite(req
.data
, req
.length
, 1, f
);
1123 der_free_octet_string(nonce
);
1125 hx509_certs_free(&reqcerts
);
1126 hx509_certs_free(&pool
);
1132 ocsp_print(struct ocsp_print_options
*opt
, int argc
, char **argv
)
1134 hx509_revoke_ocsp_print(context
, argv
[0], stdout
);
1143 verify_o(hx509_context hxcontext
, void *ctx
, hx509_cert c
)
1145 heim_octet_string
*os
= ctx
;
1149 ret
= hx509_ocsp_verify(context
, 0, c
, 0,
1150 os
->data
, os
->length
, &expiration
);
1152 char *s
= hx509_get_error_string(hxcontext
, ret
);
1153 printf("ocsp_verify: %s: %d\n", s
, ret
);
1154 hx509_free_error_string(s
);
1156 printf("expire: %d\n", (int)expiration
);
1163 ocsp_verify(struct ocsp_verify_options
*opt
, int argc
, char **argv
)
1168 heim_octet_string os
;
1170 hx509_lock_init(context
, &lock
);
1172 if (opt
->ocsp_file_string
== NULL
)
1173 errx(1, "no ocsp file given");
1175 ret
= _hx509_map_file_os(opt
->ocsp_file_string
, &os
);
1177 err(1, "map_file: %s: %d", argv
[0], ret
);
1179 ret
= hx509_certs_init(context
, "MEMORY:test-certs", 0, NULL
, &certs
);
1180 if (ret
) hx509_err(context
, 1, ret
, "hx509_certs_init: MEMORY");
1182 for (i
= 0; i
< argc
; i
++) {
1183 ret
= hx509_certs_append(context
, certs
, lock
, argv
[i
]);
1185 hx509_err(context
, 1, ret
, "hx509_certs_append: %s", argv
[i
]);
1188 ret
= hx509_certs_iter_f(context
, certs
, verify_o
, &os
);
1190 hx509_certs_free(&certs
);
1191 _hx509_unmap_file_os(&os
);
1192 hx509_lock_free(lock
);
1198 read_private_key(const char *fn
, hx509_private_key
*key
)
1200 hx509_private_key
*keys
;
1206 ret
= hx509_certs_init(context
, fn
, 0, NULL
, &certs
);
1208 hx509_err(context
, 1, ret
, "hx509_certs_init: %s", fn
);
1210 ret
= _hx509_certs_keys_get(context
, certs
, &keys
);
1211 hx509_certs_free(&certs
);
1213 hx509_err(context
, 1, ret
, "hx509_certs_keys_get");
1214 if (keys
[0] == NULL
)
1215 errx(1, "no keys in key store: %s", fn
);
1217 *key
= _hx509_private_key_ref(keys
[0]);
1218 _hx509_certs_keys_free(context
, keys
);
1224 get_key(const char *fn
, const char *type
, int optbits
,
1225 hx509_private_key
*signer
)
1232 unsigned char *p0
, *p
;
1237 errx(1, "no key argument, don't know here to store key");
1239 if (strcasecmp(type
, "rsa") != 0)
1240 errx(1, "can only handle rsa keys for now");
1243 BN_set_word(e
, 0x10001);
1250 errx(1, "RSA_new failed");
1252 ret
= RSA_generate_key_ex(rsa
, bits
, e
, NULL
);
1254 errx(1, "RSA_new failed");
1258 len
= i2d_RSAPrivateKey(rsa
, NULL
);
1260 p0
= p
= malloc(len
);
1262 errx(1, "out of memory");
1264 i2d_RSAPrivateKey(rsa
, &p
);
1266 rk_dumpdata(fn
, p0
, len
);
1272 } else if (fn
== NULL
)
1273 err(1, "no private key");
1275 ret
= read_private_key(fn
, signer
);
1277 err(1, "read_private_key");
1281 request_create(struct request_create_options
*opt
, int argc
, char **argv
)
1283 heim_octet_string request
;
1286 hx509_private_key signer
;
1287 SubjectPublicKeyInfo key
;
1288 const char *outfile
= argv
[0];
1290 memset(&key
, 0, sizeof(key
));
1292 get_key(opt
->key_string
,
1293 opt
->generate_key_string
,
1294 opt
->key_bits_integer
,
1297 hx509_request_init(context
, &req
);
1299 if (opt
->subject_string
) {
1300 hx509_name name
= NULL
;
1302 ret
= hx509_parse_name(context
, opt
->subject_string
, &name
);
1304 errx(1, "hx509_parse_name: %d\n", ret
);
1305 hx509_request_set_name(context
, req
, name
);
1307 if (opt
->verbose_flag
) {
1309 hx509_name_to_string(name
, &s
);
1312 hx509_name_free(&name
);
1315 for (i
= 0; i
< opt
->email_strings
.num_strings
; i
++) {
1316 ret
= _hx509_request_add_email(context
, req
,
1317 opt
->email_strings
.strings
[i
]);
1319 hx509_err(context
, 1, ret
, "hx509_request_add_email");
1322 for (i
= 0; i
< opt
->dnsname_strings
.num_strings
; i
++) {
1323 ret
= _hx509_request_add_dns_name(context
, req
,
1324 opt
->dnsname_strings
.strings
[i
]);
1326 hx509_err(context
, 1, ret
, "hx509_request_add_dns_name");
1330 ret
= hx509_private_key2SPKI(context
, signer
, &key
);
1332 errx(1, "hx509_private_key2SPKI: %d\n", ret
);
1334 ret
= hx509_request_set_SubjectPublicKeyInfo(context
,
1337 free_SubjectPublicKeyInfo(&key
);
1339 hx509_err(context
, 1, ret
, "hx509_request_set_SubjectPublicKeyInfo");
1341 ret
= _hx509_request_to_pkcs10(context
,
1346 hx509_err(context
, 1, ret
, "_hx509_request_to_pkcs10");
1348 hx509_private_key_free(&signer
);
1349 hx509_request_free(&req
);
1352 rk_dumpdata(outfile
, request
.data
, request
.length
);
1353 der_free_octet_string(&request
);
1359 request_print(struct request_print_options
*opt
, int argc
, char **argv
)
1363 printf("request print\n");
1365 for (i
= 0; i
< argc
; i
++) {
1368 ret
= _hx509_request_parse(context
, argv
[i
], &req
);
1370 hx509_err(context
, 1, ret
, "parse_request: %s", argv
[i
]);
1372 ret
= _hx509_request_print(context
, req
, stdout
);
1373 hx509_request_free(&req
);
1375 hx509_err(context
, 1, ret
, "Failed to print file %s", argv
[i
]);
1382 info(void *opt
, int argc
, char **argv
)
1385 ENGINE_add_conf_module();
1388 const RSA_METHOD
*m
= RSA_get_default_method();
1390 printf("rsa: %s\n", m
->name
);
1393 const DH_METHOD
*m
= DH_get_default_method();
1395 printf("dh: %s\n", m
->name
);
1399 printf("ecdsa: ECDSA_METHOD-not-export\n");
1403 printf("ecdsa: hcrypto null\n");
1407 int ret
= RAND_status();
1408 printf("rand: %s\n", ret
== 1 ? "ok" : "not available");
1415 random_data(void *opt
, int argc
, char **argv
)
1420 len
= parse_bytes(argv
[0], "byte");
1422 fprintf(stderr
, "bad argument to random-data\n");
1428 fprintf(stderr
, "out of memory\n");
1432 ret
= RAND_bytes(ptr
, len
);
1435 fprintf(stderr
, "did not get cryptographic strong random\n");
1439 fwrite(ptr
, len
, 1, stdout
);
1448 crypto_available(struct crypto_available_options
*opt
, int argc
, char **argv
)
1450 AlgorithmIdentifier
*val
;
1451 unsigned int len
, i
;
1454 if (opt
->type_string
) {
1455 if (strcmp(opt
->type_string
, "all") == 0)
1456 type
= HX509_SELECT_ALL
;
1457 else if (strcmp(opt
->type_string
, "digest") == 0)
1458 type
= HX509_SELECT_DIGEST
;
1459 else if (strcmp(opt
->type_string
, "public-sig") == 0)
1460 type
= HX509_SELECT_PUBLIC_SIG
;
1461 else if (strcmp(opt
->type_string
, "secret") == 0)
1462 type
= HX509_SELECT_SECRET_ENC
;
1464 errx(1, "unknown type: %s", opt
->type_string
);
1466 type
= HX509_SELECT_ALL
;
1468 ret
= hx509_crypto_available(context
, type
, NULL
, &val
, &len
);
1470 errx(1, "hx509_crypto_available");
1472 for (i
= 0; i
< len
; i
++) {
1474 der_print_heim_oid (&val
[i
].algorithm
, '.', &s
);
1479 hx509_crypto_free_algs(val
, len
);
1485 crypto_select(struct crypto_select_options
*opt
, int argc
, char **argv
)
1487 hx509_peer_info peer
= NULL
;
1488 AlgorithmIdentifier selected
;
1492 if (opt
->type_string
) {
1493 if (strcmp(opt
->type_string
, "digest") == 0)
1494 type
= HX509_SELECT_DIGEST
;
1495 else if (strcmp(opt
->type_string
, "public-sig") == 0)
1496 type
= HX509_SELECT_PUBLIC_SIG
;
1497 else if (strcmp(opt
->type_string
, "secret") == 0)
1498 type
= HX509_SELECT_SECRET_ENC
;
1500 errx(1, "unknown type: %s", opt
->type_string
);
1502 type
= HX509_SELECT_DIGEST
;
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
) != 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 context
, hx509_ca_tbs tbs
, struct cert_type_opt
*opt
)
1563 return hx509_ca_tbs_add_eku(context
, tbs
, &asn1_oid_id_pkix_kp_serverAuth
);
1567 https_client(hx509_context context
, hx509_ca_tbs tbs
, struct cert_type_opt
*opt
)
1569 return hx509_ca_tbs_add_eku(context
, tbs
, &asn1_oid_id_pkix_kp_clientAuth
);
1573 peap_server(hx509_context context
, hx509_ca_tbs tbs
, struct cert_type_opt
*opt
)
1575 return hx509_ca_tbs_add_eku(context
, tbs
, &asn1_oid_id_pkix_kp_serverAuth
);
1579 pkinit_kdc(hx509_context context
, hx509_ca_tbs tbs
, struct cert_type_opt
*opt
)
1582 return hx509_ca_tbs_add_eku(context
, tbs
, &asn1_oid_id_pkkdcekuoid
);
1586 pkinit_client(hx509_context context
, hx509_ca_tbs tbs
, struct cert_type_opt
*opt
)
1592 ret
= hx509_ca_tbs_add_eku(context
, 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 context
, hx509_ca_tbs tbs
, struct cert_type_opt
*opt
)
1606 return hx509_ca_tbs_add_eku(context
, 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 context
,
1668 const struct certificate_sign_options
*opt
)
1670 struct cert_type_opt ctopt
;
1674 memset(&ctopt
, 0, sizeof(ctopt
));
1676 for (i
= 0; i
< opt
->type_strings
.num_strings
; i
++) {
1677 const char *type
= opt
->type_strings
.strings
[i
];
1679 for (j
= 0; j
< sizeof(certtypes
)/sizeof(certtypes
[0]); j
++) {
1680 if (strcasecmp(type
, certtypes
[j
].type
) == 0) {
1681 ret
= (*certtypes
[j
].eval
)(context
, tbs
, &ctopt
);
1683 hx509_err(context
, 1, ret
,
1684 "Failed to evaluate cert type %s", type
);
1688 if (j
>= sizeof(certtypes
)/sizeof(certtypes
[0])) {
1689 fprintf(stderr
, "Unknown certificate type %s\n\n", type
);
1690 fprintf(stderr
, "Available types:\n");
1691 print_eval_types(stderr
);
1696 if (opt
->pk_init_principal_string
) {
1698 errx(1, "pk-init principal given but no pk-init oid");
1700 ret
= hx509_ca_tbs_add_san_pkinit(context
, tbs
,
1701 opt
->pk_init_principal_string
);
1703 hx509_err(context
, 1, ret
, "hx509_ca_tbs_add_san_pkinit");
1706 if (opt
->ms_upn_string
) {
1708 errx(1, "MS upn given but no pk-init oid");
1710 ret
= hx509_ca_tbs_add_san_ms_upn(context
, tbs
, opt
->ms_upn_string
);
1712 hx509_err(context
, 1, ret
, "hx509_ca_tbs_add_san_ms_upn");
1716 for (i
= 0; i
< opt
->hostname_strings
.num_strings
; i
++) {
1717 const char *hostname
= opt
->hostname_strings
.strings
[i
];
1719 ret
= hx509_ca_tbs_add_san_hostname(context
, tbs
, hostname
);
1721 hx509_err(context
, 1, ret
, "hx509_ca_tbs_add_san_hostname");
1724 for (i
= 0; i
< opt
->email_strings
.num_strings
; i
++) {
1725 const char *email
= opt
->email_strings
.strings
[i
];
1727 ret
= hx509_ca_tbs_add_san_rfc822name(context
, tbs
, email
);
1729 hx509_err(context
, 1, ret
, "hx509_ca_tbs_add_san_hostname");
1731 ret
= hx509_ca_tbs_add_eku(context
, tbs
,
1732 &asn1_oid_id_pkix_kp_emailProtection
);
1734 hx509_err(context
, 1, ret
, "hx509_ca_tbs_add_eku");
1737 if (opt
->jid_string
) {
1738 ret
= hx509_ca_tbs_add_san_jid(context
, tbs
, opt
->jid_string
);
1740 hx509_err(context
, 1, ret
, "hx509_ca_tbs_add_san_jid");
1747 hxtool_ca(struct certificate_sign_options
*opt
, int argc
, char **argv
)
1751 hx509_cert signer
= NULL
, cert
= NULL
;
1752 hx509_private_key private_key
= NULL
;
1753 hx509_private_key cert_key
= NULL
;
1754 hx509_name subject
= NULL
;
1755 SubjectPublicKeyInfo spki
;
1758 memset(&spki
, 0, sizeof(spki
));
1760 if (opt
->ca_certificate_string
== NULL
&& !opt
->self_signed_flag
)
1761 errx(1, "--ca-certificate argument missing (not using --self-signed)");
1762 if (opt
->ca_private_key_string
== NULL
&& opt
->generate_key_string
== NULL
&& opt
->self_signed_flag
)
1763 errx(1, "--ca-private-key argument missing (using --self-signed)");
1764 if (opt
->certificate_string
== NULL
)
1765 errx(1, "--certificate argument missing");
1767 if (opt
->template_certificate_string
) {
1768 if (opt
->template_fields_string
== NULL
)
1769 errx(1, "--template-certificate not no --template-fields");
1772 if (opt
->lifetime_string
) {
1773 delta
= parse_time(opt
->lifetime_string
, "day");
1775 errx(1, "Invalid lifetime: %s", opt
->lifetime_string
);
1778 if (opt
->ca_certificate_string
) {
1779 hx509_certs cacerts
= NULL
;
1782 ret
= hx509_certs_init(context
, opt
->ca_certificate_string
, 0,
1785 hx509_err(context
, 1, ret
,
1786 "hx509_certs_init: %s", opt
->ca_certificate_string
);
1788 ret
= hx509_query_alloc(context
, &q
);
1790 errx(1, "hx509_query_alloc: %d", ret
);
1792 hx509_query_match_option(q
, HX509_QUERY_OPTION_PRIVATE_KEY
);
1793 if (!opt
->issue_proxy_flag
)
1794 hx509_query_match_option(q
, HX509_QUERY_OPTION_KU_KEYCERTSIGN
);
1796 ret
= hx509_certs_find(context
, cacerts
, q
, &signer
);
1797 hx509_query_free(context
, q
);
1798 hx509_certs_free(&cacerts
);
1800 hx509_err(context
, 1, ret
, "no CA certificate found");
1801 } else if (opt
->self_signed_flag
) {
1802 if (opt
->generate_key_string
== NULL
1803 && opt
->ca_private_key_string
== NULL
)
1804 errx(1, "no signing private key");
1806 if (opt
->req_string
)
1807 errx(1, "can't be self-signing and have a request at the same time");
1809 errx(1, "missing ca key");
1811 if (opt
->ca_private_key_string
) {
1813 ret
= read_private_key(opt
->ca_private_key_string
, &private_key
);
1815 err(1, "read_private_key");
1817 ret
= hx509_private_key2SPKI(context
, private_key
, &spki
);
1819 errx(1, "hx509_private_key2SPKI: %d\n", ret
);
1821 if (opt
->self_signed_flag
)
1822 cert_key
= private_key
;
1825 if (opt
->req_string
) {
1828 ret
= _hx509_request_parse(context
, opt
->req_string
, &req
);
1830 hx509_err(context
, 1, ret
, "parse_request: %s", opt
->req_string
);
1831 ret
= hx509_request_get_name(context
, req
, &subject
);
1833 hx509_err(context
, 1, ret
, "get name");
1834 ret
= hx509_request_get_SubjectPublicKeyInfo(context
, req
, &spki
);
1836 hx509_err(context
, 1, ret
, "get spki");
1837 hx509_request_free(&req
);
1840 if (opt
->generate_key_string
) {
1841 struct hx509_generate_private_context
*keyctx
;
1843 ret
= _hx509_generate_private_key_init(context
,
1844 &asn1_oid_id_pkcs1_rsaEncryption
,
1847 hx509_err(context
, 1, ret
, "generate private key");
1849 if (opt
->issue_ca_flag
)
1850 _hx509_generate_private_key_is_ca(context
, keyctx
);
1852 if (opt
->key_bits_integer
)
1853 _hx509_generate_private_key_bits(context
, keyctx
,
1854 opt
->key_bits_integer
);
1856 ret
= _hx509_generate_private_key(context
, keyctx
,
1858 _hx509_generate_private_key_free(&keyctx
);
1860 hx509_err(context
, 1, ret
, "generate private key");
1862 ret
= hx509_private_key2SPKI(context
, cert_key
, &spki
);
1864 errx(1, "hx509_private_key2SPKI: %d\n", ret
);
1866 if (opt
->self_signed_flag
)
1867 private_key
= cert_key
;
1870 if (opt
->certificate_private_key_string
) {
1871 ret
= read_private_key(opt
->certificate_private_key_string
, &cert_key
);
1873 err(1, "read_private_key for certificate");
1876 if (opt
->subject_string
) {
1878 hx509_name_free(&subject
);
1879 ret
= hx509_parse_name(context
, opt
->subject_string
, &subject
);
1881 hx509_err(context
, 1, ret
, "hx509_parse_name");
1888 ret
= hx509_ca_tbs_init(context
, &tbs
);
1890 hx509_err(context
, 1, ret
, "hx509_ca_tbs_init");
1892 if (opt
->template_certificate_string
) {
1893 hx509_cert
template;
1897 ret
= hx509_certs_init(context
, opt
->template_certificate_string
, 0,
1900 hx509_err(context
, 1, ret
,
1901 "hx509_certs_init: %s", opt
->template_certificate_string
);
1903 ret
= hx509_get_one_cert(context
, tcerts
, &template);
1905 hx509_certs_free(&tcerts
);
1907 hx509_err(context
, 1, ret
, "no template certificate found");
1909 flags
= parse_units(opt
->template_fields_string
,
1910 hx509_ca_tbs_template_units(), "");
1912 ret
= hx509_ca_tbs_set_template(context
, tbs
, flags
, template);
1914 hx509_err(context
, 1, ret
, "hx509_ca_tbs_set_template");
1916 hx509_cert_free(template);
1919 if (opt
->serial_number_string
) {
1920 heim_integer serialNumber
;
1922 ret
= der_parse_hex_heim_integer(opt
->serial_number_string
,
1925 err(1, "der_parse_hex_heim_integer");
1926 ret
= hx509_ca_tbs_set_serialnumber(context
, tbs
, &serialNumber
);
1928 hx509_err(context
, 1, ret
, "hx509_ca_tbs_init");
1929 der_free_heim_integer(&serialNumber
);
1932 if (spki
.subjectPublicKey
.length
) {
1933 ret
= hx509_ca_tbs_set_spki(context
, tbs
, &spki
);
1935 hx509_err(context
, 1, ret
, "hx509_ca_tbs_set_spki");
1939 ret
= hx509_ca_tbs_set_subject(context
, tbs
, subject
);
1941 hx509_err(context
, 1, ret
, "hx509_ca_tbs_set_subject");
1944 if (opt
->crl_uri_string
) {
1945 ret
= hx509_ca_tbs_add_crl_dp_uri(context
, tbs
,
1946 opt
->crl_uri_string
, NULL
);
1948 hx509_err(context
, 1, ret
, "hx509_ca_tbs_add_crl_dp_uri");
1951 eval_types(context
, tbs
, opt
);
1953 if (opt
->issue_ca_flag
) {
1954 ret
= hx509_ca_tbs_set_ca(context
, tbs
, opt
->path_length_integer
);
1956 hx509_err(context
, 1, ret
, "hx509_ca_tbs_set_ca");
1958 if (opt
->issue_proxy_flag
) {
1959 ret
= hx509_ca_tbs_set_proxy(context
, tbs
, opt
->path_length_integer
);
1961 hx509_err(context
, 1, ret
, "hx509_ca_tbs_set_proxy");
1963 if (opt
->domain_controller_flag
) {
1964 hx509_ca_tbs_set_domaincontroller(context
, tbs
);
1966 hx509_err(context
, 1, ret
, "hx509_ca_tbs_set_domaincontroller");
1970 ret
= hx509_ca_tbs_set_notAfter_lifetime(context
, tbs
, delta
);
1972 hx509_err(context
, 1, ret
, "hx509_ca_tbs_set_notAfter_lifetime");
1975 if (opt
->self_signed_flag
) {
1976 ret
= hx509_ca_sign_self(context
, tbs
, private_key
, &cert
);
1978 hx509_err(context
, 1, ret
, "hx509_ca_sign_self");
1980 ret
= hx509_ca_sign(context
, tbs
, signer
, &cert
);
1982 hx509_err(context
, 1, ret
, "hx509_ca_sign");
1986 ret
= _hx509_cert_assign_key(cert
, cert_key
);
1988 hx509_err(context
, 1, ret
, "_hx509_cert_assign_key");
1994 ret
= hx509_certs_init(context
, opt
->certificate_string
,
1995 HX509_CERTS_CREATE
, NULL
, &certs
);
1997 hx509_err(context
, 1, ret
, "hx509_certs_init");
1999 ret
= hx509_certs_add(context
, certs
, cert
);
2001 hx509_err(context
, 1, ret
, "hx509_certs_add");
2003 ret
= hx509_certs_store(context
, certs
, 0, NULL
);
2005 hx509_err(context
, 1, ret
, "hx509_certs_store");
2007 hx509_certs_free(&certs
);
2011 hx509_name_free(&subject
);
2013 hx509_cert_free(signer
);
2014 hx509_cert_free(cert
);
2015 free_SubjectPublicKeyInfo(&spki
);
2017 if (private_key
!= cert_key
)
2018 hx509_private_key_free(&private_key
);
2019 hx509_private_key_free(&cert_key
);
2021 hx509_ca_tbs_free(&tbs
);
2027 test_one_cert(hx509_context hxcontext
, void *ctx
, hx509_cert cert
)
2029 heim_octet_string sd
, c
;
2030 hx509_verify_ctx vctx
= ctx
;
2031 hx509_certs signer
= NULL
;
2035 if (_hx509_cert_private_key(cert
) == NULL
)
2038 ret
= hx509_cms_create_signed_1(context
, 0, NULL
, NULL
, 0,
2039 NULL
, cert
, NULL
, NULL
, NULL
, &sd
);
2041 errx(1, "hx509_cms_create_signed_1");
2043 ret
= hx509_cms_verify_signed(context
, vctx
, 0, sd
.data
, sd
.length
,
2044 NULL
, NULL
, &type
, &c
, &signer
);
2047 hx509_err(context
, 1, ret
, "hx509_cms_verify_signed");
2049 printf("create-signature verify-sigature done\n");
2057 test_crypto(struct test_crypto_options
*opt
, int argc
, char ** argv
)
2059 hx509_verify_ctx vctx
;
2064 hx509_lock_init(context
, &lock
);
2065 lock_strings(lock
, &opt
->pass_strings
);
2067 ret
= hx509_certs_init(context
, "MEMORY:test-crypto", 0, NULL
, &certs
);
2068 if (ret
) hx509_err(context
, 1, ret
, "hx509_certs_init: MEMORY");
2070 for (i
= 0; i
< argc
; i
++) {
2071 ret
= hx509_certs_append(context
, certs
, lock
, argv
[i
]);
2073 hx509_err(context
, 1, ret
, "hx509_certs_append");
2076 ret
= hx509_verify_init_ctx(context
, &vctx
);
2078 hx509_err(context
, 1, ret
, "hx509_verify_init_ctx");
2080 hx509_verify_attach_anchors(vctx
, certs
);
2082 ret
= hx509_certs_iter_f(context
, certs
, test_one_cert
, vctx
);
2084 hx509_err(context
, 1, ret
, "hx509_cert_iter");
2086 hx509_certs_free(&certs
);
2092 statistic_print(struct statistic_print_options
*opt
, int argc
, char **argv
)
2096 if (stat_file_string
== NULL
)
2097 errx(1, "no stat file");
2099 if (opt
->type_integer
)
2100 type
= opt
->type_integer
;
2102 hx509_query_unparse_stats(context
, type
, stdout
);
2111 crl_sign(struct crl_sign_options
*opt
, int argc
, char **argv
)
2114 heim_octet_string os
;
2115 hx509_cert signer
= NULL
;
2119 hx509_lock_init(context
, &lock
);
2120 lock_strings(lock
, &opt
->pass_strings
);
2122 ret
= hx509_crl_alloc(context
, &crl
);
2124 errx(1, "crl alloc");
2126 if (opt
->signer_string
== NULL
)
2127 errx(1, "signer missing");
2130 hx509_certs certs
= NULL
;
2133 ret
= hx509_certs_init(context
, opt
->signer_string
, 0,
2136 hx509_err(context
, 1, ret
,
2137 "hx509_certs_init: %s", opt
->signer_string
);
2139 ret
= hx509_query_alloc(context
, &q
);
2141 hx509_err(context
, 1, ret
, "hx509_query_alloc: %d", ret
);
2143 hx509_query_match_option(q
, HX509_QUERY_OPTION_PRIVATE_KEY
);
2145 ret
= hx509_certs_find(context
, certs
, q
, &signer
);
2146 hx509_query_free(context
, q
);
2147 hx509_certs_free(&certs
);
2149 hx509_err(context
, 1, ret
, "no signer certificate found");
2152 if (opt
->lifetime_string
) {
2155 delta
= parse_time(opt
->lifetime_string
, "day");
2157 errx(1, "Invalid lifetime: %s", opt
->lifetime_string
);
2159 hx509_crl_lifetime(context
, crl
, delta
);
2163 hx509_certs revoked
= NULL
;
2166 ret
= hx509_certs_init(context
, "MEMORY:revoked-certs", 0,
2169 hx509_err(context
, 1, ret
,
2170 "hx509_certs_init: MEMORY cert");
2172 for (i
= 0; i
< argc
; i
++) {
2173 ret
= hx509_certs_append(context
, revoked
, lock
, argv
[i
]);
2175 hx509_err(context
, 1, ret
, "hx509_certs_append: %s", argv
[i
]);
2178 hx509_crl_add_revoked_certs(context
, crl
, revoked
);
2179 hx509_certs_free(&revoked
);
2182 hx509_crl_sign(context
, signer
, crl
, &os
);
2184 if (opt
->crl_file_string
)
2185 rk_dumpdata(opt
->crl_file_string
, os
.data
, os
.length
);
2189 hx509_crl_free(context
, &crl
);
2190 hx509_cert_free(signer
);
2191 hx509_lock_free(lock
);
2201 help(void *opt
, int argc
, char **argv
)
2203 sl_slc_help(commands
, argc
, argv
);
2208 main(int argc
, char **argv
)
2210 int ret
, optidx
= 0;
2212 setprogname (argv
[0]);
2214 if(getarg(args
, num_args
, argc
, argv
, &optidx
))
2219 print_version(NULL
);
2228 ret
= hx509_context_init(&context
);
2230 errx(1, "hx509_context_init failed with %d", ret
);
2232 if (stat_file_string
)
2233 hx509_query_statistic_file(context
, stat_file_string
);
2235 ret
= sl_command(commands
, argc
, argv
);
2237 warnx ("unrecognized command: %s", argv
[0]);
2239 hx509_context_free(&context
);