1 /* apps/x509.c */ 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 <stdio.h> 61 #include <stdlib.h> 62 #include <string.h> 63 #ifdef NO_STDIO 64 #define APPS_WIN16 65 #endif 66 #include "apps.h" 67 #include <openssl/bio.h> 68 #include <openssl/asn1.h> 69 #include <openssl/err.h> 70 #include <openssl/bn.h> 71 #include <openssl/evp.h> 72 #include <openssl/x509.h> 73 #include <openssl/x509v3.h> 74 #include <openssl/objects.h> 75 #include <openssl/pem.h> 76 77 #undef PROG 78 #define PROG x509_main 79 80 #undef POSTFIX 81 #define POSTFIX ".srl" 82 #define DEF_DAYS 30 83 84 static char *x509_usage[]={ 85 "usage: x509 args\n", 86 " -inform arg - input format - default PEM (one of DER, NET or PEM)\n", 87 " -outform arg - output format - default PEM (one of DER, NET or PEM)\n", 88 " -keyform arg - private key format - default PEM\n", 89 " -CAform arg - CA format - default PEM\n", 90 " -CAkeyform arg - CA key format - default PEM\n", 91 " -in arg - input file - default stdin\n", 92 " -out arg - output file - default stdout\n", 93 " -passin arg - private key password source\n", 94 " -serial - print serial number value\n", 95 " -hash - print hash value\n", 96 " -subject - print subject DN\n", 97 " -issuer - print issuer DN\n", 98 " -email - print email address(es)\n", 99 " -startdate - notBefore field\n", 100 " -enddate - notAfter field\n", 101 " -purpose - print out certificate purposes\n", 102 " -dates - both Before and After dates\n", 103 " -modulus - print the RSA key modulus\n", 104 " -pubkey - output the public key\n", 105 " -fingerprint - print the certificate fingerprint\n", 106 " -alias - output certificate alias\n", 107 " -noout - no certificate output\n", 108 " -trustout - output a \"trusted\" certificate\n", 109 " -clrtrust - clear all trusted purposes\n", 110 " -clrreject - clear all rejected purposes\n", 111 " -addtrust arg - trust certificate for a given purpose\n", 112 " -addreject arg - reject certificate for a given purpose\n", 113 " -setalias arg - set certificate alias\n", 114 " -days arg - How long till expiry of a signed certificate - def 30 days\n", 115 " -checkend arg - check whether the cert expires in the next arg seconds\n", 116 " exit 1 if so, 0 if not\n", 117 " -signkey arg - self sign cert with arg\n", 118 " -x509toreq - output a certification request object\n", 119 " -req - input is a certificate request, sign and output.\n", 120 " -CA arg - set the CA certificate, must be PEM format.\n", 121 " -CAkey arg - set the CA key, must be PEM format\n", 122 " missing, it is assumed to be in the CA file.\n", 123 " -CAcreateserial - create serial number file if it does not exist\n", 124 " -CAserial - serial file\n", 125 " -text - print the certificate in text form\n", 126 " -C - print out C code forms\n", 127 " -md2/-md5/-sha1/-mdc2 - digest to use\n", 128 " -extfile - configuration file with X509V3 extensions to add\n", 129 " -extensions - section from config file with X509V3 extensions to add\n", 130 " -clrext - delete extensions before signing and input certificate\n", 131 " -nameopt arg - various certificate name options\n", 132 NULL 133 }; 134 135 static int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx); 136 static int sign (X509 *x, EVP_PKEY *pkey,int days,int clrext, const EVP_MD *digest, 137 LHASH *conf, char *section); 138 static int x509_certify (X509_STORE *ctx,char *CAfile,const EVP_MD *digest, 139 X509 *x,X509 *xca,EVP_PKEY *pkey,char *serial, 140 int create,int days, int clrext, LHASH *conf, char *section); 141 static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt); 142 static int reqfile=0; 143 144 int MAIN(int, char **); 145 146 int MAIN(int argc, char **argv) 147 { 148 int ret=1; 149 X509_REQ *req=NULL; 150 X509 *x=NULL,*xca=NULL; 151 ASN1_OBJECT *objtmp; 152 EVP_PKEY *Upkey=NULL,*CApkey=NULL; 153 int i,num,badops=0; 154 BIO *out=NULL; 155 BIO *STDout=NULL; 156 STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL; 157 int informat,outformat,keyformat,CAformat,CAkeyformat; 158 char *infile=NULL,*outfile=NULL,*keyfile=NULL,*CAfile=NULL; 159 char *CAkeyfile=NULL,*CAserial=NULL; 160 char *alias=NULL; 161 int text=0,serial=0,hash=0,subject=0,issuer=0,startdate=0,enddate=0; 162 int noout=0,sign_flag=0,CA_flag=0,CA_createserial=0,email=0; 163 int trustout=0,clrtrust=0,clrreject=0,aliasout=0,clrext=0; 164 int C=0; 165 int x509req=0,days=DEF_DAYS,modulus=0,pubkey=0; 166 int pprint = 0; 167 char **pp; 168 X509_STORE *ctx=NULL; 169 X509_REQ *rq=NULL; 170 int fingerprint=0; 171 char buf[256]; 172 const EVP_MD *md_alg,*digest=EVP_md5(); 173 LHASH *extconf = NULL; 174 char *extsect = NULL, *extfile = NULL, *passin = NULL, *passargin = NULL; 175 int need_rand = 0; 176 int checkend=0,checkoffset=0; 177 unsigned long nmflag = 0; 178 179 reqfile=0; 180 181 apps_startup(); 182 183 if (bio_err == NULL) 184 bio_err=BIO_new_fp(stderr,BIO_NOCLOSE); 185 STDout=BIO_new_fp(stdout,BIO_NOCLOSE); 186 #ifdef VMS 187 { 188 BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 189 STDout = BIO_push(tmpbio, STDout); 190 } 191 #endif 192 193 informat=FORMAT_PEM; 194 outformat=FORMAT_PEM; 195 keyformat=FORMAT_PEM; 196 CAformat=FORMAT_PEM; 197 CAkeyformat=FORMAT_PEM; 198 199 ctx=X509_STORE_new(); 200 if (ctx == NULL) goto end; 201 X509_STORE_set_verify_cb_func(ctx,callb); 202 203 argc--; 204 argv++; 205 num=0; 206 while (argc >= 1) 207 { 208 if (strcmp(*argv,"-inform") == 0) 209 { 210 if (--argc < 1) goto bad; 211 informat=str2fmt(*(++argv)); 212 } 213 else if (strcmp(*argv,"-outform") == 0) 214 { 215 if (--argc < 1) goto bad; 216 outformat=str2fmt(*(++argv)); 217 } 218 else if (strcmp(*argv,"-keyform") == 0) 219 { 220 if (--argc < 1) goto bad; 221 keyformat=str2fmt(*(++argv)); 222 } 223 else if (strcmp(*argv,"-req") == 0) 224 { 225 reqfile=1; 226 need_rand = 1; 227 } 228 else if (strcmp(*argv,"-CAform") == 0) 229 { 230 if (--argc < 1) goto bad; 231 CAformat=str2fmt(*(++argv)); 232 } 233 else if (strcmp(*argv,"-CAkeyform") == 0) 234 { 235 if (--argc < 1) goto bad; 236 CAkeyformat=str2fmt(*(++argv)); 237 } 238 else if (strcmp(*argv,"-days") == 0) 239 { 240 if (--argc < 1) goto bad; 241 days=atoi(*(++argv)); 242 if (days == 0) 243 { 244 BIO_printf(STDout,"bad number of days\n"); 245 goto bad; 246 } 247 } 248 else if (strcmp(*argv,"-passin") == 0) 249 { 250 if (--argc < 1) goto bad; 251 passargin= *(++argv); 252 } 253 else if (strcmp(*argv,"-extfile") == 0) 254 { 255 if (--argc < 1) goto bad; 256 extfile= *(++argv); 257 } 258 else if (strcmp(*argv,"-extensions") == 0) 259 { 260 if (--argc < 1) goto bad; 261 extsect= *(++argv); 262 } 263 else if (strcmp(*argv,"-in") == 0) 264 { 265 if (--argc < 1) goto bad; 266 infile= *(++argv); 267 } 268 else if (strcmp(*argv,"-out") == 0) 269 { 270 if (--argc < 1) goto bad; 271 outfile= *(++argv); 272 } 273 else if (strcmp(*argv,"-signkey") == 0) 274 { 275 if (--argc < 1) goto bad; 276 keyfile= *(++argv); 277 sign_flag= ++num; 278 need_rand = 1; 279 } 280 else if (strcmp(*argv,"-CA") == 0) 281 { 282 if (--argc < 1) goto bad; 283 CAfile= *(++argv); 284 CA_flag= ++num; 285 need_rand = 1; 286 } 287 else if (strcmp(*argv,"-CAkey") == 0) 288 { 289 if (--argc < 1) goto bad; 290 CAkeyfile= *(++argv); 291 } 292 else if (strcmp(*argv,"-CAserial") == 0) 293 { 294 if (--argc < 1) goto bad; 295 CAserial= *(++argv); 296 } 297 else if (strcmp(*argv,"-addtrust") == 0) 298 { 299 if (--argc < 1) goto bad; 300 if (!(objtmp = OBJ_txt2obj(*(++argv), 0))) 301 { 302 BIO_printf(bio_err, 303 "Invalid trust object value %s\n", *argv); 304 goto bad; 305 } 306 if (!trust) trust = sk_ASN1_OBJECT_new_null(); 307 sk_ASN1_OBJECT_push(trust, objtmp); 308 trustout = 1; 309 } 310 else if (strcmp(*argv,"-addreject") == 0) 311 { 312 if (--argc < 1) goto bad; 313 if (!(objtmp = OBJ_txt2obj(*(++argv), 0))) 314 { 315 BIO_printf(bio_err, 316 "Invalid reject object value %s\n", *argv); 317 goto bad; 318 } 319 if (!reject) reject = sk_ASN1_OBJECT_new_null(); 320 sk_ASN1_OBJECT_push(reject, objtmp); 321 trustout = 1; 322 } 323 else if (strcmp(*argv,"-setalias") == 0) 324 { 325 if (--argc < 1) goto bad; 326 alias= *(++argv); 327 trustout = 1; 328 } 329 else if (strcmp(*argv,"-nameopt") == 0) 330 { 331 if (--argc < 1) goto bad; 332 if (!set_name_ex(&nmflag, *(++argv))) goto bad; 333 } 334 else if (strcmp(*argv,"-setalias") == 0) 335 { 336 if (--argc < 1) goto bad; 337 alias= *(++argv); 338 trustout = 1; 339 } 340 else if (strcmp(*argv,"-C") == 0) 341 C= ++num; 342 else if (strcmp(*argv,"-email") == 0) 343 email= ++num; 344 else if (strcmp(*argv,"-serial") == 0) 345 serial= ++num; 346 else if (strcmp(*argv,"-modulus") == 0) 347 modulus= ++num; 348 else if (strcmp(*argv,"-pubkey") == 0) 349 pubkey= ++num; 350 else if (strcmp(*argv,"-x509toreq") == 0) 351 x509req= ++num; 352 else if (strcmp(*argv,"-text") == 0) 353 text= ++num; 354 else if (strcmp(*argv,"-hash") == 0) 355 hash= ++num; 356 else if (strcmp(*argv,"-subject") == 0) 357 subject= ++num; 358 else if (strcmp(*argv,"-issuer") == 0) 359 issuer= ++num; 360 else if (strcmp(*argv,"-fingerprint") == 0) 361 fingerprint= ++num; 362 else if (strcmp(*argv,"-dates") == 0) 363 { 364 startdate= ++num; 365 enddate= ++num; 366 } 367 else if (strcmp(*argv,"-purpose") == 0) 368 pprint= ++num; 369 else if (strcmp(*argv,"-startdate") == 0) 370 startdate= ++num; 371 else if (strcmp(*argv,"-enddate") == 0) 372 enddate= ++num; 373 else if (strcmp(*argv,"-checkend") == 0) 374 { 375 if (--argc < 1) goto bad; 376 checkoffset=atoi(*(++argv)); 377 checkend=1; 378 } 379 else if (strcmp(*argv,"-noout") == 0) 380 noout= ++num; 381 else if (strcmp(*argv,"-trustout") == 0) 382 trustout= 1; 383 else if (strcmp(*argv,"-clrtrust") == 0) 384 clrtrust= ++num; 385 else if (strcmp(*argv,"-clrreject") == 0) 386 clrreject= ++num; 387 else if (strcmp(*argv,"-alias") == 0) 388 aliasout= ++num; 389 else if (strcmp(*argv,"-CAcreateserial") == 0) 390 CA_createserial= ++num; 391 else if (strcmp(*argv,"-clrext") == 0) 392 clrext = 1; 393 #if 1 /* stay backwards-compatible with 0.9.5; this should go away soon */ 394 else if (strcmp(*argv,"-crlext") == 0) 395 { 396 BIO_printf(bio_err,"use -clrext instead of -crlext\n"); 397 clrext = 1; 398 } 399 #endif 400 else if ((md_alg=EVP_get_digestbyname(*argv + 1))) 401 { 402 /* ok */ 403 digest=md_alg; 404 } 405 else 406 { 407 BIO_printf(bio_err,"unknown option %s\n",*argv); 408 badops=1; 409 break; 410 } 411 argc--; 412 argv++; 413 } 414 415 if (badops) 416 { 417 bad: 418 for (pp=x509_usage; (*pp != NULL); pp++) 419 BIO_printf(bio_err,*pp); 420 goto end; 421 } 422 423 if (need_rand) 424 app_RAND_load_file(NULL, bio_err, 0); 425 426 ERR_load_crypto_strings(); 427 428 if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) 429 { 430 BIO_printf(bio_err, "Error getting password\n"); 431 goto end; 432 } 433 434 if (!X509_STORE_set_default_paths(ctx)) 435 { 436 ERR_print_errors(bio_err); 437 goto end; 438 } 439 440 if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM)) 441 { CAkeyfile=CAfile; } 442 else if ((CA_flag) && (CAkeyfile == NULL)) 443 { 444 BIO_printf(bio_err,"need to specify a CAkey if using the CA command\n"); 445 goto end; 446 } 447 448 if (extfile) 449 { 450 long errorline; 451 X509V3_CTX ctx2; 452 if (!(extconf=CONF_load(NULL,extfile,&errorline))) 453 { 454 if (errorline <= 0) 455 BIO_printf(bio_err, 456 "error loading the config file '%s'\n", 457 extfile); 458 else 459 BIO_printf(bio_err, 460 "error on line %ld of config file '%s'\n" 461 ,errorline,extfile); 462 goto end; 463 } 464 if (!extsect && !(extsect = CONF_get_string(extconf, "default", 465 "extensions"))) extsect = "default"; 466 X509V3_set_ctx_test(&ctx2); 467 X509V3_set_conf_lhash(&ctx2, extconf); 468 if (!X509V3_EXT_add_conf(extconf, &ctx2, extsect, NULL)) 469 { 470 BIO_printf(bio_err, 471 "Error Loading extension section %s\n", 472 extsect); 473 ERR_print_errors(bio_err); 474 goto end; 475 } 476 } 477 478 479 if (reqfile) 480 { 481 EVP_PKEY *pkey; 482 X509_CINF *ci; 483 BIO *in; 484 485 if (!sign_flag && !CA_flag) 486 { 487 BIO_printf(bio_err,"We need a private key to sign with\n"); 488 goto end; 489 } 490 in=BIO_new(BIO_s_file()); 491 if (in == NULL) 492 { 493 ERR_print_errors(bio_err); 494 goto end; 495 } 496 497 if (infile == NULL) 498 BIO_set_fp(in,stdin,BIO_NOCLOSE|BIO_FP_TEXT); 499 else 500 { 501 if (BIO_read_filename(in,infile) <= 0) 502 { 503 perror(infile); 504 BIO_free(in); 505 goto end; 506 } 507 } 508 req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL); 509 BIO_free(in); 510 511 if (req == NULL) 512 { 513 ERR_print_errors(bio_err); 514 goto end; 515 } 516 517 if ( (req->req_info == NULL) || 518 (req->req_info->pubkey == NULL) || 519 (req->req_info->pubkey->public_key == NULL) || 520 (req->req_info->pubkey->public_key->data == NULL)) 521 { 522 BIO_printf(bio_err,"The certificate request appears to corrupted\n"); 523 BIO_printf(bio_err,"It does not contain a public key\n"); 524 goto end; 525 } 526 if ((pkey=X509_REQ_get_pubkey(req)) == NULL) 527 { 528 BIO_printf(bio_err,"error unpacking public key\n"); 529 goto end; 530 } 531 i=X509_REQ_verify(req,pkey); 532 EVP_PKEY_free(pkey); 533 if (i < 0) 534 { 535 BIO_printf(bio_err,"Signature verification error\n"); 536 ERR_print_errors(bio_err); 537 goto end; 538 } 539 if (i == 0) 540 { 541 BIO_printf(bio_err,"Signature did not match the certificate request\n"); 542 goto end; 543 } 544 else 545 BIO_printf(bio_err,"Signature ok\n"); 546 547 print_name(bio_err, "subject=", X509_REQ_get_subject_name(req), nmflag); 548 549 if ((x=X509_new()) == NULL) goto end; 550 ci=x->cert_info; 551 552 if (!ASN1_INTEGER_set(X509_get_serialNumber(x),0)) goto end; 553 if (!X509_set_issuer_name(x,req->req_info->subject)) goto end; 554 if (!X509_set_subject_name(x,req->req_info->subject)) goto end; 555 556 X509_gmtime_adj(X509_get_notBefore(x),0); 557 X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days); 558 559 pkey = X509_REQ_get_pubkey(req); 560 X509_set_pubkey(x,pkey); 561 EVP_PKEY_free(pkey); 562 } 563 else 564 x=load_cert(bio_err,infile,informat); 565 566 if (x == NULL) goto end; 567 if (CA_flag) 568 { 569 xca=load_cert(bio_err,CAfile,CAformat); 570 if (xca == NULL) goto end; 571 } 572 573 if (!noout || text) 574 { 575 OBJ_create("2.99999.3", 576 "SET.ex3","SET x509v3 extension 3"); 577 578 out=BIO_new(BIO_s_file()); 579 if (out == NULL) 580 { 581 ERR_print_errors(bio_err); 582 goto end; 583 } 584 if (outfile == NULL) 585 { 586 BIO_set_fp(out,stdout,BIO_NOCLOSE); 587 #ifdef VMS 588 { 589 BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 590 out = BIO_push(tmpbio, out); 591 } 592 #endif 593 } 594 else 595 { 596 if (BIO_write_filename(out,outfile) <= 0) 597 { 598 perror(outfile); 599 goto end; 600 } 601 } 602 } 603 604 if (alias) X509_alias_set1(x, (unsigned char *)alias, -1); 605 606 if (clrtrust) X509_trust_clear(x); 607 if (clrreject) X509_reject_clear(x); 608 609 if (trust) 610 { 611 for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++) 612 { 613 objtmp = sk_ASN1_OBJECT_value(trust, i); 614 X509_add1_trust_object(x, objtmp); 615 } 616 } 617 618 if (reject) 619 { 620 for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++) 621 { 622 objtmp = sk_ASN1_OBJECT_value(reject, i); 623 X509_add1_reject_object(x, objtmp); 624 } 625 } 626 627 if (num) 628 { 629 for (i=1; i<=num; i++) 630 { 631 if (issuer == i) 632 { 633 print_name(STDout, "issuer= ", 634 X509_get_issuer_name(x), nmflag); 635 } 636 else if (subject == i) 637 { 638 print_name(STDout, "subject= ", 639 X509_get_subject_name(x), nmflag); 640 } 641 else if (serial == i) 642 { 643 BIO_printf(STDout,"serial="); 644 i2a_ASN1_INTEGER(STDout,x->cert_info->serialNumber); 645 BIO_printf(STDout,"\n"); 646 } 647 else if (email == i) 648 { 649 int j; 650 STACK *emlst; 651 emlst = X509_get1_email(x); 652 for (j = 0; j < sk_num(emlst); j++) 653 BIO_printf(STDout, "%s\n", sk_value(emlst, j)); 654 X509_email_free(emlst); 655 } 656 else if (aliasout == i) 657 { 658 unsigned char *alstr; 659 alstr = X509_alias_get0(x, NULL); 660 if (alstr) BIO_printf(STDout,"%s\n", alstr); 661 else BIO_puts(STDout,"<No Alias>\n"); 662 } 663 else if (hash == i) 664 { 665 BIO_printf(STDout,"%08lx\n",X509_subject_name_hash(x)); 666 } 667 else if (pprint == i) 668 { 669 X509_PURPOSE *ptmp; 670 int j; 671 BIO_printf(STDout, "Certificate purposes:\n"); 672 for (j = 0; j < X509_PURPOSE_get_count(); j++) 673 { 674 ptmp = X509_PURPOSE_get0(j); 675 purpose_print(STDout, x, ptmp); 676 } 677 } 678 else 679 if (modulus == i) 680 { 681 EVP_PKEY *pkey; 682 683 pkey=X509_get_pubkey(x); 684 if (pkey == NULL) 685 { 686 BIO_printf(bio_err,"Modulus=unavailable\n"); 687 ERR_print_errors(bio_err); 688 goto end; 689 } 690 BIO_printf(STDout,"Modulus="); 691 #ifndef NO_RSA 692 if (pkey->type == EVP_PKEY_RSA) 693 BN_print(STDout,pkey->pkey.rsa->n); 694 else 695 #endif 696 #ifndef NO_DSA 697 if (pkey->type == EVP_PKEY_DSA) 698 BN_print(STDout,pkey->pkey.dsa->pub_key); 699 else 700 #endif 701 BIO_printf(STDout,"Wrong Algorithm type"); 702 BIO_printf(STDout,"\n"); 703 EVP_PKEY_free(pkey); 704 } 705 else 706 if (pubkey == i) 707 { 708 EVP_PKEY *pkey; 709 710 pkey=X509_get_pubkey(x); 711 if (pkey == NULL) 712 { 713 BIO_printf(bio_err,"Error getting public key\n"); 714 ERR_print_errors(bio_err); 715 goto end; 716 } 717 PEM_write_bio_PUBKEY(STDout, pkey); 718 EVP_PKEY_free(pkey); 719 } 720 else 721 if (C == i) 722 { 723 unsigned char *d; 724 char *m; 725 int y,z; 726 727 X509_NAME_oneline(X509_get_subject_name(x), 728 buf,256); 729 BIO_printf(STDout,"/* subject:%s */\n",buf); 730 m=X509_NAME_oneline( 731 X509_get_issuer_name(x),buf,256); 732 BIO_printf(STDout,"/* issuer :%s */\n",buf); 733 734 z=i2d_X509(x,NULL); 735 m=OPENSSL_malloc(z); 736 737 d=(unsigned char *)m; 738 z=i2d_X509_NAME(X509_get_subject_name(x),&d); 739 BIO_printf(STDout,"unsigned char XXX_subject_name[%d]={\n",z); 740 d=(unsigned char *)m; 741 for (y=0; y<z; y++) 742 { 743 BIO_printf(STDout,"0x%02X,",d[y]); 744 if ((y & 0x0f) == 0x0f) BIO_printf(STDout,"\n"); 745 } 746 if (y%16 != 0) BIO_printf(STDout,"\n"); 747 BIO_printf(STDout,"};\n"); 748 749 z=i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x),&d); 750 BIO_printf(STDout,"unsigned char XXX_public_key[%d]={\n",z); 751 d=(unsigned char *)m; 752 for (y=0; y<z; y++) 753 { 754 BIO_printf(STDout,"0x%02X,",d[y]); 755 if ((y & 0x0f) == 0x0f) 756 BIO_printf(STDout,"\n"); 757 } 758 if (y%16 != 0) BIO_printf(STDout,"\n"); 759 BIO_printf(STDout,"};\n"); 760 761 z=i2d_X509(x,&d); 762 BIO_printf(STDout,"unsigned char XXX_certificate[%d]={\n",z); 763 d=(unsigned char *)m; 764 for (y=0; y<z; y++) 765 { 766 BIO_printf(STDout,"0x%02X,",d[y]); 767 if ((y & 0x0f) == 0x0f) 768 BIO_printf(STDout,"\n"); 769 } 770 if (y%16 != 0) BIO_printf(STDout,"\n"); 771 BIO_printf(STDout,"};\n"); 772 773 OPENSSL_free(m); 774 } 775 else if (text == i) 776 { 777 X509_print(out,x); 778 } 779 else if (startdate == i) 780 { 781 BIO_puts(STDout,"notBefore="); 782 ASN1_TIME_print(STDout,X509_get_notBefore(x)); 783 BIO_puts(STDout,"\n"); 784 } 785 else if (enddate == i) 786 { 787 BIO_puts(STDout,"notAfter="); 788 ASN1_TIME_print(STDout,X509_get_notAfter(x)); 789 BIO_puts(STDout,"\n"); 790 } 791 else if (fingerprint == i) 792 { 793 int j; 794 unsigned int n; 795 unsigned char md[EVP_MAX_MD_SIZE]; 796 797 if (!X509_digest(x,digest,md,&n)) 798 { 799 BIO_printf(bio_err,"out of memory\n"); 800 goto end; 801 } 802 BIO_printf(STDout,"%s Fingerprint=", 803 OBJ_nid2sn(EVP_MD_type(digest))); 804 for (j=0; j<(int)n; j++) 805 { 806 BIO_printf(STDout,"%02X%c",md[j], 807 (j+1 == (int)n) 808 ?'\n':':'); 809 } 810 } 811 812 /* should be in the library */ 813 else if ((sign_flag == i) && (x509req == 0)) 814 { 815 BIO_printf(bio_err,"Getting Private key\n"); 816 if (Upkey == NULL) 817 { 818 Upkey=load_key(bio_err, 819 keyfile,keyformat, passin); 820 if (Upkey == NULL) goto end; 821 } 822 #ifndef NO_DSA 823 if (Upkey->type == EVP_PKEY_DSA) 824 digest=EVP_dss1(); 825 #endif 826 827 assert(need_rand); 828 if (!sign(x,Upkey,days,clrext,digest, 829 extconf, extsect)) goto end; 830 } 831 else if (CA_flag == i) 832 { 833 BIO_printf(bio_err,"Getting CA Private Key\n"); 834 if (CAkeyfile != NULL) 835 { 836 CApkey=load_key(bio_err, 837 CAkeyfile,CAkeyformat, passin); 838 if (CApkey == NULL) goto end; 839 } 840 #ifndef NO_DSA 841 if (CApkey->type == EVP_PKEY_DSA) 842 digest=EVP_dss1(); 843 #endif 844 845 assert(need_rand); 846 if (!x509_certify(ctx,CAfile,digest,x,xca, 847 CApkey, CAserial,CA_createserial,days, clrext, 848 extconf, extsect)) 849 goto end; 850 } 851 else if (x509req == i) 852 { 853 EVP_PKEY *pk; 854 855 BIO_printf(bio_err,"Getting request Private Key\n"); 856 if (keyfile == NULL) 857 { 858 BIO_printf(bio_err,"no request key file specified\n"); 859 goto end; 860 } 861 else 862 { 863 pk=load_key(bio_err, 864 keyfile,FORMAT_PEM, passin); 865 if (pk == NULL) goto end; 866 } 867 868 BIO_printf(bio_err,"Generating certificate request\n"); 869 870 #ifndef NO_DSA 871 if (pk->type == EVP_PKEY_DSA) 872 digest=EVP_dss1(); 873 #endif 874 875 rq=X509_to_X509_REQ(x,pk,digest); 876 EVP_PKEY_free(pk); 877 if (rq == NULL) 878 { 879 ERR_print_errors(bio_err); 880 goto end; 881 } 882 if (!noout) 883 { 884 X509_REQ_print(out,rq); 885 PEM_write_bio_X509_REQ(out,rq); 886 } 887 noout=1; 888 } 889 } 890 } 891 892 if (checkend) 893 { 894 time_t tnow=time(NULL); 895 896 if (ASN1_UTCTIME_cmp_time_t(X509_get_notAfter(x), tnow+checkoffset) == -1) 897 { 898 BIO_printf(out,"Certificate will expire\n"); 899 ret=1; 900 } 901 else 902 { 903 BIO_printf(out,"Certificate will not expire\n"); 904 ret=0; 905 } 906 goto end; 907 } 908 909 if (noout) 910 { 911 ret=0; 912 goto end; 913 } 914 915 if (outformat == FORMAT_ASN1) 916 i=i2d_X509_bio(out,x); 917 else if (outformat == FORMAT_PEM) 918 { 919 if (trustout) i=PEM_write_bio_X509_AUX(out,x); 920 else i=PEM_write_bio_X509(out,x); 921 } 922 else if (outformat == FORMAT_NETSCAPE) 923 { 924 ASN1_HEADER ah; 925 ASN1_OCTET_STRING os; 926 927 os.data=(unsigned char *)NETSCAPE_CERT_HDR; 928 os.length=strlen(NETSCAPE_CERT_HDR); 929 ah.header= &os; 930 ah.data=(char *)x; 931 ah.meth=X509_asn1_meth(); 932 933 /* no macro for this one yet */ 934 i=ASN1_i2d_bio(i2d_ASN1_HEADER,out,(unsigned char *)&ah); 935 } 936 else { 937 BIO_printf(bio_err,"bad output format specified for outfile\n"); 938 goto end; 939 } 940 if (!i) 941 { 942 BIO_printf(bio_err,"unable to write certificate\n"); 943 ERR_print_errors(bio_err); 944 goto end; 945 } 946 ret=0; 947 end: 948 if (need_rand) 949 app_RAND_write_file(NULL, bio_err); 950 OBJ_cleanup(); 951 CONF_free(extconf); 952 BIO_free_all(out); 953 BIO_free_all(STDout); 954 X509_STORE_free(ctx); 955 X509_REQ_free(req); 956 X509_free(x); 957 X509_free(xca); 958 EVP_PKEY_free(Upkey); 959 EVP_PKEY_free(CApkey); 960 X509_REQ_free(rq); 961 sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free); 962 sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free); 963 if (passin) OPENSSL_free(passin); 964 EXIT(ret); 965 } 966 967 static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest, 968 X509 *x, X509 *xca, EVP_PKEY *pkey, char *serialfile, int create, 969 int days, int clrext, LHASH *conf, char *section) 970 { 971 int ret=0; 972 BIO *io=NULL; 973 MS_STATIC char buf2[1024]; 974 char *buf=NULL,*p; 975 BIGNUM *serial=NULL; 976 ASN1_INTEGER *bs=NULL,bs2; 977 X509_STORE_CTX xsc; 978 EVP_PKEY *upkey; 979 980 upkey = X509_get_pubkey(xca); 981 EVP_PKEY_copy_parameters(upkey,pkey); 982 EVP_PKEY_free(upkey); 983 984 X509_STORE_CTX_init(&xsc,ctx,x,NULL); 985 buf=OPENSSL_malloc(EVP_PKEY_size(pkey)*2+ 986 ((serialfile == NULL) 987 ?(strlen(CAfile)+strlen(POSTFIX)+1) 988 :(strlen(serialfile)))+1); 989 if (buf == NULL) { BIO_printf(bio_err,"out of mem\n"); goto end; } 990 if (serialfile == NULL) 991 { 992 strcpy(buf,CAfile); 993 for (p=buf; *p; p++) 994 if (*p == '.') 995 { 996 *p='\0'; 997 break; 998 } 999 strcat(buf,POSTFIX); 1000 } 1001 else 1002 strcpy(buf,serialfile); 1003 serial=BN_new(); 1004 bs=ASN1_INTEGER_new(); 1005 if ((serial == NULL) || (bs == NULL)) 1006 { 1007 ERR_print_errors(bio_err); 1008 goto end; 1009 } 1010 1011 io=BIO_new(BIO_s_file()); 1012 if (io == NULL) 1013 { 1014 ERR_print_errors(bio_err); 1015 goto end; 1016 } 1017 1018 if (BIO_read_filename(io,buf) <= 0) 1019 { 1020 if (!create) 1021 { 1022 perror(buf); 1023 goto end; 1024 } 1025 else 1026 { 1027 ASN1_INTEGER_set(bs,1); 1028 BN_one(serial); 1029 } 1030 } 1031 else 1032 { 1033 if (!a2i_ASN1_INTEGER(io,bs,buf2,1024)) 1034 { 1035 BIO_printf(bio_err,"unable to load serial number from %s\n",buf); 1036 ERR_print_errors(bio_err); 1037 goto end; 1038 } 1039 else 1040 { 1041 serial=BN_bin2bn(bs->data,bs->length,serial); 1042 if (serial == NULL) 1043 { 1044 BIO_printf(bio_err,"error converting bin 2 bn"); 1045 goto end; 1046 } 1047 } 1048 } 1049 1050 if (!BN_add_word(serial,1)) 1051 { BIO_printf(bio_err,"add_word failure\n"); goto end; } 1052 bs2.data=(unsigned char *)buf2; 1053 bs2.length=BN_bn2bin(serial,bs2.data); 1054 1055 if (BIO_write_filename(io,buf) <= 0) 1056 { 1057 BIO_printf(bio_err,"error attempting to write serial number file\n"); 1058 perror(buf); 1059 goto end; 1060 } 1061 i2a_ASN1_INTEGER(io,&bs2); 1062 BIO_puts(io,"\n"); 1063 BIO_free(io); 1064 io=NULL; 1065 1066 if (!X509_STORE_add_cert(ctx,x)) goto end; 1067 1068 /* NOTE: this certificate can/should be self signed, unless it was 1069 * a certificate request in which case it is not. */ 1070 X509_STORE_CTX_set_cert(&xsc,x); 1071 if (!reqfile && !X509_verify_cert(&xsc)) 1072 goto end; 1073 1074 if (!X509_check_private_key(xca,pkey)) 1075 { 1076 BIO_printf(bio_err,"CA certificate and CA private key do not match\n"); 1077 goto end; 1078 } 1079 1080 if (!X509_set_issuer_name(x,X509_get_subject_name(xca))) goto end; 1081 if (!X509_set_serialNumber(x,bs)) goto end; 1082 1083 if (X509_gmtime_adj(X509_get_notBefore(x),0L) == NULL) 1084 goto end; 1085 1086 /* hardwired expired */ 1087 if (X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days) == NULL) 1088 goto end; 1089 1090 if (clrext) 1091 { 1092 while (X509_get_ext_count(x) > 0) X509_delete_ext(x, 0); 1093 } 1094 1095 if (conf) 1096 { 1097 X509V3_CTX ctx2; 1098 X509_set_version(x,2); /* version 3 certificate */ 1099 X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0); 1100 X509V3_set_conf_lhash(&ctx2, conf); 1101 if (!X509V3_EXT_add_conf(conf, &ctx2, section, x)) goto end; 1102 } 1103 1104 if (!X509_sign(x,pkey,digest)) goto end; 1105 ret=1; 1106 end: 1107 X509_STORE_CTX_cleanup(&xsc); 1108 if (!ret) 1109 ERR_print_errors(bio_err); 1110 if (buf != NULL) OPENSSL_free(buf); 1111 if (bs != NULL) ASN1_INTEGER_free(bs); 1112 if (io != NULL) BIO_free(io); 1113 if (serial != NULL) BN_free(serial); 1114 return ret; 1115 } 1116 1117 static int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx) 1118 { 1119 int err; 1120 X509 *err_cert; 1121 1122 /* it is ok to use a self signed certificate 1123 * This case will catch both the initial ok == 0 and the 1124 * final ok == 1 calls to this function */ 1125 err=X509_STORE_CTX_get_error(ctx); 1126 if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) 1127 return 1; 1128 1129 /* BAD we should have gotten an error. Normally if everything 1130 * worked X509_STORE_CTX_get_error(ctx) will still be set to 1131 * DEPTH_ZERO_SELF_.... */ 1132 if (ok) 1133 { 1134 BIO_printf(bio_err,"error with certificate to be certified - should be self signed\n"); 1135 return 0; 1136 } 1137 else 1138 { 1139 err_cert=X509_STORE_CTX_get_current_cert(ctx); 1140 print_name(bio_err, NULL, X509_get_subject_name(err_cert),0); 1141 BIO_printf(bio_err,"error with certificate - error %d at depth %d\n%s\n", 1142 err,X509_STORE_CTX_get_error_depth(ctx), 1143 X509_verify_cert_error_string(err)); 1144 return 1; 1145 } 1146 } 1147 1148 /* self sign */ 1149 static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, const EVP_MD *digest, 1150 LHASH *conf, char *section) 1151 { 1152 1153 EVP_PKEY *pktmp; 1154 1155 pktmp = X509_get_pubkey(x); 1156 EVP_PKEY_copy_parameters(pktmp,pkey); 1157 EVP_PKEY_save_parameters(pktmp,1); 1158 EVP_PKEY_free(pktmp); 1159 1160 if (!X509_set_issuer_name(x,X509_get_subject_name(x))) goto err; 1161 if (X509_gmtime_adj(X509_get_notBefore(x),0) == NULL) goto err; 1162 1163 /* Lets just make it 12:00am GMT, Jan 1 1970 */ 1164 /* memcpy(x->cert_info->validity->notBefore,"700101120000Z",13); */ 1165 /* 28 days to be certified */ 1166 1167 if (X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days) == NULL) 1168 goto err; 1169 1170 if (!X509_set_pubkey(x,pkey)) goto err; 1171 if (clrext) 1172 { 1173 while (X509_get_ext_count(x) > 0) X509_delete_ext(x, 0); 1174 } 1175 if (conf) 1176 { 1177 X509V3_CTX ctx; 1178 X509_set_version(x,2); /* version 3 certificate */ 1179 X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0); 1180 X509V3_set_conf_lhash(&ctx, conf); 1181 if (!X509V3_EXT_add_conf(conf, &ctx, section, x)) goto err; 1182 } 1183 if (!X509_sign(x,pkey,digest)) goto err; 1184 return 1; 1185 err: 1186 ERR_print_errors(bio_err); 1187 return 0; 1188 } 1189 1190 static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt) 1191 { 1192 int id, i, idret; 1193 char *pname; 1194 id = X509_PURPOSE_get_id(pt); 1195 pname = X509_PURPOSE_get0_name(pt); 1196 for (i = 0; i < 2; i++) 1197 { 1198 idret = X509_check_purpose(cert, id, i); 1199 BIO_printf(bio, "%s%s : ", pname, i ? " CA" : ""); 1200 if (idret == 1) BIO_printf(bio, "Yes\n"); 1201 else if (idret == 0) BIO_printf(bio, "No\n"); 1202 else BIO_printf(bio, "Yes (WARNING code=%d)\n", idret); 1203 } 1204 return 1; 1205 } 1206 1207 1208 1209