1 /* $OpenBSD: x509.c,v 1.36 2024/01/12 11:24:03 job Exp $ */ 2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3 * All rights reserved. 4 * 5 * This package is an SSL implementation written 6 * by Eric Young (eay@cryptsoft.com). 7 * The implementation was written so as to conform with Netscapes SSL. 8 * 9 * This library is free for commercial and non-commercial use as long as 10 * the following conditions are aheared to. The following conditions 11 * apply to all code found in this distribution, be it the RC4, RSA, 12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13 * included with this distribution is covered by the same copyright terms 14 * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15 * 16 * Copyright remains Eric Young's, and as such any Copyright notices in 17 * the code are not to be removed. 18 * If this package is used in a product, Eric Young should be given attribution 19 * as the author of the parts of the library used. 20 * This can be in the form of a textual message at program startup or 21 * in documentation (online or textual) provided with the package. 22 * 23 * Redistribution and use in source and binary forms, with or without 24 * modification, are permitted provided that the following conditions 25 * are met: 26 * 1. Redistributions of source code must retain the copyright 27 * notice, this list of conditions and the following disclaimer. 28 * 2. Redistributions in binary form must reproduce the above copyright 29 * notice, this list of conditions and the following disclaimer in the 30 * documentation and/or other materials provided with the distribution. 31 * 3. All advertising materials mentioning features or use of this software 32 * must display the following acknowledgement: 33 * "This product includes cryptographic software written by 34 * Eric Young (eay@cryptsoft.com)" 35 * The word 'cryptographic' can be left out if the rouines from the library 36 * being used are not cryptographic related :-). 37 * 4. If you include any Windows specific code (or a derivative thereof) from 38 * the apps directory (application code) you must include an acknowledgement: 39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40 * 41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 * SUCH DAMAGE. 52 * 53 * The licence and distribution terms for any publically available version or 54 * derivative of this code cannot be changed. i.e. this code cannot simply be 55 * copied and put under another distribution licence 56 * [including the GNU Public Licence.] 57 */ 58 59 #include <assert.h> 60 #include <limits.h> 61 #include <stdio.h> 62 #include <stdlib.h> 63 #include <string.h> 64 65 #include "apps.h" 66 67 #include <openssl/asn1.h> 68 #include <openssl/bio.h> 69 #include <openssl/bn.h> 70 #include <openssl/dsa.h> 71 #include <openssl/err.h> 72 #include <openssl/evp.h> 73 #include <openssl/objects.h> 74 #include <openssl/pem.h> 75 #include <openssl/rsa.h> 76 #include <openssl/x509.h> 77 #include <openssl/x509v3.h> 78 79 #define POSTFIX ".srl" 80 #define DEF_DAYS 30 81 82 static int callb(int ok, X509_STORE_CTX *ctx); 83 static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, 84 const EVP_MD *digest, CONF *conf, char *section, X509_NAME *issuer); 85 static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest, 86 X509 *x, X509 *xca, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *sigopts, 87 char *serial, int create, int days, int clrext, CONF *conf, char *section, 88 ASN1_INTEGER *sno, X509_NAME *issuer); 89 static int purpose_print(BIO *bio, X509 *cert, const X509_PURPOSE *pt); 90 91 static struct { 92 char *alias; 93 int aliasout; 94 int badops; 95 int C; 96 int CA_createserial; 97 int CA_flag; 98 char *CAfile; 99 int CAformat; 100 char *CAkeyfile; 101 int CAkeyformat; 102 char *CAserial; 103 unsigned long certflag; 104 int checkend; 105 int checkoffset; 106 unsigned long chtype; 107 int clrext; 108 int clrreject; 109 int clrtrust; 110 int days; 111 const EVP_MD *digest; 112 int email; 113 int enddate; 114 char *extfile; 115 char *extsect; 116 int fingerprint; 117 char *force_pubkey; 118 char *infile; 119 int informat; 120 int issuer; 121 int issuer_hash; 122 #ifndef OPENSSL_NO_MD5 123 int issuer_hash_old; 124 #endif 125 char *keyfile; 126 int keyformat; 127 const EVP_MD *md_alg; 128 int modulus; 129 int multirdn; 130 int next_serial; 131 unsigned long nmflag; 132 int noout; 133 int num; 134 int ocspid; 135 ASN1_OBJECT *objtmp; 136 int ocsp_uri; 137 char *outfile; 138 int outformat; 139 char *passargin; 140 int pprint; 141 int pubkey; 142 STACK_OF(ASN1_OBJECT) *reject; 143 int reqfile; 144 int serial; 145 char *set_issuer; 146 char *set_subject; 147 int sign_flag; 148 STACK_OF(OPENSSL_STRING) *sigopts; 149 ASN1_INTEGER *sno; 150 int startdate; 151 int subject; 152 int subject_hash; 153 #ifndef OPENSSL_NO_MD5 154 int subject_hash_old; 155 #endif 156 int text; 157 STACK_OF(ASN1_OBJECT) *trust; 158 int trustout; 159 int x509req; 160 } cfg; 161 162 static int 163 x509_opt_addreject(char *arg) 164 { 165 if ((cfg.objtmp = OBJ_txt2obj(arg, 0)) == NULL) { 166 BIO_printf(bio_err, "Invalid reject object value %s\n", arg); 167 return (1); 168 } 169 170 if (cfg.reject == NULL && 171 (cfg.reject = sk_ASN1_OBJECT_new_null()) == NULL) 172 return (1); 173 174 if (!sk_ASN1_OBJECT_push(cfg.reject, cfg.objtmp)) 175 return (1); 176 177 cfg.trustout = 1; 178 return (0); 179 } 180 181 static int 182 x509_opt_addtrust(char *arg) 183 { 184 if ((cfg.objtmp = OBJ_txt2obj(arg, 0)) == NULL) { 185 BIO_printf(bio_err, "Invalid trust object value %s\n", arg); 186 return (1); 187 } 188 189 if (cfg.trust == NULL && 190 (cfg.trust = sk_ASN1_OBJECT_new_null()) == NULL) 191 return (1); 192 193 if (!sk_ASN1_OBJECT_push(cfg.trust, cfg.objtmp)) 194 return (1); 195 196 cfg.trustout = 1; 197 return (0); 198 } 199 200 static int 201 x509_opt_ca(char *arg) 202 { 203 cfg.CAfile = arg; 204 cfg.CA_flag = ++cfg.num; 205 return (0); 206 } 207 208 static int 209 x509_opt_certopt(char *arg) 210 { 211 if (!set_cert_ex(&cfg.certflag, arg)) 212 return (1); 213 214 return (0); 215 } 216 217 static int 218 x509_opt_checkend(char *arg) 219 { 220 const char *errstr; 221 222 cfg.checkoffset = strtonum(arg, 0, INT_MAX, &errstr); 223 if (errstr != NULL) { 224 BIO_printf(bio_err, "checkend unusable: %s\n", errstr); 225 return (1); 226 } 227 cfg.checkend = 1; 228 return (0); 229 } 230 231 static int 232 x509_opt_dates(void) 233 { 234 cfg.startdate = ++cfg.num; 235 cfg.enddate = ++cfg.num; 236 return (0); 237 } 238 239 static int 240 x509_opt_days(char *arg) 241 { 242 const char *errstr; 243 244 cfg.days = strtonum(arg, 1, INT_MAX, &errstr); 245 if (errstr != NULL) { 246 BIO_printf(bio_err, "bad number of days: %s\n", errstr); 247 return (1); 248 } 249 return (0); 250 } 251 252 static int 253 x509_opt_digest(int argc, char **argv, int *argsused) 254 { 255 char *name = argv[0]; 256 257 if (*name++ != '-') 258 return (1); 259 260 if ((cfg.md_alg = EVP_get_digestbyname(name)) != NULL) { 261 cfg.digest = cfg.md_alg; 262 } else { 263 BIO_printf(bio_err, "unknown option %s\n", *argv); 264 cfg.badops = 1; 265 return (1); 266 } 267 268 *argsused = 1; 269 return (0); 270 } 271 272 static int 273 x509_opt_nameopt(char *arg) 274 { 275 if (!set_name_ex(&cfg.nmflag, arg)) 276 return (1); 277 278 return (0); 279 } 280 281 static int 282 x509_opt_set_serial(char *arg) 283 { 284 ASN1_INTEGER_free(cfg.sno); 285 if ((cfg.sno = s2i_ASN1_INTEGER(NULL, arg)) == NULL) 286 return (1); 287 288 return (0); 289 } 290 291 static int 292 x509_opt_setalias(char *arg) 293 { 294 cfg.alias = arg; 295 cfg.trustout = 1; 296 return (0); 297 } 298 299 static int 300 x509_opt_signkey(char *arg) 301 { 302 cfg.keyfile = arg; 303 cfg.sign_flag = ++cfg.num; 304 return (0); 305 } 306 307 static int 308 x509_opt_sigopt(char *arg) 309 { 310 if (cfg.sigopts == NULL && 311 (cfg.sigopts = sk_OPENSSL_STRING_new_null()) == NULL) 312 return (1); 313 314 if (!sk_OPENSSL_STRING_push(cfg.sigopts, arg)) 315 return (1); 316 317 return (0); 318 } 319 320 static int 321 x509_opt_utf8(void) 322 { 323 cfg.chtype = MBSTRING_UTF8; 324 return (0); 325 } 326 327 static const struct option x509_options[] = { 328 { 329 .name = "C", 330 .desc = "Convert the certificate into C code", 331 .type = OPTION_ORDER, 332 .opt.order = &cfg.C, 333 .order = &cfg.num, 334 }, 335 { 336 .name = "addreject", 337 .argname = "arg", 338 .desc = "Reject certificate for a given purpose", 339 .type = OPTION_ARG_FUNC, 340 .opt.argfunc = x509_opt_addreject, 341 }, 342 { 343 .name = "addtrust", 344 .argname = "arg", 345 .desc = "Trust certificate for a given purpose", 346 .type = OPTION_ARG_FUNC, 347 .opt.argfunc = x509_opt_addtrust, 348 }, 349 { 350 .name = "alias", 351 .desc = "Output certificate alias", 352 .type = OPTION_ORDER, 353 .opt.order = &cfg.aliasout, 354 .order = &cfg.num, 355 }, 356 { 357 .name = "CA", 358 .argname = "file", 359 .desc = "CA certificate in PEM format unless -CAform is specified", 360 .type = OPTION_ARG_FUNC, 361 .opt.argfunc = x509_opt_ca, 362 }, 363 { 364 .name = "CAcreateserial", 365 .desc = "Create serial number file if it does not exist", 366 .type = OPTION_ORDER, 367 .opt.order = &cfg.CA_createserial, 368 .order = &cfg.num, 369 }, 370 { 371 .name = "CAform", 372 .argname = "fmt", 373 .desc = "CA format - default PEM", 374 .type = OPTION_ARG_FORMAT, 375 .opt.value = &cfg.CAformat, 376 }, 377 { 378 .name = "CAkey", 379 .argname = "file", 380 .desc = "CA key in PEM format unless -CAkeyform is specified\n" 381 "if omitted, the key is assumed to be in the CA file", 382 .type = OPTION_ARG, 383 .opt.arg = &cfg.CAkeyfile, 384 }, 385 { 386 .name = "CAkeyform", 387 .argname = "fmt", 388 .desc = "CA key format - default PEM", 389 .type = OPTION_ARG_FORMAT, 390 .opt.value = &cfg.CAkeyformat, 391 }, 392 { 393 .name = "CAserial", 394 .argname = "file", 395 .desc = "Serial file", 396 .type = OPTION_ARG, 397 .opt.arg = &cfg.CAserial, 398 }, 399 { 400 .name = "certopt", 401 .argname = "option", 402 .desc = "Various certificate text options", 403 .type = OPTION_ARG_FUNC, 404 .opt.argfunc = x509_opt_certopt, 405 }, 406 { 407 .name = "checkend", 408 .argname = "arg", 409 .desc = "Check whether the cert expires in the next arg seconds\n" 410 "exit 1 if so, 0 if not", 411 .type = OPTION_ARG_FUNC, 412 .opt.argfunc = x509_opt_checkend, 413 }, 414 { 415 .name = "clrext", 416 .desc = "Clear all extensions", 417 .type = OPTION_FLAG, 418 .opt.flag = &cfg.clrext, 419 }, 420 { 421 .name = "clrreject", 422 .desc = "Clear all rejected purposes", 423 .type = OPTION_ORDER, 424 .opt.order = &cfg.clrreject, 425 .order = &cfg.num, 426 }, 427 { 428 .name = "clrtrust", 429 .desc = "Clear all trusted purposes", 430 .type = OPTION_ORDER, 431 .opt.order = &cfg.clrtrust, 432 .order = &cfg.num, 433 }, 434 { 435 .name = "dates", 436 .desc = "Both Before and After dates", 437 .type = OPTION_FUNC, 438 .opt.func = x509_opt_dates, 439 }, 440 { 441 .name = "days", 442 .argname = "arg", 443 .desc = "How long till expiry of a signed certificate - def 30 days", 444 .type = OPTION_ARG_FUNC, 445 .opt.argfunc = x509_opt_days, 446 }, 447 { 448 .name = "email", 449 .desc = "Print email address(es)", 450 .type = OPTION_ORDER, 451 .opt.order = &cfg.email, 452 .order = &cfg.num, 453 }, 454 { 455 .name = "enddate", 456 .desc = "Print notAfter field", 457 .type = OPTION_ORDER, 458 .opt.order = &cfg.enddate, 459 .order = &cfg.num, 460 }, 461 { 462 .name = "extensions", 463 .argname = "section", 464 .desc = "Section from config file with X509V3 extensions to add", 465 .type = OPTION_ARG, 466 .opt.arg = &cfg.extsect, 467 }, 468 { 469 .name = "extfile", 470 .argname = "file", 471 .desc = "Configuration file with X509V3 extensions to add", 472 .type = OPTION_ARG, 473 .opt.arg = &cfg.extfile, 474 }, 475 { 476 .name = "fingerprint", 477 .desc = "Print the certificate fingerprint", 478 .type = OPTION_ORDER, 479 .opt.order = &cfg.fingerprint, 480 .order = &cfg.num, 481 }, 482 { 483 .name = "force_pubkey", 484 .argname = "key", 485 .desc = "Force the public key to be put in the certificate", 486 .type = OPTION_ARG, 487 .opt.arg = &cfg.force_pubkey, 488 }, 489 { 490 .name = "hash", 491 .desc = "Synonym for -subject_hash", 492 .type = OPTION_ORDER, 493 .opt.order = &cfg.subject_hash, 494 .order = &cfg.num, 495 }, 496 { 497 .name = "in", 498 .argname = "file", 499 .desc = "Input file - default stdin", 500 .type = OPTION_ARG, 501 .opt.arg = &cfg.infile, 502 }, 503 { 504 .name = "inform", 505 .argname = "fmt", 506 .desc = "Input format - default PEM (one of DER, NET or PEM)", 507 .type = OPTION_ARG_FORMAT, 508 .opt.value = &cfg.informat, 509 }, 510 { 511 .name = "issuer", 512 .desc = "Print issuer name", 513 .type = OPTION_ORDER, 514 .opt.order = &cfg.issuer, 515 .order = &cfg.num, 516 }, 517 { 518 .name = "issuer_hash", 519 .desc = "Print issuer hash value", 520 .type = OPTION_ORDER, 521 .opt.order = &cfg.issuer_hash, 522 .order = &cfg.num, 523 }, 524 #ifndef OPENSSL_NO_MD5 525 { 526 .name = "issuer_hash_old", 527 .desc = "Print old-style (MD5) issuer hash value", 528 .type = OPTION_ORDER, 529 .opt.order = &cfg.issuer_hash_old, 530 .order = &cfg.num, 531 }, 532 #endif 533 { 534 .name = "keyform", 535 .argname = "fmt", 536 .desc = "Private key format - default PEM", 537 .type = OPTION_ARG_FORMAT, 538 .opt.value = &cfg.keyformat, 539 }, 540 { 541 .name = "modulus", 542 .desc = "Print the RSA key modulus", 543 .type = OPTION_ORDER, 544 .opt.order = &cfg.modulus, 545 .order = &cfg.num, 546 }, 547 { 548 .name = "multivalue-rdn", 549 .desc = "Enable support for multivalued RDNs", 550 .type = OPTION_FLAG, 551 .opt.flag = &cfg.multirdn, 552 }, 553 { 554 .name = "nameopt", 555 .argname = "option", 556 .desc = "Various certificate name options", 557 .type = OPTION_ARG_FUNC, 558 .opt.argfunc = x509_opt_nameopt, 559 }, 560 { 561 .name = "next_serial", 562 .desc = "Print the next serial number", 563 .type = OPTION_ORDER, 564 .opt.order = &cfg.next_serial, 565 .order = &cfg.num, 566 }, 567 { 568 .name = "noout", 569 .desc = "No certificate output", 570 .type = OPTION_ORDER, 571 .opt.order = &cfg.noout, 572 .order = &cfg.num, 573 }, 574 { 575 .name = "ocsp_uri", 576 .desc = "Print OCSP Responder URL(s)", 577 .type = OPTION_ORDER, 578 .opt.order = &cfg.ocsp_uri, 579 .order = &cfg.num, 580 }, 581 { 582 .name = "ocspid", 583 .desc = "Print OCSP hash values for the subject name and public key", 584 .type = OPTION_ORDER, 585 .opt.order = &cfg.ocspid, 586 .order = &cfg.num, 587 }, 588 { 589 .name = "out", 590 .argname = "file", 591 .desc = "Output file - default stdout", 592 .type = OPTION_ARG, 593 .opt.arg = &cfg.outfile, 594 }, 595 { 596 .name = "outform", 597 .argname = "fmt", 598 .desc = "Output format - default PEM (one of DER, NET or PEM)", 599 .type = OPTION_ARG_FORMAT, 600 .opt.value = &cfg.outformat, 601 }, 602 { 603 .name = "passin", 604 .argname = "src", 605 .desc = "Private key password source", 606 .type = OPTION_ARG, 607 .opt.arg = &cfg.passargin, 608 }, 609 { 610 .name = "pubkey", 611 .desc = "Output the public key", 612 .type = OPTION_ORDER, 613 .opt.order = &cfg.pubkey, 614 .order = &cfg.num, 615 }, 616 { 617 .name = "purpose", 618 .desc = "Print out certificate purposes", 619 .type = OPTION_ORDER, 620 .opt.order = &cfg.pprint, 621 .order = &cfg.num, 622 }, 623 { 624 .name = "req", 625 .desc = "Input is a certificate request, sign and output", 626 .type = OPTION_FLAG, 627 .opt.flag = &cfg.reqfile, 628 }, 629 { 630 .name = "serial", 631 .desc = "Print serial number value", 632 .type = OPTION_ORDER, 633 .opt.order = &cfg.serial, 634 .order = &cfg.num, 635 }, 636 { 637 .name = "set_issuer", 638 .argname = "name", 639 .desc = "Set the issuer name", 640 .type = OPTION_ARG, 641 .opt.arg = &cfg.set_issuer, 642 }, 643 { 644 .name = "set_serial", 645 .argname = "n", 646 .desc = "Serial number to use", 647 .type = OPTION_ARG_FUNC, 648 .opt.argfunc = x509_opt_set_serial, 649 }, 650 { 651 .name = "set_subject", 652 .argname = "name", 653 .desc = "Set the subject name", 654 .type = OPTION_ARG, 655 .opt.arg = &cfg.set_subject, 656 }, 657 { 658 .name = "setalias", 659 .argname = "arg", 660 .desc = "Set certificate alias", 661 .type = OPTION_ARG_FUNC, 662 .opt.argfunc = x509_opt_setalias, 663 }, 664 { 665 .name = "signkey", 666 .argname = "file", 667 .desc = "Self sign cert with arg", 668 .type = OPTION_ARG_FUNC, 669 .opt.argfunc = x509_opt_signkey, 670 }, 671 { 672 .name = "sigopt", 673 .argname = "nm:v", 674 .desc = "Various signature algorithm options", 675 .type = OPTION_ARG_FUNC, 676 .opt.argfunc = x509_opt_sigopt, 677 }, 678 { 679 .name = "startdate", 680 .desc = "Print notBefore field", 681 .type = OPTION_ORDER, 682 .opt.order = &cfg.startdate, 683 .order = &cfg.num, 684 }, 685 { 686 .name = "subj", 687 .type = OPTION_ARG, 688 .opt.arg = &cfg.set_subject, 689 }, 690 { 691 .name = "subject", 692 .desc = "Print subject name", 693 .type = OPTION_ORDER, 694 .opt.order = &cfg.subject, 695 .order = &cfg.num, 696 }, 697 { 698 .name = "subject_hash", 699 .desc = "Print subject hash value", 700 .type = OPTION_ORDER, 701 .opt.order = &cfg.subject_hash, 702 .order = &cfg.num, 703 }, 704 #ifndef OPENSSL_NO_MD5 705 { 706 .name = "subject_hash_old", 707 .desc = "Print old-style (MD5) subject hash value", 708 .type = OPTION_ORDER, 709 .opt.order = &cfg.subject_hash_old, 710 .order = &cfg.num, 711 }, 712 #endif 713 { 714 .name = "text", 715 .desc = "Print the certificate in text form", 716 .type = OPTION_ORDER, 717 .opt.order = &cfg.text, 718 .order = &cfg.num, 719 }, 720 { 721 .name = "trustout", 722 .desc = "Output a trusted certificate", 723 .type = OPTION_FLAG, 724 .opt.flag = &cfg.trustout, 725 }, 726 { 727 .name = "utf8", 728 .desc = "Input characters are in UTF-8 (default ASCII)", 729 .type = OPTION_FUNC, 730 .opt.func = x509_opt_utf8, 731 }, 732 { 733 .name = "x509toreq", 734 .desc = "Output a certification request object", 735 .type = OPTION_ORDER, 736 .opt.order = &cfg.x509req, 737 .order = &cfg.num, 738 }, 739 { 740 .name = NULL, 741 .desc = "", 742 .type = OPTION_ARGV_FUNC, 743 .opt.argvfunc = x509_opt_digest, 744 }, 745 { NULL }, 746 }; 747 748 static void 749 x509_usage(void) 750 { 751 fprintf(stderr, "usage: x509 " 752 "[-C] [-addreject arg] [-addtrust arg] [-alias] [-CA file]\n" 753 " [-CAcreateserial] [-CAform der | pem] [-CAkey file]\n" 754 " [-CAkeyform der | pem] [-CAserial file] [-certopt option]\n" 755 " [-checkend arg] [-clrext] [-clrreject] [-clrtrust] [-dates]\n" 756 " [-days arg] [-email] [-enddate] [-extensions section]\n" 757 " [-extfile file] [-fingerprint] [-force_pubkey key] [-hash]\n" 758 " [-in file] [-inform der | net | pem] [-issuer]\n" 759 " [-issuer_hash] [-issuer_hash_old] [-keyform der | pem]\n" 760 " [-md5 | -sha1] [-modulus] [-multivalue-rdn]\n" 761 " [-nameopt option] [-next_serial] [-noout] [-ocsp_uri]\n" 762 " [-ocspid] [-out file] [-outform der | net | pem]\n" 763 " [-passin arg] [-pubkey] [-purpose] [-req] [-serial]\n" 764 " [-set_issuer name] [-set_serial n] [-set_subject name]\n" 765 " [-setalias arg] [-signkey file] [-sigopt nm:v] [-startdate]\n" 766 " [-subject] [-subject_hash] [-subject_hash_old] [-text]\n" 767 " [-trustout] [-utf8] [-x509toreq]\n"); 768 fprintf(stderr, "\n"); 769 options_usage(x509_options); 770 fprintf(stderr, "\n"); 771 } 772 773 int 774 x509_main(int argc, char **argv) 775 { 776 int ret = 1; 777 X509_REQ *req = NULL; 778 X509 *x = NULL, *xca = NULL; 779 X509_NAME *iname = NULL, *sname = NULL; 780 EVP_PKEY *Fpkey = NULL, *Upkey = NULL, *CApkey = NULL; 781 int i; 782 BIO *out = NULL; 783 BIO *STDout = NULL; 784 X509_STORE *ctx = NULL; 785 X509_REQ *rq = NULL; 786 char buf[256]; 787 CONF *extconf = NULL; 788 char *passin = NULL; 789 790 if (pledge("stdio cpath wpath rpath tty", NULL) == -1) { 791 perror("pledge"); 792 exit(1); 793 } 794 795 memset(&cfg, 0, sizeof(cfg)); 796 cfg.chtype = MBSTRING_ASC; 797 cfg.days = DEF_DAYS; 798 cfg.informat = FORMAT_PEM; 799 cfg.outformat = FORMAT_PEM; 800 cfg.keyformat = FORMAT_PEM; 801 cfg.CAformat = FORMAT_PEM; 802 cfg.CAkeyformat = FORMAT_PEM; 803 804 STDout = BIO_new_fp(stdout, BIO_NOCLOSE); 805 806 ctx = X509_STORE_new(); 807 if (ctx == NULL) 808 goto end; 809 X509_STORE_set_verify_cb(ctx, callb); 810 811 if (options_parse(argc, argv, x509_options, NULL, NULL) != 0) 812 goto bad; 813 814 if (cfg.badops) { 815 bad: 816 x509_usage(); 817 goto end; 818 } 819 820 if (!app_passwd(bio_err, cfg.passargin, NULL, &passin, NULL)) { 821 BIO_printf(bio_err, "Error getting password\n"); 822 goto end; 823 } 824 if (!X509_STORE_set_default_paths(ctx)) { 825 ERR_print_errors(bio_err); 826 goto end; 827 } 828 if (cfg.CAkeyfile == NULL && cfg.CA_flag && cfg.CAformat == FORMAT_PEM) { 829 cfg.CAkeyfile = cfg.CAfile; 830 } else if (cfg.CA_flag && cfg.CAkeyfile == NULL) { 831 BIO_printf(bio_err, 832 "need to specify a CAkey if using the CA command\n"); 833 goto end; 834 } 835 if (cfg.extfile != NULL) { 836 long errorline = -1; 837 X509V3_CTX ctx2; 838 extconf = NCONF_new(NULL); 839 if (!NCONF_load(extconf, cfg.extfile, &errorline)) { 840 if (errorline <= 0) 841 BIO_printf(bio_err, 842 "error loading the config file '%s'\n", 843 cfg.extfile); 844 else 845 BIO_printf(bio_err, 846 "error on line %ld of config file '%s'\n", 847 errorline, cfg.extfile); 848 goto end; 849 } 850 if (cfg.extsect == NULL) { 851 cfg.extsect = NCONF_get_string(extconf, "default", 852 "extensions"); 853 if (cfg.extsect == NULL) { 854 ERR_clear_error(); 855 cfg.extsect = "default"; 856 } 857 } 858 X509V3_set_ctx_test(&ctx2); 859 X509V3_set_nconf(&ctx2, extconf); 860 if (!X509V3_EXT_add_nconf(extconf, &ctx2, cfg.extsect, NULL)) { 861 BIO_printf(bio_err, 862 "Error Loading extension section %s\n", cfg.extsect); 863 ERR_print_errors(bio_err); 864 goto end; 865 } 866 } 867 if (cfg.force_pubkey != NULL) { 868 if ((Fpkey = load_pubkey(bio_err, cfg.force_pubkey, 869 cfg.keyformat, 0, NULL, "Forced key")) == NULL) 870 goto end; 871 } 872 if (cfg.reqfile) { 873 EVP_PKEY *pkey; 874 BIO *in; 875 876 if (!cfg.sign_flag && !cfg.CA_flag) { 877 BIO_printf(bio_err, 878 "We need a private key to sign with\n"); 879 goto end; 880 } 881 in = BIO_new(BIO_s_file()); 882 if (in == NULL) { 883 ERR_print_errors(bio_err); 884 goto end; 885 } 886 if (cfg.infile == NULL) 887 BIO_set_fp(in, stdin, BIO_NOCLOSE | BIO_FP_TEXT); 888 else { 889 if (BIO_read_filename(in, cfg.infile) <= 0) { 890 perror(cfg.infile); 891 BIO_free(in); 892 goto end; 893 } 894 } 895 req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL); 896 BIO_free(in); 897 898 if (req == NULL) { 899 ERR_print_errors(bio_err); 900 goto end; 901 } 902 if ((pkey = X509_REQ_get0_pubkey(req)) == NULL) { 903 BIO_printf(bio_err, "error unpacking public key\n"); 904 goto end; 905 } 906 i = X509_REQ_verify(req, pkey); 907 if (i < 0) { 908 BIO_printf(bio_err, "Signature verification error\n"); 909 ERR_print_errors(bio_err); 910 goto end; 911 } 912 if (i == 0) { 913 BIO_printf(bio_err, 914 "Signature did not match the certificate request\n"); 915 goto end; 916 } else 917 BIO_printf(bio_err, "Signature ok\n"); 918 919 print_name(bio_err, "subject=", X509_REQ_get_subject_name(req), 920 cfg.nmflag); 921 922 if ((x = X509_new()) == NULL) 923 goto end; 924 925 if (cfg.sno == NULL) { 926 cfg.sno = ASN1_INTEGER_new(); 927 if (cfg.sno == NULL || !rand_serial(NULL, cfg.sno)) 928 goto end; 929 if (!X509_set_serialNumber(x, cfg.sno)) 930 goto end; 931 ASN1_INTEGER_free(cfg.sno); 932 cfg.sno = NULL; 933 } else if (!X509_set_serialNumber(x, cfg.sno)) 934 goto end; 935 936 if (cfg.set_issuer != NULL) { 937 iname = parse_name(cfg.set_issuer, cfg.chtype, 938 cfg.multirdn); 939 if (iname == NULL) 940 goto end; 941 } 942 943 if (cfg.set_subject != NULL) 944 sname = parse_name(cfg.set_subject, cfg.chtype, 945 cfg.multirdn); 946 else 947 sname = X509_NAME_dup(X509_REQ_get_subject_name(req)); 948 if (sname == NULL) 949 goto end; 950 if (!X509_set_subject_name(x, sname)) 951 goto end; 952 953 if (X509_gmtime_adj(X509_get_notBefore(x), 0) == NULL) 954 goto end; 955 if (X509_time_adj_ex(X509_get_notAfter(x), cfg.days, 0, 956 NULL) == NULL) 957 goto end; 958 959 if ((pkey = Fpkey) == NULL) 960 pkey = X509_REQ_get0_pubkey(req); 961 if (pkey == NULL) 962 goto end; 963 if (!X509_set_pubkey(x, pkey)) 964 goto end; 965 } else { 966 x = load_cert(bio_err, cfg.infile, cfg.informat, NULL, 967 "Certificate"); 968 } 969 if (x == NULL) 970 goto end; 971 972 if (cfg.CA_flag) { 973 xca = load_cert(bio_err, cfg.CAfile, cfg.CAformat, NULL, 974 "CA Certificate"); 975 if (xca == NULL) 976 goto end; 977 } 978 if (!cfg.noout || cfg.text || cfg.next_serial) { 979 OBJ_create("2.99999.3", "SET.ex3", "SET x509v3 extension 3"); 980 981 out = BIO_new(BIO_s_file()); 982 if (out == NULL) { 983 ERR_print_errors(bio_err); 984 goto end; 985 } 986 if (cfg.outfile == NULL) { 987 BIO_set_fp(out, stdout, BIO_NOCLOSE); 988 } else { 989 if (BIO_write_filename(out, cfg.outfile) <= 0) { 990 perror(cfg.outfile); 991 goto end; 992 } 993 } 994 } 995 if (cfg.alias != NULL) { 996 if (!X509_alias_set1(x, (unsigned char *)cfg.alias, -1)) 997 goto end; 998 } 999 1000 if (cfg.clrtrust) 1001 X509_trust_clear(x); 1002 if (cfg.clrreject) 1003 X509_reject_clear(x); 1004 1005 if (cfg.trust != NULL) { 1006 for (i = 0; i < sk_ASN1_OBJECT_num(cfg.trust); i++) { 1007 cfg.objtmp = sk_ASN1_OBJECT_value(cfg.trust, i); 1008 if (!X509_add1_trust_object(x, cfg.objtmp)) 1009 goto end; 1010 } 1011 } 1012 if (cfg.reject != NULL) { 1013 for (i = 0; i < sk_ASN1_OBJECT_num(cfg.reject); i++) { 1014 cfg.objtmp = sk_ASN1_OBJECT_value(cfg.reject, i); 1015 if (!X509_add1_reject_object(x, cfg.objtmp)) 1016 goto end; 1017 } 1018 } 1019 if (cfg.num) { 1020 for (i = 1; i <= cfg.num; i++) { 1021 if (cfg.issuer == i) { 1022 print_name(STDout, "issuer= ", 1023 X509_get_issuer_name(x), cfg.nmflag); 1024 } else if (cfg.subject == i) { 1025 print_name(STDout, "subject= ", 1026 X509_get_subject_name(x), cfg.nmflag); 1027 } else if (cfg.serial == i) { 1028 BIO_printf(STDout, "serial="); 1029 i2a_ASN1_INTEGER(STDout, 1030 X509_get_serialNumber(x)); 1031 BIO_printf(STDout, "\n"); 1032 } else if (cfg.next_serial == i) { 1033 BIGNUM *bnser; 1034 ASN1_INTEGER *ser; 1035 1036 ser = X509_get_serialNumber(x); 1037 if (ser == NULL) 1038 goto end; 1039 bnser = ASN1_INTEGER_to_BN(ser, NULL); 1040 if (bnser == NULL) 1041 goto end; 1042 if (!BN_add_word(bnser, 1)) { 1043 BN_free(bnser); 1044 goto end; 1045 } 1046 ser = BN_to_ASN1_INTEGER(bnser, NULL); 1047 if (ser == NULL) { 1048 BN_free(bnser); 1049 goto end; 1050 } 1051 BN_free(bnser); 1052 i2a_ASN1_INTEGER(out, ser); 1053 ASN1_INTEGER_free(ser); 1054 BIO_puts(out, "\n"); 1055 } else if (cfg.email == i || cfg.ocsp_uri == i) { 1056 STACK_OF(OPENSSL_STRING) *emlst; 1057 int j; 1058 1059 if (cfg.email == i) 1060 emlst = X509_get1_email(x); 1061 else 1062 emlst = X509_get1_ocsp(x); 1063 for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++) 1064 BIO_printf(STDout, "%s\n", 1065 sk_OPENSSL_STRING_value(emlst, j)); 1066 X509_email_free(emlst); 1067 } else if (cfg.aliasout == i) { 1068 unsigned char *albuf; 1069 int buflen; 1070 albuf = X509_alias_get0(x, &buflen); 1071 if (albuf != NULL) 1072 BIO_printf(STDout, "%.*s\n", 1073 buflen, albuf); 1074 else 1075 BIO_puts(STDout, "<No Alias>\n"); 1076 } else if (cfg.subject_hash == i) { 1077 BIO_printf(STDout, "%08lx\n", 1078 X509_subject_name_hash(x)); 1079 } 1080 #ifndef OPENSSL_NO_MD5 1081 else if (cfg.subject_hash_old == i) { 1082 BIO_printf(STDout, "%08lx\n", 1083 X509_subject_name_hash_old(x)); 1084 } 1085 #endif 1086 else if (cfg.issuer_hash == i) { 1087 BIO_printf(STDout, "%08lx\n", 1088 X509_issuer_name_hash(x)); 1089 } 1090 #ifndef OPENSSL_NO_MD5 1091 else if (cfg.issuer_hash_old == i) { 1092 BIO_printf(STDout, "%08lx\n", 1093 X509_issuer_name_hash_old(x)); 1094 } 1095 #endif 1096 else if (cfg.pprint == i) { 1097 const X509_PURPOSE *ptmp; 1098 int j; 1099 1100 BIO_printf(STDout, "Certificate purposes:\n"); 1101 for (j = 0; j < X509_PURPOSE_get_count(); j++) { 1102 ptmp = X509_PURPOSE_get0(j); 1103 purpose_print(STDout, x, ptmp); 1104 } 1105 } else if (cfg.modulus == i) { 1106 EVP_PKEY *pkey; 1107 1108 pkey = X509_get0_pubkey(x); 1109 if (pkey == NULL) { 1110 BIO_printf(bio_err, 1111 "Modulus=unavailable\n"); 1112 ERR_print_errors(bio_err); 1113 goto end; 1114 } 1115 BIO_printf(STDout, "Modulus="); 1116 if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) { 1117 RSA *rsa = EVP_PKEY_get0_RSA(pkey); 1118 const BIGNUM *n = NULL; 1119 1120 RSA_get0_key(rsa, &n, NULL, NULL); 1121 BN_print(STDout, n); 1122 } else if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA) { 1123 DSA *dsa = EVP_PKEY_get0_DSA(pkey); 1124 const BIGNUM *pub_key = NULL; 1125 1126 DSA_get0_key(dsa, &pub_key, NULL); 1127 1128 BN_print(STDout, pub_key); 1129 } else 1130 BIO_printf(STDout, 1131 "Wrong Algorithm type"); 1132 BIO_printf(STDout, "\n"); 1133 } else if (cfg.pubkey == i) { 1134 EVP_PKEY *pkey; 1135 1136 pkey = X509_get0_pubkey(x); 1137 if (pkey == NULL) { 1138 BIO_printf(bio_err, 1139 "Error getting public key\n"); 1140 ERR_print_errors(bio_err); 1141 goto end; 1142 } 1143 PEM_write_bio_PUBKEY(STDout, pkey); 1144 } else if (cfg.C == i) { 1145 unsigned char *d; 1146 char *m; 1147 int y, z; 1148 1149 m = X509_NAME_oneline(X509_get_subject_name(x), 1150 buf, sizeof buf); 1151 if (m == NULL) 1152 goto end; 1153 BIO_printf(STDout, "/* subject:%s */\n", buf); 1154 m = X509_NAME_oneline(X509_get_issuer_name(x), 1155 buf, sizeof buf); 1156 if (m == NULL) 1157 goto end; 1158 BIO_printf(STDout, "/* issuer :%s */\n", buf); 1159 1160 z = i2d_X509(x, NULL); 1161 if (z < 0) 1162 goto end; 1163 1164 m = malloc(z); 1165 if (m == NULL) { 1166 BIO_printf(bio_err, "out of mem\n"); 1167 goto end; 1168 } 1169 1170 d = (unsigned char *) m; 1171 z = i2d_X509_NAME(X509_get_subject_name(x), &d); 1172 if (z < 0) { 1173 free(m); 1174 goto end; 1175 } 1176 BIO_printf(STDout, 1177 "unsigned char XXX_subject_name[%d]={\n", z); 1178 d = (unsigned char *) m; 1179 for (y = 0; y < z; y++) { 1180 BIO_printf(STDout, "0x%02X,", d[y]); 1181 if ((y & 0x0f) == 0x0f) 1182 BIO_printf(STDout, "\n"); 1183 } 1184 if (y % 16 != 0) 1185 BIO_printf(STDout, "\n"); 1186 BIO_printf(STDout, "};\n"); 1187 1188 z = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &d); 1189 if (z < 0) { 1190 free(m); 1191 goto end; 1192 } 1193 BIO_printf(STDout, 1194 "unsigned char XXX_public_key[%d]={\n", z); 1195 d = (unsigned char *) m; 1196 for (y = 0; y < z; y++) { 1197 BIO_printf(STDout, "0x%02X,", d[y]); 1198 if ((y & 0x0f) == 0x0f) 1199 BIO_printf(STDout, "\n"); 1200 } 1201 if (y % 16 != 0) 1202 BIO_printf(STDout, "\n"); 1203 BIO_printf(STDout, "};\n"); 1204 1205 z = i2d_X509(x, &d); 1206 if (z < 0) { 1207 free(m); 1208 goto end; 1209 } 1210 BIO_printf(STDout, 1211 "unsigned char XXX_certificate[%d]={\n", z); 1212 d = (unsigned char *) m; 1213 for (y = 0; y < z; y++) { 1214 BIO_printf(STDout, "0x%02X,", d[y]); 1215 if ((y & 0x0f) == 0x0f) 1216 BIO_printf(STDout, "\n"); 1217 } 1218 if (y % 16 != 0) 1219 BIO_printf(STDout, "\n"); 1220 BIO_printf(STDout, "};\n"); 1221 1222 free(m); 1223 } else if (cfg.text == i) { 1224 if(!X509_print_ex(STDout, x, cfg.nmflag, 1225 cfg.certflag)) 1226 goto end; 1227 } else if (cfg.startdate == i) { 1228 ASN1_TIME *nB = X509_get_notBefore(x); 1229 1230 BIO_puts(STDout, "notBefore="); 1231 if (!ASN1_TIME_to_tm(nB, NULL)) 1232 BIO_puts(STDout, 1233 "INVALID RFC5280 TIME"); 1234 else 1235 ASN1_TIME_print(STDout, nB); 1236 BIO_puts(STDout, "\n"); 1237 } else if (cfg.enddate == i) { 1238 ASN1_TIME *nA = X509_get_notAfter(x); 1239 1240 BIO_puts(STDout, "notAfter="); 1241 if (!ASN1_TIME_to_tm(nA, NULL)) 1242 BIO_puts(STDout, 1243 "INVALID RFC5280 TIME"); 1244 else 1245 ASN1_TIME_print(STDout, nA); 1246 BIO_puts(STDout, "\n"); 1247 } else if (cfg.fingerprint == i) { 1248 int j; 1249 unsigned int n; 1250 unsigned char md[EVP_MAX_MD_SIZE]; 1251 const EVP_MD *fdig = cfg.digest; 1252 1253 if (fdig == NULL) 1254 fdig = EVP_sha256(); 1255 1256 if (!X509_digest(x, fdig, md, &n)) { 1257 BIO_printf(bio_err, "out of memory\n"); 1258 goto end; 1259 } 1260 BIO_printf(STDout, "%s Fingerprint=", 1261 OBJ_nid2sn(EVP_MD_type(fdig))); 1262 for (j = 0; j < (int) n; j++) { 1263 BIO_printf(STDout, "%02X%c", md[j], 1264 (j + 1 == (int)n) ? '\n' : ':'); 1265 } 1266 1267 /* should be in the library */ 1268 } else if (cfg.sign_flag == i && cfg.x509req == 0) { 1269 BIO_printf(bio_err, "Getting Private key\n"); 1270 if (Upkey == NULL) { 1271 Upkey = load_key(bio_err, cfg.keyfile, 1272 cfg.keyformat, 0, passin, 1273 "Private key"); 1274 if (Upkey == NULL) 1275 goto end; 1276 } 1277 if (!sign(x, Upkey, cfg.days, 1278 cfg.clrext, cfg.digest, 1279 extconf, cfg.extsect, iname)) 1280 goto end; 1281 } else if (cfg.CA_flag == i) { 1282 BIO_printf(bio_err, "Getting CA Private Key\n"); 1283 if (cfg.CAkeyfile != NULL) { 1284 CApkey = load_key(bio_err, cfg.CAkeyfile, 1285 cfg.CAkeyformat, 0, passin, 1286 "CA Private Key"); 1287 if (CApkey == NULL) 1288 goto end; 1289 } 1290 if (!x509_certify(ctx, cfg.CAfile, cfg.digest, 1291 x, xca, CApkey, cfg.sigopts, cfg.CAserial, 1292 cfg.CA_createserial, cfg.days, cfg.clrext, 1293 extconf, cfg.extsect, cfg.sno, iname)) 1294 goto end; 1295 } else if (cfg.x509req == i) { 1296 EVP_PKEY *pk; 1297 1298 BIO_printf(bio_err, 1299 "Getting request Private Key\n"); 1300 if (cfg.keyfile == NULL) { 1301 BIO_printf(bio_err, 1302 "no request key file specified\n"); 1303 goto end; 1304 } else { 1305 pk = load_key(bio_err, cfg.keyfile, 1306 cfg.keyformat, 0, passin, 1307 "request key"); 1308 if (pk == NULL) 1309 goto end; 1310 } 1311 1312 BIO_printf(bio_err, 1313 "Generating certificate request\n"); 1314 1315 rq = X509_to_X509_REQ(x, pk, cfg.digest); 1316 EVP_PKEY_free(pk); 1317 if (rq == NULL) { 1318 ERR_print_errors(bio_err); 1319 goto end; 1320 } 1321 if (!cfg.noout) { 1322 if (!X509_REQ_print(out, rq)) 1323 goto end; 1324 if (!PEM_write_bio_X509_REQ(out, rq)) 1325 goto end; 1326 } 1327 cfg.noout = 1; 1328 } else if (cfg.ocspid == i) { 1329 if (!X509_ocspid_print(out, x)) 1330 goto end; 1331 } 1332 } 1333 } 1334 if (cfg.checkend) { 1335 time_t tcheck = time(NULL) + cfg.checkoffset; 1336 int timecheck = X509_cmp_time(X509_get_notAfter(x), &tcheck); 1337 if (timecheck == 0) { 1338 BIO_printf(out, "Certificate expiry time is invalid\n"); 1339 ret = 1; 1340 } else if (timecheck < 0) { 1341 BIO_printf(out, "Certificate will expire\n"); 1342 ret = 1; 1343 } else { 1344 BIO_printf(out, "Certificate will not expire\n"); 1345 ret = 0; 1346 } 1347 goto end; 1348 } 1349 if (cfg.noout) { 1350 ret = 0; 1351 goto end; 1352 } 1353 if (cfg.outformat == FORMAT_ASN1) 1354 i = i2d_X509_bio(out, x); 1355 else if (cfg.outformat == FORMAT_PEM) { 1356 if (cfg.trustout) 1357 i = PEM_write_bio_X509_AUX(out, x); 1358 else 1359 i = PEM_write_bio_X509(out, x); 1360 } else { 1361 BIO_printf(bio_err, 1362 "bad output format specified for outfile\n"); 1363 goto end; 1364 } 1365 if (!i) { 1366 BIO_printf(bio_err, "unable to write certificate\n"); 1367 ERR_print_errors(bio_err); 1368 goto end; 1369 } 1370 ret = 0; 1371 1372 end: 1373 OBJ_cleanup(); 1374 NCONF_free(extconf); 1375 BIO_free_all(out); 1376 BIO_free_all(STDout); 1377 X509_NAME_free(iname); 1378 X509_NAME_free(sname); 1379 X509_STORE_free(ctx); 1380 X509_REQ_free(req); 1381 X509_free(x); 1382 X509_free(xca); 1383 EVP_PKEY_free(Fpkey); 1384 EVP_PKEY_free(Upkey); 1385 EVP_PKEY_free(CApkey); 1386 sk_OPENSSL_STRING_free(cfg.sigopts); 1387 X509_REQ_free(rq); 1388 ASN1_INTEGER_free(cfg.sno); 1389 sk_ASN1_OBJECT_pop_free(cfg.trust, ASN1_OBJECT_free); 1390 sk_ASN1_OBJECT_pop_free(cfg.reject, ASN1_OBJECT_free); 1391 free(passin); 1392 1393 return (ret); 1394 } 1395 1396 static ASN1_INTEGER * 1397 x509_load_serial(char *CAfile, char *serialfile, int create) 1398 { 1399 char *buf = NULL, *p; 1400 ASN1_INTEGER *bs = NULL; 1401 BIGNUM *serial = NULL; 1402 size_t len; 1403 1404 len = ((serialfile == NULL) ? (strlen(CAfile) + strlen(POSTFIX) + 1) : 1405 (strlen(serialfile))) + 1; 1406 buf = malloc(len); 1407 if (buf == NULL) { 1408 BIO_printf(bio_err, "out of mem\n"); 1409 goto end; 1410 } 1411 if (serialfile == NULL) { 1412 strlcpy(buf, CAfile, len); 1413 for (p = buf; *p; p++) 1414 if (*p == '.') { 1415 *p = '\0'; 1416 break; 1417 } 1418 strlcat(buf, POSTFIX, len); 1419 } else 1420 strlcpy(buf, serialfile, len); 1421 1422 serial = load_serial(buf, create, NULL); 1423 if (serial == NULL) 1424 goto end; 1425 1426 if (!BN_add_word(serial, 1)) { 1427 BIO_printf(bio_err, "add_word failure\n"); 1428 goto end; 1429 } 1430 if (!save_serial(buf, NULL, serial, &bs)) 1431 goto end; 1432 1433 end: 1434 free(buf); 1435 BN_free(serial); 1436 1437 return bs; 1438 } 1439 1440 static int 1441 x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest, X509 *x, 1442 X509 *xca, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *sigopts, 1443 char *serialfile, int create, int days, int clrext, CONF *conf, 1444 char *section, ASN1_INTEGER *sno, X509_NAME *issuer) 1445 { 1446 int ret = 0; 1447 ASN1_INTEGER *bs = NULL; 1448 X509_STORE_CTX *xsc = NULL; 1449 EVP_PKEY *upkey; 1450 1451 upkey = X509_get0_pubkey(xca); 1452 if (upkey == NULL) 1453 goto end; 1454 EVP_PKEY_copy_parameters(upkey, pkey); 1455 1456 if ((xsc = X509_STORE_CTX_new()) == NULL) 1457 goto end; 1458 if (!X509_STORE_CTX_init(xsc, ctx, x, NULL)) { 1459 BIO_printf(bio_err, "Error initialising X509 store\n"); 1460 goto end; 1461 } 1462 if (sno != NULL) 1463 bs = sno; 1464 else if ((bs = x509_load_serial(CAfile, serialfile, create)) == NULL) 1465 goto end; 1466 1467 /* if (!X509_STORE_add_cert(ctx,x)) goto end;*/ 1468 1469 /* 1470 * NOTE: this certificate can/should be self signed, unless it was a 1471 * certificate request in which case it is not. 1472 */ 1473 X509_STORE_CTX_set_cert(xsc, x); 1474 X509_STORE_CTX_set_flags(xsc, X509_V_FLAG_CHECK_SS_SIGNATURE); 1475 if (!cfg.reqfile && X509_verify_cert(xsc) <= 0) 1476 goto end; 1477 1478 if (!X509_check_private_key(xca, pkey)) { 1479 BIO_printf(bio_err, 1480 "CA certificate and CA private key do not match\n"); 1481 goto end; 1482 } 1483 1484 if (issuer == NULL) 1485 issuer = X509_get_subject_name(xca); 1486 if (issuer == NULL) 1487 goto end; 1488 if (!X509_set_issuer_name(x, issuer)) 1489 goto end; 1490 1491 if (!X509_set_serialNumber(x, bs)) 1492 goto end; 1493 1494 if (X509_gmtime_adj(X509_get_notBefore(x), 0L) == NULL) 1495 goto end; 1496 1497 /* hardwired expired */ 1498 if (X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL) == NULL) 1499 goto end; 1500 1501 if (clrext) { 1502 while (X509_get_ext_count(x) > 0) { 1503 if (X509_delete_ext(x, 0) == NULL) 1504 goto end; 1505 } 1506 } 1507 if (conf != NULL) { 1508 X509V3_CTX ctx2; 1509 if (!X509_set_version(x, 2)) /* version 3 certificate */ 1510 goto end; 1511 X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0); 1512 X509V3_set_nconf(&ctx2, conf); 1513 if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x)) 1514 goto end; 1515 } 1516 if (!do_X509_sign(bio_err, x, pkey, digest, sigopts)) 1517 goto end; 1518 1519 ret = 1; 1520 end: 1521 X509_STORE_CTX_free(xsc); 1522 if (!ret) 1523 ERR_print_errors(bio_err); 1524 if (sno == NULL) 1525 ASN1_INTEGER_free(bs); 1526 return ret; 1527 } 1528 1529 static int 1530 callb(int ok, X509_STORE_CTX *ctx) 1531 { 1532 int err; 1533 X509 *err_cert; 1534 1535 /* 1536 * it is ok to use a self signed certificate This case will catch 1537 * both the initial ok == 0 and the final ok == 1 calls to this 1538 * function 1539 */ 1540 err = X509_STORE_CTX_get_error(ctx); 1541 if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) 1542 return 1; 1543 1544 /* 1545 * BAD we should have gotten an error. Normally if everything worked 1546 * X509_STORE_CTX_get_error(ctx) will still be set to 1547 * DEPTH_ZERO_SELF_.... 1548 */ 1549 if (ok) { 1550 BIO_printf(bio_err, 1551 "error with certificate to be certified - should be self signed\n"); 1552 return 0; 1553 } else { 1554 err_cert = X509_STORE_CTX_get_current_cert(ctx); 1555 print_name(bio_err, NULL, X509_get_subject_name(err_cert), 0); 1556 BIO_printf(bio_err, 1557 "error with certificate - error %d at depth %d\n%s\n", 1558 err, X509_STORE_CTX_get_error_depth(ctx), 1559 X509_verify_cert_error_string(err)); 1560 return 1; 1561 } 1562 } 1563 1564 /* self sign */ 1565 static int 1566 sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, const EVP_MD *digest, 1567 CONF *conf, char *section, X509_NAME *issuer) 1568 { 1569 EVP_PKEY *pktmp; 1570 1571 pktmp = X509_get0_pubkey(x); 1572 if (pktmp == NULL) 1573 goto err; 1574 EVP_PKEY_copy_parameters(pktmp, pkey); 1575 EVP_PKEY_save_parameters(pktmp, 1); 1576 1577 if (issuer == NULL) 1578 issuer = X509_get_subject_name(x); 1579 if (issuer == NULL) 1580 goto err; 1581 if (!X509_set_issuer_name(x, issuer)) 1582 goto err; 1583 if (X509_gmtime_adj(X509_get_notBefore(x), 0) == NULL) 1584 goto err; 1585 1586 /* Lets just make it 12:00am GMT, Jan 1 1970 */ 1587 /* memcpy(x->cert_info->validity->notBefore,"700101120000Z",13); */ 1588 /* 28 days to be certified */ 1589 1590 if (X509_gmtime_adj(X509_get_notAfter(x), 1591 (long) 60 * 60 * 24 * days) == NULL) 1592 goto err; 1593 1594 if (!X509_set_pubkey(x, pkey)) 1595 goto err; 1596 if (clrext) { 1597 while (X509_get_ext_count(x) > 0) { 1598 if (X509_delete_ext(x, 0) == NULL) 1599 goto err; 1600 } 1601 } 1602 if (conf != NULL) { 1603 X509V3_CTX ctx; 1604 if (!X509_set_version(x, 2)) /* version 3 certificate */ 1605 goto err; 1606 X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0); 1607 X509V3_set_nconf(&ctx, conf); 1608 if (!X509V3_EXT_add_nconf(conf, &ctx, section, x)) 1609 goto err; 1610 } 1611 if (!X509_sign(x, pkey, digest)) 1612 goto err; 1613 1614 return 1; 1615 1616 err: 1617 ERR_print_errors(bio_err); 1618 return 0; 1619 } 1620 1621 static int 1622 purpose_print(BIO *bio, X509 *cert, const X509_PURPOSE *pt) 1623 { 1624 int id, i, idret; 1625 const char *pname; 1626 1627 id = X509_PURPOSE_get_id(pt); 1628 pname = X509_PURPOSE_get0_name(pt); 1629 for (i = 0; i < 2; i++) { 1630 idret = X509_check_purpose(cert, id, i); 1631 BIO_printf(bio, "%s%s : ", pname, i ? " CA" : ""); 1632 if (idret == 1) 1633 BIO_printf(bio, "Yes\n"); 1634 else if (idret == 0) 1635 BIO_printf(bio, "No\n"); 1636 else 1637 BIO_printf(bio, "Yes (WARNING code=%d)\n", idret); 1638 } 1639 return 1; 1640 } 1641