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
, NULL
, NULL
},
49 { "version", 0, arg_flag
, &version_flag
, NULL
, NULL
},
50 { "help", 0, arg_flag
, &help_flag
, NULL
, NULL
}
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 contextp
, 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(contextp
, certs
, lock
, s
->strings
[i
]);
91 hx509_err(contextp
, 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 contextp
,
118 hx509_peer_info
*peer
,
119 const getarg_strings
*s
)
121 AlgorithmIdentifier
*val
;
124 ret
= hx509_peer_info_alloc(contextp
, peer
);
126 hx509_err(contextp
, 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(contextp
, *peer
, val
, s
->num_strings
);
137 hx509_err(contextp
, 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 contextp
, 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
);
218 pd
.detached_data
= 0;
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
, &pd
);
227 errx(1, "PEM reader failed: %d", ret
);
229 if (pd
.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 contextp
, 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 ret
= asprintf(&outfile
, "%s.%s", infile
,
376 opt
->pem_flag
? "pem" : "cms-signeddata");
377 if (ret
== -1 || outfile
== NULL
)
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 retx
= hx509_certs_append(context
, certs
, inlock
, argv
[0]);
807 hx509_err(context
, 1, retx
, "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
);
1139 revoke_print(struct revoke_print_options
*opt
, int argc
, char **argv
)
1141 hx509_revoke_ctx revoke_ctx
;
1144 ret
= hx509_revoke_init(context
, &revoke_ctx
);
1146 errx(1, "hx509_revoke_init: %d", ret
);
1151 if (strncmp(s
, "crl:", 4) == 0) {
1154 ret
= hx509_revoke_add_crl(context
, revoke_ctx
, s
);
1156 errx(1, "hx509_revoke_add_crl: %s: %d", s
, ret
);
1158 } else if (strncmp(s
, "ocsp:", 4) == 0) {
1161 ret
= hx509_revoke_add_ocsp(context
, revoke_ctx
, s
);
1163 errx(1, "hx509_revoke_add_ocsp: %s: %d", s
, ret
);
1166 errx(1, "unknown option to verify: `%s'\n", s
);
1170 ret
= hx509_revoke_print(context
, revoke_ctx
, stdout
);
1172 warnx("hx509_revoke_print: %d", ret
);
1182 verify_o(hx509_context hxcontext
, void *ctx
, hx509_cert c
)
1184 heim_octet_string
*os
= ctx
;
1188 ret
= hx509_ocsp_verify(context
, 0, c
, 0,
1189 os
->data
, os
->length
, &expiration
);
1191 char *s
= hx509_get_error_string(hxcontext
, ret
);
1192 printf("ocsp_verify: %s: %d\n", s
, ret
);
1193 hx509_free_error_string(s
);
1195 printf("expire: %d\n", (int)expiration
);
1202 ocsp_verify(struct ocsp_verify_options
*opt
, int argc
, char **argv
)
1207 heim_octet_string os
;
1209 hx509_lock_init(context
, &lock
);
1211 if (opt
->ocsp_file_string
== NULL
)
1212 errx(1, "no ocsp file given");
1214 ret
= _hx509_map_file_os(opt
->ocsp_file_string
, &os
);
1216 err(1, "map_file: %s: %d", argv
[0], ret
);
1218 ret
= hx509_certs_init(context
, "MEMORY:test-certs", 0, NULL
, &certs
);
1219 if (ret
) hx509_err(context
, 1, ret
, "hx509_certs_init: MEMORY");
1221 for (i
= 0; i
< argc
; i
++) {
1222 ret
= hx509_certs_append(context
, certs
, lock
, argv
[i
]);
1224 hx509_err(context
, 1, ret
, "hx509_certs_append: %s", argv
[i
]);
1227 ret
= hx509_certs_iter_f(context
, certs
, verify_o
, &os
);
1229 hx509_certs_free(&certs
);
1230 _hx509_unmap_file_os(&os
);
1231 hx509_lock_free(lock
);
1237 read_private_key(const char *fn
, hx509_private_key
*key
)
1239 hx509_private_key
*keys
;
1245 ret
= hx509_certs_init(context
, fn
, 0, NULL
, &certs
);
1247 hx509_err(context
, 1, ret
, "hx509_certs_init: %s", fn
);
1249 ret
= _hx509_certs_keys_get(context
, certs
, &keys
);
1250 hx509_certs_free(&certs
);
1252 hx509_err(context
, 1, ret
, "hx509_certs_keys_get");
1253 if (keys
[0] == NULL
)
1254 errx(1, "no keys in key store: %s", fn
);
1256 *key
= _hx509_private_key_ref(keys
[0]);
1257 _hx509_certs_keys_free(context
, keys
);
1263 get_key(const char *fn
, const char *type
, int optbits
,
1264 hx509_private_key
*signer
)
1271 unsigned char *p0
, *p
;
1276 errx(1, "no key argument, don't know here to store key");
1278 if (strcasecmp(type
, "rsa") != 0)
1279 errx(1, "can only handle rsa keys for now");
1282 BN_set_word(e
, 0x10001);
1289 errx(1, "RSA_new failed");
1291 ret
= RSA_generate_key_ex(rsa
, bits
, e
, NULL
);
1293 errx(1, "RSA_new failed");
1297 len
= i2d_RSAPrivateKey(rsa
, NULL
);
1299 p0
= p
= malloc(len
);
1301 errx(1, "out of memory");
1303 i2d_RSAPrivateKey(rsa
, &p
);
1305 rk_dumpdata(fn
, p0
, len
);
1311 } else if (fn
== NULL
)
1312 err(1, "no private key");
1314 ret
= read_private_key(fn
, signer
);
1316 err(1, "read_private_key");
1320 request_create(struct request_create_options
*opt
, int argc
, char **argv
)
1322 heim_octet_string request
;
1325 hx509_private_key signer
;
1326 SubjectPublicKeyInfo key
;
1327 const char *outfile
= argv
[0];
1329 memset(&key
, 0, sizeof(key
));
1331 get_key(opt
->key_string
,
1332 opt
->generate_key_string
,
1333 opt
->key_bits_integer
,
1336 hx509_request_init(context
, &req
);
1338 if (opt
->subject_string
) {
1339 hx509_name name
= NULL
;
1341 ret
= hx509_parse_name(context
, opt
->subject_string
, &name
);
1343 errx(1, "hx509_parse_name: %d\n", ret
);
1344 hx509_request_set_name(context
, req
, name
);
1346 if (opt
->verbose_flag
) {
1348 hx509_name_to_string(name
, &s
);
1351 hx509_name_free(&name
);
1354 for (i
= 0; i
< opt
->email_strings
.num_strings
; i
++) {
1355 ret
= _hx509_request_add_email(context
, req
,
1356 opt
->email_strings
.strings
[i
]);
1358 hx509_err(context
, 1, ret
, "hx509_request_add_email");
1361 for (i
= 0; i
< opt
->dnsname_strings
.num_strings
; i
++) {
1362 ret
= _hx509_request_add_dns_name(context
, req
,
1363 opt
->dnsname_strings
.strings
[i
]);
1365 hx509_err(context
, 1, ret
, "hx509_request_add_dns_name");
1369 ret
= hx509_private_key2SPKI(context
, signer
, &key
);
1371 errx(1, "hx509_private_key2SPKI: %d\n", ret
);
1373 ret
= hx509_request_set_SubjectPublicKeyInfo(context
,
1376 free_SubjectPublicKeyInfo(&key
);
1378 hx509_err(context
, 1, ret
, "hx509_request_set_SubjectPublicKeyInfo");
1380 ret
= _hx509_request_to_pkcs10(context
,
1385 hx509_err(context
, 1, ret
, "_hx509_request_to_pkcs10");
1387 hx509_private_key_free(&signer
);
1388 hx509_request_free(&req
);
1391 rk_dumpdata(outfile
, request
.data
, request
.length
);
1392 der_free_octet_string(&request
);
1398 request_print(struct request_print_options
*opt
, int argc
, char **argv
)
1402 printf("request print\n");
1404 for (i
= 0; i
< argc
; i
++) {
1407 ret
= _hx509_request_parse(context
, argv
[i
], &req
);
1409 hx509_err(context
, 1, ret
, "parse_request: %s", argv
[i
]);
1411 ret
= _hx509_request_print(context
, req
, stdout
);
1412 hx509_request_free(&req
);
1414 hx509_err(context
, 1, ret
, "Failed to print file %s", argv
[i
]);
1421 info(void *opt
, int argc
, char **argv
)
1424 ENGINE_add_conf_module();
1427 const RSA_METHOD
*m
= RSA_get_default_method();
1429 printf("rsa: %s\n", m
->name
);
1432 const DH_METHOD
*m
= DH_get_default_method();
1434 printf("dh: %s\n", m
->name
);
1438 printf("ecdsa: ECDSA_METHOD-not-export\n");
1442 printf("ecdsa: hcrypto null\n");
1446 int ret
= RAND_status();
1447 printf("rand: %s\n", ret
== 1 ? "ok" : "not available");
1454 random_data(void *opt
, int argc
, char **argv
)
1459 len
= parse_bytes(argv
[0], "byte");
1461 fprintf(stderr
, "bad argument to random-data\n");
1467 fprintf(stderr
, "out of memory\n");
1471 ret
= RAND_bytes(ptr
, len
);
1474 fprintf(stderr
, "did not get cryptographic strong random\n");
1478 fwrite(ptr
, len
, 1, stdout
);
1487 crypto_available(struct crypto_available_options
*opt
, int argc
, char **argv
)
1489 AlgorithmIdentifier
*val
;
1490 unsigned int len
, i
;
1491 int ret
, type
= HX509_SELECT_ALL
;
1493 if (opt
->type_string
) {
1494 if (strcmp(opt
->type_string
, "all") == 0)
1495 type
= HX509_SELECT_ALL
;
1496 else if (strcmp(opt
->type_string
, "digest") == 0)
1497 type
= HX509_SELECT_DIGEST
;
1498 else if (strcmp(opt
->type_string
, "public-sig") == 0)
1499 type
= HX509_SELECT_PUBLIC_SIG
;
1500 else if (strcmp(opt
->type_string
, "secret") == 0)
1501 type
= HX509_SELECT_SECRET_ENC
;
1503 errx(1, "unknown type: %s", opt
->type_string
);
1506 ret
= hx509_crypto_available(context
, type
, NULL
, &val
, &len
);
1508 errx(1, "hx509_crypto_available");
1510 for (i
= 0; i
< len
; i
++) {
1512 der_print_heim_oid (&val
[i
].algorithm
, '.', &s
);
1517 hx509_crypto_free_algs(val
, len
);
1523 crypto_select(struct crypto_select_options
*opt
, int argc
, char **argv
)
1525 hx509_peer_info peer
= NULL
;
1526 AlgorithmIdentifier selected
;
1527 int ret
, type
= HX509_SELECT_DIGEST
;
1530 if (opt
->type_string
) {
1531 if (strcmp(opt
->type_string
, "digest") == 0)
1532 type
= HX509_SELECT_DIGEST
;
1533 else if (strcmp(opt
->type_string
, "public-sig") == 0)
1534 type
= HX509_SELECT_PUBLIC_SIG
;
1535 else if (strcmp(opt
->type_string
, "secret") == 0)
1536 type
= HX509_SELECT_SECRET_ENC
;
1538 errx(1, "unknown type: %s", opt
->type_string
);
1541 if (opt
->peer_cmstype_strings
.num_strings
)
1542 peer_strings(context
, &peer
, &opt
->peer_cmstype_strings
);
1544 ret
= hx509_crypto_select(context
, type
, NULL
, peer
, &selected
);
1546 errx(1, "hx509_crypto_available");
1548 der_print_heim_oid (&selected
.algorithm
, '.', &s
);
1551 free_AlgorithmIdentifier(&selected
);
1553 hx509_peer_info_free(peer
);
1559 hxtool_hex(struct hex_options
*opt
, int argc
, char **argv
)
1562 if (opt
->decode_flag
) {
1563 char buf
[1024], buf2
[1024], *p
;
1566 while(fgets(buf
, sizeof(buf
), stdin
) != NULL
) {
1567 buf
[strcspn(buf
, "\r\n")] = '\0';
1569 while(isspace(*(unsigned char *)p
))
1571 len
= hex_decode(p
, buf2
, strlen(p
));
1573 errx(1, "hex_decode failed");
1574 if (fwrite(buf2
, 1, len
, stdout
) != (size_t)len
)
1575 errx(1, "fwrite failed");
1581 while((len
= fread(buf
, 1, sizeof(buf
), stdin
)) != 0) {
1582 len
= hex_encode(buf
, len
, &p
);
1585 fprintf(stdout
, "%s\n", p
);
1592 struct cert_type_opt
{
1598 https_server(hx509_context contextp
, hx509_ca_tbs tbs
, struct cert_type_opt
*opt
)
1600 return hx509_ca_tbs_add_eku(contextp
, tbs
, &asn1_oid_id_pkix_kp_serverAuth
);
1604 https_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_clientAuth
);
1610 peap_server(hx509_context contextp
, hx509_ca_tbs tbs
, struct cert_type_opt
*opt
)
1612 return hx509_ca_tbs_add_eku(contextp
, tbs
, &asn1_oid_id_pkix_kp_serverAuth
);
1616 pkinit_kdc(hx509_context contextp
, hx509_ca_tbs tbs
, struct cert_type_opt
*opt
)
1619 return hx509_ca_tbs_add_eku(contextp
, tbs
, &asn1_oid_id_pkkdcekuoid
);
1623 pkinit_client(hx509_context contextp
, hx509_ca_tbs tbs
, struct cert_type_opt
*opt
)
1629 ret
= hx509_ca_tbs_add_eku(contextp
, tbs
, &asn1_oid_id_pkekuoid
);
1633 ret
= hx509_ca_tbs_add_eku(context
, tbs
, &asn1_oid_id_ms_client_authentication
);
1637 return hx509_ca_tbs_add_eku(context
, tbs
, &asn1_oid_id_pkinit_ms_eku
);
1641 email_client(hx509_context contextp
, hx509_ca_tbs tbs
, struct cert_type_opt
*opt
)
1643 return hx509_ca_tbs_add_eku(contextp
, tbs
, &asn1_oid_id_pkix_kp_emailProtection
);
1649 int (*eval
)(hx509_context
, hx509_ca_tbs
, struct cert_type_opt
*);
1653 "Used for HTTPS server and many other TLS server certificate types",
1658 "Used for HTTPS client certificates",
1663 "Certificate will be use for email",
1668 "Certificate used for Kerberos PK-INIT client certificates",
1673 "Certificates used for Kerberos PK-INIT KDC certificates",
1678 "Certificate used for Radius PEAP (Protected EAP)",
1684 print_eval_types(FILE *out
)
1689 table
= rtbl_create();
1690 rtbl_add_column_by_id (table
, 0, "Name", 0);
1691 rtbl_add_column_by_id (table
, 1, "Description", 0);
1693 for (i
= 0; i
< sizeof(certtypes
)/sizeof(certtypes
[0]); i
++) {
1694 rtbl_add_column_entry_by_id(table
, 0, certtypes
[i
].type
);
1695 rtbl_add_column_entry_by_id(table
, 1, certtypes
[i
].desc
);
1698 rtbl_format (table
, out
);
1699 rtbl_destroy (table
);
1703 eval_types(hx509_context contextp
,
1705 const struct certificate_sign_options
*opt
)
1707 struct cert_type_opt ctopt
;
1712 memset(&ctopt
, 0, sizeof(ctopt
));
1714 for (i
= 0; i
< opt
->type_strings
.num_strings
; i
++) {
1715 const char *type
= opt
->type_strings
.strings
[i
];
1717 for (j
= 0; j
< sizeof(certtypes
)/sizeof(certtypes
[0]); j
++) {
1718 if (strcasecmp(type
, certtypes
[j
].type
) == 0) {
1719 ret
= (*certtypes
[j
].eval
)(contextp
, tbs
, &ctopt
);
1721 hx509_err(contextp
, 1, ret
,
1722 "Failed to evaluate cert type %s", type
);
1726 if (j
>= sizeof(certtypes
)/sizeof(certtypes
[0])) {
1727 fprintf(stderr
, "Unknown certificate type %s\n\n", type
);
1728 fprintf(stderr
, "Available types:\n");
1729 print_eval_types(stderr
);
1734 for (i
= 0; i
< opt
->pk_init_principal_strings
.num_strings
; i
++) {
1735 const char *pk_init_princ
= opt
->pk_init_principal_strings
.strings
[i
];
1738 errx(1, "pk-init principal given but no pk-init oid");
1740 ret
= hx509_ca_tbs_add_san_pkinit(contextp
, tbs
, pk_init_princ
);
1742 hx509_err(contextp
, 1, ret
, "hx509_ca_tbs_add_san_pkinit");
1745 if (opt
->ms_upn_string
) {
1747 errx(1, "MS upn given but no pk-init oid");
1749 ret
= hx509_ca_tbs_add_san_ms_upn(contextp
, tbs
, opt
->ms_upn_string
);
1751 hx509_err(contextp
, 1, ret
, "hx509_ca_tbs_add_san_ms_upn");
1755 for (i
= 0; i
< opt
->hostname_strings
.num_strings
; i
++) {
1756 const char *hostname
= opt
->hostname_strings
.strings
[i
];
1758 ret
= hx509_ca_tbs_add_san_hostname(contextp
, tbs
, hostname
);
1760 hx509_err(contextp
, 1, ret
, "hx509_ca_tbs_add_san_hostname");
1763 for (i
= 0; i
< opt
->email_strings
.num_strings
; i
++) {
1764 const char *email
= opt
->email_strings
.strings
[i
];
1766 ret
= hx509_ca_tbs_add_san_rfc822name(contextp
, tbs
, email
);
1768 hx509_err(contextp
, 1, ret
, "hx509_ca_tbs_add_san_hostname");
1770 ret
= hx509_ca_tbs_add_eku(contextp
, tbs
,
1771 &asn1_oid_id_pkix_kp_emailProtection
);
1773 hx509_err(contextp
, 1, ret
, "hx509_ca_tbs_add_eku");
1776 if (opt
->jid_string
) {
1777 ret
= hx509_ca_tbs_add_san_jid(contextp
, tbs
, opt
->jid_string
);
1779 hx509_err(contextp
, 1, ret
, "hx509_ca_tbs_add_san_jid");
1786 hxtool_ca(struct certificate_sign_options
*opt
, int argc
, char **argv
)
1790 hx509_cert signer
= NULL
, cert
= NULL
;
1791 hx509_private_key private_key
= NULL
;
1792 hx509_private_key cert_key
= NULL
;
1793 hx509_name subject
= NULL
;
1794 SubjectPublicKeyInfo spki
;
1797 memset(&spki
, 0, sizeof(spki
));
1799 if (opt
->ca_certificate_string
== NULL
&& !opt
->self_signed_flag
)
1800 errx(1, "--ca-certificate argument missing (not using --self-signed)");
1801 if (opt
->ca_private_key_string
== NULL
&& opt
->generate_key_string
== NULL
&& opt
->self_signed_flag
)
1802 errx(1, "--ca-private-key argument missing (using --self-signed)");
1803 if (opt
->certificate_string
== NULL
)
1804 errx(1, "--certificate argument missing");
1806 if (opt
->template_certificate_string
) {
1807 if (opt
->template_fields_string
== NULL
)
1808 errx(1, "--template-certificate not no --template-fields");
1811 if (opt
->lifetime_string
) {
1812 delta
= parse_time(opt
->lifetime_string
, "day");
1814 errx(1, "Invalid lifetime: %s", opt
->lifetime_string
);
1817 if (opt
->ca_certificate_string
) {
1818 hx509_certs cacerts
= NULL
;
1821 ret
= hx509_certs_init(context
, opt
->ca_certificate_string
, 0,
1824 hx509_err(context
, 1, ret
,
1825 "hx509_certs_init: %s", opt
->ca_certificate_string
);
1827 ret
= hx509_query_alloc(context
, &q
);
1829 errx(1, "hx509_query_alloc: %d", ret
);
1831 hx509_query_match_option(q
, HX509_QUERY_OPTION_PRIVATE_KEY
);
1832 if (!opt
->issue_proxy_flag
)
1833 hx509_query_match_option(q
, HX509_QUERY_OPTION_KU_KEYCERTSIGN
);
1835 ret
= hx509_certs_find(context
, cacerts
, q
, &signer
);
1836 hx509_query_free(context
, q
);
1837 hx509_certs_free(&cacerts
);
1839 hx509_err(context
, 1, ret
, "no CA certificate found");
1840 } else if (opt
->self_signed_flag
) {
1841 if (opt
->generate_key_string
== NULL
1842 && opt
->ca_private_key_string
== NULL
)
1843 errx(1, "no signing private key");
1845 if (opt
->req_string
)
1846 errx(1, "can't be self-signing and have a request at the same time");
1848 errx(1, "missing ca key");
1850 if (opt
->ca_private_key_string
) {
1852 ret
= read_private_key(opt
->ca_private_key_string
, &private_key
);
1854 err(1, "read_private_key");
1856 ret
= hx509_private_key2SPKI(context
, private_key
, &spki
);
1858 errx(1, "hx509_private_key2SPKI: %d\n", ret
);
1860 if (opt
->self_signed_flag
)
1861 cert_key
= private_key
;
1864 if (opt
->req_string
) {
1867 ret
= _hx509_request_parse(context
, opt
->req_string
, &req
);
1869 hx509_err(context
, 1, ret
, "parse_request: %s", opt
->req_string
);
1870 ret
= hx509_request_get_name(context
, req
, &subject
);
1872 hx509_err(context
, 1, ret
, "get name");
1873 ret
= hx509_request_get_SubjectPublicKeyInfo(context
, req
, &spki
);
1875 hx509_err(context
, 1, ret
, "get spki");
1876 hx509_request_free(&req
);
1879 if (opt
->generate_key_string
) {
1880 struct hx509_generate_private_context
*keyctx
;
1882 ret
= _hx509_generate_private_key_init(context
,
1883 &asn1_oid_id_pkcs1_rsaEncryption
,
1886 hx509_err(context
, 1, ret
, "generate private key");
1888 if (opt
->issue_ca_flag
)
1889 _hx509_generate_private_key_is_ca(context
, keyctx
);
1891 if (opt
->key_bits_integer
)
1892 _hx509_generate_private_key_bits(context
, keyctx
,
1893 opt
->key_bits_integer
);
1895 ret
= _hx509_generate_private_key(context
, keyctx
,
1897 _hx509_generate_private_key_free(&keyctx
);
1899 hx509_err(context
, 1, ret
, "generate private key");
1901 ret
= hx509_private_key2SPKI(context
, cert_key
, &spki
);
1903 errx(1, "hx509_private_key2SPKI: %d\n", ret
);
1905 if (opt
->self_signed_flag
)
1906 private_key
= cert_key
;
1909 if (opt
->certificate_private_key_string
) {
1910 ret
= read_private_key(opt
->certificate_private_key_string
, &cert_key
);
1912 err(1, "read_private_key for certificate");
1915 if (opt
->subject_string
) {
1917 hx509_name_free(&subject
);
1918 ret
= hx509_parse_name(context
, opt
->subject_string
, &subject
);
1920 hx509_err(context
, 1, ret
, "hx509_parse_name");
1927 ret
= hx509_ca_tbs_init(context
, &tbs
);
1929 hx509_err(context
, 1, ret
, "hx509_ca_tbs_init");
1931 if (opt
->signature_algorithm_string
) {
1932 const AlgorithmIdentifier
*sigalg
;
1933 if (strcasecmp(opt
->signature_algorithm_string
, "rsa-with-sha1") == 0)
1934 sigalg
= hx509_signature_rsa_with_sha1();
1935 else if (strcasecmp(opt
->signature_algorithm_string
, "rsa-with-sha256") == 0)
1936 sigalg
= hx509_signature_rsa_with_sha256();
1938 errx(1, "unsupported sigature algorith");
1939 hx509_ca_tbs_set_signature_algorithm(context
, tbs
, sigalg
);
1942 if (opt
->template_certificate_string
) {
1943 hx509_cert
template;
1947 ret
= hx509_certs_init(context
, opt
->template_certificate_string
, 0,
1950 hx509_err(context
, 1, ret
,
1951 "hx509_certs_init: %s", opt
->template_certificate_string
);
1953 ret
= hx509_get_one_cert(context
, tcerts
, &template);
1955 hx509_certs_free(&tcerts
);
1957 hx509_err(context
, 1, ret
, "no template certificate found");
1959 flags
= parse_units(opt
->template_fields_string
,
1960 hx509_ca_tbs_template_units(), "");
1962 ret
= hx509_ca_tbs_set_template(context
, tbs
, flags
, template);
1964 hx509_err(context
, 1, ret
, "hx509_ca_tbs_set_template");
1966 hx509_cert_free(template);
1969 if (opt
->serial_number_string
) {
1970 heim_integer serialNumber
;
1972 ret
= der_parse_hex_heim_integer(opt
->serial_number_string
,
1975 err(1, "der_parse_hex_heim_integer");
1976 ret
= hx509_ca_tbs_set_serialnumber(context
, tbs
, &serialNumber
);
1978 hx509_err(context
, 1, ret
, "hx509_ca_tbs_init");
1979 der_free_heim_integer(&serialNumber
);
1982 if (spki
.subjectPublicKey
.length
) {
1983 ret
= hx509_ca_tbs_set_spki(context
, tbs
, &spki
);
1985 hx509_err(context
, 1, ret
, "hx509_ca_tbs_set_spki");
1989 ret
= hx509_ca_tbs_set_subject(context
, tbs
, subject
);
1991 hx509_err(context
, 1, ret
, "hx509_ca_tbs_set_subject");
1994 if (opt
->crl_uri_string
) {
1995 ret
= hx509_ca_tbs_add_crl_dp_uri(context
, tbs
,
1996 opt
->crl_uri_string
, NULL
);
1998 hx509_err(context
, 1, ret
, "hx509_ca_tbs_add_crl_dp_uri");
2001 eval_types(context
, tbs
, opt
);
2003 if (opt
->issue_ca_flag
) {
2004 ret
= hx509_ca_tbs_set_ca(context
, tbs
, opt
->path_length_integer
);
2006 hx509_err(context
, 1, ret
, "hx509_ca_tbs_set_ca");
2008 if (opt
->issue_proxy_flag
) {
2009 ret
= hx509_ca_tbs_set_proxy(context
, tbs
, opt
->path_length_integer
);
2011 hx509_err(context
, 1, ret
, "hx509_ca_tbs_set_proxy");
2013 if (opt
->domain_controller_flag
) {
2014 hx509_ca_tbs_set_domaincontroller(context
, tbs
);
2016 hx509_err(context
, 1, ret
, "hx509_ca_tbs_set_domaincontroller");
2020 ret
= hx509_ca_tbs_set_notAfter_lifetime(context
, tbs
, delta
);
2022 hx509_err(context
, 1, ret
, "hx509_ca_tbs_set_notAfter_lifetime");
2025 if (opt
->self_signed_flag
) {
2026 ret
= hx509_ca_sign_self(context
, tbs
, private_key
, &cert
);
2028 hx509_err(context
, 1, ret
, "hx509_ca_sign_self");
2030 ret
= hx509_ca_sign(context
, tbs
, signer
, &cert
);
2032 hx509_err(context
, 1, ret
, "hx509_ca_sign");
2036 ret
= _hx509_cert_assign_key(cert
, cert_key
);
2038 hx509_err(context
, 1, ret
, "_hx509_cert_assign_key");
2044 ret
= hx509_certs_init(context
, opt
->certificate_string
,
2045 HX509_CERTS_CREATE
, NULL
, &certs
);
2047 hx509_err(context
, 1, ret
, "hx509_certs_init");
2049 ret
= hx509_certs_add(context
, certs
, cert
);
2051 hx509_err(context
, 1, ret
, "hx509_certs_add");
2053 ret
= hx509_certs_store(context
, certs
, 0, NULL
);
2055 hx509_err(context
, 1, ret
, "hx509_certs_store");
2057 hx509_certs_free(&certs
);
2061 hx509_name_free(&subject
);
2063 hx509_cert_free(signer
);
2064 hx509_cert_free(cert
);
2065 free_SubjectPublicKeyInfo(&spki
);
2067 if (private_key
!= cert_key
)
2068 hx509_private_key_free(&private_key
);
2069 hx509_private_key_free(&cert_key
);
2071 hx509_ca_tbs_free(&tbs
);
2077 test_one_cert(hx509_context hxcontext
, void *ctx
, hx509_cert cert
)
2079 heim_octet_string sd
, c
;
2080 hx509_verify_ctx vctx
= ctx
;
2081 hx509_certs signer
= NULL
;
2085 if (_hx509_cert_private_key(cert
) == NULL
)
2088 ret
= hx509_cms_create_signed_1(context
, 0, NULL
, NULL
, 0,
2089 NULL
, cert
, NULL
, NULL
, NULL
, &sd
);
2091 errx(1, "hx509_cms_create_signed_1");
2093 ret
= hx509_cms_verify_signed(context
, vctx
, 0, sd
.data
, sd
.length
,
2094 NULL
, NULL
, &type
, &c
, &signer
);
2097 hx509_err(context
, 1, ret
, "hx509_cms_verify_signed");
2099 printf("create-signature verify-sigature done\n");
2107 test_crypto(struct test_crypto_options
*opt
, int argc
, char ** argv
)
2109 hx509_verify_ctx vctx
;
2114 hx509_lock_init(context
, &lock
);
2115 lock_strings(lock
, &opt
->pass_strings
);
2117 ret
= hx509_certs_init(context
, "MEMORY:test-crypto", 0, NULL
, &certs
);
2118 if (ret
) hx509_err(context
, 1, ret
, "hx509_certs_init: MEMORY");
2120 for (i
= 0; i
< argc
; i
++) {
2121 ret
= hx509_certs_append(context
, certs
, lock
, argv
[i
]);
2123 hx509_err(context
, 1, ret
, "hx509_certs_append");
2126 ret
= hx509_verify_init_ctx(context
, &vctx
);
2128 hx509_err(context
, 1, ret
, "hx509_verify_init_ctx");
2130 hx509_verify_attach_anchors(vctx
, certs
);
2132 ret
= hx509_certs_iter_f(context
, certs
, test_one_cert
, vctx
);
2134 hx509_err(context
, 1, ret
, "hx509_cert_iter");
2136 hx509_certs_free(&certs
);
2142 statistic_print(struct statistic_print_options
*opt
, int argc
, char **argv
)
2146 if (stat_file_string
== NULL
)
2147 errx(1, "no stat file");
2149 if (opt
->type_integer
)
2150 type
= opt
->type_integer
;
2152 hx509_query_unparse_stats(context
, type
, stdout
);
2161 crl_sign(struct crl_sign_options
*opt
, int argc
, char **argv
)
2164 heim_octet_string os
;
2165 hx509_cert signer
= NULL
;
2169 hx509_lock_init(context
, &lock
);
2170 lock_strings(lock
, &opt
->pass_strings
);
2172 ret
= hx509_crl_alloc(context
, &crl
);
2174 errx(1, "crl alloc");
2176 if (opt
->signer_string
== NULL
)
2177 errx(1, "signer missing");
2180 hx509_certs certs
= NULL
;
2183 ret
= hx509_certs_init(context
, opt
->signer_string
, 0,
2186 hx509_err(context
, 1, ret
,
2187 "hx509_certs_init: %s", opt
->signer_string
);
2189 ret
= hx509_query_alloc(context
, &q
);
2191 hx509_err(context
, 1, ret
, "hx509_query_alloc: %d", ret
);
2193 hx509_query_match_option(q
, HX509_QUERY_OPTION_PRIVATE_KEY
);
2195 ret
= hx509_certs_find(context
, certs
, q
, &signer
);
2196 hx509_query_free(context
, q
);
2197 hx509_certs_free(&certs
);
2199 hx509_err(context
, 1, ret
, "no signer certificate found");
2202 if (opt
->lifetime_string
) {
2205 delta
= parse_time(opt
->lifetime_string
, "day");
2207 errx(1, "Invalid lifetime: %s", opt
->lifetime_string
);
2209 hx509_crl_lifetime(context
, crl
, delta
);
2213 hx509_certs revoked
= NULL
;
2216 ret
= hx509_certs_init(context
, "MEMORY:revoked-certs", 0,
2219 hx509_err(context
, 1, ret
,
2220 "hx509_certs_init: MEMORY cert");
2222 for (i
= 0; i
< argc
; i
++) {
2223 ret
= hx509_certs_append(context
, revoked
, lock
, argv
[i
]);
2225 hx509_err(context
, 1, ret
, "hx509_certs_append: %s", argv
[i
]);
2228 hx509_crl_add_revoked_certs(context
, crl
, revoked
);
2229 hx509_certs_free(&revoked
);
2232 hx509_crl_sign(context
, signer
, crl
, &os
);
2234 if (opt
->crl_file_string
)
2235 rk_dumpdata(opt
->crl_file_string
, os
.data
, os
.length
);
2239 hx509_crl_free(context
, &crl
);
2240 hx509_cert_free(signer
);
2241 hx509_lock_free(lock
);
2251 help(void *opt
, int argc
, char **argv
)
2253 sl_slc_help(commands
, argc
, argv
);
2258 main(int argc
, char **argv
)
2260 int ret
, optidx
= 0;
2262 setprogname (argv
[0]);
2264 if(getarg(args
, num_args
, argc
, argv
, &optidx
))
2269 print_version(NULL
);
2278 ret
= hx509_context_init(&context
);
2280 errx(1, "hx509_context_init failed with %d", ret
);
2282 if (stat_file_string
)
2283 hx509_query_statistic_file(context
, stat_file_string
);
2285 ret
= sl_command(commands
, argc
, argv
);
2287 warnx ("unrecognized command: %s", argv
[0]);
2289 hx509_context_free(&context
);