1 /* 2 * Copyright (c) 2004 - 2007 Kungliga Tekniska H�gskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 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. 16 * 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. 20 * 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. 32 */ 33 34 #include "hx_locl.h" 35 RCSID("$Id: hxtool.c 22333 2007-12-17 01:03:43Z lha $"); 36 37 #include <hxtool-commands.h> 38 #include <sl.h> 39 #include <parse_time.h> 40 41 static hx509_context context; 42 43 static char *stat_file_string; 44 static int version_flag; 45 static int help_flag; 46 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 } 51 }; 52 int num_args = sizeof(args) / sizeof(args[0]); 53 54 static void 55 usage(int code) 56 { 57 arg_printusage(args, num_args, NULL, "command"); 58 printf("Use \"%s help\" to get more help\n", getprogname()); 59 exit(code); 60 } 61 62 /* 63 * 64 */ 65 66 static void 67 lock_strings(hx509_lock lock, getarg_strings *pass) 68 { 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); 75 } 76 } 77 78 /* 79 * 80 */ 81 82 static void 83 certs_strings(hx509_context context, const char *type, hx509_certs certs, 84 hx509_lock lock, const getarg_strings *s) 85 { 86 int i, ret; 87 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]); 93 } 94 } 95 96 /* 97 * 98 */ 99 100 static void 101 parse_oid(const char *str, const heim_oid *def, heim_oid *oid) 102 { 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"); 110 } 111 112 /* 113 * 114 */ 115 116 static void 117 peer_strings(hx509_context context, 118 hx509_peer_info *peer, 119 const getarg_strings *s) 120 { 121 AlgorithmIdentifier *val; 122 int ret, i; 123 124 ret = hx509_peer_info_alloc(context, peer); 125 if (ret) 126 hx509_err(context, 1, ret, "hx509_peer_info_alloc"); 127 128 val = calloc(s->num_strings, sizeof(*val)); 129 if (val == NULL) 130 err(1, "malloc"); 131 132 for (i = 0; i < s->num_strings; i++) 133 parse_oid(s->strings[i], NULL, &val[i].algorithm); 134 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"); 138 139 for (i = 0; i < s->num_strings; i++) 140 free_AlgorithmIdentifier(&val[i]); 141 free(val); 142 } 143 144 /* 145 * 146 */ 147 148 int 149 cms_verify_sd(struct cms_verify_sd_options *opt, int argc, char **argv) 150 { 151 hx509_verify_ctx ctx = NULL; 152 heim_oid type; 153 heim_octet_string c, co, signeddata, *sd = NULL; 154 hx509_certs store = NULL; 155 hx509_certs signers = NULL; 156 hx509_certs anchors = NULL; 157 hx509_lock lock; 158 int ret; 159 160 size_t sz; 161 void *p; 162 163 if (opt->missing_revoke_flag) 164 hx509_context_set_missing_revoke(context, 1); 165 166 hx509_lock_init(context, &lock); 167 lock_strings(lock, &opt->pass_strings); 168 169 ret = _hx509_map_file(argv[0], &p, &sz, NULL); 170 if (ret) 171 err(1, "map_file: %s: %d", argv[0], ret); 172 173 if (opt->signed_content_string) { 174 ret = _hx509_map_file_os(opt->signed_content_string, &signeddata, NULL); 175 if (ret) 176 err(1, "map_file: %s: %d", opt->signed_content_string, ret); 177 sd = &signeddata; 178 } 179 180 ret = hx509_verify_init_ctx(context, &ctx); 181 182 ret = hx509_certs_init(context, "MEMORY:cms-anchors", 0, NULL, &anchors); 183 ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &store); 184 185 certs_strings(context, "anchors", anchors, lock, &opt->anchors_strings); 186 certs_strings(context, "store", store, lock, &opt->certificate_strings); 187 188 co.data = p; 189 co.length = sz; 190 191 if (opt->content_info_flag) { 192 heim_octet_string uwco; 193 heim_oid oid; 194 195 ret = hx509_cms_unwrap_ContentInfo(&co, &oid, &uwco, NULL); 196 if (ret) 197 errx(1, "hx509_cms_unwrap_ContentInfo: %d", ret); 198 199 if (der_heim_oid_cmp(&oid, oid_id_pkcs7_signedData()) != 0) 200 errx(1, "Content is not SignedData"); 201 der_free_oid(&oid); 202 203 co = uwco; 204 } 205 206 hx509_verify_attach_anchors(ctx, anchors); 207 208 ret = hx509_cms_verify_signed(context, ctx, co.data, co.length, sd, 209 store, &type, &c, &signers); 210 if (co.data != p) 211 der_free_octet_string(&co); 212 if (ret) 213 hx509_err(context, 1, ret, "hx509_cms_verify_signed"); 214 215 { 216 char *str; 217 der_print_heim_oid(&type, '.', &str); 218 printf("type: %s\n", str); 219 free(str); 220 der_free_oid(&type); 221 } 222 printf("signers:\n"); 223 hx509_certs_iter(context, signers, hx509_ci_print_names, stdout); 224 225 hx509_verify_destroy_ctx(ctx); 226 227 hx509_certs_free(&store); 228 hx509_certs_free(&signers); 229 hx509_certs_free(&anchors); 230 231 hx509_lock_free(lock); 232 233 ret = _hx509_write_file(argv[1], c.data, c.length); 234 if (ret) 235 errx(1, "hx509_write_file: %d", ret); 236 237 der_free_octet_string(&c); 238 _hx509_unmap_file(p, sz); 239 if (sd) 240 _hx509_unmap_file_os(sd); 241 242 return 0; 243 } 244 245 int 246 cms_create_sd(struct cms_create_sd_options *opt, int argc, char **argv) 247 { 248 heim_oid contentType; 249 hx509_peer_info peer = NULL; 250 heim_octet_string o; 251 hx509_query *q; 252 hx509_lock lock; 253 hx509_certs store, pool, anchors; 254 hx509_cert cert; 255 size_t sz; 256 void *p; 257 int ret, flags = 0; 258 char *signer_name = NULL; 259 260 memset(&contentType, 0, sizeof(contentType)); 261 262 if (argc < 2) 263 errx(1, "argc < 2"); 264 265 hx509_lock_init(context, &lock); 266 lock_strings(lock, &opt->pass_strings); 267 268 ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &store); 269 ret = hx509_certs_init(context, "MEMORY:cert-pool", 0, NULL, &pool); 270 271 certs_strings(context, "store", store, lock, &opt->certificate_strings); 272 certs_strings(context, "pool", pool, lock, &opt->pool_strings); 273 274 if (opt->anchors_strings.num_strings) { 275 ret = hx509_certs_init(context, "MEMORY:cert-anchors", 276 0, NULL, &anchors); 277 certs_strings(context, "anchors", anchors, lock, &opt->anchors_strings); 278 } else 279 anchors = NULL; 280 281 if (opt->detached_signature_flag) 282 flags |= HX509_CMS_SIGATURE_DETACHED; 283 if (opt->id_by_name_flag) 284 flags |= HX509_CMS_SIGATURE_ID_NAME; 285 286 ret = hx509_query_alloc(context, &q); 287 if (ret) 288 errx(1, "hx509_query_alloc: %d", ret); 289 290 hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); 291 hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE); 292 293 if (opt->signer_string) 294 hx509_query_match_friendly_name(q, opt->signer_string); 295 296 ret = hx509_certs_find(context, store, q, &cert); 297 hx509_query_free(context, q); 298 if (ret) 299 hx509_err(context, 1, ret, "hx509_certs_find"); 300 301 ret = _hx509_map_file(argv[0], &p, &sz, NULL); 302 if (ret) 303 err(1, "map_file: %s: %d", argv[0], ret); 304 305 if (opt->peer_alg_strings.num_strings) 306 peer_strings(context, &peer, &opt->peer_alg_strings); 307 308 parse_oid(opt->content_type_string, oid_id_pkcs7_data(), &contentType); 309 310 ret = hx509_cms_create_signed_1(context, 311 flags, 312 &contentType, 313 p, 314 sz, 315 NULL, 316 cert, 317 peer, 318 anchors, 319 pool, 320 &o); 321 if (ret) 322 errx(1, "hx509_cms_create_signed: %d", ret); 323 324 { 325 hx509_name name; 326 327 ret = hx509_cert_get_subject(cert, &name); 328 if (ret) 329 errx(1, "hx509_cert_get_subject"); 330 331 ret = hx509_name_to_string(name, &signer_name); 332 hx509_name_free(&name); 333 if (ret) 334 errx(1, "hx509_name_to_string"); 335 } 336 337 338 hx509_certs_free(&anchors); 339 hx509_certs_free(&pool); 340 hx509_cert_free(cert); 341 hx509_certs_free(&store); 342 _hx509_unmap_file(p, sz); 343 hx509_lock_free(lock); 344 hx509_peer_info_free(peer); 345 der_free_oid(&contentType); 346 347 if (opt->content_info_flag) { 348 heim_octet_string wo; 349 350 ret = hx509_cms_wrap_ContentInfo(oid_id_pkcs7_signedData(), &o, &wo); 351 if (ret) 352 errx(1, "hx509_cms_wrap_ContentInfo: %d", ret); 353 354 der_free_octet_string(&o); 355 o = wo; 356 } 357 358 if (opt->pem_flag) { 359 hx509_pem_header *header = NULL; 360 FILE *f; 361 362 hx509_pem_add_header(&header, "Content-disposition", 363 opt->detached_signature_flag ? "detached" : "inline"); 364 hx509_pem_add_header(&header, "Signer", signer_name); 365 366 f = fopen(argv[1], "w"); 367 if (f == NULL) 368 err(1, "open %s", argv[1]); 369 370 ret = hx509_pem_write(context, "CMS SIGNEDDATA", header, f, 371 o.data, o.length); 372 fclose(f); 373 hx509_pem_free_header(header); 374 if (ret) 375 errx(1, "hx509_pem_write: %d", ret); 376 377 } else { 378 ret = _hx509_write_file(argv[1], o.data, o.length); 379 if (ret) 380 errx(1, "hx509_write_file: %d", ret); 381 } 382 383 free(signer_name); 384 free(o.data); 385 386 return 0; 387 } 388 389 int 390 cms_unenvelope(struct cms_unenvelope_options *opt, int argc, char **argv) 391 { 392 heim_oid contentType = { 0, NULL }; 393 heim_octet_string o, co; 394 hx509_certs certs; 395 size_t sz; 396 void *p; 397 int ret; 398 hx509_lock lock; 399 400 hx509_lock_init(context, &lock); 401 lock_strings(lock, &opt->pass_strings); 402 403 ret = _hx509_map_file(argv[0], &p, &sz, NULL); 404 if (ret) 405 err(1, "map_file: %s: %d", argv[0], ret); 406 407 co.data = p; 408 co.length = sz; 409 410 if (opt->content_info_flag) { 411 heim_octet_string uwco; 412 heim_oid oid; 413 414 ret = hx509_cms_unwrap_ContentInfo(&co, &oid, &uwco, NULL); 415 if (ret) 416 errx(1, "hx509_cms_unwrap_ContentInfo: %d", ret); 417 418 if (der_heim_oid_cmp(&oid, oid_id_pkcs7_envelopedData()) != 0) 419 errx(1, "Content is not SignedData"); 420 der_free_oid(&oid); 421 422 co = uwco; 423 } 424 425 ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &certs); 426 if (ret) 427 errx(1, "hx509_certs_init: MEMORY: %d", ret); 428 429 certs_strings(context, "store", certs, lock, &opt->certificate_strings); 430 431 ret = hx509_cms_unenvelope(context, certs, 0, co.data, co.length, 432 NULL, &contentType, &o); 433 if (co.data != p) 434 der_free_octet_string(&co); 435 if (ret) 436 hx509_err(context, 1, ret, "hx509_cms_unenvelope"); 437 438 _hx509_unmap_file(p, sz); 439 hx509_lock_free(lock); 440 hx509_certs_free(&certs); 441 der_free_oid(&contentType); 442 443 ret = _hx509_write_file(argv[1], o.data, o.length); 444 if (ret) 445 errx(1, "hx509_write_file: %d", ret); 446 447 der_free_octet_string(&o); 448 449 return 0; 450 } 451 452 int 453 cms_create_enveloped(struct cms_envelope_options *opt, int argc, char **argv) 454 { 455 heim_oid contentType; 456 heim_octet_string o; 457 const heim_oid *enctype = NULL; 458 hx509_query *q; 459 hx509_certs certs; 460 hx509_cert cert; 461 int ret; 462 size_t sz; 463 void *p; 464 hx509_lock lock; 465 466 memset(&contentType, 0, sizeof(contentType)); 467 468 hx509_lock_init(context, &lock); 469 lock_strings(lock, &opt->pass_strings); 470 471 ret = _hx509_map_file(argv[0], &p, &sz, NULL); 472 if (ret) 473 err(1, "map_file: %s: %d", argv[0], ret); 474 475 ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &certs); 476 477 certs_strings(context, "store", certs, lock, &opt->certificate_strings); 478 479 if (opt->encryption_type_string) { 480 enctype = hx509_crypto_enctype_by_name(opt->encryption_type_string); 481 if (enctype == NULL) 482 errx(1, "encryption type: %s no found", 483 opt->encryption_type_string); 484 } 485 486 ret = hx509_query_alloc(context, &q); 487 if (ret) 488 errx(1, "hx509_query_alloc: %d", ret); 489 490 hx509_query_match_option(q, HX509_QUERY_OPTION_KU_ENCIPHERMENT); 491 492 ret = hx509_certs_find(context, certs, q, &cert); 493 hx509_query_free(context, q); 494 if (ret) 495 errx(1, "hx509_certs_find: %d", ret); 496 497 parse_oid(opt->content_type_string, oid_id_pkcs7_data(), &contentType); 498 499 ret = hx509_cms_envelope_1(context, 0, cert, p, sz, enctype, 500 &contentType, &o); 501 if (ret) 502 errx(1, "hx509_cms_envelope_1: %d", ret); 503 504 hx509_cert_free(cert); 505 hx509_certs_free(&certs); 506 _hx509_unmap_file(p, sz); 507 der_free_oid(&contentType); 508 509 if (opt->content_info_flag) { 510 heim_octet_string wo; 511 512 ret = hx509_cms_wrap_ContentInfo(oid_id_pkcs7_envelopedData(), &o, &wo); 513 if (ret) 514 errx(1, "hx509_cms_wrap_ContentInfo: %d", ret); 515 516 der_free_octet_string(&o); 517 o = wo; 518 } 519 520 hx509_lock_free(lock); 521 522 ret = _hx509_write_file(argv[1], o.data, o.length); 523 if (ret) 524 errx(1, "hx509_write_file: %d", ret); 525 526 der_free_octet_string(&o); 527 528 return 0; 529 } 530 531 static void 532 print_certificate(hx509_context hxcontext, hx509_cert cert, int verbose) 533 { 534 hx509_name name; 535 const char *fn; 536 char *str; 537 int ret; 538 539 fn = hx509_cert_get_friendly_name(cert); 540 if (fn) 541 printf(" friendly name: %s\n", fn); 542 printf(" private key: %s\n", 543 _hx509_cert_private_key(cert) ? "yes" : "no"); 544 545 ret = hx509_cert_get_issuer(cert, &name); 546 hx509_name_to_string(name, &str); 547 hx509_name_free(&name); 548 printf(" issuer: \"%s\"\n", str); 549 free(str); 550 551 ret = hx509_cert_get_subject(cert, &name); 552 hx509_name_to_string(name, &str); 553 hx509_name_free(&name); 554 printf(" subject: \"%s\"\n", str); 555 free(str); 556 557 { 558 heim_integer serialNumber; 559 560 hx509_cert_get_serialnumber(cert, &serialNumber); 561 der_print_hex_heim_integer(&serialNumber, &str); 562 der_free_heim_integer(&serialNumber); 563 printf(" serial: %s\n", str); 564 free(str); 565 } 566 567 printf(" keyusage: "); 568 ret = hx509_cert_keyusage_print(hxcontext, cert, &str); 569 if (ret == 0) { 570 printf("%s\n", str); 571 free(str); 572 } else 573 printf("no"); 574 575 if (verbose) { 576 hx509_validate_ctx vctx; 577 578 hx509_validate_ctx_init(hxcontext, &vctx); 579 hx509_validate_ctx_set_print(vctx, hx509_print_stdout, stdout); 580 hx509_validate_ctx_add_flags(vctx, HX509_VALIDATE_F_VALIDATE); 581 hx509_validate_ctx_add_flags(vctx, HX509_VALIDATE_F_VERBOSE); 582 583 hx509_validate_cert(hxcontext, vctx, cert); 584 585 hx509_validate_ctx_free(vctx); 586 } 587 } 588 589 590 struct print_s { 591 int counter; 592 int verbose; 593 }; 594 595 static int 596 print_f(hx509_context hxcontext, void *ctx, hx509_cert cert) 597 { 598 struct print_s *s = ctx; 599 600 printf("cert: %d\n", s->counter++); 601 print_certificate(context, cert, s->verbose); 602 603 return 0; 604 } 605 606 int 607 pcert_print(struct print_options *opt, int argc, char **argv) 608 { 609 hx509_certs certs; 610 hx509_lock lock; 611 struct print_s s; 612 613 s.counter = 0; 614 s.verbose = opt->content_flag; 615 616 hx509_lock_init(context, &lock); 617 lock_strings(lock, &opt->pass_strings); 618 619 while(argc--) { 620 int ret; 621 ret = hx509_certs_init(context, argv[0], 0, lock, &certs); 622 if (ret) 623 hx509_err(context, 1, ret, "hx509_certs_init"); 624 if (opt->info_flag) 625 hx509_certs_info(context, certs, NULL, NULL); 626 hx509_certs_iter(context, certs, print_f, &s); 627 hx509_certs_free(&certs); 628 argv++; 629 } 630 631 hx509_lock_free(lock); 632 633 return 0; 634 } 635 636 637 static int 638 validate_f(hx509_context hxcontext, void *ctx, hx509_cert c) 639 { 640 hx509_validate_cert(hxcontext, ctx, c); 641 return 0; 642 } 643 644 int 645 pcert_validate(struct validate_options *opt, int argc, char **argv) 646 { 647 hx509_validate_ctx ctx; 648 hx509_certs certs; 649 hx509_lock lock; 650 651 hx509_lock_init(context, &lock); 652 lock_strings(lock, &opt->pass_strings); 653 654 hx509_validate_ctx_init(context, &ctx); 655 hx509_validate_ctx_set_print(ctx, hx509_print_stdout, stdout); 656 hx509_validate_ctx_add_flags(ctx, HX509_VALIDATE_F_VALIDATE); 657 658 while(argc--) { 659 int ret; 660 ret = hx509_certs_init(context, argv[0], 0, lock, &certs); 661 if (ret) 662 errx(1, "hx509_certs_init: %d", ret); 663 hx509_certs_iter(context, certs, validate_f, ctx); 664 hx509_certs_free(&certs); 665 argv++; 666 } 667 hx509_validate_ctx_free(ctx); 668 669 hx509_lock_free(lock); 670 671 return 0; 672 } 673 674 int 675 certificate_copy(struct certificate_copy_options *opt, int argc, char **argv) 676 { 677 hx509_certs certs; 678 hx509_lock lock; 679 int ret; 680 681 hx509_lock_init(context, &lock); 682 lock_strings(lock, &opt->in_pass_strings); 683 684 ret = hx509_certs_init(context, argv[argc - 1], 685 HX509_CERTS_CREATE, lock, &certs); 686 if (ret) 687 hx509_err(context, 1, ret, "hx509_certs_init"); 688 689 while(argc-- > 1) { 690 int ret; 691 ret = hx509_certs_append(context, certs, lock, argv[0]); 692 if (ret) 693 hx509_err(context, 1, ret, "hx509_certs_append"); 694 argv++; 695 } 696 697 ret = hx509_certs_store(context, certs, 0, NULL); 698 if (ret) 699 hx509_err(context, 1, ret, "hx509_certs_store"); 700 701 hx509_certs_free(&certs); 702 hx509_lock_free(lock); 703 704 return 0; 705 } 706 707 struct verify { 708 hx509_verify_ctx ctx; 709 hx509_certs chain; 710 const char *hostname; 711 int errors; 712 }; 713 714 static int 715 verify_f(hx509_context hxcontext, void *ctx, hx509_cert c) 716 { 717 struct verify *v = ctx; 718 int ret; 719 720 ret = hx509_verify_path(hxcontext, v->ctx, c, v->chain); 721 if (ret) { 722 char *s = hx509_get_error_string(hxcontext, ret); 723 printf("verify_path: %s: %d\n", s, ret); 724 hx509_free_error_string(s); 725 v->errors++; 726 } else 727 printf("path ok\n"); 728 729 if (v->hostname) { 730 ret = hx509_verify_hostname(hxcontext, c, 0, HX509_HN_HOSTNAME, 731 v->hostname, NULL, 0); 732 if (ret) { 733 printf("verify_hostname: %d\n", ret); 734 v->errors++; 735 } 736 } 737 738 return 0; 739 } 740 741 int 742 pcert_verify(struct verify_options *opt, int argc, char **argv) 743 { 744 hx509_certs anchors, chain, certs; 745 hx509_revoke_ctx revoke_ctx; 746 hx509_verify_ctx ctx; 747 struct verify v; 748 int ret; 749 750 memset(&v, 0, sizeof(v)); 751 752 if (opt->missing_revoke_flag) 753 hx509_context_set_missing_revoke(context, 1); 754 755 ret = hx509_verify_init_ctx(context, &ctx); 756 ret = hx509_certs_init(context, "MEMORY:anchors", 0, NULL, &anchors); 757 ret = hx509_certs_init(context, "MEMORY:chain", 0, NULL, &chain); 758 ret = hx509_certs_init(context, "MEMORY:certs", 0, NULL, &certs); 759 760 if (opt->allow_proxy_certificate_flag) 761 hx509_verify_set_proxy_certificate(ctx, 1); 762 763 if (opt->time_string) { 764 const char *p; 765 struct tm tm; 766 time_t t; 767 768 memset(&tm, 0, sizeof(tm)); 769 770 p = strptime (opt->time_string, "%Y-%m-%d", &tm); 771 if (p == NULL) 772 errx(1, "Failed to parse time %s, need to be on format %%Y-%%m-%%d", 773 opt->time_string); 774 775 t = tm2time (tm, 0); 776 777 hx509_verify_set_time(ctx, t); 778 } 779 780 if (opt->hostname_string) 781 v.hostname = opt->hostname_string; 782 if (opt->max_depth_integer) 783 hx509_verify_set_max_depth(ctx, opt->max_depth_integer); 784 785 ret = hx509_revoke_init(context, &revoke_ctx); 786 if (ret) 787 errx(1, "hx509_revoke_init: %d", ret); 788 789 while(argc--) { 790 char *s = *argv++; 791 792 if (strncmp(s, "chain:", 6) == 0) { 793 s += 6; 794 795 ret = hx509_certs_append(context, chain, NULL, s); 796 if (ret) 797 hx509_err(context, 1, ret, "hx509_certs_append: chain: %s: %d", s, ret); 798 799 } else if (strncmp(s, "anchor:", 7) == 0) { 800 s += 7; 801 802 ret = hx509_certs_append(context, anchors, NULL, s); 803 if (ret) 804 hx509_err(context, 1, ret, "hx509_certs_append: anchor: %s: %d", s, ret); 805 806 } else if (strncmp(s, "cert:", 5) == 0) { 807 s += 5; 808 809 ret = hx509_certs_append(context, certs, NULL, s); 810 if (ret) 811 hx509_err(context, 1, ret, "hx509_certs_append: certs: %s: %d", 812 s, ret); 813 814 } else if (strncmp(s, "crl:", 4) == 0) { 815 s += 4; 816 817 ret = hx509_revoke_add_crl(context, revoke_ctx, s); 818 if (ret) 819 errx(1, "hx509_revoke_add_crl: %s: %d", s, ret); 820 821 } else if (strncmp(s, "ocsp:", 4) == 0) { 822 s += 5; 823 824 ret = hx509_revoke_add_ocsp(context, revoke_ctx, s); 825 if (ret) 826 errx(1, "hx509_revoke_add_ocsp: %s: %d", s, ret); 827 828 } else { 829 errx(1, "unknown option to verify: `%s'\n", s); 830 } 831 } 832 833 hx509_verify_attach_anchors(ctx, anchors); 834 hx509_verify_attach_revoke(ctx, revoke_ctx); 835 836 v.ctx = ctx; 837 v.chain = chain; 838 839 hx509_certs_iter(context, certs, verify_f, &v); 840 841 hx509_verify_destroy_ctx(ctx); 842 843 hx509_certs_free(&certs); 844 hx509_certs_free(&chain); 845 hx509_certs_free(&anchors); 846 847 hx509_revoke_free(&revoke_ctx); 848 849 if (v.errors) { 850 printf("failed verifing %d checks\n", v.errors); 851 return 1; 852 } 853 854 return 0; 855 } 856 857 int 858 query(struct query_options *opt, int argc, char **argv) 859 { 860 hx509_lock lock; 861 hx509_query *q; 862 hx509_certs certs; 863 hx509_cert c; 864 int ret; 865 866 ret = hx509_query_alloc(context, &q); 867 if (ret) 868 errx(1, "hx509_query_alloc: %d", ret); 869 870 hx509_lock_init(context, &lock); 871 lock_strings(lock, &opt->pass_strings); 872 873 ret = hx509_certs_init(context, "MEMORY:cert-store", 0, NULL, &certs); 874 875 while (argc > 0) { 876 877 ret = hx509_certs_append(context, certs, lock, argv[0]); 878 if (ret) 879 errx(1, "hx509_certs_append: %s: %d", argv[0], ret); 880 881 argc--; 882 argv++; 883 } 884 885 if (opt->friendlyname_string) 886 hx509_query_match_friendly_name(q, opt->friendlyname_string); 887 888 if (opt->private_key_flag) 889 hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); 890 891 if (opt->keyEncipherment_flag) 892 hx509_query_match_option(q, HX509_QUERY_OPTION_KU_ENCIPHERMENT); 893 894 if (opt->digitalSignature_flag) 895 hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE); 896 897 ret = hx509_certs_find(context, certs, q, &c); 898 hx509_query_free(context, q); 899 if (ret) 900 printf("no match found (%d)\n", ret); 901 else { 902 printf("match found\n"); 903 if (opt->print_flag) 904 print_certificate(context, c, 0); 905 } 906 907 hx509_cert_free(c); 908 hx509_certs_free(&certs); 909 910 hx509_lock_free(lock); 911 912 return ret; 913 } 914 915 int 916 ocsp_fetch(struct ocsp_fetch_options *opt, int argc, char **argv) 917 { 918 hx509_certs reqcerts, pool; 919 heim_octet_string req, nonce_data, *nonce = &nonce_data; 920 hx509_lock lock; 921 int i, ret; 922 char *file; 923 const char *url = "/"; 924 925 memset(&nonce, 0, sizeof(nonce)); 926 927 hx509_lock_init(context, &lock); 928 lock_strings(lock, &opt->pass_strings); 929 930 /* no nonce */ 931 if (!opt->nonce_flag) 932 nonce = NULL; 933 934 if (opt->url_path_string) 935 url = opt->url_path_string; 936 937 ret = hx509_certs_init(context, "MEMORY:ocsp-pool", 0, NULL, &pool); 938 939 certs_strings(context, "ocsp-pool", pool, lock, &opt->pool_strings); 940 941 file = argv[0]; 942 943 ret = hx509_certs_init(context, "MEMORY:ocsp-req", 0, NULL, &reqcerts); 944 945 for (i = 1; i < argc; i++) { 946 ret = hx509_certs_append(context, reqcerts, lock, argv[i]); 947 if (ret) 948 errx(1, "hx509_certs_append: req: %s: %d", argv[i], ret); 949 } 950 951 ret = hx509_ocsp_request(context, reqcerts, pool, NULL, NULL, &req, nonce); 952 if (ret) 953 errx(1, "hx509_ocsp_request: req: %d", ret); 954 955 { 956 FILE *f; 957 958 f = fopen(file, "w"); 959 if (f == NULL) 960 abort(); 961 962 fprintf(f, 963 "POST %s HTTP/1.0\r\n" 964 "Content-Type: application/ocsp-request\r\n" 965 "Content-Length: %ld\r\n" 966 "\r\n", 967 url, 968 (unsigned long)req.length); 969 fwrite(req.data, req.length, 1, f); 970 fclose(f); 971 } 972 973 if (nonce) 974 der_free_octet_string(nonce); 975 976 hx509_certs_free(&reqcerts); 977 hx509_certs_free(&pool); 978 979 return 0; 980 } 981 982 int 983 ocsp_print(struct ocsp_print_options *opt, int argc, char **argv) 984 { 985 hx509_revoke_ocsp_print(context, argv[0], stdout); 986 return 0; 987 } 988 989 /* 990 * 991 */ 992 993 static int 994 verify_o(hx509_context hxcontext, void *ctx, hx509_cert c) 995 { 996 heim_octet_string *os = ctx; 997 time_t expiration; 998 int ret; 999 1000 ret = hx509_ocsp_verify(context, 0, c, 0, 1001 os->data, os->length, &expiration); 1002 if (ret) { 1003 char *s = hx509_get_error_string(hxcontext, ret); 1004 printf("ocsp_verify: %s: %d\n", s, ret); 1005 hx509_free_error_string(s); 1006 } else 1007 printf("expire: %d\n", (int)expiration); 1008 1009 return ret; 1010 } 1011 1012 1013 int 1014 ocsp_verify(struct ocsp_verify_options *opt, int argc, char **argv) 1015 { 1016 hx509_lock lock; 1017 hx509_certs certs; 1018 int ret, i; 1019 heim_octet_string os; 1020 1021 hx509_lock_init(context, &lock); 1022 1023 if (opt->ocsp_file_string == NULL) 1024 errx(1, "no ocsp file given"); 1025 1026 ret = _hx509_map_file(opt->ocsp_file_string, &os.data, &os.length, NULL); 1027 if (ret) 1028 err(1, "map_file: %s: %d", argv[0], ret); 1029 1030 ret = hx509_certs_init(context, "MEMORY:test-certs", 0, NULL, &certs); 1031 1032 for (i = 0; i < argc; i++) { 1033 ret = hx509_certs_append(context, certs, lock, argv[i]); 1034 if (ret) 1035 hx509_err(context, 1, ret, "hx509_certs_append: %s", argv[i]); 1036 } 1037 1038 ret = hx509_certs_iter(context, certs, verify_o, &os); 1039 1040 hx509_certs_free(&certs); 1041 _hx509_unmap_file(os.data, os.length); 1042 hx509_lock_free(lock); 1043 1044 return ret; 1045 } 1046 1047 static int 1048 read_private_key(const char *fn, hx509_private_key *key) 1049 { 1050 hx509_private_key *keys; 1051 hx509_certs certs; 1052 int ret; 1053 1054 *key = NULL; 1055 1056 ret = hx509_certs_init(context, fn, 0, NULL, &certs); 1057 if (ret) 1058 hx509_err(context, 1, ret, "hx509_certs_init: %s", fn); 1059 1060 ret = _hx509_certs_keys_get(context, certs, &keys); 1061 hx509_certs_free(&certs); 1062 if (ret) 1063 hx509_err(context, 1, ret, "hx509_certs_keys_get"); 1064 if (keys[0] == NULL) 1065 errx(1, "no keys in key store: %s", fn); 1066 1067 *key = _hx509_private_key_ref(keys[0]); 1068 _hx509_certs_keys_free(context, keys); 1069 1070 return 0; 1071 } 1072 1073 static void 1074 get_key(const char *fn, const char *type, int optbits, 1075 hx509_private_key *signer) 1076 { 1077 int ret; 1078 1079 if (type) { 1080 BIGNUM *e; 1081 RSA *rsa; 1082 unsigned char *p0, *p; 1083 size_t len; 1084 int bits = 1024; 1085 1086 if (fn == NULL) 1087 errx(1, "no key argument, don't know here to store key"); 1088 1089 if (strcasecmp(type, "rsa") != 0) 1090 errx(1, "can only handle rsa keys for now"); 1091 1092 e = BN_new(); 1093 BN_set_word(e, 0x10001); 1094 1095 if (optbits) 1096 bits = optbits; 1097 1098 rsa = RSA_new(); 1099 if(rsa == NULL) 1100 errx(1, "RSA_new failed"); 1101 1102 ret = RSA_generate_key_ex(rsa, bits, e, NULL); 1103 if(ret != 1) 1104 errx(1, "RSA_new failed"); 1105 1106 BN_free(e); 1107 1108 len = i2d_RSAPrivateKey(rsa, NULL); 1109 1110 p0 = p = malloc(len); 1111 if (p == NULL) 1112 errx(1, "out of memory"); 1113 1114 i2d_RSAPrivateKey(rsa, &p); 1115 1116 rk_dumpdata(fn, p0, len); 1117 memset(p0, 0, len); 1118 free(p0); 1119 1120 RSA_free(rsa); 1121 1122 } else if (fn == NULL) 1123 err(1, "no private key"); 1124 1125 ret = read_private_key(fn, signer); 1126 if (ret) 1127 err(1, "read_private_key"); 1128 } 1129 1130 int 1131 request_create(struct request_create_options *opt, int argc, char **argv) 1132 { 1133 heim_octet_string request; 1134 hx509_request req; 1135 int ret, i; 1136 hx509_private_key signer; 1137 SubjectPublicKeyInfo key; 1138 const char *outfile = argv[0]; 1139 1140 memset(&key, 0, sizeof(key)); 1141 1142 get_key(opt->key_string, 1143 opt->generate_key_string, 1144 opt->key_bits_integer, 1145 &signer); 1146 1147 _hx509_request_init(context, &req); 1148 1149 if (opt->subject_string) { 1150 hx509_name name = NULL; 1151 1152 ret = hx509_parse_name(context, opt->subject_string, &name); 1153 if (ret) 1154 errx(1, "hx509_parse_name: %d\n", ret); 1155 _hx509_request_set_name(context, req, name); 1156 1157 if (opt->verbose_flag) { 1158 char *s; 1159 hx509_name_to_string(name, &s); 1160 printf("%s\n", s); 1161 } 1162 hx509_name_free(&name); 1163 } 1164 1165 for (i = 0; i < opt->email_strings.num_strings; i++) { 1166 ret = _hx509_request_add_email(context, req, 1167 opt->email_strings.strings[i]); 1168 } 1169 1170 for (i = 0; i < opt->dnsname_strings.num_strings; i++) { 1171 ret = _hx509_request_add_dns_name(context, req, 1172 opt->dnsname_strings.strings[i]); 1173 } 1174 1175 1176 ret = _hx509_private_key2SPKI(context, signer, &key); 1177 if (ret) 1178 errx(1, "_hx509_private_key2SPKI: %d\n", ret); 1179 1180 ret = _hx509_request_set_SubjectPublicKeyInfo(context, 1181 req, 1182 &key); 1183 free_SubjectPublicKeyInfo(&key); 1184 if (ret) 1185 hx509_err(context, 1, ret, "_hx509_request_set_SubjectPublicKeyInfo"); 1186 1187 ret = _hx509_request_to_pkcs10(context, 1188 req, 1189 signer, 1190 &request); 1191 if (ret) 1192 hx509_err(context, 1, ret, "_hx509_request_to_pkcs10"); 1193 1194 _hx509_private_key_free(&signer); 1195 _hx509_request_free(&req); 1196 1197 if (ret == 0) 1198 rk_dumpdata(outfile, request.data, request.length); 1199 der_free_octet_string(&request); 1200 1201 return 0; 1202 } 1203 1204 int 1205 request_print(struct request_print_options *opt, int argc, char **argv) 1206 { 1207 int ret, i; 1208 1209 printf("request print\n"); 1210 1211 for (i = 0; i < argc; i++) { 1212 hx509_request req; 1213 1214 ret = _hx509_request_parse(context, argv[i], &req); 1215 if (ret) 1216 hx509_err(context, 1, ret, "parse_request: %s", argv[i]); 1217 1218 ret = _hx509_request_print(context, req, stdout); 1219 _hx509_request_free(&req); 1220 if (ret) 1221 hx509_err(context, 1, ret, "Failed to print file %s", argv[i]); 1222 } 1223 1224 return 0; 1225 } 1226 1227 int 1228 info(void *opt, int argc, char **argv) 1229 { 1230 1231 ENGINE_add_conf_module(); 1232 1233 { 1234 const RSA_METHOD *m = RSA_get_default_method(); 1235 if (m != NULL) 1236 printf("rsa: %s\n", m->name); 1237 } 1238 { 1239 const DH_METHOD *m = DH_get_default_method(); 1240 if (m != NULL) 1241 printf("dh: %s\n", m->name); 1242 } 1243 { 1244 int ret = RAND_status(); 1245 printf("rand: %s\n", ret == 1 ? "ok" : "not available"); 1246 } 1247 1248 return 0; 1249 } 1250 1251 int 1252 random_data(void *opt, int argc, char **argv) 1253 { 1254 void *ptr; 1255 int len, ret; 1256 1257 len = parse_bytes(argv[0], "byte"); 1258 if (len <= 0) { 1259 fprintf(stderr, "bad argument to random-data\n"); 1260 return 1; 1261 } 1262 1263 ptr = malloc(len); 1264 if (ptr == NULL) { 1265 fprintf(stderr, "out of memory\n"); 1266 return 1; 1267 } 1268 1269 ret = RAND_bytes(ptr, len); 1270 if (ret != 1) { 1271 free(ptr); 1272 fprintf(stderr, "did not get cryptographic strong random\n"); 1273 return 1; 1274 } 1275 1276 fwrite(ptr, len, 1, stdout); 1277 fflush(stdout); 1278 1279 free(ptr); 1280 1281 return 0; 1282 } 1283 1284 int 1285 crypto_available(struct crypto_available_options *opt, int argc, char **argv) 1286 { 1287 AlgorithmIdentifier *val; 1288 unsigned int len, i; 1289 int ret, type; 1290 1291 if (opt->type_string) { 1292 if (strcmp(opt->type_string, "all") == 0) 1293 type = HX509_SELECT_ALL; 1294 else if (strcmp(opt->type_string, "digest") == 0) 1295 type = HX509_SELECT_DIGEST; 1296 else if (strcmp(opt->type_string, "public-sig") == 0) 1297 type = HX509_SELECT_PUBLIC_SIG; 1298 else if (strcmp(opt->type_string, "secret") == 0) 1299 type = HX509_SELECT_SECRET_ENC; 1300 else 1301 errx(1, "unknown type: %s", opt->type_string); 1302 } else 1303 type = HX509_SELECT_ALL; 1304 1305 ret = hx509_crypto_available(context, type, NULL, &val, &len); 1306 if (ret) 1307 errx(1, "hx509_crypto_available"); 1308 1309 for (i = 0; i < len; i++) { 1310 char *s; 1311 der_print_heim_oid (&val[i].algorithm, '.', &s); 1312 printf("%s\n", s); 1313 free(s); 1314 } 1315 1316 hx509_crypto_free_algs(val, len); 1317 1318 return 0; 1319 } 1320 1321 int 1322 crypto_select(struct crypto_select_options *opt, int argc, char **argv) 1323 { 1324 hx509_peer_info peer = NULL; 1325 AlgorithmIdentifier selected; 1326 int ret, type; 1327 char *s; 1328 1329 if (opt->type_string) { 1330 if (strcmp(opt->type_string, "digest") == 0) 1331 type = HX509_SELECT_DIGEST; 1332 else if (strcmp(opt->type_string, "public-sig") == 0) 1333 type = HX509_SELECT_PUBLIC_SIG; 1334 else if (strcmp(opt->type_string, "secret") == 0) 1335 type = HX509_SELECT_SECRET_ENC; 1336 else 1337 errx(1, "unknown type: %s", opt->type_string); 1338 } else 1339 type = HX509_SELECT_DIGEST; 1340 1341 if (opt->peer_cmstype_strings.num_strings) 1342 peer_strings(context, &peer, &opt->peer_cmstype_strings); 1343 1344 ret = hx509_crypto_select(context, type, NULL, peer, &selected); 1345 if (ret) 1346 errx(1, "hx509_crypto_available"); 1347 1348 der_print_heim_oid (&selected.algorithm, '.', &s); 1349 printf("%s\n", s); 1350 free(s); 1351 free_AlgorithmIdentifier(&selected); 1352 1353 hx509_peer_info_free(peer); 1354 1355 return 0; 1356 } 1357 1358 int 1359 hxtool_hex(struct hex_options *opt, int argc, char **argv) 1360 { 1361 1362 if (opt->decode_flag) { 1363 char buf[1024], buf2[1024], *p; 1364 ssize_t len; 1365 1366 while(fgets(buf, sizeof(buf), stdin) != NULL) { 1367 buf[strcspn(buf, "\r\n")] = '\0'; 1368 p = buf; 1369 while(isspace(*(unsigned char *)p)) 1370 p++; 1371 len = hex_decode(p, buf2, strlen(p)); 1372 if (len < 0) 1373 errx(1, "hex_decode failed"); 1374 if (fwrite(buf2, 1, len, stdout) != len) 1375 errx(1, "fwrite failed"); 1376 } 1377 } else { 1378 char buf[28], *p; 1379 size_t len; 1380 1381 while((len = fread(buf, 1, sizeof(buf), stdin)) != 0) { 1382 len = hex_encode(buf, len, &p); 1383 fprintf(stdout, "%s\n", p); 1384 free(p); 1385 } 1386 } 1387 return 0; 1388 } 1389 1390 static int 1391 eval_types(hx509_context context, 1392 hx509_ca_tbs tbs, 1393 const struct certificate_sign_options *opt) 1394 { 1395 int pkinit = 0; 1396 int i, ret; 1397 1398 for (i = 0; i < opt->type_strings.num_strings; i++) { 1399 const char *type = opt->type_strings.strings[i]; 1400 1401 if (strcmp(type, "https-server") == 0) { 1402 ret = hx509_ca_tbs_add_eku(context, tbs, 1403 oid_id_pkix_kp_serverAuth()); 1404 if (ret) 1405 hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku"); 1406 } else if (strcmp(type, "https-client") == 0) { 1407 ret = hx509_ca_tbs_add_eku(context, tbs, 1408 oid_id_pkix_kp_clientAuth()); 1409 if (ret) 1410 hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku"); 1411 } else if (strcmp(type, "peap-server") == 0) { 1412 ret = hx509_ca_tbs_add_eku(context, tbs, 1413 oid_id_pkix_kp_serverAuth()); 1414 if (ret) 1415 hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku"); 1416 } else if (strcmp(type, "pkinit-kdc") == 0) { 1417 pkinit++; 1418 ret = hx509_ca_tbs_add_eku(context, tbs, 1419 oid_id_pkkdcekuoid()); 1420 if (ret) 1421 hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku"); 1422 } else if (strcmp(type, "pkinit-client") == 0) { 1423 pkinit++; 1424 ret = hx509_ca_tbs_add_eku(context, tbs, 1425 oid_id_pkekuoid()); 1426 if (ret) 1427 hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku"); 1428 1429 ret = hx509_ca_tbs_add_eku(context, tbs, 1430 oid_id_ms_client_authentication()); 1431 if (ret) 1432 hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku"); 1433 1434 ret = hx509_ca_tbs_add_eku(context, tbs, 1435 oid_id_pkinit_ms_eku()); 1436 if (ret) 1437 hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku"); 1438 1439 } else if (strcmp(type, "email") == 0) { 1440 ret = hx509_ca_tbs_add_eku(context, tbs, 1441 oid_id_pkix_kp_emailProtection()); 1442 if (ret) 1443 hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku"); 1444 } else 1445 errx(1, "unknown type %s", type); 1446 } 1447 1448 if (pkinit > 1) 1449 errx(1, "More the one PK-INIT type given"); 1450 1451 if (opt->pk_init_principal_string) { 1452 if (!pkinit) 1453 errx(1, "pk-init principal given but no pk-init oid"); 1454 1455 ret = hx509_ca_tbs_add_san_pkinit(context, tbs, 1456 opt->pk_init_principal_string); 1457 if (ret) 1458 hx509_err(context, 1, ret, "hx509_ca_tbs_add_san_pkinit"); 1459 } 1460 1461 if (opt->ms_upn_string) { 1462 if (!pkinit) 1463 errx(1, "MS up given but no pk-init oid"); 1464 1465 ret = hx509_ca_tbs_add_san_ms_upn(context, tbs, opt->ms_upn_string); 1466 if (ret) 1467 hx509_err(context, 1, ret, "hx509_ca_tbs_add_san_ms_upn"); 1468 } 1469 1470 1471 for (i = 0; i < opt->hostname_strings.num_strings; i++) { 1472 const char *hostname = opt->hostname_strings.strings[i]; 1473 1474 ret = hx509_ca_tbs_add_san_hostname(context, tbs, hostname); 1475 if (ret) 1476 hx509_err(context, 1, ret, "hx509_ca_tbs_add_san_hostname"); 1477 } 1478 1479 for (i = 0; i < opt->email_strings.num_strings; i++) { 1480 const char *email = opt->email_strings.strings[i]; 1481 1482 ret = hx509_ca_tbs_add_san_rfc822name(context, tbs, email); 1483 if (ret) 1484 hx509_err(context, 1, ret, "hx509_ca_tbs_add_san_hostname"); 1485 1486 ret = hx509_ca_tbs_add_eku(context, tbs, 1487 oid_id_pkix_kp_emailProtection()); 1488 if (ret) 1489 hx509_err(context, 1, ret, "hx509_ca_tbs_add_eku"); 1490 } 1491 1492 if (opt->jid_string) { 1493 ret = hx509_ca_tbs_add_san_jid(context, tbs, opt->jid_string); 1494 if (ret) 1495 hx509_err(context, 1, ret, "hx509_ca_tbs_add_san_jid"); 1496 } 1497 1498 return 0; 1499 } 1500 1501 int 1502 hxtool_ca(struct certificate_sign_options *opt, int argc, char **argv) 1503 { 1504 int ret; 1505 hx509_ca_tbs tbs; 1506 hx509_cert signer = NULL, cert = NULL; 1507 hx509_private_key private_key = NULL; 1508 hx509_private_key cert_key = NULL; 1509 hx509_name subject = NULL; 1510 SubjectPublicKeyInfo spki; 1511 int delta = 0; 1512 1513 memset(&spki, 0, sizeof(spki)); 1514 1515 if (opt->ca_certificate_string == NULL && !opt->self_signed_flag) 1516 errx(1, "--ca-certificate argument missing (not using --self-signed)"); 1517 if (opt->ca_private_key_string == NULL && opt->generate_key_string == NULL && opt->self_signed_flag) 1518 errx(1, "--ca-private-key argument missing (using --self-signed)"); 1519 if (opt->certificate_string == NULL) 1520 errx(1, "--certificate argument missing"); 1521 1522 if (opt->template_certificate_string) { 1523 if (opt->template_fields_string == NULL) 1524 errx(1, "--template-certificate not no --template-fields"); 1525 } 1526 1527 if (opt->lifetime_string) { 1528 delta = parse_time(opt->lifetime_string, "day"); 1529 if (delta < 0) 1530 errx(1, "Invalid lifetime: %s", opt->lifetime_string); 1531 } 1532 1533 if (opt->ca_certificate_string) { 1534 hx509_certs cacerts = NULL; 1535 hx509_query *q; 1536 1537 ret = hx509_certs_init(context, opt->ca_certificate_string, 0, 1538 NULL, &cacerts); 1539 if (ret) 1540 hx509_err(context, 1, ret, 1541 "hx509_certs_init: %s", opt->ca_certificate_string); 1542 1543 ret = hx509_query_alloc(context, &q); 1544 if (ret) 1545 errx(1, "hx509_query_alloc: %d", ret); 1546 1547 hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); 1548 if (!opt->issue_proxy_flag) 1549 hx509_query_match_option(q, HX509_QUERY_OPTION_KU_KEYCERTSIGN); 1550 1551 ret = hx509_certs_find(context, cacerts, q, &signer); 1552 hx509_query_free(context, q); 1553 hx509_certs_free(&cacerts); 1554 if (ret) 1555 hx509_err(context, 1, ret, "no CA certificate found"); 1556 } else if (opt->self_signed_flag) { 1557 if (opt->generate_key_string == NULL 1558 && opt->ca_private_key_string == NULL) 1559 errx(1, "no signing private key"); 1560 } else 1561 errx(1, "missing ca key"); 1562 1563 if (opt->ca_private_key_string) { 1564 1565 ret = read_private_key(opt->ca_private_key_string, &private_key); 1566 if (ret) 1567 err(1, "read_private_key"); 1568 1569 ret = _hx509_private_key2SPKI(context, private_key, &spki); 1570 if (ret) 1571 errx(1, "_hx509_private_key2SPKI: %d\n", ret); 1572 1573 if (opt->self_signed_flag) 1574 cert_key = private_key; 1575 } 1576 1577 if (opt->req_string) { 1578 hx509_request req; 1579 1580 ret = _hx509_request_parse(context, opt->req_string, &req); 1581 if (ret) 1582 hx509_err(context, 1, ret, "parse_request: %s", opt->req_string); 1583 ret = _hx509_request_get_name(context, req, &subject); 1584 if (ret) 1585 hx509_err(context, 1, ret, "get name"); 1586 ret = _hx509_request_get_SubjectPublicKeyInfo(context, req, &spki); 1587 if (ret) 1588 hx509_err(context, 1, ret, "get spki"); 1589 _hx509_request_free(&req); 1590 } 1591 1592 if (opt->generate_key_string) { 1593 struct hx509_generate_private_context *keyctx; 1594 1595 ret = _hx509_generate_private_key_init(context, 1596 oid_id_pkcs1_rsaEncryption(), 1597 &keyctx); 1598 1599 if (opt->issue_ca_flag) 1600 _hx509_generate_private_key_is_ca(context, keyctx); 1601 1602 if (opt->key_bits_integer) 1603 _hx509_generate_private_key_bits(context, keyctx, 1604 opt->key_bits_integer); 1605 1606 ret = _hx509_generate_private_key(context, keyctx, 1607 &cert_key); 1608 _hx509_generate_private_key_free(&keyctx); 1609 if (ret) 1610 hx509_err(context, 1, ret, "generate private key"); 1611 1612 ret = _hx509_private_key2SPKI(context, cert_key, &spki); 1613 if (ret) 1614 errx(1, "_hx509_private_key2SPKI: %d\n", ret); 1615 1616 if (opt->self_signed_flag) 1617 private_key = cert_key; 1618 } 1619 1620 if (opt->certificate_private_key_string) { 1621 ret = read_private_key(opt->certificate_private_key_string, &cert_key); 1622 if (ret) 1623 err(1, "read_private_key for certificate"); 1624 } 1625 1626 if (opt->subject_string) { 1627 if (subject) 1628 hx509_name_free(&subject); 1629 ret = hx509_parse_name(context, opt->subject_string, &subject); 1630 if (ret) 1631 hx509_err(context, 1, ret, "hx509_parse_name"); 1632 } 1633 1634 /* 1635 * 1636 */ 1637 1638 ret = hx509_ca_tbs_init(context, &tbs); 1639 if (ret) 1640 hx509_err(context, 1, ret, "hx509_ca_tbs_init"); 1641 1642 if (opt->template_certificate_string) { 1643 hx509_cert template; 1644 hx509_certs tcerts; 1645 int flags; 1646 1647 ret = hx509_certs_init(context, opt->template_certificate_string, 0, 1648 NULL, &tcerts); 1649 if (ret) 1650 hx509_err(context, 1, ret, 1651 "hx509_certs_init: %s", opt->template_certificate_string); 1652 1653 ret = hx509_get_one_cert(context, tcerts, &template); 1654 1655 hx509_certs_free(&tcerts); 1656 if (ret) 1657 hx509_err(context, 1, ret, "no template certificate found"); 1658 1659 flags = parse_units(opt->template_fields_string, 1660 hx509_ca_tbs_template_units(), ""); 1661 1662 ret = hx509_ca_tbs_set_template(context, tbs, flags, template); 1663 if (ret) 1664 hx509_err(context, 1, ret, "hx509_ca_tbs_set_template"); 1665 1666 hx509_cert_free(template); 1667 } 1668 1669 if (opt->serial_number_string) { 1670 heim_integer serialNumber; 1671 1672 ret = der_parse_hex_heim_integer(opt->serial_number_string, 1673 &serialNumber); 1674 if (ret) 1675 err(1, "der_parse_hex_heim_integer"); 1676 ret = hx509_ca_tbs_set_serialnumber(context, tbs, &serialNumber); 1677 if (ret) 1678 hx509_err(context, 1, ret, "hx509_ca_tbs_init"); 1679 der_free_heim_integer(&serialNumber); 1680 } 1681 1682 if (spki.subjectPublicKey.length) { 1683 ret = hx509_ca_tbs_set_spki(context, tbs, &spki); 1684 if (ret) 1685 hx509_err(context, 1, ret, "hx509_ca_tbs_set_spki"); 1686 } 1687 1688 if (subject) { 1689 ret = hx509_ca_tbs_set_subject(context, tbs, subject); 1690 if (ret) 1691 hx509_err(context, 1, ret, "hx509_ca_tbs_set_subject"); 1692 } 1693 1694 if (opt->crl_uri_string) { 1695 ret = hx509_ca_tbs_add_crl_dp_uri(context, tbs, 1696 opt->crl_uri_string, NULL); 1697 if (ret) 1698 hx509_err(context, 1, ret, "hx509_ca_tbs_add_crl_dp_uri"); 1699 } 1700 1701 eval_types(context, tbs, opt); 1702 1703 if (opt->issue_ca_flag) { 1704 ret = hx509_ca_tbs_set_ca(context, tbs, opt->path_length_integer); 1705 if (ret) 1706 hx509_err(context, 1, ret, "hx509_ca_tbs_set_ca"); 1707 } 1708 if (opt->issue_proxy_flag) { 1709 ret = hx509_ca_tbs_set_proxy(context, tbs, opt->path_length_integer); 1710 if (ret) 1711 hx509_err(context, 1, ret, "hx509_ca_tbs_set_proxy"); 1712 } 1713 if (opt->domain_controller_flag) { 1714 hx509_ca_tbs_set_domaincontroller(context, tbs); 1715 if (ret) 1716 hx509_err(context, 1, ret, "hx509_ca_tbs_set_domaincontroller"); 1717 } 1718 1719 if (delta) { 1720 ret = hx509_ca_tbs_set_notAfter_lifetime(context, tbs, delta); 1721 if (ret) 1722 hx509_err(context, 1, ret, "hx509_ca_tbs_set_notAfter_lifetime"); 1723 } 1724 1725 if (opt->self_signed_flag) { 1726 ret = hx509_ca_sign_self(context, tbs, private_key, &cert); 1727 if (ret) 1728 hx509_err(context, 1, ret, "hx509_ca_sign_self"); 1729 } else { 1730 ret = hx509_ca_sign(context, tbs, signer, &cert); 1731 if (ret) 1732 hx509_err(context, 1, ret, "hx509_ca_sign"); 1733 } 1734 1735 if (cert_key) { 1736 ret = _hx509_cert_assign_key(cert, cert_key); 1737 if (ret) 1738 hx509_err(context, 1, ret, "_hx509_cert_assign_key"); 1739 } 1740 1741 { 1742 hx509_certs certs; 1743 1744 ret = hx509_certs_init(context, opt->certificate_string, 1745 HX509_CERTS_CREATE, NULL, &certs); 1746 if (ret) 1747 hx509_err(context, 1, ret, "hx509_certs_init"); 1748 1749 ret = hx509_certs_add(context, certs, cert); 1750 if (ret) 1751 hx509_err(context, 1, ret, "hx509_certs_add"); 1752 1753 ret = hx509_certs_store(context, certs, 0, NULL); 1754 if (ret) 1755 hx509_err(context, 1, ret, "hx509_certs_store"); 1756 1757 hx509_certs_free(&certs); 1758 } 1759 1760 if (subject) 1761 hx509_name_free(&subject); 1762 if (signer) 1763 hx509_cert_free(signer); 1764 hx509_cert_free(cert); 1765 free_SubjectPublicKeyInfo(&spki); 1766 1767 if (private_key != cert_key) 1768 _hx509_private_key_free(&private_key); 1769 _hx509_private_key_free(&cert_key); 1770 1771 hx509_ca_tbs_free(&tbs); 1772 1773 return 0; 1774 } 1775 1776 static int 1777 test_one_cert(hx509_context hxcontext, void *ctx, hx509_cert cert) 1778 { 1779 heim_octet_string sd, c; 1780 hx509_verify_ctx vctx = ctx; 1781 hx509_certs signer = NULL; 1782 heim_oid type; 1783 int ret; 1784 1785 if (_hx509_cert_private_key(cert) == NULL) 1786 return 0; 1787 1788 ret = hx509_cms_create_signed_1(context, 0, NULL, NULL, 0, 1789 NULL, cert, NULL, NULL, NULL, &sd); 1790 if (ret) 1791 errx(1, "hx509_cms_create_signed_1"); 1792 1793 ret = hx509_cms_verify_signed(context, vctx, sd.data, sd.length, 1794 NULL, NULL, &type, &c, &signer); 1795 free(sd.data); 1796 if (ret) 1797 hx509_err(context, 1, ret, "hx509_cms_verify_signed"); 1798 1799 printf("create-signature verify-sigature done\n"); 1800 1801 free(c.data); 1802 1803 return 0; 1804 } 1805 1806 int 1807 test_crypto(struct test_crypto_options *opt, int argc, char ** argv) 1808 { 1809 hx509_verify_ctx vctx; 1810 hx509_certs certs; 1811 hx509_lock lock; 1812 int i, ret; 1813 1814 hx509_lock_init(context, &lock); 1815 lock_strings(lock, &opt->pass_strings); 1816 1817 ret = hx509_certs_init(context, "MEMORY:test-crypto", 0, NULL, &certs); 1818 1819 for (i = 0; i < argc; i++) { 1820 ret = hx509_certs_append(context, certs, lock, argv[i]); 1821 if (ret) 1822 hx509_err(context, 1, ret, "hx509_certs_append"); 1823 } 1824 1825 ret = hx509_verify_init_ctx(context, &vctx); 1826 if (ret) 1827 hx509_err(context, 1, ret, "hx509_verify_init_ctx"); 1828 1829 hx509_verify_attach_anchors(vctx, certs); 1830 1831 ret = hx509_certs_iter(context, certs, test_one_cert, vctx); 1832 1833 hx509_certs_free(&certs); 1834 1835 return 0; 1836 } 1837 1838 int 1839 statistic_print(struct statistic_print_options*opt, int argc, char **argv) 1840 { 1841 int type = 0; 1842 1843 if (stat_file_string == NULL) 1844 errx(1, "no stat file"); 1845 1846 if (opt->type_integer) 1847 type = opt->type_integer; 1848 1849 hx509_query_unparse_stats(context, type, stdout); 1850 return 0; 1851 } 1852 1853 /* 1854 * 1855 */ 1856 1857 int 1858 crl_sign(struct crl_sign_options *opt, int argc, char **argv) 1859 { 1860 hx509_crl crl; 1861 heim_octet_string os; 1862 hx509_cert signer = NULL; 1863 hx509_lock lock; 1864 int ret; 1865 1866 hx509_lock_init(context, &lock); 1867 lock_strings(lock, &opt->pass_strings); 1868 1869 ret = hx509_crl_alloc(context, &crl); 1870 if (ret) 1871 errx(1, "crl alloc"); 1872 1873 if (opt->signer_string == NULL) 1874 errx(1, "signer missing"); 1875 1876 { 1877 hx509_certs certs = NULL; 1878 hx509_query *q; 1879 1880 ret = hx509_certs_init(context, opt->signer_string, 0, 1881 NULL, &certs); 1882 if (ret) 1883 hx509_err(context, 1, ret, 1884 "hx509_certs_init: %s", opt->signer_string); 1885 1886 ret = hx509_query_alloc(context, &q); 1887 if (ret) 1888 hx509_err(context, 1, ret, "hx509_query_alloc: %d", ret); 1889 1890 hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); 1891 1892 ret = hx509_certs_find(context, certs, q, &signer); 1893 hx509_query_free(context, q); 1894 hx509_certs_free(&certs); 1895 if (ret) 1896 hx509_err(context, 1, ret, "no signer certificate found"); 1897 } 1898 1899 if (opt->lifetime_string) { 1900 int delta; 1901 1902 delta = parse_time(opt->lifetime_string, "day"); 1903 if (delta < 0) 1904 errx(1, "Invalid lifetime: %s", opt->lifetime_string); 1905 1906 hx509_crl_lifetime(context, crl, delta); 1907 } 1908 1909 { 1910 hx509_certs revoked = NULL; 1911 int i; 1912 1913 ret = hx509_certs_init(context, "MEMORY:revoked-certs", 0, 1914 NULL, &revoked); 1915 1916 for (i = 0; i < argc; i++) { 1917 ret = hx509_certs_append(context, revoked, lock, argv[i]); 1918 if (ret) 1919 hx509_err(context, 1, ret, "hx509_certs_append: %s", argv[i]); 1920 } 1921 1922 hx509_crl_add_revoked_certs(context, crl, revoked); 1923 hx509_certs_free(&revoked); 1924 } 1925 1926 hx509_crl_sign(context, signer, crl, &os); 1927 1928 if (opt->crl_file_string) 1929 rk_dumpdata(opt->crl_file_string, os.data, os.length); 1930 1931 free(os.data); 1932 1933 hx509_crl_free(context, &crl); 1934 hx509_cert_free(signer); 1935 hx509_lock_free(lock); 1936 1937 return 0; 1938 } 1939 1940 /* 1941 * 1942 */ 1943 1944 int 1945 help(void *opt, int argc, char **argv) 1946 { 1947 sl_slc_help(commands, argc, argv); 1948 return 0; 1949 } 1950 1951 int 1952 main(int argc, char **argv) 1953 { 1954 int ret, optidx = 0; 1955 1956 setprogname (argv[0]); 1957 1958 if(getarg(args, num_args, argc, argv, &optidx)) 1959 usage(1); 1960 if(help_flag) 1961 usage(0); 1962 if(version_flag) { 1963 print_version(NULL); 1964 exit(0); 1965 } 1966 argv += optidx; 1967 argc -= optidx; 1968 1969 if (argc == 0) 1970 usage(1); 1971 1972 ret = hx509_context_init(&context); 1973 if (ret) 1974 errx(1, "hx509_context_init failed with %d", ret); 1975 1976 if (stat_file_string) 1977 hx509_query_statistic_file(context, stat_file_string); 1978 1979 ret = sl_command(commands, argc, argv); 1980 if(ret == -1) 1981 warnx ("unrecognized command: %s", argv[0]); 1982 1983 hx509_context_free(&context); 1984 1985 return ret; 1986 } 1987