Use DES_set_key_unchecked().
[heimdal.git] / lib / hx509 / hxtool.c
blob8c5e1b6ed64f924ee4d606b924299f256cb99c87
1 /*
2 * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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
31 * SUCH DAMAGE.
34 #include "hx_locl.h"
35 RCSID("$Id$");
37 #include <hxtool-commands.h>
38 #include <sl.h>
39 #include <parse_time.h>
41 static hx509_context context;
43 static char *stat_file_string;
44 static int version_flag;
45 static int help_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]);
54 static void
55 usage(int code)
57 arg_printusage(args, num_args, NULL, "command");
58 printf("Use \"%s help\" to get more help\n", getprogname());
59 exit(code);
66 static void
67 lock_strings(hx509_lock lock, getarg_strings *pass)
69 int i;
70 for (i = 0; i < pass->num_strings; i++) {
71 int ret = hx509_lock_command_string(lock, pass->strings[i]);
72 if (ret)
73 errx(1, "hx509_lock_command_string: %s: %d",
74 pass->strings[i], ret);
82 static void
83 certs_strings(hx509_context context, const char *type, hx509_certs certs,
84 hx509_lock lock, const getarg_strings *s)
86 int i, ret;
88 for (i = 0; i < s->num_strings; i++) {
89 ret = hx509_certs_append(context, certs, lock, s->strings[i]);
90 if (ret)
91 hx509_err(context, 1, ret,
92 "hx509_certs_append: %s %s", type, s->strings[i]);
100 static void
101 parse_oid(const char *str, const heim_oid *def, heim_oid *oid)
103 int ret;
104 if (str)
105 ret = der_parse_heim_oid (str, " .", oid);
106 else
107 ret = der_copy_oid(def, oid);
108 if (ret)
109 errx(1, "parse_oid failed for: %s", str ? str : "default oid");
116 static void
117 peer_strings(hx509_context context,
118 hx509_peer_info *peer,
119 const getarg_strings *s)
121 AlgorithmIdentifier *val;
122 int ret, i;
124 ret = hx509_peer_info_alloc(context, peer);
125 if (ret)
126 hx509_err(context, 1, ret, "hx509_peer_info_alloc");
128 val = calloc(s->num_strings, sizeof(*val));
129 if (val == NULL)
130 err(1, "malloc");
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);
136 if (ret)
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]);
141 free(val);
148 static int
149 pem_reader(hx509_context context, const char *type,
150 const hx509_pem_header *headers,
151 const void *data , size_t length, void *ctx)
153 heim_octet_string *c = (heim_octet_string *)ctx;
155 c->data = malloc(length);
156 if (c->data == NULL)
157 return ENOMEM;
158 memcpy(c->data, data, length);
159 c->length = length;
161 return 0;
169 cms_verify_sd(struct cms_verify_sd_options *opt, int argc, char **argv)
171 hx509_verify_ctx ctx = NULL;
172 heim_oid type;
173 heim_octet_string c, co, signeddata, *sd = NULL;
174 hx509_certs store = NULL;
175 hx509_certs signers = NULL;
176 hx509_certs anchors = NULL;
177 hx509_lock lock;
178 int ret;
180 size_t sz;
181 void *p;
183 if (opt->missing_revoke_flag)
184 hx509_context_set_missing_revoke(context, 1);
186 hx509_lock_init(context, &lock);
187 lock_strings(lock, &opt->pass_strings);
189 ret = hx509_verify_init_ctx(context, &ctx);
191 ret = hx509_certs_init(context, "MEMORY:cms-anchors", 0, NULL, &anchors);
192 ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &store);
194 certs_strings(context, "anchors", anchors, lock, &opt->anchors_strings);
195 certs_strings(context, "store", store, lock, &opt->certificate_strings);
197 if (opt->pem_flag) {
198 FILE *f;
200 f = fopen(argv[0], "r");
201 if (f == NULL)
202 err(1, "Failed to open file %s", argv[0]);
204 ret = hx509_pem_read(context, f, pem_reader, &co);
205 fclose(f);
206 if (ret)
207 errx(1, "PEM reader failed: %d", ret);
208 } else {
209 ret = _hx509_map_file(argv[0], &p, &sz, NULL);
210 if (ret)
211 err(1, "map_file: %s: %d", argv[0], ret);
213 co.data = p;
214 co.length = sz;
217 if (opt->signed_content_string) {
218 ret = _hx509_map_file_os(opt->signed_content_string, &signeddata, NULL);
219 if (ret)
220 errx(1, "map_file: %s: %d", opt->signed_content_string, ret);
221 sd = &signeddata;
224 if (opt->content_info_flag) {
225 heim_octet_string uwco;
226 heim_oid oid;
228 ret = hx509_cms_unwrap_ContentInfo(&co, &oid, &uwco, NULL);
229 if (ret)
230 errx(1, "hx509_cms_unwrap_ContentInfo: %d", ret);
232 if (der_heim_oid_cmp(&oid, oid_id_pkcs7_signedData()) != 0)
233 errx(1, "Content is not SignedData");
234 der_free_oid(&oid);
236 co = uwco;
239 hx509_verify_attach_anchors(ctx, anchors);
241 ret = hx509_cms_verify_signed(context, ctx, co.data, co.length, sd,
242 store, &type, &c, &signers);
243 if (co.data != p)
244 der_free_octet_string(&co);
245 if (ret)
246 hx509_err(context, 1, ret, "hx509_cms_verify_signed");
249 char *str;
250 der_print_heim_oid(&type, '.', &str);
251 printf("type: %s\n", str);
252 free(str);
253 der_free_oid(&type);
255 printf("signers:\n");
256 hx509_certs_iter(context, signers, hx509_ci_print_names, stdout);
258 hx509_verify_destroy_ctx(ctx);
260 hx509_certs_free(&store);
261 hx509_certs_free(&signers);
262 hx509_certs_free(&anchors);
264 hx509_lock_free(lock);
266 ret = _hx509_write_file(argv[1], c.data, c.length);
267 if (ret)
268 errx(1, "hx509_write_file: %d", ret);
270 der_free_octet_string(&c);
271 if (opt->pem_flag)
272 der_free_octet_string(&co);
273 else
274 _hx509_unmap_file(p, sz);
275 if (sd)
276 _hx509_unmap_file_os(sd);
278 return 0;
282 cms_create_sd(struct cms_create_sd_options *opt, int argc, char **argv)
284 heim_oid contentType;
285 hx509_peer_info peer = NULL;
286 heim_octet_string o;
287 hx509_query *q;
288 hx509_lock lock;
289 hx509_certs store, pool, anchors;
290 hx509_cert cert;
291 size_t sz;
292 void *p;
293 int ret, flags = 0;
294 char *signer_name = NULL;
296 memset(&contentType, 0, sizeof(contentType));
298 if (argc < 2)
299 errx(1, "argc < 2");
301 hx509_lock_init(context, &lock);
302 lock_strings(lock, &opt->pass_strings);
304 ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &store);
305 ret = hx509_certs_init(context, "MEMORY:cert-pool", 0, NULL, &pool);
307 certs_strings(context, "store", store, lock, &opt->certificate_strings);
308 certs_strings(context, "pool", pool, lock, &opt->pool_strings);
310 if (opt->anchors_strings.num_strings) {
311 ret = hx509_certs_init(context, "MEMORY:cert-anchors",
312 0, NULL, &anchors);
313 certs_strings(context, "anchors", anchors, lock, &opt->anchors_strings);
314 } else
315 anchors = NULL;
317 if (opt->detached_signature_flag)
318 flags |= HX509_CMS_SIGATURE_DETACHED;
319 if (opt->id_by_name_flag)
320 flags |= HX509_CMS_SIGATURE_ID_NAME;
322 ret = hx509_query_alloc(context, &q);
323 if (ret)
324 errx(1, "hx509_query_alloc: %d", ret);
326 hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
327 hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE);
329 if (opt->signer_string)
330 hx509_query_match_friendly_name(q, opt->signer_string);
332 ret = hx509_certs_find(context, store, q, &cert);
333 hx509_query_free(context, q);
334 if (ret)
335 hx509_err(context, 1, ret, "hx509_certs_find");
337 ret = _hx509_map_file(argv[0], &p, &sz, NULL);
338 if (ret)
339 err(1, "map_file: %s: %d", argv[0], ret);
341 if (opt->peer_alg_strings.num_strings)
342 peer_strings(context, &peer, &opt->peer_alg_strings);
344 parse_oid(opt->content_type_string, oid_id_pkcs7_data(), &contentType);
346 ret = hx509_cms_create_signed_1(context,
347 flags,
348 &contentType,
350 sz,
351 NULL,
352 cert,
353 peer,
354 anchors,
355 pool,
356 &o);
357 if (ret)
358 errx(1, "hx509_cms_create_signed: %d", ret);
361 hx509_name name;
363 ret = hx509_cert_get_subject(cert, &name);
364 if (ret)
365 errx(1, "hx509_cert_get_subject");
367 ret = hx509_name_to_string(name, &signer_name);
368 hx509_name_free(&name);
369 if (ret)
370 errx(1, "hx509_name_to_string");
374 hx509_certs_free(&anchors);
375 hx509_certs_free(&pool);
376 hx509_cert_free(cert);
377 hx509_certs_free(&store);
378 _hx509_unmap_file(p, sz);
379 hx509_lock_free(lock);
380 hx509_peer_info_free(peer);
381 der_free_oid(&contentType);
383 if (opt->content_info_flag) {
384 heim_octet_string wo;
386 ret = hx509_cms_wrap_ContentInfo(oid_id_pkcs7_signedData(), &o, &wo);
387 if (ret)
388 errx(1, "hx509_cms_wrap_ContentInfo: %d", ret);
390 der_free_octet_string(&o);
391 o = wo;
394 if (opt->pem_flag) {
395 hx509_pem_header *header = NULL;
396 FILE *f;
398 hx509_pem_add_header(&header, "Content-disposition",
399 opt->detached_signature_flag ?
400 "detached" : "inline");
401 hx509_pem_add_header(&header, "Signer", signer_name);
403 f = fopen(argv[1], "w");
404 if (f == NULL)
405 err(1, "open %s", argv[1]);
407 ret = hx509_pem_write(context, "CMS SIGNEDDATA", header, f,
408 o.data, o.length);
409 fclose(f);
410 hx509_pem_free_header(header);
411 if (ret)
412 errx(1, "hx509_pem_write: %d", ret);
414 } else {
415 ret = _hx509_write_file(argv[1], o.data, o.length);
416 if (ret)
417 errx(1, "hx509_write_file: %d", ret);
420 free(signer_name);
421 free(o.data);
423 return 0;
427 cms_unenvelope(struct cms_unenvelope_options *opt, int argc, char **argv)
429 heim_oid contentType = { 0, NULL };
430 heim_octet_string o, co;
431 hx509_certs certs;
432 size_t sz;
433 void *p;
434 int ret;
435 hx509_lock lock;
437 hx509_lock_init(context, &lock);
438 lock_strings(lock, &opt->pass_strings);
440 ret = _hx509_map_file(argv[0], &p, &sz, NULL);
441 if (ret)
442 err(1, "map_file: %s: %d", argv[0], ret);
444 co.data = p;
445 co.length = sz;
447 if (opt->content_info_flag) {
448 heim_octet_string uwco;
449 heim_oid oid;
451 ret = hx509_cms_unwrap_ContentInfo(&co, &oid, &uwco, NULL);
452 if (ret)
453 errx(1, "hx509_cms_unwrap_ContentInfo: %d", ret);
455 if (der_heim_oid_cmp(&oid, oid_id_pkcs7_envelopedData()) != 0)
456 errx(1, "Content is not SignedData");
457 der_free_oid(&oid);
459 co = uwco;
462 ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &certs);
463 if (ret)
464 errx(1, "hx509_certs_init: MEMORY: %d", ret);
466 certs_strings(context, "store", certs, lock, &opt->certificate_strings);
468 ret = hx509_cms_unenvelope(context, certs, 0, co.data, co.length,
469 NULL, &contentType, &o);
470 if (co.data != p)
471 der_free_octet_string(&co);
472 if (ret)
473 hx509_err(context, 1, ret, "hx509_cms_unenvelope");
475 _hx509_unmap_file(p, sz);
476 hx509_lock_free(lock);
477 hx509_certs_free(&certs);
478 der_free_oid(&contentType);
480 ret = _hx509_write_file(argv[1], o.data, o.length);
481 if (ret)
482 errx(1, "hx509_write_file: %d", ret);
484 der_free_octet_string(&o);
486 return 0;
490 cms_create_enveloped(struct cms_envelope_options *opt, int argc, char **argv)
492 heim_oid contentType;
493 heim_octet_string o;
494 const heim_oid *enctype = NULL;
495 hx509_query *q;
496 hx509_certs certs;
497 hx509_cert cert;
498 int ret;
499 size_t sz;
500 void *p;
501 hx509_lock lock;
503 memset(&contentType, 0, sizeof(contentType));
505 hx509_lock_init(context, &lock);
506 lock_strings(lock, &opt->pass_strings);
508 ret = _hx509_map_file(argv[0], &p, &sz, NULL);
509 if (ret)
510 err(1, "map_file: %s: %d", argv[0], ret);
512 ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &certs);
514 certs_strings(context, "store", certs, lock, &opt->certificate_strings);
516 if (opt->encryption_type_string) {
517 enctype = hx509_crypto_enctype_by_name(opt->encryption_type_string);
518 if (enctype == NULL)
519 errx(1, "encryption type: %s no found",
520 opt->encryption_type_string);
523 ret = hx509_query_alloc(context, &q);
524 if (ret)
525 errx(1, "hx509_query_alloc: %d", ret);
527 hx509_query_match_option(q, HX509_QUERY_OPTION_KU_ENCIPHERMENT);
529 ret = hx509_certs_find(context, certs, q, &cert);
530 hx509_query_free(context, q);
531 if (ret)
532 errx(1, "hx509_certs_find: %d", ret);
534 parse_oid(opt->content_type_string, oid_id_pkcs7_data(), &contentType);
536 ret = hx509_cms_envelope_1(context, 0, cert, p, sz, enctype,
537 &contentType, &o);
538 if (ret)
539 errx(1, "hx509_cms_envelope_1: %d", ret);
541 hx509_cert_free(cert);
542 hx509_certs_free(&certs);
543 _hx509_unmap_file(p, sz);
544 der_free_oid(&contentType);
546 if (opt->content_info_flag) {
547 heim_octet_string wo;
549 ret = hx509_cms_wrap_ContentInfo(oid_id_pkcs7_envelopedData(), &o, &wo);
550 if (ret)
551 errx(1, "hx509_cms_wrap_ContentInfo: %d", ret);
553 der_free_octet_string(&o);
554 o = wo;
557 hx509_lock_free(lock);
559 ret = _hx509_write_file(argv[1], o.data, o.length);
560 if (ret)
561 errx(1, "hx509_write_file: %d", ret);
563 der_free_octet_string(&o);
565 return 0;
568 static void
569 print_certificate(hx509_context hxcontext, hx509_cert cert, int verbose)
571 hx509_name name;
572 const char *fn;
573 char *str;
574 int ret;
576 fn = hx509_cert_get_friendly_name(cert);
577 if (fn)
578 printf(" friendly name: %s\n", fn);
579 printf(" private key: %s\n",
580 _hx509_cert_private_key(cert) ? "yes" : "no");
582 ret = hx509_cert_get_issuer(cert, &name);
583 hx509_name_to_string(name, &str);
584 hx509_name_free(&name);
585 printf(" issuer: \"%s\"\n", str);
586 free(str);
588 ret = hx509_cert_get_subject(cert, &name);
589 hx509_name_to_string(name, &str);
590 hx509_name_free(&name);
591 printf(" subject: \"%s\"\n", str);
592 free(str);
595 heim_integer serialNumber;
597 hx509_cert_get_serialnumber(cert, &serialNumber);
598 der_print_hex_heim_integer(&serialNumber, &str);
599 der_free_heim_integer(&serialNumber);
600 printf(" serial: %s\n", str);
601 free(str);
604 printf(" keyusage: ");
605 ret = hx509_cert_keyusage_print(hxcontext, cert, &str);
606 if (ret == 0) {
607 printf("%s\n", str);
608 free(str);
609 } else
610 printf("no");
612 if (verbose) {
613 hx509_validate_ctx vctx;
615 hx509_validate_ctx_init(hxcontext, &vctx);
616 hx509_validate_ctx_set_print(vctx, hx509_print_stdout, stdout);
617 hx509_validate_ctx_add_flags(vctx, HX509_VALIDATE_F_VALIDATE);
618 hx509_validate_ctx_add_flags(vctx, HX509_VALIDATE_F_VERBOSE);
620 hx509_validate_cert(hxcontext, vctx, cert);
622 hx509_validate_ctx_free(vctx);
627 struct print_s {
628 int counter;
629 int verbose;
632 static int
633 print_f(hx509_context hxcontext, void *ctx, hx509_cert cert)
635 struct print_s *s = ctx;
637 printf("cert: %d\n", s->counter++);
638 print_certificate(context, cert, s->verbose);
640 return 0;
644 pcert_print(struct print_options *opt, int argc, char **argv)
646 hx509_certs certs;
647 hx509_lock lock;
648 struct print_s s;
650 s.counter = 0;
651 s.verbose = opt->content_flag;
653 hx509_lock_init(context, &lock);
654 lock_strings(lock, &opt->pass_strings);
656 while(argc--) {
657 int ret;
658 ret = hx509_certs_init(context, argv[0], 0, lock, &certs);
659 if (ret)
660 hx509_err(context, 1, ret, "hx509_certs_init");
661 if (opt->info_flag)
662 hx509_certs_info(context, certs, NULL, NULL);
663 hx509_certs_iter(context, certs, print_f, &s);
664 hx509_certs_free(&certs);
665 argv++;
668 hx509_lock_free(lock);
670 return 0;
674 static int
675 validate_f(hx509_context hxcontext, void *ctx, hx509_cert c)
677 hx509_validate_cert(hxcontext, ctx, c);
678 return 0;
682 pcert_validate(struct validate_options *opt, int argc, char **argv)
684 hx509_validate_ctx ctx;
685 hx509_certs certs;
686 hx509_lock lock;
688 hx509_lock_init(context, &lock);
689 lock_strings(lock, &opt->pass_strings);
691 hx509_validate_ctx_init(context, &ctx);
692 hx509_validate_ctx_set_print(ctx, hx509_print_stdout, stdout);
693 hx509_validate_ctx_add_flags(ctx, HX509_VALIDATE_F_VALIDATE);
695 while(argc--) {
696 int ret;
697 ret = hx509_certs_init(context, argv[0], 0, lock, &certs);
698 if (ret)
699 errx(1, "hx509_certs_init: %d", ret);
700 hx509_certs_iter(context, certs, validate_f, ctx);
701 hx509_certs_free(&certs);
702 argv++;
704 hx509_validate_ctx_free(ctx);
706 hx509_lock_free(lock);
708 return 0;
712 certificate_copy(struct certificate_copy_options *opt, int argc, char **argv)
714 hx509_certs certs;
715 hx509_lock lock;
716 int ret;
718 hx509_lock_init(context, &lock);
719 lock_strings(lock, &opt->in_pass_strings);
721 ret = hx509_certs_init(context, argv[argc - 1],
722 HX509_CERTS_CREATE, lock, &certs);
723 if (ret)
724 hx509_err(context, 1, ret, "hx509_certs_init");
726 while(argc-- > 1) {
727 int ret;
728 ret = hx509_certs_append(context, certs, lock, argv[0]);
729 if (ret)
730 hx509_err(context, 1, ret, "hx509_certs_append");
731 argv++;
734 ret = hx509_certs_store(context, certs, 0, NULL);
735 if (ret)
736 hx509_err(context, 1, ret, "hx509_certs_store");
738 hx509_certs_free(&certs);
739 hx509_lock_free(lock);
741 return 0;
744 struct verify {
745 hx509_verify_ctx ctx;
746 hx509_certs chain;
747 const char *hostname;
748 int errors;
751 static int
752 verify_f(hx509_context hxcontext, void *ctx, hx509_cert c)
754 struct verify *v = ctx;
755 int ret;
757 ret = hx509_verify_path(hxcontext, v->ctx, c, v->chain);
758 if (ret) {
759 char *s = hx509_get_error_string(hxcontext, ret);
760 printf("verify_path: %s: %d\n", s, ret);
761 hx509_free_error_string(s);
762 v->errors++;
763 } else
764 printf("path ok\n");
766 if (v->hostname) {
767 ret = hx509_verify_hostname(hxcontext, c, 0, HX509_HN_HOSTNAME,
768 v->hostname, NULL, 0);
769 if (ret) {
770 printf("verify_hostname: %d\n", ret);
771 v->errors++;
775 return 0;
779 pcert_verify(struct verify_options *opt, int argc, char **argv)
781 hx509_certs anchors, chain, certs;
782 hx509_revoke_ctx revoke_ctx;
783 hx509_verify_ctx ctx;
784 struct verify v;
785 int ret;
787 memset(&v, 0, sizeof(v));
789 if (opt->missing_revoke_flag)
790 hx509_context_set_missing_revoke(context, 1);
792 ret = hx509_verify_init_ctx(context, &ctx);
793 ret = hx509_certs_init(context, "MEMORY:anchors", 0, NULL, &anchors);
794 ret = hx509_certs_init(context, "MEMORY:chain", 0, NULL, &chain);
795 ret = hx509_certs_init(context, "MEMORY:certs", 0, NULL, &certs);
797 if (opt->allow_proxy_certificate_flag)
798 hx509_verify_set_proxy_certificate(ctx, 1);
800 if (opt->time_string) {
801 const char *p;
802 struct tm tm;
803 time_t t;
805 memset(&tm, 0, sizeof(tm));
807 p = strptime (opt->time_string, "%Y-%m-%d", &tm);
808 if (p == NULL)
809 errx(1, "Failed to parse time %s, need to be on format %%Y-%%m-%%d",
810 opt->time_string);
812 t = tm2time (tm, 0);
814 hx509_verify_set_time(ctx, t);
817 if (opt->hostname_string)
818 v.hostname = opt->hostname_string;
819 if (opt->max_depth_integer)
820 hx509_verify_set_max_depth(ctx, opt->max_depth_integer);
822 ret = hx509_revoke_init(context, &revoke_ctx);
823 if (ret)
824 errx(1, "hx509_revoke_init: %d", ret);
826 while(argc--) {
827 char *s = *argv++;
829 if (strncmp(s, "chain:", 6) == 0) {
830 s += 6;
832 ret = hx509_certs_append(context, chain, NULL, s);
833 if (ret)
834 hx509_err(context, 1, ret, "hx509_certs_append: chain: %s: %d", s, ret);
836 } else if (strncmp(s, "anchor:", 7) == 0) {
837 s += 7;
839 ret = hx509_certs_append(context, anchors, NULL, s);
840 if (ret)
841 hx509_err(context, 1, ret, "hx509_certs_append: anchor: %s: %d", s, ret);
843 } else if (strncmp(s, "cert:", 5) == 0) {
844 s += 5;
846 ret = hx509_certs_append(context, certs, NULL, s);
847 if (ret)
848 hx509_err(context, 1, ret, "hx509_certs_append: certs: %s: %d",
849 s, ret);
851 } else if (strncmp(s, "crl:", 4) == 0) {
852 s += 4;
854 ret = hx509_revoke_add_crl(context, revoke_ctx, s);
855 if (ret)
856 errx(1, "hx509_revoke_add_crl: %s: %d", s, ret);
858 } else if (strncmp(s, "ocsp:", 4) == 0) {
859 s += 5;
861 ret = hx509_revoke_add_ocsp(context, revoke_ctx, s);
862 if (ret)
863 errx(1, "hx509_revoke_add_ocsp: %s: %d", s, ret);
865 } else {
866 errx(1, "unknown option to verify: `%s'\n", s);
870 hx509_verify_attach_anchors(ctx, anchors);
871 hx509_verify_attach_revoke(ctx, revoke_ctx);
873 v.ctx = ctx;
874 v.chain = chain;
876 hx509_certs_iter(context, certs, verify_f, &v);
878 hx509_verify_destroy_ctx(ctx);
880 hx509_certs_free(&certs);
881 hx509_certs_free(&chain);
882 hx509_certs_free(&anchors);
884 hx509_revoke_free(&revoke_ctx);
886 if (v.errors) {
887 printf("failed verifing %d checks\n", v.errors);
888 return 1;
891 return 0;
895 query(struct query_options *opt, int argc, char **argv)
897 hx509_lock lock;
898 hx509_query *q;
899 hx509_certs certs;
900 hx509_cert c;
901 int ret;
903 ret = hx509_query_alloc(context, &q);
904 if (ret)
905 errx(1, "hx509_query_alloc: %d", ret);
907 hx509_lock_init(context, &lock);
908 lock_strings(lock, &opt->pass_strings);
910 ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &certs);
912 while (argc > 0) {
914 ret = hx509_certs_append(context, certs, lock, argv[0]);
915 if (ret)
916 errx(1, "hx509_certs_append: %s: %d", argv[0], ret);
918 argc--;
919 argv++;
922 if (opt->friendlyname_string)
923 hx509_query_match_friendly_name(q, opt->friendlyname_string);
925 if (opt->eku_string) {
926 heim_oid oid;
928 parse_oid(opt->eku_string, NULL, &oid);
930 ret = hx509_query_match_eku(q, &oid);
931 if (ret)
932 errx(1, "hx509_query_match_eku: %d", ret);
933 der_free_oid(&oid);
936 if (opt->private_key_flag)
937 hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
939 if (opt->keyEncipherment_flag)
940 hx509_query_match_option(q, HX509_QUERY_OPTION_KU_ENCIPHERMENT);
942 if (opt->digitalSignature_flag)
943 hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE);
945 if (opt->expr_string)
946 hx509_query_match_expr(context, q, opt->expr_string);
948 ret = hx509_certs_find(context, certs, q, &c);
949 hx509_query_free(context, q);
950 if (ret)
951 printf("no match found (%d)\n", ret);
952 else {
953 printf("match found\n");
954 if (opt->print_flag)
955 print_certificate(context, c, 0);
958 hx509_cert_free(c);
959 hx509_certs_free(&certs);
961 hx509_lock_free(lock);
963 return ret;
967 ocsp_fetch(struct ocsp_fetch_options *opt, int argc, char **argv)
969 hx509_certs reqcerts, pool;
970 heim_octet_string req, nonce_data, *nonce = &nonce_data;
971 hx509_lock lock;
972 int i, ret;
973 char *file;
974 const char *url = "/";
976 memset(&nonce, 0, sizeof(nonce));
978 hx509_lock_init(context, &lock);
979 lock_strings(lock, &opt->pass_strings);
981 /* no nonce */
982 if (!opt->nonce_flag)
983 nonce = NULL;
985 if (opt->url_path_string)
986 url = opt->url_path_string;
988 ret = hx509_certs_init(context, "MEMORY:ocsp-pool", 0, NULL, &pool);
990 certs_strings(context, "ocsp-pool", pool, lock, &opt->pool_strings);
992 file = argv[0];
994 ret = hx509_certs_init(context, "MEMORY:ocsp-req", 0, NULL, &reqcerts);
996 for (i = 1; i < argc; i++) {
997 ret = hx509_certs_append(context, reqcerts, lock, argv[i]);
998 if (ret)
999 errx(1, "hx509_certs_append: req: %s: %d", argv[i], ret);
1002 ret = hx509_ocsp_request(context, reqcerts, pool, NULL, NULL, &req, nonce);
1003 if (ret)
1004 errx(1, "hx509_ocsp_request: req: %d", ret);
1007 FILE *f;
1009 f = fopen(file, "w");
1010 if (f == NULL)
1011 abort();
1013 fprintf(f,
1014 "POST %s HTTP/1.0\r\n"
1015 "Content-Type: application/ocsp-request\r\n"
1016 "Content-Length: %ld\r\n"
1017 "\r\n",
1018 url,
1019 (unsigned long)req.length);
1020 fwrite(req.data, req.length, 1, f);
1021 fclose(f);
1024 if (nonce)
1025 der_free_octet_string(nonce);
1027 hx509_certs_free(&reqcerts);
1028 hx509_certs_free(&pool);
1030 return 0;
1034 ocsp_print(struct ocsp_print_options *opt, int argc, char **argv)
1036 hx509_revoke_ocsp_print(context, argv[0], stdout);
1037 return 0;
1044 static int
1045 verify_o(hx509_context hxcontext, void *ctx, hx509_cert c)
1047 heim_octet_string *os = ctx;
1048 time_t expiration;
1049 int ret;
1051 ret = hx509_ocsp_verify(context, 0, c, 0,
1052 os->data, os->length, &expiration);
1053 if (ret) {
1054 char *s = hx509_get_error_string(hxcontext, ret);
1055 printf("ocsp_verify: %s: %d\n", s, ret);
1056 hx509_free_error_string(s);
1057 } else
1058 printf("expire: %d\n", (int)expiration);
1060 return ret;
1065 ocsp_verify(struct ocsp_verify_options *opt, int argc, char **argv)
1067 hx509_lock lock;
1068 hx509_certs certs;
1069 int ret, i;
1070 heim_octet_string os;
1072 hx509_lock_init(context, &lock);
1074 if (opt->ocsp_file_string == NULL)
1075 errx(1, "no ocsp file given");
1077 ret = _hx509_map_file(opt->ocsp_file_string, &os.data, &os.length, NULL);
1078 if (ret)
1079 err(1, "map_file: %s: %d", argv[0], ret);
1081 ret = hx509_certs_init(context, "MEMORY:test-certs", 0, NULL, &certs);
1083 for (i = 0; i < argc; i++) {
1084 ret = hx509_certs_append(context, certs, lock, argv[i]);
1085 if (ret)
1086 hx509_err(context, 1, ret, "hx509_certs_append: %s", argv[i]);
1089 ret = hx509_certs_iter(context, certs, verify_o, &os);
1091 hx509_certs_free(&certs);
1092 _hx509_unmap_file(os.data, os.length);
1093 hx509_lock_free(lock);
1095 return ret;
1098 static int
1099 read_private_key(const char *fn, hx509_private_key *key)
1101 hx509_private_key *keys;
1102 hx509_certs certs;
1103 int ret;
1105 *key = NULL;
1107 ret = hx509_certs_init(context, fn, 0, NULL, &certs);
1108 if (ret)
1109 hx509_err(context, 1, ret, "hx509_certs_init: %s", fn);
1111 ret = _hx509_certs_keys_get(context, certs, &keys);
1112 hx509_certs_free(&certs);
1113 if (ret)
1114 hx509_err(context, 1, ret, "hx509_certs_keys_get");
1115 if (keys[0] == NULL)
1116 errx(1, "no keys in key store: %s", fn);
1118 *key = _hx509_private_key_ref(keys[0]);
1119 _hx509_certs_keys_free(context, keys);
1121 return 0;
1124 static void
1125 get_key(const char *fn, const char *type, int optbits,
1126 hx509_private_key *signer)
1128 int ret;
1130 if (type) {
1131 BIGNUM *e;
1132 RSA *rsa;
1133 unsigned char *p0, *p;
1134 size_t len;
1135 int bits = 1024;
1137 if (fn == NULL)
1138 errx(1, "no key argument, don't know here to store key");
1140 if (strcasecmp(type, "rsa") != 0)
1141 errx(1, "can only handle rsa keys for now");
1143 e = BN_new();
1144 BN_set_word(e, 0x10001);
1146 if (optbits)
1147 bits = optbits;
1149 rsa = RSA_new();
1150 if(rsa == NULL)
1151 errx(1, "RSA_new failed");
1153 ret = RSA_generate_key_ex(rsa, bits, e, NULL);
1154 if(ret != 1)
1155 errx(1, "RSA_new failed");
1157 BN_free(e);
1159 len = i2d_RSAPrivateKey(rsa, NULL);
1161 p0 = p = malloc(len);
1162 if (p == NULL)
1163 errx(1, "out of memory");
1165 i2d_RSAPrivateKey(rsa, &p);
1167 rk_dumpdata(fn, p0, len);
1168 memset(p0, 0, len);
1169 free(p0);
1171 RSA_free(rsa);
1173 } else if (fn == NULL)
1174 err(1, "no private key");
1176 ret = read_private_key(fn, signer);
1177 if (ret)
1178 err(1, "read_private_key");
1182 request_create(struct request_create_options *opt, int argc, char **argv)
1184 heim_octet_string request;
1185 hx509_request req;
1186 int ret, i;
1187 hx509_private_key signer;
1188 SubjectPublicKeyInfo key;
1189 const char *outfile = argv[0];
1191 memset(&key, 0, sizeof(key));
1193 get_key(opt->key_string,
1194 opt->generate_key_string,
1195 opt->key_bits_integer,
1196 &signer);
1198 _hx509_request_init(context, &req);
1200 if (opt->subject_string) {
1201 hx509_name name = NULL;
1203 ret = hx509_parse_name(context, opt->subject_string, &name);
1204 if (ret)
1205 errx(1, "hx509_parse_name: %d\n", ret);
1206 _hx509_request_set_name(context, req, name);
1208 if (opt->verbose_flag) {
1209 char *s;
1210 hx509_name_to_string(name, &s);
1211 printf("%s\n", s);
1213 hx509_name_free(&name);
1216 for (i = 0; i < opt->email_strings.num_strings; i++) {
1217 ret = _hx509_request_add_email(context, req,
1218 opt->email_strings.strings[i]);
1221 for (i = 0; i < opt->dnsname_strings.num_strings; i++) {
1222 ret = _hx509_request_add_dns_name(context, req,
1223 opt->dnsname_strings.strings[i]);
1227 ret = _hx509_private_key2SPKI(context, signer, &key);
1228 if (ret)
1229 errx(1, "_hx509_private_key2SPKI: %d\n", ret);
1231 ret = _hx509_request_set_SubjectPublicKeyInfo(context,
1232 req,
1233 &key);
1234 free_SubjectPublicKeyInfo(&key);
1235 if (ret)
1236 hx509_err(context, 1, ret, "_hx509_request_set_SubjectPublicKeyInfo");
1238 ret = _hx509_request_to_pkcs10(context,
1239 req,
1240 signer,
1241 &request);
1242 if (ret)
1243 hx509_err(context, 1, ret, "_hx509_request_to_pkcs10");
1245 _hx509_private_key_free(&signer);
1246 _hx509_request_free(&req);
1248 if (ret == 0)
1249 rk_dumpdata(outfile, request.data, request.length);
1250 der_free_octet_string(&request);
1252 return 0;
1256 request_print(struct request_print_options *opt, int argc, char **argv)
1258 int ret, i;
1260 printf("request print\n");
1262 for (i = 0; i < argc; i++) {
1263 hx509_request req;
1265 ret = _hx509_request_parse(context, argv[i], &req);
1266 if (ret)
1267 hx509_err(context, 1, ret, "parse_request: %s", argv[i]);
1269 ret = _hx509_request_print(context, req, stdout);
1270 _hx509_request_free(&req);
1271 if (ret)
1272 hx509_err(context, 1, ret, "Failed to print file %s", argv[i]);
1275 return 0;
1279 info(void *opt, int argc, char **argv)
1282 ENGINE_add_conf_module();
1285 const RSA_METHOD *m = RSA_get_default_method();
1286 if (m != NULL)
1287 printf("rsa: %s\n", m->name);
1290 const DH_METHOD *m = DH_get_default_method();
1291 if (m != NULL)
1292 printf("dh: %s\n", m->name);
1295 int ret = RAND_status();
1296 printf("rand: %s\n", ret == 1 ? "ok" : "not available");
1299 return 0;
1303 random_data(void *opt, int argc, char **argv)
1305 void *ptr;
1306 int len, ret;
1308 len = parse_bytes(argv[0], "byte");
1309 if (len <= 0) {
1310 fprintf(stderr, "bad argument to random-data\n");
1311 return 1;
1314 ptr = malloc(len);
1315 if (ptr == NULL) {
1316 fprintf(stderr, "out of memory\n");
1317 return 1;
1320 ret = RAND_bytes(ptr, len);
1321 if (ret != 1) {
1322 free(ptr);
1323 fprintf(stderr, "did not get cryptographic strong random\n");
1324 return 1;
1327 fwrite(ptr, len, 1, stdout);
1328 fflush(stdout);
1330 free(ptr);
1332 return 0;
1336 crypto_available(struct crypto_available_options *opt, int argc, char **argv)
1338 AlgorithmIdentifier *val;
1339 unsigned int len, i;
1340 int ret, type;
1342 if (opt->type_string) {
1343 if (strcmp(opt->type_string, "all") == 0)
1344 type = HX509_SELECT_ALL;
1345 else if (strcmp(opt->type_string, "digest") == 0)
1346 type = HX509_SELECT_DIGEST;
1347 else if (strcmp(opt->type_string, "public-sig") == 0)
1348 type = HX509_SELECT_PUBLIC_SIG;
1349 else if (strcmp(opt->type_string, "secret") == 0)
1350 type = HX509_SELECT_SECRET_ENC;
1351 else
1352 errx(1, "unknown type: %s", opt->type_string);
1353 } else
1354 type = HX509_SELECT_ALL;
1356 ret = hx509_crypto_available(context, type, NULL, &val, &len);
1357 if (ret)
1358 errx(1, "hx509_crypto_available");
1360 for (i = 0; i < len; i++) {
1361 char *s;
1362 der_print_heim_oid (&val[i].algorithm, '.', &s);
1363 printf("%s\n", s);
1364 free(s);
1367 hx509_crypto_free_algs(val, len);
1369 return 0;
1373 crypto_select(struct crypto_select_options *opt, int argc, char **argv)
1375 hx509_peer_info peer = NULL;
1376 AlgorithmIdentifier selected;
1377 int ret, type;
1378 char *s;
1380 if (opt->type_string) {
1381 if (strcmp(opt->type_string, "digest") == 0)
1382 type = HX509_SELECT_DIGEST;
1383 else if (strcmp(opt->type_string, "public-sig") == 0)
1384 type = HX509_SELECT_PUBLIC_SIG;
1385 else if (strcmp(opt->type_string, "secret") == 0)
1386 type = HX509_SELECT_SECRET_ENC;
1387 else
1388 errx(1, "unknown type: %s", opt->type_string);
1389 } else
1390 type = HX509_SELECT_DIGEST;
1392 if (opt->peer_cmstype_strings.num_strings)
1393 peer_strings(context, &peer, &opt->peer_cmstype_strings);
1395 ret = hx509_crypto_select(context, type, NULL, peer, &selected);
1396 if (ret)
1397 errx(1, "hx509_crypto_available");
1399 der_print_heim_oid (&selected.algorithm, '.', &s);
1400 printf("%s\n", s);
1401 free(s);
1402 free_AlgorithmIdentifier(&selected);
1404 hx509_peer_info_free(peer);
1406 return 0;
1410 hxtool_hex(struct hex_options *opt, int argc, char **argv)
1413 if (opt->decode_flag) {
1414 char buf[1024], buf2[1024], *p;
1415 ssize_t len;
1417 while(fgets(buf, sizeof(buf), stdin) != NULL) {
1418 buf[strcspn(buf, "\r\n")] = '\0';
1419 p = buf;
1420 while(isspace(*(unsigned char *)p))
1421 p++;
1422 len = hex_decode(p, buf2, strlen(p));
1423 if (len < 0)
1424 errx(1, "hex_decode failed");
1425 if (fwrite(buf2, 1, len, stdout) != len)
1426 errx(1, "fwrite failed");
1428 } else {
1429 char buf[28], *p;
1430 size_t len;
1432 while((len = fread(buf, 1, sizeof(buf), stdin)) != 0) {
1433 len = hex_encode(buf, len, &p);
1434 fprintf(stdout, "%s\n", p);
1435 free(p);
1438 return 0;
1441 static int
1442 eval_types(hx509_context context,
1443 hx509_ca_tbs tbs,
1444 const struct certificate_sign_options *opt)
1446 int pkinit = 0;
1447 int i, ret;
1449 for (i = 0; i < opt->type_strings.num_strings; i++) {
1450 const char *type = opt->type_strings.strings[i];
1452 if (strcmp(type, "https-server") == 0) {
1453 ret = hx509_ca_tbs_add_eku(context, tbs,
1454 oid_id_pkix_kp_serverAuth());
1455 if (ret)
1456 hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku");
1457 } else if (strcmp(type, "https-client") == 0) {
1458 ret = hx509_ca_tbs_add_eku(context, tbs,
1459 oid_id_pkix_kp_clientAuth());
1460 if (ret)
1461 hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku");
1462 } else if (strcmp(type, "peap-server") == 0) {
1463 ret = hx509_ca_tbs_add_eku(context, tbs,
1464 oid_id_pkix_kp_serverAuth());
1465 if (ret)
1466 hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku");
1467 } else if (strcmp(type, "pkinit-kdc") == 0) {
1468 pkinit++;
1469 ret = hx509_ca_tbs_add_eku(context, tbs,
1470 oid_id_pkkdcekuoid());
1471 if (ret)
1472 hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku");
1473 } else if (strcmp(type, "pkinit-client") == 0) {
1474 pkinit++;
1475 ret = hx509_ca_tbs_add_eku(context, tbs,
1476 oid_id_pkekuoid());
1477 if (ret)
1478 hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku");
1480 ret = hx509_ca_tbs_add_eku(context, tbs,
1481 oid_id_ms_client_authentication());
1482 if (ret)
1483 hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku");
1485 ret = hx509_ca_tbs_add_eku(context, tbs,
1486 oid_id_pkinit_ms_eku());
1487 if (ret)
1488 hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku");
1490 } else if (strcmp(type, "email") == 0) {
1491 ret = hx509_ca_tbs_add_eku(context, tbs,
1492 oid_id_pkix_kp_emailProtection());
1493 if (ret)
1494 hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku");
1495 } else
1496 errx(1, "unknown type %s", type);
1499 if (pkinit > 1)
1500 errx(1, "More the one PK-INIT type given");
1502 if (opt->pk_init_principal_string) {
1503 if (!pkinit)
1504 errx(1, "pk-init principal given but no pk-init oid");
1506 ret = hx509_ca_tbs_add_san_pkinit(context, tbs,
1507 opt->pk_init_principal_string);
1508 if (ret)
1509 hx509_err(context, 1, ret, "hx509_ca_tbs_add_san_pkinit");
1512 if (opt->ms_upn_string) {
1513 if (!pkinit)
1514 errx(1, "MS up given but no pk-init oid");
1516 ret = hx509_ca_tbs_add_san_ms_upn(context, tbs, opt->ms_upn_string);
1517 if (ret)
1518 hx509_err(context, 1, ret, "hx509_ca_tbs_add_san_ms_upn");
1522 for (i = 0; i < opt->hostname_strings.num_strings; i++) {
1523 const char *hostname = opt->hostname_strings.strings[i];
1525 ret = hx509_ca_tbs_add_san_hostname(context, tbs, hostname);
1526 if (ret)
1527 hx509_err(context, 1, ret, "hx509_ca_tbs_add_san_hostname");
1530 for (i = 0; i < opt->email_strings.num_strings; i++) {
1531 const char *email = opt->email_strings.strings[i];
1533 ret = hx509_ca_tbs_add_san_rfc822name(context, tbs, email);
1534 if (ret)
1535 hx509_err(context, 1, ret, "hx509_ca_tbs_add_san_hostname");
1537 ret = hx509_ca_tbs_add_eku(context, tbs,
1538 oid_id_pkix_kp_emailProtection());
1539 if (ret)
1540 hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku");
1543 if (opt->jid_string) {
1544 ret = hx509_ca_tbs_add_san_jid(context, tbs, opt->jid_string);
1545 if (ret)
1546 hx509_err(context, 1, ret, "hx509_ca_tbs_add_san_jid");
1549 return 0;
1553 hxtool_ca(struct certificate_sign_options *opt, int argc, char **argv)
1555 int ret;
1556 hx509_ca_tbs tbs;
1557 hx509_cert signer = NULL, cert = NULL;
1558 hx509_private_key private_key = NULL;
1559 hx509_private_key cert_key = NULL;
1560 hx509_name subject = NULL;
1561 SubjectPublicKeyInfo spki;
1562 int delta = 0;
1564 memset(&spki, 0, sizeof(spki));
1566 if (opt->ca_certificate_string == NULL && !opt->self_signed_flag)
1567 errx(1, "--ca-certificate argument missing (not using --self-signed)");
1568 if (opt->ca_private_key_string == NULL && opt->generate_key_string == NULL && opt->self_signed_flag)
1569 errx(1, "--ca-private-key argument missing (using --self-signed)");
1570 if (opt->certificate_string == NULL)
1571 errx(1, "--certificate argument missing");
1573 if (opt->template_certificate_string) {
1574 if (opt->template_fields_string == NULL)
1575 errx(1, "--template-certificate not no --template-fields");
1578 if (opt->lifetime_string) {
1579 delta = parse_time(opt->lifetime_string, "day");
1580 if (delta < 0)
1581 errx(1, "Invalid lifetime: %s", opt->lifetime_string);
1584 if (opt->ca_certificate_string) {
1585 hx509_certs cacerts = NULL;
1586 hx509_query *q;
1588 ret = hx509_certs_init(context, opt->ca_certificate_string, 0,
1589 NULL, &cacerts);
1590 if (ret)
1591 hx509_err(context, 1, ret,
1592 "hx509_certs_init: %s", opt->ca_certificate_string);
1594 ret = hx509_query_alloc(context, &q);
1595 if (ret)
1596 errx(1, "hx509_query_alloc: %d", ret);
1598 hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
1599 if (!opt->issue_proxy_flag)
1600 hx509_query_match_option(q, HX509_QUERY_OPTION_KU_KEYCERTSIGN);
1602 ret = hx509_certs_find(context, cacerts, q, &signer);
1603 hx509_query_free(context, q);
1604 hx509_certs_free(&cacerts);
1605 if (ret)
1606 hx509_err(context, 1, ret, "no CA certificate found");
1607 } else if (opt->self_signed_flag) {
1608 if (opt->generate_key_string == NULL
1609 && opt->ca_private_key_string == NULL)
1610 errx(1, "no signing private key");
1611 } else
1612 errx(1, "missing ca key");
1614 if (opt->ca_private_key_string) {
1616 ret = read_private_key(opt->ca_private_key_string, &private_key);
1617 if (ret)
1618 err(1, "read_private_key");
1620 ret = _hx509_private_key2SPKI(context, private_key, &spki);
1621 if (ret)
1622 errx(1, "_hx509_private_key2SPKI: %d\n", ret);
1624 if (opt->self_signed_flag)
1625 cert_key = private_key;
1628 if (opt->req_string) {
1629 hx509_request req;
1631 ret = _hx509_request_parse(context, opt->req_string, &req);
1632 if (ret)
1633 hx509_err(context, 1, ret, "parse_request: %s", opt->req_string);
1634 ret = _hx509_request_get_name(context, req, &subject);
1635 if (ret)
1636 hx509_err(context, 1, ret, "get name");
1637 ret = _hx509_request_get_SubjectPublicKeyInfo(context, req, &spki);
1638 if (ret)
1639 hx509_err(context, 1, ret, "get spki");
1640 _hx509_request_free(&req);
1643 if (opt->generate_key_string) {
1644 struct hx509_generate_private_context *keyctx;
1646 ret = _hx509_generate_private_key_init(context,
1647 oid_id_pkcs1_rsaEncryption(),
1648 &keyctx);
1650 if (opt->issue_ca_flag)
1651 _hx509_generate_private_key_is_ca(context, keyctx);
1653 if (opt->key_bits_integer)
1654 _hx509_generate_private_key_bits(context, keyctx,
1655 opt->key_bits_integer);
1657 ret = _hx509_generate_private_key(context, keyctx,
1658 &cert_key);
1659 _hx509_generate_private_key_free(&keyctx);
1660 if (ret)
1661 hx509_err(context, 1, ret, "generate private key");
1663 ret = _hx509_private_key2SPKI(context, cert_key, &spki);
1664 if (ret)
1665 errx(1, "_hx509_private_key2SPKI: %d\n", ret);
1667 if (opt->self_signed_flag)
1668 private_key = cert_key;
1671 if (opt->certificate_private_key_string) {
1672 ret = read_private_key(opt->certificate_private_key_string, &cert_key);
1673 if (ret)
1674 err(1, "read_private_key for certificate");
1677 if (opt->subject_string) {
1678 if (subject)
1679 hx509_name_free(&subject);
1680 ret = hx509_parse_name(context, opt->subject_string, &subject);
1681 if (ret)
1682 hx509_err(context, 1, ret, "hx509_parse_name");
1689 ret = hx509_ca_tbs_init(context, &tbs);
1690 if (ret)
1691 hx509_err(context, 1, ret, "hx509_ca_tbs_init");
1693 if (opt->template_certificate_string) {
1694 hx509_cert template;
1695 hx509_certs tcerts;
1696 int flags;
1698 ret = hx509_certs_init(context, opt->template_certificate_string, 0,
1699 NULL, &tcerts);
1700 if (ret)
1701 hx509_err(context, 1, ret,
1702 "hx509_certs_init: %s", opt->template_certificate_string);
1704 ret = hx509_get_one_cert(context, tcerts, &template);
1706 hx509_certs_free(&tcerts);
1707 if (ret)
1708 hx509_err(context, 1, ret, "no template certificate found");
1710 flags = parse_units(opt->template_fields_string,
1711 hx509_ca_tbs_template_units(), "");
1713 ret = hx509_ca_tbs_set_template(context, tbs, flags, template);
1714 if (ret)
1715 hx509_err(context, 1, ret, "hx509_ca_tbs_set_template");
1717 hx509_cert_free(template);
1720 if (opt->serial_number_string) {
1721 heim_integer serialNumber;
1723 ret = der_parse_hex_heim_integer(opt->serial_number_string,
1724 &serialNumber);
1725 if (ret)
1726 err(1, "der_parse_hex_heim_integer");
1727 ret = hx509_ca_tbs_set_serialnumber(context, tbs, &serialNumber);
1728 if (ret)
1729 hx509_err(context, 1, ret, "hx509_ca_tbs_init");
1730 der_free_heim_integer(&serialNumber);
1733 if (spki.subjectPublicKey.length) {
1734 ret = hx509_ca_tbs_set_spki(context, tbs, &spki);
1735 if (ret)
1736 hx509_err(context, 1, ret, "hx509_ca_tbs_set_spki");
1739 if (subject) {
1740 ret = hx509_ca_tbs_set_subject(context, tbs, subject);
1741 if (ret)
1742 hx509_err(context, 1, ret, "hx509_ca_tbs_set_subject");
1745 if (opt->crl_uri_string) {
1746 ret = hx509_ca_tbs_add_crl_dp_uri(context, tbs,
1747 opt->crl_uri_string, NULL);
1748 if (ret)
1749 hx509_err(context, 1, ret, "hx509_ca_tbs_add_crl_dp_uri");
1752 eval_types(context, tbs, opt);
1754 if (opt->issue_ca_flag) {
1755 ret = hx509_ca_tbs_set_ca(context, tbs, opt->path_length_integer);
1756 if (ret)
1757 hx509_err(context, 1, ret, "hx509_ca_tbs_set_ca");
1759 if (opt->issue_proxy_flag) {
1760 ret = hx509_ca_tbs_set_proxy(context, tbs, opt->path_length_integer);
1761 if (ret)
1762 hx509_err(context, 1, ret, "hx509_ca_tbs_set_proxy");
1764 if (opt->domain_controller_flag) {
1765 hx509_ca_tbs_set_domaincontroller(context, tbs);
1766 if (ret)
1767 hx509_err(context, 1, ret, "hx509_ca_tbs_set_domaincontroller");
1770 if (delta) {
1771 ret = hx509_ca_tbs_set_notAfter_lifetime(context, tbs, delta);
1772 if (ret)
1773 hx509_err(context, 1, ret, "hx509_ca_tbs_set_notAfter_lifetime");
1776 if (opt->self_signed_flag) {
1777 ret = hx509_ca_sign_self(context, tbs, private_key, &cert);
1778 if (ret)
1779 hx509_err(context, 1, ret, "hx509_ca_sign_self");
1780 } else {
1781 ret = hx509_ca_sign(context, tbs, signer, &cert);
1782 if (ret)
1783 hx509_err(context, 1, ret, "hx509_ca_sign");
1786 if (cert_key) {
1787 ret = _hx509_cert_assign_key(cert, cert_key);
1788 if (ret)
1789 hx509_err(context, 1, ret, "_hx509_cert_assign_key");
1793 hx509_certs certs;
1795 ret = hx509_certs_init(context, opt->certificate_string,
1796 HX509_CERTS_CREATE, NULL, &certs);
1797 if (ret)
1798 hx509_err(context, 1, ret, "hx509_certs_init");
1800 ret = hx509_certs_add(context, certs, cert);
1801 if (ret)
1802 hx509_err(context, 1, ret, "hx509_certs_add");
1804 ret = hx509_certs_store(context, certs, 0, NULL);
1805 if (ret)
1806 hx509_err(context, 1, ret, "hx509_certs_store");
1808 hx509_certs_free(&certs);
1811 if (subject)
1812 hx509_name_free(&subject);
1813 if (signer)
1814 hx509_cert_free(signer);
1815 hx509_cert_free(cert);
1816 free_SubjectPublicKeyInfo(&spki);
1818 if (private_key != cert_key)
1819 _hx509_private_key_free(&private_key);
1820 _hx509_private_key_free(&cert_key);
1822 hx509_ca_tbs_free(&tbs);
1824 return 0;
1827 static int
1828 test_one_cert(hx509_context hxcontext, void *ctx, hx509_cert cert)
1830 heim_octet_string sd, c;
1831 hx509_verify_ctx vctx = ctx;
1832 hx509_certs signer = NULL;
1833 heim_oid type;
1834 int ret;
1836 if (_hx509_cert_private_key(cert) == NULL)
1837 return 0;
1839 ret = hx509_cms_create_signed_1(context, 0, NULL, NULL, 0,
1840 NULL, cert, NULL, NULL, NULL, &sd);
1841 if (ret)
1842 errx(1, "hx509_cms_create_signed_1");
1844 ret = hx509_cms_verify_signed(context, vctx, sd.data, sd.length,
1845 NULL, NULL, &type, &c, &signer);
1846 free(sd.data);
1847 if (ret)
1848 hx509_err(context, 1, ret, "hx509_cms_verify_signed");
1850 printf("create-signature verify-sigature done\n");
1852 free(c.data);
1854 return 0;
1858 test_crypto(struct test_crypto_options *opt, int argc, char ** argv)
1860 hx509_verify_ctx vctx;
1861 hx509_certs certs;
1862 hx509_lock lock;
1863 int i, ret;
1865 hx509_lock_init(context, &lock);
1866 lock_strings(lock, &opt->pass_strings);
1868 ret = hx509_certs_init(context, "MEMORY:test-crypto", 0, NULL, &certs);
1870 for (i = 0; i < argc; i++) {
1871 ret = hx509_certs_append(context, certs, lock, argv[i]);
1872 if (ret)
1873 hx509_err(context, 1, ret, "hx509_certs_append");
1876 ret = hx509_verify_init_ctx(context, &vctx);
1877 if (ret)
1878 hx509_err(context, 1, ret, "hx509_verify_init_ctx");
1880 hx509_verify_attach_anchors(vctx, certs);
1882 ret = hx509_certs_iter(context, certs, test_one_cert, vctx);
1884 hx509_certs_free(&certs);
1886 return 0;
1890 statistic_print(struct statistic_print_options*opt, int argc, char **argv)
1892 int type = 0;
1894 if (stat_file_string == NULL)
1895 errx(1, "no stat file");
1897 if (opt->type_integer)
1898 type = opt->type_integer;
1900 hx509_query_unparse_stats(context, type, stdout);
1901 return 0;
1909 crl_sign(struct crl_sign_options *opt, int argc, char **argv)
1911 hx509_crl crl;
1912 heim_octet_string os;
1913 hx509_cert signer = NULL;
1914 hx509_lock lock;
1915 int ret;
1917 hx509_lock_init(context, &lock);
1918 lock_strings(lock, &opt->pass_strings);
1920 ret = hx509_crl_alloc(context, &crl);
1921 if (ret)
1922 errx(1, "crl alloc");
1924 if (opt->signer_string == NULL)
1925 errx(1, "signer missing");
1928 hx509_certs certs = NULL;
1929 hx509_query *q;
1931 ret = hx509_certs_init(context, opt->signer_string, 0,
1932 NULL, &certs);
1933 if (ret)
1934 hx509_err(context, 1, ret,
1935 "hx509_certs_init: %s", opt->signer_string);
1937 ret = hx509_query_alloc(context, &q);
1938 if (ret)
1939 hx509_err(context, 1, ret, "hx509_query_alloc: %d", ret);
1941 hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
1943 ret = hx509_certs_find(context, certs, q, &signer);
1944 hx509_query_free(context, q);
1945 hx509_certs_free(&certs);
1946 if (ret)
1947 hx509_err(context, 1, ret, "no signer certificate found");
1950 if (opt->lifetime_string) {
1951 int delta;
1953 delta = parse_time(opt->lifetime_string, "day");
1954 if (delta < 0)
1955 errx(1, "Invalid lifetime: %s", opt->lifetime_string);
1957 hx509_crl_lifetime(context, crl, delta);
1961 hx509_certs revoked = NULL;
1962 int i;
1964 ret = hx509_certs_init(context, "MEMORY:revoked-certs", 0,
1965 NULL, &revoked);
1967 for (i = 0; i < argc; i++) {
1968 ret = hx509_certs_append(context, revoked, lock, argv[i]);
1969 if (ret)
1970 hx509_err(context, 1, ret, "hx509_certs_append: %s", argv[i]);
1973 hx509_crl_add_revoked_certs(context, crl, revoked);
1974 hx509_certs_free(&revoked);
1977 hx509_crl_sign(context, signer, crl, &os);
1979 if (opt->crl_file_string)
1980 rk_dumpdata(opt->crl_file_string, os.data, os.length);
1982 free(os.data);
1984 hx509_crl_free(context, &crl);
1985 hx509_cert_free(signer);
1986 hx509_lock_free(lock);
1988 return 0;
1996 help(void *opt, int argc, char **argv)
1998 sl_slc_help(commands, argc, argv);
1999 return 0;
2003 main(int argc, char **argv)
2005 int ret, optidx = 0;
2007 setprogname (argv[0]);
2009 if(getarg(args, num_args, argc, argv, &optidx))
2010 usage(1);
2011 if(help_flag)
2012 usage(0);
2013 if(version_flag) {
2014 print_version(NULL);
2015 exit(0);
2017 argv += optidx;
2018 argc -= optidx;
2020 if (argc == 0)
2021 usage(1);
2023 ret = hx509_context_init(&context);
2024 if (ret)
2025 errx(1, "hx509_context_init failed with %d", ret);
2027 if (stat_file_string)
2028 hx509_query_statistic_file(context, stat_file_string);
2030 ret = sl_command(commands, argc, argv);
2031 if(ret == -1)
2032 warnx ("unrecognized command: %s", argv[0]);
2034 hx509_context_free(&context);
2036 return ret;