No empty .Rs/.Re
[netbsd-mini2440.git] / crypto / dist / heimdal / lib / hx509 / hxtool.c
blob08e7fb7186da260e8b69c12b49e95d0892099608
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("$Heimdal: hxtool.c 22333 2007-12-17 01:03:43Z lha $"
36 "$NetBSD$");
38 #include <hxtool-commands.h>
39 #include <sl.h>
40 #include <parse_time.h>
42 static hx509_context context;
44 static char *stat_file_string;
45 static int version_flag;
46 static int help_flag;
48 struct getargs args[] = {
49 { "statistic-file", 0, arg_string, &stat_file_string },
50 { "version", 0, arg_flag, &version_flag },
51 { "help", 0, arg_flag, &help_flag }
53 int num_args = sizeof(args) / sizeof(args[0]);
55 static void
56 usage(int code)
58 arg_printusage(args, num_args, NULL, "command");
59 printf("Use \"%s help\" to get more help\n", getprogname());
60 exit(code);
67 static void
68 lock_strings(hx509_lock lock, getarg_strings *pass)
70 int i;
71 for (i = 0; i < pass->num_strings; i++) {
72 int ret = hx509_lock_command_string(lock, pass->strings[i]);
73 if (ret)
74 errx(1, "hx509_lock_command_string: %s: %d",
75 pass->strings[i], ret);
83 static void
84 certs_strings(hx509_context context, const char *type, hx509_certs certs,
85 hx509_lock lock, const getarg_strings *s)
87 int i, ret;
89 for (i = 0; i < s->num_strings; i++) {
90 ret = hx509_certs_append(context, certs, lock, s->strings[i]);
91 if (ret)
92 hx509_err(context, 1, ret,
93 "hx509_certs_append: %s %s", type, s->strings[i]);
101 static void
102 parse_oid(const char *str, const heim_oid *def, heim_oid *oid)
104 int ret;
105 if (str)
106 ret = der_parse_heim_oid (str, " .", oid);
107 else
108 ret = der_copy_oid(def, oid);
109 if (ret)
110 errx(1, "parse_oid failed for: %s", str ? str : "default oid");
117 static void
118 peer_strings(hx509_context context,
119 hx509_peer_info *peer,
120 const getarg_strings *s)
122 AlgorithmIdentifier *val;
123 int ret, i;
125 ret = hx509_peer_info_alloc(context, peer);
126 if (ret)
127 hx509_err(context, 1, ret, "hx509_peer_info_alloc");
129 val = calloc(s->num_strings, sizeof(*val));
130 if (val == NULL)
131 err(1, "malloc");
133 for (i = 0; i < s->num_strings; i++)
134 parse_oid(s->strings[i], NULL, &val[i].algorithm);
136 ret = hx509_peer_info_set_cms_algs(context, *peer, val, s->num_strings);
137 if (ret)
138 hx509_err(context, 1, ret, "hx509_peer_info_set_cms_algs");
140 for (i = 0; i < s->num_strings; i++)
141 free_AlgorithmIdentifier(&val[i]);
142 free(val);
150 cms_verify_sd(struct cms_verify_sd_options *opt, int argc, char **argv)
152 hx509_verify_ctx ctx = NULL;
153 heim_oid type;
154 heim_octet_string c, co, signeddata, *sd = NULL;
155 hx509_certs store = NULL;
156 hx509_certs signers = NULL;
157 hx509_certs anchors = NULL;
158 hx509_lock lock;
159 int ret;
161 size_t sz;
162 void *p;
164 if (opt->missing_revoke_flag)
165 hx509_context_set_missing_revoke(context, 1);
167 hx509_lock_init(context, &lock);
168 lock_strings(lock, &opt->pass_strings);
170 ret = _hx509_map_file(argv[0], &p, &sz, NULL);
171 if (ret)
172 err(1, "map_file: %s: %d", argv[0], ret);
174 if (opt->signed_content_string) {
175 ret = _hx509_map_file_os(opt->signed_content_string, &signeddata, NULL);
176 if (ret)
177 err(1, "map_file: %s: %d", opt->signed_content_string, ret);
178 sd = &signeddata;
181 ret = hx509_verify_init_ctx(context, &ctx);
183 ret = hx509_certs_init(context, "MEMORY:cms-anchors", 0, NULL, &anchors);
184 ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &store);
186 certs_strings(context, "anchors", anchors, lock, &opt->anchors_strings);
187 certs_strings(context, "store", store, lock, &opt->certificate_strings);
189 co.data = p;
190 co.length = sz;
192 if (opt->content_info_flag) {
193 heim_octet_string uwco;
194 heim_oid oid;
196 ret = hx509_cms_unwrap_ContentInfo(&co, &oid, &uwco, NULL);
197 if (ret)
198 errx(1, "hx509_cms_unwrap_ContentInfo: %d", ret);
200 if (der_heim_oid_cmp(&oid, oid_id_pkcs7_signedData()) != 0)
201 errx(1, "Content is not SignedData");
202 der_free_oid(&oid);
204 co = uwco;
207 hx509_verify_attach_anchors(ctx, anchors);
209 ret = hx509_cms_verify_signed(context, ctx, co.data, co.length, sd,
210 store, &type, &c, &signers);
211 if (co.data != p)
212 der_free_octet_string(&co);
213 if (ret)
214 hx509_err(context, 1, ret, "hx509_cms_verify_signed");
217 char *str;
218 der_print_heim_oid(&type, '.', &str);
219 printf("type: %s\n", str);
220 free(str);
221 der_free_oid(&type);
223 printf("signers:\n");
224 hx509_certs_iter(context, signers, hx509_ci_print_names, stdout);
226 hx509_verify_destroy_ctx(ctx);
228 hx509_certs_free(&store);
229 hx509_certs_free(&signers);
230 hx509_certs_free(&anchors);
232 hx509_lock_free(lock);
234 ret = _hx509_write_file(argv[1], c.data, c.length);
235 if (ret)
236 errx(1, "hx509_write_file: %d", ret);
238 der_free_octet_string(&c);
239 _hx509_unmap_file(p, sz);
240 if (sd)
241 _hx509_unmap_file_os(sd);
243 return 0;
247 cms_create_sd(struct cms_create_sd_options *opt, int argc, char **argv)
249 heim_oid contentType;
250 hx509_peer_info peer = NULL;
251 heim_octet_string o;
252 hx509_query *q;
253 hx509_lock lock;
254 hx509_certs store, pool, anchors;
255 hx509_cert cert;
256 size_t sz;
257 void *p;
258 int ret, flags = 0;
259 char *signer_name = NULL;
261 memset(&contentType, 0, sizeof(contentType));
263 if (argc < 2)
264 errx(1, "argc < 2");
266 hx509_lock_init(context, &lock);
267 lock_strings(lock, &opt->pass_strings);
269 ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &store);
270 ret = hx509_certs_init(context, "MEMORY:cert-pool", 0, NULL, &pool);
272 certs_strings(context, "store", store, lock, &opt->certificate_strings);
273 certs_strings(context, "pool", pool, lock, &opt->pool_strings);
275 if (opt->anchors_strings.num_strings) {
276 ret = hx509_certs_init(context, "MEMORY:cert-anchors",
277 0, NULL, &anchors);
278 certs_strings(context, "anchors", anchors, lock, &opt->anchors_strings);
279 } else
280 anchors = NULL;
282 if (opt->detached_signature_flag)
283 flags |= HX509_CMS_SIGATURE_DETACHED;
284 if (opt->id_by_name_flag)
285 flags |= HX509_CMS_SIGATURE_ID_NAME;
287 ret = hx509_query_alloc(context, &q);
288 if (ret)
289 errx(1, "hx509_query_alloc: %d", ret);
291 hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
292 hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE);
294 if (opt->signer_string)
295 hx509_query_match_friendly_name(q, opt->signer_string);
297 ret = hx509_certs_find(context, store, q, &cert);
298 hx509_query_free(context, q);
299 if (ret)
300 hx509_err(context, 1, ret, "hx509_certs_find");
302 ret = _hx509_map_file(argv[0], &p, &sz, NULL);
303 if (ret)
304 err(1, "map_file: %s: %d", argv[0], ret);
306 if (opt->peer_alg_strings.num_strings)
307 peer_strings(context, &peer, &opt->peer_alg_strings);
309 parse_oid(opt->content_type_string, oid_id_pkcs7_data(), &contentType);
311 ret = hx509_cms_create_signed_1(context,
312 flags,
313 &contentType,
315 sz,
316 NULL,
317 cert,
318 peer,
319 anchors,
320 pool,
321 &o);
322 if (ret)
323 errx(1, "hx509_cms_create_signed: %d", ret);
326 hx509_name name;
328 ret = hx509_cert_get_subject(cert, &name);
329 if (ret)
330 errx(1, "hx509_cert_get_subject");
332 ret = hx509_name_to_string(name, &signer_name);
333 hx509_name_free(&name);
334 if (ret)
335 errx(1, "hx509_name_to_string");
339 hx509_certs_free(&anchors);
340 hx509_certs_free(&pool);
341 hx509_cert_free(cert);
342 hx509_certs_free(&store);
343 _hx509_unmap_file(p, sz);
344 hx509_lock_free(lock);
345 hx509_peer_info_free(peer);
346 der_free_oid(&contentType);
348 if (opt->content_info_flag) {
349 heim_octet_string wo;
351 ret = hx509_cms_wrap_ContentInfo(oid_id_pkcs7_signedData(), &o, &wo);
352 if (ret)
353 errx(1, "hx509_cms_wrap_ContentInfo: %d", ret);
355 der_free_octet_string(&o);
356 o = wo;
359 if (opt->pem_flag) {
360 hx509_pem_header *header = NULL;
361 FILE *f;
363 hx509_pem_add_header(&header, "Content-disposition",
364 opt->detached_signature_flag ? "detached" : "inline");
365 hx509_pem_add_header(&header, "Signer", signer_name);
367 f = fopen(argv[1], "w");
368 if (f == NULL)
369 err(1, "open %s", argv[1]);
371 ret = hx509_pem_write(context, "CMS SIGNEDDATA", header, f,
372 o.data, o.length);
373 fclose(f);
374 hx509_pem_free_header(header);
375 if (ret)
376 errx(1, "hx509_pem_write: %d", ret);
378 } else {
379 ret = _hx509_write_file(argv[1], o.data, o.length);
380 if (ret)
381 errx(1, "hx509_write_file: %d", ret);
384 free(signer_name);
385 free(o.data);
387 return 0;
391 cms_unenvelope(struct cms_unenvelope_options *opt, int argc, char **argv)
393 heim_oid contentType = { 0, NULL };
394 heim_octet_string o, co;
395 hx509_certs certs;
396 size_t sz;
397 void *p;
398 int ret;
399 hx509_lock lock;
401 hx509_lock_init(context, &lock);
402 lock_strings(lock, &opt->pass_strings);
404 ret = _hx509_map_file(argv[0], &p, &sz, NULL);
405 if (ret)
406 err(1, "map_file: %s: %d", argv[0], ret);
408 co.data = p;
409 co.length = sz;
411 if (opt->content_info_flag) {
412 heim_octet_string uwco;
413 heim_oid oid;
415 ret = hx509_cms_unwrap_ContentInfo(&co, &oid, &uwco, NULL);
416 if (ret)
417 errx(1, "hx509_cms_unwrap_ContentInfo: %d", ret);
419 if (der_heim_oid_cmp(&oid, oid_id_pkcs7_envelopedData()) != 0)
420 errx(1, "Content is not SignedData");
421 der_free_oid(&oid);
423 co = uwco;
426 ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &certs);
427 if (ret)
428 errx(1, "hx509_certs_init: MEMORY: %d", ret);
430 certs_strings(context, "store", certs, lock, &opt->certificate_strings);
432 ret = hx509_cms_unenvelope(context, certs, 0, co.data, co.length,
433 NULL, &contentType, &o);
434 if (co.data != p)
435 der_free_octet_string(&co);
436 if (ret)
437 hx509_err(context, 1, ret, "hx509_cms_unenvelope");
439 _hx509_unmap_file(p, sz);
440 hx509_lock_free(lock);
441 hx509_certs_free(&certs);
442 der_free_oid(&contentType);
444 ret = _hx509_write_file(argv[1], o.data, o.length);
445 if (ret)
446 errx(1, "hx509_write_file: %d", ret);
448 der_free_octet_string(&o);
450 return 0;
454 cms_create_enveloped(struct cms_envelope_options *opt, int argc, char **argv)
456 heim_oid contentType;
457 heim_octet_string o;
458 const heim_oid *enctype = NULL;
459 hx509_query *q;
460 hx509_certs certs;
461 hx509_cert cert;
462 int ret;
463 size_t sz;
464 void *p;
465 hx509_lock lock;
467 memset(&contentType, 0, sizeof(contentType));
469 hx509_lock_init(context, &lock);
470 lock_strings(lock, &opt->pass_strings);
472 ret = _hx509_map_file(argv[0], &p, &sz, NULL);
473 if (ret)
474 err(1, "map_file: %s: %d", argv[0], ret);
476 ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &certs);
478 certs_strings(context, "store", certs, lock, &opt->certificate_strings);
480 if (opt->encryption_type_string) {
481 enctype = hx509_crypto_enctype_by_name(opt->encryption_type_string);
482 if (enctype == NULL)
483 errx(1, "encryption type: %s no found",
484 opt->encryption_type_string);
487 ret = hx509_query_alloc(context, &q);
488 if (ret)
489 errx(1, "hx509_query_alloc: %d", ret);
491 hx509_query_match_option(q, HX509_QUERY_OPTION_KU_ENCIPHERMENT);
493 ret = hx509_certs_find(context, certs, q, &cert);
494 hx509_query_free(context, q);
495 if (ret)
496 errx(1, "hx509_certs_find: %d", ret);
498 parse_oid(opt->content_type_string, oid_id_pkcs7_data(), &contentType);
500 ret = hx509_cms_envelope_1(context, 0, cert, p, sz, enctype,
501 &contentType, &o);
502 if (ret)
503 errx(1, "hx509_cms_envelope_1: %d", ret);
505 hx509_cert_free(cert);
506 hx509_certs_free(&certs);
507 _hx509_unmap_file(p, sz);
508 der_free_oid(&contentType);
510 if (opt->content_info_flag) {
511 heim_octet_string wo;
513 ret = hx509_cms_wrap_ContentInfo(oid_id_pkcs7_envelopedData(), &o, &wo);
514 if (ret)
515 errx(1, "hx509_cms_wrap_ContentInfo: %d", ret);
517 der_free_octet_string(&o);
518 o = wo;
521 hx509_lock_free(lock);
523 ret = _hx509_write_file(argv[1], o.data, o.length);
524 if (ret)
525 errx(1, "hx509_write_file: %d", ret);
527 der_free_octet_string(&o);
529 return 0;
532 static void
533 print_certificate(hx509_context hxcontext, hx509_cert cert, int verbose)
535 hx509_name name;
536 const char *fn;
537 char *str;
538 int ret;
540 fn = hx509_cert_get_friendly_name(cert);
541 if (fn)
542 printf(" friendly name: %s\n", fn);
543 printf(" private key: %s\n",
544 _hx509_cert_private_key(cert) ? "yes" : "no");
546 ret = hx509_cert_get_issuer(cert, &name);
547 hx509_name_to_string(name, &str);
548 hx509_name_free(&name);
549 printf(" issuer: \"%s\"\n", str);
550 free(str);
552 ret = hx509_cert_get_subject(cert, &name);
553 hx509_name_to_string(name, &str);
554 hx509_name_free(&name);
555 printf(" subject: \"%s\"\n", str);
556 free(str);
559 heim_integer serialNumber;
561 hx509_cert_get_serialnumber(cert, &serialNumber);
562 der_print_hex_heim_integer(&serialNumber, &str);
563 der_free_heim_integer(&serialNumber);
564 printf(" serial: %s\n", str);
565 free(str);
568 printf(" keyusage: ");
569 ret = hx509_cert_keyusage_print(hxcontext, cert, &str);
570 if (ret == 0) {
571 printf("%s\n", str);
572 free(str);
573 } else
574 printf("no");
576 if (verbose) {
577 hx509_validate_ctx vctx;
579 hx509_validate_ctx_init(hxcontext, &vctx);
580 hx509_validate_ctx_set_print(vctx, hx509_print_stdout, stdout);
581 hx509_validate_ctx_add_flags(vctx, HX509_VALIDATE_F_VALIDATE);
582 hx509_validate_ctx_add_flags(vctx, HX509_VALIDATE_F_VERBOSE);
584 hx509_validate_cert(hxcontext, vctx, cert);
586 hx509_validate_ctx_free(vctx);
591 struct print_s {
592 int counter;
593 int verbose;
596 static int
597 print_f(hx509_context hxcontext, void *ctx, hx509_cert cert)
599 struct print_s *s = ctx;
601 printf("cert: %d\n", s->counter++);
602 print_certificate(context, cert, s->verbose);
604 return 0;
608 pcert_print(struct print_options *opt, int argc, char **argv)
610 hx509_certs certs;
611 hx509_lock lock;
612 struct print_s s;
614 s.counter = 0;
615 s.verbose = opt->content_flag;
617 hx509_lock_init(context, &lock);
618 lock_strings(lock, &opt->pass_strings);
620 while(argc--) {
621 int ret;
622 ret = hx509_certs_init(context, argv[0], 0, lock, &certs);
623 if (ret)
624 hx509_err(context, 1, ret, "hx509_certs_init");
625 if (opt->info_flag)
626 hx509_certs_info(context, certs, NULL, NULL);
627 hx509_certs_iter(context, certs, print_f, &s);
628 hx509_certs_free(&certs);
629 argv++;
632 hx509_lock_free(lock);
634 return 0;
638 static int
639 validate_f(hx509_context hxcontext, void *ctx, hx509_cert c)
641 hx509_validate_cert(hxcontext, ctx, c);
642 return 0;
646 pcert_validate(struct validate_options *opt, int argc, char **argv)
648 hx509_validate_ctx ctx;
649 hx509_certs certs;
650 hx509_lock lock;
652 hx509_lock_init(context, &lock);
653 lock_strings(lock, &opt->pass_strings);
655 hx509_validate_ctx_init(context, &ctx);
656 hx509_validate_ctx_set_print(ctx, hx509_print_stdout, stdout);
657 hx509_validate_ctx_add_flags(ctx, HX509_VALIDATE_F_VALIDATE);
659 while(argc--) {
660 int ret;
661 ret = hx509_certs_init(context, argv[0], 0, lock, &certs);
662 if (ret)
663 errx(1, "hx509_certs_init: %d", ret);
664 hx509_certs_iter(context, certs, validate_f, ctx);
665 hx509_certs_free(&certs);
666 argv++;
668 hx509_validate_ctx_free(ctx);
670 hx509_lock_free(lock);
672 return 0;
676 certificate_copy(struct certificate_copy_options *opt, int argc, char **argv)
678 hx509_certs certs;
679 hx509_lock lock;
680 int ret;
682 hx509_lock_init(context, &lock);
683 lock_strings(lock, &opt->in_pass_strings);
685 ret = hx509_certs_init(context, argv[argc - 1],
686 HX509_CERTS_CREATE, lock, &certs);
687 if (ret)
688 hx509_err(context, 1, ret, "hx509_certs_init");
690 while(argc-- > 1) {
691 int ret;
692 ret = hx509_certs_append(context, certs, lock, argv[0]);
693 if (ret)
694 hx509_err(context, 1, ret, "hx509_certs_append");
695 argv++;
698 ret = hx509_certs_store(context, certs, 0, NULL);
699 if (ret)
700 hx509_err(context, 1, ret, "hx509_certs_store");
702 hx509_certs_free(&certs);
703 hx509_lock_free(lock);
705 return 0;
708 struct verify {
709 hx509_verify_ctx ctx;
710 hx509_certs chain;
711 const char *hostname;
712 int errors;
715 static int
716 verify_f(hx509_context hxcontext, void *ctx, hx509_cert c)
718 struct verify *v = ctx;
719 int ret;
721 ret = hx509_verify_path(hxcontext, v->ctx, c, v->chain);
722 if (ret) {
723 char *s = hx509_get_error_string(hxcontext, ret);
724 printf("verify_path: %s: %d\n", s, ret);
725 hx509_free_error_string(s);
726 v->errors++;
727 } else
728 printf("path ok\n");
730 if (v->hostname) {
731 ret = hx509_verify_hostname(hxcontext, c, 0, HX509_HN_HOSTNAME,
732 v->hostname, NULL, 0);
733 if (ret) {
734 printf("verify_hostname: %d\n", ret);
735 v->errors++;
739 return 0;
743 pcert_verify(struct verify_options *opt, int argc, char **argv)
745 hx509_certs anchors, chain, certs;
746 hx509_revoke_ctx revoke_ctx;
747 hx509_verify_ctx ctx;
748 struct verify v;
749 int ret;
751 memset(&v, 0, sizeof(v));
753 if (opt->missing_revoke_flag)
754 hx509_context_set_missing_revoke(context, 1);
756 ret = hx509_verify_init_ctx(context, &ctx);
757 ret = hx509_certs_init(context, "MEMORY:anchors", 0, NULL, &anchors);
758 ret = hx509_certs_init(context, "MEMORY:chain", 0, NULL, &chain);
759 ret = hx509_certs_init(context, "MEMORY:certs", 0, NULL, &certs);
761 if (opt->allow_proxy_certificate_flag)
762 hx509_verify_set_proxy_certificate(ctx, 1);
764 if (opt->time_string) {
765 const char *p;
766 struct tm tm;
767 time_t t;
769 memset(&tm, 0, sizeof(tm));
771 p = strptime (opt->time_string, "%Y-%m-%d", &tm);
772 if (p == NULL)
773 errx(1, "Failed to parse time %s, need to be on format %%Y-%%m-%%d",
774 opt->time_string);
776 t = tm2time (tm, 0);
778 hx509_verify_set_time(ctx, t);
781 if (opt->hostname_string)
782 v.hostname = opt->hostname_string;
783 if (opt->max_depth_integer)
784 hx509_verify_set_max_depth(ctx, opt->max_depth_integer);
786 ret = hx509_revoke_init(context, &revoke_ctx);
787 if (ret)
788 errx(1, "hx509_revoke_init: %d", ret);
790 while(argc--) {
791 char *s = *argv++;
793 if (strncmp(s, "chain:", 6) == 0) {
794 s += 6;
796 ret = hx509_certs_append(context, chain, NULL, s);
797 if (ret)
798 hx509_err(context, 1, ret, "hx509_certs_append: chain: %s: %d", s, ret);
800 } else if (strncmp(s, "anchor:", 7) == 0) {
801 s += 7;
803 ret = hx509_certs_append(context, anchors, NULL, s);
804 if (ret)
805 hx509_err(context, 1, ret, "hx509_certs_append: anchor: %s: %d", s, ret);
807 } else if (strncmp(s, "cert:", 5) == 0) {
808 s += 5;
810 ret = hx509_certs_append(context, certs, NULL, s);
811 if (ret)
812 hx509_err(context, 1, ret, "hx509_certs_append: certs: %s: %d",
813 s, ret);
815 } else if (strncmp(s, "crl:", 4) == 0) {
816 s += 4;
818 ret = hx509_revoke_add_crl(context, revoke_ctx, s);
819 if (ret)
820 errx(1, "hx509_revoke_add_crl: %s: %d", s, ret);
822 } else if (strncmp(s, "ocsp:", 4) == 0) {
823 s += 5;
825 ret = hx509_revoke_add_ocsp(context, revoke_ctx, s);
826 if (ret)
827 errx(1, "hx509_revoke_add_ocsp: %s: %d", s, ret);
829 } else {
830 errx(1, "unknown option to verify: `%s'\n", s);
834 hx509_verify_attach_anchors(ctx, anchors);
835 hx509_verify_attach_revoke(ctx, revoke_ctx);
837 v.ctx = ctx;
838 v.chain = chain;
840 hx509_certs_iter(context, certs, verify_f, &v);
842 hx509_verify_destroy_ctx(ctx);
844 hx509_certs_free(&certs);
845 hx509_certs_free(&chain);
846 hx509_certs_free(&anchors);
848 hx509_revoke_free(&revoke_ctx);
850 if (v.errors) {
851 printf("failed verifing %d checks\n", v.errors);
852 return 1;
855 return 0;
859 query(struct query_options *opt, int argc, char **argv)
861 hx509_lock lock;
862 hx509_query *q;
863 hx509_certs certs;
864 hx509_cert c;
865 int ret;
867 ret = hx509_query_alloc(context, &q);
868 if (ret)
869 errx(1, "hx509_query_alloc: %d", ret);
871 hx509_lock_init(context, &lock);
872 lock_strings(lock, &opt->pass_strings);
874 ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &certs);
876 while (argc > 0) {
878 ret = hx509_certs_append(context, certs, lock, argv[0]);
879 if (ret)
880 errx(1, "hx509_certs_append: %s: %d", argv[0], ret);
882 argc--;
883 argv++;
886 if (opt->friendlyname_string)
887 hx509_query_match_friendly_name(q, opt->friendlyname_string);
889 if (opt->private_key_flag)
890 hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
892 if (opt->keyEncipherment_flag)
893 hx509_query_match_option(q, HX509_QUERY_OPTION_KU_ENCIPHERMENT);
895 if (opt->digitalSignature_flag)
896 hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE);
898 ret = hx509_certs_find(context, certs, q, &c);
899 hx509_query_free(context, q);
900 if (ret)
901 printf("no match found (%d)\n", ret);
902 else {
903 printf("match found\n");
904 if (opt->print_flag)
905 print_certificate(context, c, 0);
908 hx509_cert_free(c);
909 hx509_certs_free(&certs);
911 hx509_lock_free(lock);
913 return ret;
917 ocsp_fetch(struct ocsp_fetch_options *opt, int argc, char **argv)
919 hx509_certs reqcerts, pool;
920 heim_octet_string req, nonce_data, *nonce = &nonce_data;
921 hx509_lock lock;
922 int i, ret;
923 char *file;
924 const char *url = "/";
926 memset(&nonce, 0, sizeof(nonce));
928 hx509_lock_init(context, &lock);
929 lock_strings(lock, &opt->pass_strings);
931 /* no nonce */
932 if (!opt->nonce_flag)
933 nonce = NULL;
935 if (opt->url_path_string)
936 url = opt->url_path_string;
938 ret = hx509_certs_init(context, "MEMORY:ocsp-pool", 0, NULL, &pool);
940 certs_strings(context, "ocsp-pool", pool, lock, &opt->pool_strings);
942 file = argv[0];
944 ret = hx509_certs_init(context, "MEMORY:ocsp-req", 0, NULL, &reqcerts);
946 for (i = 1; i < argc; i++) {
947 ret = hx509_certs_append(context, reqcerts, lock, argv[i]);
948 if (ret)
949 errx(1, "hx509_certs_append: req: %s: %d", argv[i], ret);
952 ret = hx509_ocsp_request(context, reqcerts, pool, NULL, NULL, &req, nonce);
953 if (ret)
954 errx(1, "hx509_ocsp_request: req: %d", ret);
957 FILE *f;
959 f = fopen(file, "w");
960 if (f == NULL)
961 abort();
963 fprintf(f,
964 "POST %s HTTP/1.0\r\n"
965 "Content-Type: application/ocsp-request\r\n"
966 "Content-Length: %ld\r\n"
967 "\r\n",
968 url,
969 (unsigned long)req.length);
970 fwrite(req.data, req.length, 1, f);
971 fclose(f);
974 if (nonce)
975 der_free_octet_string(nonce);
977 hx509_certs_free(&reqcerts);
978 hx509_certs_free(&pool);
980 return 0;
984 ocsp_print(struct ocsp_print_options *opt, int argc, char **argv)
986 hx509_revoke_ocsp_print(context, argv[0], stdout);
987 return 0;
994 static int
995 verify_o(hx509_context hxcontext, void *ctx, hx509_cert c)
997 heim_octet_string *os = ctx;
998 time_t expiration;
999 int ret;
1001 ret = hx509_ocsp_verify(context, 0, c, 0,
1002 os->data, os->length, &expiration);
1003 if (ret) {
1004 char *s = hx509_get_error_string(hxcontext, ret);
1005 printf("ocsp_verify: %s: %d\n", s, ret);
1006 hx509_free_error_string(s);
1007 } else
1008 printf("expire: %d\n", (int)expiration);
1010 return ret;
1015 ocsp_verify(struct ocsp_verify_options *opt, int argc, char **argv)
1017 hx509_lock lock;
1018 hx509_certs certs;
1019 int ret, i;
1020 heim_octet_string os;
1022 hx509_lock_init(context, &lock);
1024 if (opt->ocsp_file_string == NULL)
1025 errx(1, "no ocsp file given");
1027 ret = _hx509_map_file(opt->ocsp_file_string, &os.data, &os.length, NULL);
1028 if (ret)
1029 err(1, "map_file: %s: %d", argv[0], ret);
1031 ret = hx509_certs_init(context, "MEMORY:test-certs", 0, NULL, &certs);
1033 for (i = 0; i < argc; i++) {
1034 ret = hx509_certs_append(context, certs, lock, argv[i]);
1035 if (ret)
1036 hx509_err(context, 1, ret, "hx509_certs_append: %s", argv[i]);
1039 ret = hx509_certs_iter(context, certs, verify_o, &os);
1041 hx509_certs_free(&certs);
1042 _hx509_unmap_file(os.data, os.length);
1043 hx509_lock_free(lock);
1045 return ret;
1048 static int
1049 read_private_key(const char *fn, hx509_private_key *key)
1051 hx509_private_key *keys;
1052 hx509_certs certs;
1053 int ret;
1055 *key = NULL;
1057 ret = hx509_certs_init(context, fn, 0, NULL, &certs);
1058 if (ret)
1059 hx509_err(context, 1, ret, "hx509_certs_init: %s", fn);
1061 ret = _hx509_certs_keys_get(context, certs, &keys);
1062 hx509_certs_free(&certs);
1063 if (ret)
1064 hx509_err(context, 1, ret, "hx509_certs_keys_get");
1065 if (keys[0] == NULL)
1066 errx(1, "no keys in key store: %s", fn);
1068 *key = _hx509_private_key_ref(keys[0]);
1069 _hx509_certs_keys_free(context, keys);
1071 return 0;
1074 static void
1075 get_key(const char *fn, const char *type, int optbits,
1076 hx509_private_key *signer)
1078 int ret;
1080 if (type) {
1081 BIGNUM *e;
1082 RSA *rsa;
1083 unsigned char *p0, *p;
1084 size_t len;
1085 int bits = 1024;
1087 if (fn == NULL)
1088 errx(1, "no key argument, don't know here to store key");
1090 if (strcasecmp(type, "rsa") != 0)
1091 errx(1, "can only handle rsa keys for now");
1093 e = BN_new();
1094 BN_set_word(e, 0x10001);
1096 if (optbits)
1097 bits = optbits;
1099 rsa = RSA_new();
1100 if(rsa == NULL)
1101 errx(1, "RSA_new failed");
1103 ret = RSA_generate_key_ex(rsa, bits, e, NULL);
1104 if(ret != 1)
1105 errx(1, "RSA_new failed");
1107 BN_free(e);
1109 len = i2d_RSAPrivateKey(rsa, NULL);
1111 p0 = p = malloc(len);
1112 if (p == NULL)
1113 errx(1, "out of memory");
1115 i2d_RSAPrivateKey(rsa, &p);
1117 rk_dumpdata(fn, p0, len);
1118 memset(p0, 0, len);
1119 free(p0);
1121 RSA_free(rsa);
1123 } else if (fn == NULL)
1124 err(1, "no private key");
1126 ret = read_private_key(fn, signer);
1127 if (ret)
1128 err(1, "read_private_key");
1132 request_create(struct request_create_options *opt, int argc, char **argv)
1134 heim_octet_string request;
1135 hx509_request req;
1136 int ret, i;
1137 hx509_private_key signer;
1138 SubjectPublicKeyInfo key;
1139 const char *outfile = argv[0];
1141 memset(&key, 0, sizeof(key));
1143 get_key(opt->key_string,
1144 opt->generate_key_string,
1145 opt->key_bits_integer,
1146 &signer);
1148 _hx509_request_init(context, &req);
1150 if (opt->subject_string) {
1151 hx509_name name = NULL;
1153 ret = hx509_parse_name(context, opt->subject_string, &name);
1154 if (ret)
1155 errx(1, "hx509_parse_name: %d\n", ret);
1156 _hx509_request_set_name(context, req, name);
1158 if (opt->verbose_flag) {
1159 char *s;
1160 hx509_name_to_string(name, &s);
1161 printf("%s\n", s);
1163 hx509_name_free(&name);
1166 for (i = 0; i < opt->email_strings.num_strings; i++) {
1167 ret = _hx509_request_add_email(context, req,
1168 opt->email_strings.strings[i]);
1171 for (i = 0; i < opt->dnsname_strings.num_strings; i++) {
1172 ret = _hx509_request_add_dns_name(context, req,
1173 opt->dnsname_strings.strings[i]);
1177 ret = _hx509_private_key2SPKI(context, signer, &key);
1178 if (ret)
1179 errx(1, "_hx509_private_key2SPKI: %d\n", ret);
1181 ret = _hx509_request_set_SubjectPublicKeyInfo(context,
1182 req,
1183 &key);
1184 free_SubjectPublicKeyInfo(&key);
1185 if (ret)
1186 hx509_err(context, 1, ret, "_hx509_request_set_SubjectPublicKeyInfo");
1188 ret = _hx509_request_to_pkcs10(context,
1189 req,
1190 signer,
1191 &request);
1192 if (ret)
1193 hx509_err(context, 1, ret, "_hx509_request_to_pkcs10");
1195 _hx509_private_key_free(&signer);
1196 _hx509_request_free(&req);
1198 if (ret == 0)
1199 rk_dumpdata(outfile, request.data, request.length);
1200 der_free_octet_string(&request);
1202 return 0;
1206 request_print(struct request_print_options *opt, int argc, char **argv)
1208 int ret, i;
1210 printf("request print\n");
1212 for (i = 0; i < argc; i++) {
1213 hx509_request req;
1215 ret = _hx509_request_parse(context, argv[i], &req);
1216 if (ret)
1217 hx509_err(context, 1, ret, "parse_request: %s", argv[i]);
1219 ret = _hx509_request_print(context, req, stdout);
1220 _hx509_request_free(&req);
1221 if (ret)
1222 hx509_err(context, 1, ret, "Failed to print file %s", argv[i]);
1225 return 0;
1229 info(void *opt, int argc, char **argv)
1232 ENGINE_add_conf_module();
1235 const RSA_METHOD *m = RSA_get_default_method();
1236 if (m != NULL)
1237 printf("rsa: %s\n", m->name);
1240 const DH_METHOD *m = DH_get_default_method();
1241 if (m != NULL)
1242 printf("dh: %s\n", m->name);
1245 int ret = RAND_status();
1246 printf("rand: %s\n", ret == 1 ? "ok" : "not available");
1249 return 0;
1253 random_data(void *opt, int argc, char **argv)
1255 void *ptr;
1256 int len, ret;
1258 len = parse_bytes(argv[0], "byte");
1259 if (len <= 0) {
1260 fprintf(stderr, "bad argument to random-data\n");
1261 return 1;
1264 ptr = malloc(len);
1265 if (ptr == NULL) {
1266 fprintf(stderr, "out of memory\n");
1267 return 1;
1270 ret = RAND_bytes(ptr, len);
1271 if (ret != 1) {
1272 free(ptr);
1273 fprintf(stderr, "did not get cryptographic strong random\n");
1274 return 1;
1277 fwrite(ptr, len, 1, stdout);
1278 fflush(stdout);
1280 free(ptr);
1282 return 0;
1286 crypto_available(struct crypto_available_options *opt, int argc, char **argv)
1288 AlgorithmIdentifier *val;
1289 unsigned int len, i;
1290 int ret, type;
1292 if (opt->type_string) {
1293 if (strcmp(opt->type_string, "all") == 0)
1294 type = HX509_SELECT_ALL;
1295 else if (strcmp(opt->type_string, "digest") == 0)
1296 type = HX509_SELECT_DIGEST;
1297 else if (strcmp(opt->type_string, "public-sig") == 0)
1298 type = HX509_SELECT_PUBLIC_SIG;
1299 else if (strcmp(opt->type_string, "secret") == 0)
1300 type = HX509_SELECT_SECRET_ENC;
1301 else
1302 errx(1, "unknown type: %s", opt->type_string);
1303 } else
1304 type = HX509_SELECT_ALL;
1306 ret = hx509_crypto_available(context, type, NULL, &val, &len);
1307 if (ret)
1308 errx(1, "hx509_crypto_available");
1310 for (i = 0; i < len; i++) {
1311 char *s;
1312 der_print_heim_oid (&val[i].algorithm, '.', &s);
1313 printf("%s\n", s);
1314 free(s);
1317 hx509_crypto_free_algs(val, len);
1319 return 0;
1323 crypto_select(struct crypto_select_options *opt, int argc, char **argv)
1325 hx509_peer_info peer = NULL;
1326 AlgorithmIdentifier selected;
1327 int ret, type;
1328 char *s;
1330 if (opt->type_string) {
1331 if (strcmp(opt->type_string, "digest") == 0)
1332 type = HX509_SELECT_DIGEST;
1333 else if (strcmp(opt->type_string, "public-sig") == 0)
1334 type = HX509_SELECT_PUBLIC_SIG;
1335 else if (strcmp(opt->type_string, "secret") == 0)
1336 type = HX509_SELECT_SECRET_ENC;
1337 else
1338 errx(1, "unknown type: %s", opt->type_string);
1339 } else
1340 type = HX509_SELECT_DIGEST;
1342 if (opt->peer_cmstype_strings.num_strings)
1343 peer_strings(context, &peer, &opt->peer_cmstype_strings);
1345 ret = hx509_crypto_select(context, type, NULL, peer, &selected);
1346 if (ret)
1347 errx(1, "hx509_crypto_available");
1349 der_print_heim_oid (&selected.algorithm, '.', &s);
1350 printf("%s\n", s);
1351 free(s);
1352 free_AlgorithmIdentifier(&selected);
1354 hx509_peer_info_free(peer);
1356 return 0;
1360 hxtool_hex(struct hex_options *opt, int argc, char **argv)
1363 if (opt->decode_flag) {
1364 char buf[1024], buf2[1024], *p;
1365 ssize_t len;
1367 while(fgets(buf, sizeof(buf), stdin) != NULL) {
1368 buf[strcspn(buf, "\r\n")] = '\0';
1369 p = buf;
1370 while(isspace(*(unsigned char *)p))
1371 p++;
1372 len = hex_decode(p, buf2, strlen(p));
1373 if (len < 0)
1374 errx(1, "hex_decode failed");
1375 if (fwrite(buf2, 1, len, stdout) != len)
1376 errx(1, "fwrite failed");
1378 } else {
1379 char buf[28], *p;
1380 size_t len;
1382 while((len = fread(buf, 1, sizeof(buf), stdin)) != 0) {
1383 len = hex_encode(buf, len, &p);
1384 fprintf(stdout, "%s\n", p);
1385 free(p);
1388 return 0;
1391 static int
1392 eval_types(hx509_context context,
1393 hx509_ca_tbs tbs,
1394 const struct certificate_sign_options *opt)
1396 int pkinit = 0;
1397 int i, ret;
1399 for (i = 0; i < opt->type_strings.num_strings; i++) {
1400 const char *type = opt->type_strings.strings[i];
1402 if (strcmp(type, "https-server") == 0) {
1403 ret = hx509_ca_tbs_add_eku(context, tbs,
1404 oid_id_pkix_kp_serverAuth());
1405 if (ret)
1406 hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku");
1407 } else if (strcmp(type, "https-client") == 0) {
1408 ret = hx509_ca_tbs_add_eku(context, tbs,
1409 oid_id_pkix_kp_clientAuth());
1410 if (ret)
1411 hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku");
1412 } else if (strcmp(type, "peap-server") == 0) {
1413 ret = hx509_ca_tbs_add_eku(context, tbs,
1414 oid_id_pkix_kp_serverAuth());
1415 if (ret)
1416 hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku");
1417 } else if (strcmp(type, "pkinit-kdc") == 0) {
1418 pkinit++;
1419 ret = hx509_ca_tbs_add_eku(context, tbs,
1420 oid_id_pkkdcekuoid());
1421 if (ret)
1422 hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku");
1423 } else if (strcmp(type, "pkinit-client") == 0) {
1424 pkinit++;
1425 ret = hx509_ca_tbs_add_eku(context, tbs,
1426 oid_id_pkekuoid());
1427 if (ret)
1428 hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku");
1430 ret = hx509_ca_tbs_add_eku(context, tbs,
1431 oid_id_ms_client_authentication());
1432 if (ret)
1433 hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku");
1435 ret = hx509_ca_tbs_add_eku(context, tbs,
1436 oid_id_pkinit_ms_eku());
1437 if (ret)
1438 hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku");
1440 } else if (strcmp(type, "email") == 0) {
1441 ret = hx509_ca_tbs_add_eku(context, tbs,
1442 oid_id_pkix_kp_emailProtection());
1443 if (ret)
1444 hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku");
1445 } else
1446 errx(1, "unknown type %s", type);
1449 if (pkinit > 1)
1450 errx(1, "More the one PK-INIT type given");
1452 if (opt->pk_init_principal_string) {
1453 if (!pkinit)
1454 errx(1, "pk-init principal given but no pk-init oid");
1456 ret = hx509_ca_tbs_add_san_pkinit(context, tbs,
1457 opt->pk_init_principal_string);
1458 if (ret)
1459 hx509_err(context, 1, ret, "hx509_ca_tbs_add_san_pkinit");
1462 if (opt->ms_upn_string) {
1463 if (!pkinit)
1464 errx(1, "MS up given but no pk-init oid");
1466 ret = hx509_ca_tbs_add_san_ms_upn(context, tbs, opt->ms_upn_string);
1467 if (ret)
1468 hx509_err(context, 1, ret, "hx509_ca_tbs_add_san_ms_upn");
1472 for (i = 0; i < opt->hostname_strings.num_strings; i++) {
1473 const char *hostname = opt->hostname_strings.strings[i];
1475 ret = hx509_ca_tbs_add_san_hostname(context, tbs, hostname);
1476 if (ret)
1477 hx509_err(context, 1, ret, "hx509_ca_tbs_add_san_hostname");
1480 for (i = 0; i < opt->email_strings.num_strings; i++) {
1481 const char *email = opt->email_strings.strings[i];
1483 ret = hx509_ca_tbs_add_san_rfc822name(context, tbs, email);
1484 if (ret)
1485 hx509_err(context, 1, ret, "hx509_ca_tbs_add_san_hostname");
1487 ret = hx509_ca_tbs_add_eku(context, tbs,
1488 oid_id_pkix_kp_emailProtection());
1489 if (ret)
1490 hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku");
1493 if (opt->jid_string) {
1494 ret = hx509_ca_tbs_add_san_jid(context, tbs, opt->jid_string);
1495 if (ret)
1496 hx509_err(context, 1, ret, "hx509_ca_tbs_add_san_jid");
1499 return 0;
1503 hxtool_ca(struct certificate_sign_options *opt, int argc, char **argv)
1505 int ret;
1506 hx509_ca_tbs tbs;
1507 hx509_cert signer = NULL, cert = NULL;
1508 hx509_private_key private_key = NULL;
1509 hx509_private_key cert_key = NULL;
1510 hx509_name subject = NULL;
1511 SubjectPublicKeyInfo spki;
1512 int delta = 0;
1514 memset(&spki, 0, sizeof(spki));
1516 if (opt->ca_certificate_string == NULL && !opt->self_signed_flag)
1517 errx(1, "--ca-certificate argument missing (not using --self-signed)");
1518 if (opt->ca_private_key_string == NULL && opt->generate_key_string == NULL && opt->self_signed_flag)
1519 errx(1, "--ca-private-key argument missing (using --self-signed)");
1520 if (opt->certificate_string == NULL)
1521 errx(1, "--certificate argument missing");
1523 if (opt->template_certificate_string) {
1524 if (opt->template_fields_string == NULL)
1525 errx(1, "--template-certificate not no --template-fields");
1528 if (opt->lifetime_string) {
1529 delta = parse_time(opt->lifetime_string, "day");
1530 if (delta < 0)
1531 errx(1, "Invalid lifetime: %s", opt->lifetime_string);
1534 if (opt->ca_certificate_string) {
1535 hx509_certs cacerts = NULL;
1536 hx509_query *q;
1538 ret = hx509_certs_init(context, opt->ca_certificate_string, 0,
1539 NULL, &cacerts);
1540 if (ret)
1541 hx509_err(context, 1, ret,
1542 "hx509_certs_init: %s", opt->ca_certificate_string);
1544 ret = hx509_query_alloc(context, &q);
1545 if (ret)
1546 errx(1, "hx509_query_alloc: %d", ret);
1548 hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
1549 if (!opt->issue_proxy_flag)
1550 hx509_query_match_option(q, HX509_QUERY_OPTION_KU_KEYCERTSIGN);
1552 ret = hx509_certs_find(context, cacerts, q, &signer);
1553 hx509_query_free(context, q);
1554 hx509_certs_free(&cacerts);
1555 if (ret)
1556 hx509_err(context, 1, ret, "no CA certificate found");
1557 } else if (opt->self_signed_flag) {
1558 if (opt->generate_key_string == NULL
1559 && opt->ca_private_key_string == NULL)
1560 errx(1, "no signing private key");
1561 } else
1562 errx(1, "missing ca key");
1564 if (opt->ca_private_key_string) {
1566 ret = read_private_key(opt->ca_private_key_string, &private_key);
1567 if (ret)
1568 err(1, "read_private_key");
1570 ret = _hx509_private_key2SPKI(context, private_key, &spki);
1571 if (ret)
1572 errx(1, "_hx509_private_key2SPKI: %d\n", ret);
1574 if (opt->self_signed_flag)
1575 cert_key = private_key;
1578 if (opt->req_string) {
1579 hx509_request req;
1581 ret = _hx509_request_parse(context, opt->req_string, &req);
1582 if (ret)
1583 hx509_err(context, 1, ret, "parse_request: %s", opt->req_string);
1584 ret = _hx509_request_get_name(context, req, &subject);
1585 if (ret)
1586 hx509_err(context, 1, ret, "get name");
1587 ret = _hx509_request_get_SubjectPublicKeyInfo(context, req, &spki);
1588 if (ret)
1589 hx509_err(context, 1, ret, "get spki");
1590 _hx509_request_free(&req);
1593 if (opt->generate_key_string) {
1594 struct hx509_generate_private_context *keyctx;
1596 ret = _hx509_generate_private_key_init(context,
1597 oid_id_pkcs1_rsaEncryption(),
1598 &keyctx);
1600 if (opt->issue_ca_flag)
1601 _hx509_generate_private_key_is_ca(context, keyctx);
1603 if (opt->key_bits_integer)
1604 _hx509_generate_private_key_bits(context, keyctx,
1605 opt->key_bits_integer);
1607 ret = _hx509_generate_private_key(context, keyctx,
1608 &cert_key);
1609 _hx509_generate_private_key_free(&keyctx);
1610 if (ret)
1611 hx509_err(context, 1, ret, "generate private key");
1613 ret = _hx509_private_key2SPKI(context, cert_key, &spki);
1614 if (ret)
1615 errx(1, "_hx509_private_key2SPKI: %d\n", ret);
1617 if (opt->self_signed_flag)
1618 private_key = cert_key;
1621 if (opt->certificate_private_key_string) {
1622 ret = read_private_key(opt->certificate_private_key_string, &cert_key);
1623 if (ret)
1624 err(1, "read_private_key for certificate");
1627 if (opt->subject_string) {
1628 if (subject)
1629 hx509_name_free(&subject);
1630 ret = hx509_parse_name(context, opt->subject_string, &subject);
1631 if (ret)
1632 hx509_err(context, 1, ret, "hx509_parse_name");
1639 ret = hx509_ca_tbs_init(context, &tbs);
1640 if (ret)
1641 hx509_err(context, 1, ret, "hx509_ca_tbs_init");
1643 if (opt->template_certificate_string) {
1644 hx509_cert template;
1645 hx509_certs tcerts;
1646 int flags;
1648 ret = hx509_certs_init(context, opt->template_certificate_string, 0,
1649 NULL, &tcerts);
1650 if (ret)
1651 hx509_err(context, 1, ret,
1652 "hx509_certs_init: %s", opt->template_certificate_string);
1654 ret = hx509_get_one_cert(context, tcerts, &template);
1656 hx509_certs_free(&tcerts);
1657 if (ret)
1658 hx509_err(context, 1, ret, "no template certificate found");
1660 flags = parse_units(opt->template_fields_string,
1661 hx509_ca_tbs_template_units(), "");
1663 ret = hx509_ca_tbs_set_template(context, tbs, flags, template);
1664 if (ret)
1665 hx509_err(context, 1, ret, "hx509_ca_tbs_set_template");
1667 hx509_cert_free(template);
1670 if (opt->serial_number_string) {
1671 heim_integer serialNumber;
1673 ret = der_parse_hex_heim_integer(opt->serial_number_string,
1674 &serialNumber);
1675 if (ret)
1676 err(1, "der_parse_hex_heim_integer");
1677 ret = hx509_ca_tbs_set_serialnumber(context, tbs, &serialNumber);
1678 if (ret)
1679 hx509_err(context, 1, ret, "hx509_ca_tbs_init");
1680 der_free_heim_integer(&serialNumber);
1683 if (spki.subjectPublicKey.length) {
1684 ret = hx509_ca_tbs_set_spki(context, tbs, &spki);
1685 if (ret)
1686 hx509_err(context, 1, ret, "hx509_ca_tbs_set_spki");
1689 if (subject) {
1690 ret = hx509_ca_tbs_set_subject(context, tbs, subject);
1691 if (ret)
1692 hx509_err(context, 1, ret, "hx509_ca_tbs_set_subject");
1695 if (opt->crl_uri_string) {
1696 ret = hx509_ca_tbs_add_crl_dp_uri(context, tbs,
1697 opt->crl_uri_string, NULL);
1698 if (ret)
1699 hx509_err(context, 1, ret, "hx509_ca_tbs_add_crl_dp_uri");
1702 eval_types(context, tbs, opt);
1704 if (opt->issue_ca_flag) {
1705 ret = hx509_ca_tbs_set_ca(context, tbs, opt->path_length_integer);
1706 if (ret)
1707 hx509_err(context, 1, ret, "hx509_ca_tbs_set_ca");
1709 if (opt->issue_proxy_flag) {
1710 ret = hx509_ca_tbs_set_proxy(context, tbs, opt->path_length_integer);
1711 if (ret)
1712 hx509_err(context, 1, ret, "hx509_ca_tbs_set_proxy");
1714 if (opt->domain_controller_flag) {
1715 hx509_ca_tbs_set_domaincontroller(context, tbs);
1716 if (ret)
1717 hx509_err(context, 1, ret, "hx509_ca_tbs_set_domaincontroller");
1720 if (delta) {
1721 ret = hx509_ca_tbs_set_notAfter_lifetime(context, tbs, delta);
1722 if (ret)
1723 hx509_err(context, 1, ret, "hx509_ca_tbs_set_notAfter_lifetime");
1726 if (opt->self_signed_flag) {
1727 ret = hx509_ca_sign_self(context, tbs, private_key, &cert);
1728 if (ret)
1729 hx509_err(context, 1, ret, "hx509_ca_sign_self");
1730 } else {
1731 ret = hx509_ca_sign(context, tbs, signer, &cert);
1732 if (ret)
1733 hx509_err(context, 1, ret, "hx509_ca_sign");
1736 if (cert_key) {
1737 ret = _hx509_cert_assign_key(cert, cert_key);
1738 if (ret)
1739 hx509_err(context, 1, ret, "_hx509_cert_assign_key");
1743 hx509_certs certs;
1745 ret = hx509_certs_init(context, opt->certificate_string,
1746 HX509_CERTS_CREATE, NULL, &certs);
1747 if (ret)
1748 hx509_err(context, 1, ret, "hx509_certs_init");
1750 ret = hx509_certs_add(context, certs, cert);
1751 if (ret)
1752 hx509_err(context, 1, ret, "hx509_certs_add");
1754 ret = hx509_certs_store(context, certs, 0, NULL);
1755 if (ret)
1756 hx509_err(context, 1, ret, "hx509_certs_store");
1758 hx509_certs_free(&certs);
1761 if (subject)
1762 hx509_name_free(&subject);
1763 if (signer)
1764 hx509_cert_free(signer);
1765 hx509_cert_free(cert);
1766 free_SubjectPublicKeyInfo(&spki);
1768 if (private_key != cert_key)
1769 _hx509_private_key_free(&private_key);
1770 _hx509_private_key_free(&cert_key);
1772 hx509_ca_tbs_free(&tbs);
1774 return 0;
1777 static int
1778 test_one_cert(hx509_context hxcontext, void *ctx, hx509_cert cert)
1780 heim_octet_string sd, c;
1781 hx509_verify_ctx vctx = ctx;
1782 hx509_certs signer = NULL;
1783 heim_oid type;
1784 int ret;
1786 if (_hx509_cert_private_key(cert) == NULL)
1787 return 0;
1789 ret = hx509_cms_create_signed_1(context, 0, NULL, NULL, 0,
1790 NULL, cert, NULL, NULL, NULL, &sd);
1791 if (ret)
1792 errx(1, "hx509_cms_create_signed_1");
1794 ret = hx509_cms_verify_signed(context, vctx, sd.data, sd.length,
1795 NULL, NULL, &type, &c, &signer);
1796 free(sd.data);
1797 if (ret)
1798 hx509_err(context, 1, ret, "hx509_cms_verify_signed");
1800 printf("create-signature verify-sigature done\n");
1802 free(c.data);
1804 return 0;
1808 test_crypto(struct test_crypto_options *opt, int argc, char ** argv)
1810 hx509_verify_ctx vctx;
1811 hx509_certs certs;
1812 hx509_lock lock;
1813 int i, ret;
1815 hx509_lock_init(context, &lock);
1816 lock_strings(lock, &opt->pass_strings);
1818 ret = hx509_certs_init(context, "MEMORY:test-crypto", 0, NULL, &certs);
1820 for (i = 0; i < argc; i++) {
1821 ret = hx509_certs_append(context, certs, lock, argv[i]);
1822 if (ret)
1823 hx509_err(context, 1, ret, "hx509_certs_append");
1826 ret = hx509_verify_init_ctx(context, &vctx);
1827 if (ret)
1828 hx509_err(context, 1, ret, "hx509_verify_init_ctx");
1830 hx509_verify_attach_anchors(vctx, certs);
1832 ret = hx509_certs_iter(context, certs, test_one_cert, vctx);
1834 hx509_certs_free(&certs);
1836 return 0;
1840 statistic_print(struct statistic_print_options*opt, int argc, char **argv)
1842 int type = 0;
1844 if (stat_file_string == NULL)
1845 errx(1, "no stat file");
1847 if (opt->type_integer)
1848 type = opt->type_integer;
1850 hx509_query_unparse_stats(context, type, stdout);
1851 return 0;
1859 crl_sign(struct crl_sign_options *opt, int argc, char **argv)
1861 hx509_crl crl;
1862 heim_octet_string os;
1863 hx509_cert signer = NULL;
1864 hx509_lock lock;
1865 int ret;
1867 hx509_lock_init(context, &lock);
1868 lock_strings(lock, &opt->pass_strings);
1870 ret = hx509_crl_alloc(context, &crl);
1871 if (ret)
1872 errx(1, "crl alloc");
1874 if (opt->signer_string == NULL)
1875 errx(1, "signer missing");
1878 hx509_certs certs = NULL;
1879 hx509_query *q;
1881 ret = hx509_certs_init(context, opt->signer_string, 0,
1882 NULL, &certs);
1883 if (ret)
1884 hx509_err(context, 1, ret,
1885 "hx509_certs_init: %s", opt->signer_string);
1887 ret = hx509_query_alloc(context, &q);
1888 if (ret)
1889 hx509_err(context, 1, ret, "hx509_query_alloc: %d", ret);
1891 hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
1893 ret = hx509_certs_find(context, certs, q, &signer);
1894 hx509_query_free(context, q);
1895 hx509_certs_free(&certs);
1896 if (ret)
1897 hx509_err(context, 1, ret, "no signer certificate found");
1900 if (opt->lifetime_string) {
1901 int delta;
1903 delta = parse_time(opt->lifetime_string, "day");
1904 if (delta < 0)
1905 errx(1, "Invalid lifetime: %s", opt->lifetime_string);
1907 hx509_crl_lifetime(context, crl, delta);
1911 hx509_certs revoked = NULL;
1912 int i;
1914 ret = hx509_certs_init(context, "MEMORY:revoked-certs", 0,
1915 NULL, &revoked);
1917 for (i = 0; i < argc; i++) {
1918 ret = hx509_certs_append(context, revoked, lock, argv[i]);
1919 if (ret)
1920 hx509_err(context, 1, ret, "hx509_certs_append: %s", argv[i]);
1923 hx509_crl_add_revoked_certs(context, crl, revoked);
1924 hx509_certs_free(&revoked);
1927 hx509_crl_sign(context, signer, crl, &os);
1929 if (opt->crl_file_string)
1930 rk_dumpdata(opt->crl_file_string, os.data, os.length);
1932 free(os.data);
1934 hx509_crl_free(context, &crl);
1935 hx509_cert_free(signer);
1936 hx509_lock_free(lock);
1938 return 0;
1946 help(void *opt, int argc, char **argv)
1948 sl_slc_help(commands, argc, argv);
1949 return 0;
1953 main(int argc, char **argv)
1955 int ret, optidx = 0;
1957 setprogname (argv[0]);
1959 if(getarg(args, num_args, argc, argv, &optidx))
1960 usage(1);
1961 if(help_flag)
1962 usage(0);
1963 if(version_flag) {
1964 print_version(NULL);
1965 exit(0);
1967 argv += optidx;
1968 argc -= optidx;
1970 if (argc == 0)
1971 usage(1);
1973 ret = hx509_context_init(&context);
1974 if (ret)
1975 errx(1, "hx509_context_init failed with %d", ret);
1977 if (stat_file_string)
1978 hx509_query_statistic_file(context, stat_file_string);
1980 ret = sl_command(commands, argc, argv);
1981 if(ret == -1)
1982 warnx ("unrecognized command: %s", argv[0]);
1984 hx509_context_free(&context);
1986 return ret;