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