x509.c 31.4 KB
Newer Older
1
/* apps/x509.c */
2
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
 * All rights reserved.
 *
 * This package is an SSL implementation written
 * by Eric Young (eay@cryptsoft.com).
 * The implementation was written so as to conform with Netscapes SSL.
 * 
 * This library is free for commercial and non-commercial use as long as
 * the following conditions are aheared to.  The following conditions
 * apply to all code found in this distribution, be it the RC4, RSA,
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
 * included with this distribution is covered by the same copyright terms
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
 * 
 * Copyright remains Eric Young's, and as such any Copyright notices in
 * the code are not to be removed.
 * If this package is used in a product, Eric Young should be given attribution
 * as the author of the parts of the library used.
 * This can be in the form of a textual message at program startup or
 * in documentation (online or textual) provided with the package.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *    "This product includes cryptographic software written by
 *     Eric Young (eay@cryptsoft.com)"
 *    The word 'cryptographic' can be left out if the rouines from the library
 *    being used are not cryptographic related :-).
 * 4. If you include any Windows specific code (or a derivative thereof) from 
 *    the apps directory (application code) you must include an acknowledgement:
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
 * 
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * 
 * The licence and distribution terms for any publically available version or
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
 * copied and put under another distribution licence
 * [including the GNU Public Licence.]
 */

59
#include <assert.h>
60 61 62
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
63
#ifdef OPENSSL_NO_STDIO
64 65 66
#define APPS_WIN16
#endif
#include "apps.h"
67 68 69 70 71 72 73 74 75
#include <openssl/bio.h>
#include <openssl/asn1.h>
#include <openssl/err.h>
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/objects.h>
#include <openssl/pem.h>
76 77 78 79 80 81 82 83 84 85 86

#undef PROG
#define PROG x509_main

#undef POSTFIX
#define	POSTFIX	".srl"
#define DEF_DAYS	30

static char *x509_usage[]={
"usage: x509 args\n",
" -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 89 90 91 92
" -keyform arg    - private key format - default PEM\n",
" -CAform arg     - CA format - default PEM\n",
" -CAkeyform arg  - CA key format - default PEM\n",
" -in arg         - input file - default stdin\n",
" -out arg        - output file - default stdout\n",
D
Dr. Stephen Henson 已提交
93
" -passin arg     - private key password source\n",
94 95 96 97
" -serial         - print serial number value\n",
" -hash           - print hash value\n",
" -subject        - print subject DN\n",
" -issuer         - print issuer DN\n",
98
" -email          - print email address(es)\n",
99 100
" -startdate      - notBefore field\n",
" -enddate        - notAfter field\n",
101
" -purpose        - print out certificate purposes\n",
102 103
" -dates          - both Before and After dates\n",
" -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
" -ocspid         - print OCSP hash values for the subject name and public key\n",
109 110
" -trustout       - output a \"trusted\" certificate\n",
" -clrtrust       - clear all trusted purposes\n",
111 112 113
" -clrreject      - clear all rejected purposes\n",
" -addtrust arg   - trust certificate for a given purpose\n",
" -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 117
" -checkend arg   - check whether the cert expires in the next arg seconds\n",
"                   exit 1 if so, 0 if not\n",
118 119 120 121 122
" -signkey arg    - self sign cert with arg\n",
" -x509toreq      - output a certification request object\n",
" -req            - input is a certificate request, sign and output.\n",
" -CA arg         - set the CA certificate, must be PEM format.\n",
" -CAkey arg      - set the CA key, must be PEM format\n",
U
Ulf Möller 已提交
123
"                   missing, it is assumed to be in the CA file.\n",
124
" -CAcreateserial - create serial number file if it does not exist\n",
125
" -CAserial arg   - serial file\n",
126
" -set_serial     - serial number to use\n",
127
" -text           - print the certificate in text form\n",
128
" -C              - print out C code forms\n",
129
" -md2/-md5/-sha1/-mdc2 - digest to use\n",
130
" -extfile        - configuration file with X509V3 extensions to add\n",
131
" -extensions     - section from config file with X509V3 extensions to add\n",
132
" -clrext         - delete extensions before signing and input certificate\n",
D
 
Dr. Stephen Henson 已提交
133
" -nameopt arg    - various certificate name options\n",
134
#ifndef OPENSSL_NO_ENGINE
135
" -engine e       - use engine e, possibly a hardware device.\n",
136
#endif
137
" -certopt arg    - various certificate text options\n",
138 139 140 141
NULL
};

static int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx);
142
static int sign (X509 *x, EVP_PKEY *pkey,int days,int clrext, const EVP_MD *digest,
D
 
Dr. Stephen Henson 已提交
143
						CONF *conf, char *section);
B
Ben Laurie 已提交
144 145
static int x509_certify (X509_STORE *ctx,char *CAfile,const EVP_MD *digest,
			 X509 *x,X509 *xca,EVP_PKEY *pkey,char *serial,
D
 
Dr. Stephen Henson 已提交
146
			 int create,int days, int clrext, CONF *conf, char *section,
147
						ASN1_INTEGER *sno);
148
static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt);
149 150
static int reqfile=0;

151 152
int MAIN(int, char **);

U
Ulf Möller 已提交
153
int MAIN(int argc, char **argv)
154
	{
155
	ENGINE *e = NULL;
156 157 158
	int ret=1;
	X509_REQ *req=NULL;
	X509 *x=NULL,*xca=NULL;
159
	ASN1_OBJECT *objtmp;
160
	EVP_PKEY *Upkey=NULL,*CApkey=NULL;
161
	ASN1_INTEGER *sno = NULL;
162 163 164
	int i,num,badops=0;
	BIO *out=NULL;
	BIO *STDout=NULL;
165
	STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL;
166 167 168
	int informat,outformat,keyformat,CAformat,CAkeyformat;
	char *infile=NULL,*outfile=NULL,*keyfile=NULL,*CAfile=NULL;
	char *CAkeyfile=NULL,*CAserial=NULL;
169
	char *alias=NULL;
170
	int text=0,serial=0,hash=0,subject=0,issuer=0,startdate=0,enddate=0;
171
	int ocspid=0;
172
	int noout=0,sign_flag=0,CA_flag=0,CA_createserial=0,email=0;
173
	int trustout=0,clrtrust=0,clrreject=0,aliasout=0,clrext=0;
174
	int C=0;
175
	int x509req=0,days=DEF_DAYS,modulus=0,pubkey=0;
176
	int pprint = 0;
177 178 179 180 181
	char **pp;
	X509_STORE *ctx=NULL;
	X509_REQ *rq=NULL;
	int fingerprint=0;
	char buf[256];
B
Ben Laurie 已提交
182
	const EVP_MD *md_alg,*digest=EVP_md5();
D
 
Dr. Stephen Henson 已提交
183
	CONF *extconf = NULL;
D
Dr. Stephen Henson 已提交
184
	char *extsect = NULL, *extfile = NULL, *passin = NULL, *passargin = NULL;
185
	int need_rand = 0;
186
	int checkend=0,checkoffset=0;
187
	unsigned long nmflag = 0, certflag = 0;
188
#ifndef OPENSSL_NO_ENGINE
189
	char *engine=NULL;
190
#endif
191 192 193 194 195 196 197

	reqfile=0;

	apps_startup();

	if (bio_err == NULL)
		bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
D
Dr. Stephen Henson 已提交
198 199 200

	if (!load_config(bio_err, NULL))
		goto end;
201
	STDout=BIO_new_fp(stdout,BIO_NOCLOSE);
202
#ifdef OPENSSL_SYS_VMS
203 204 205 206 207
	{
	BIO *tmpbio = BIO_new(BIO_f_linebuffer());
	STDout = BIO_push(tmpbio, STDout);
	}
#endif
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239

	informat=FORMAT_PEM;
	outformat=FORMAT_PEM;
	keyformat=FORMAT_PEM;
	CAformat=FORMAT_PEM;
	CAkeyformat=FORMAT_PEM;

	ctx=X509_STORE_new();
	if (ctx == NULL) goto end;
	X509_STORE_set_verify_cb_func(ctx,callb);

	argc--;
	argv++;
	num=0;
	while (argc >= 1)
		{
		if 	(strcmp(*argv,"-inform") == 0)
			{
			if (--argc < 1) goto bad;
			informat=str2fmt(*(++argv));
			}
		else if (strcmp(*argv,"-outform") == 0)
			{
			if (--argc < 1) goto bad;
			outformat=str2fmt(*(++argv));
			}
		else if (strcmp(*argv,"-keyform") == 0)
			{
			if (--argc < 1) goto bad;
			keyformat=str2fmt(*(++argv));
			}
		else if (strcmp(*argv,"-req") == 0)
240
			{
241
			reqfile=1;
242 243
			need_rand = 1;
			}
244 245 246 247 248 249 250 251
		else if (strcmp(*argv,"-CAform") == 0)
			{
			if (--argc < 1) goto bad;
			CAformat=str2fmt(*(++argv));
			}
		else if (strcmp(*argv,"-CAkeyform") == 0)
			{
			if (--argc < 1) goto bad;
252
			CAkeyformat=str2fmt(*(++argv));
253 254 255 256 257 258 259
			}
		else if (strcmp(*argv,"-days") == 0)
			{
			if (--argc < 1) goto bad;
			days=atoi(*(++argv));
			if (days == 0)
				{
260
				BIO_printf(STDout,"bad number of days\n");
261 262 263
				goto bad;
				}
			}
264 265 266
		else if (strcmp(*argv,"-passin") == 0)
			{
			if (--argc < 1) goto bad;
D
Dr. Stephen Henson 已提交
267
			passargin= *(++argv);
268
			}
269
		else if (strcmp(*argv,"-extfile") == 0)
270 271 272 273
			{
			if (--argc < 1) goto bad;
			extfile= *(++argv);
			}
274 275 276 277 278
		else if (strcmp(*argv,"-extensions") == 0)
			{
			if (--argc < 1) goto bad;
			extsect= *(++argv);
			}
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
		else if (strcmp(*argv,"-in") == 0)
			{
			if (--argc < 1) goto bad;
			infile= *(++argv);
			}
		else if (strcmp(*argv,"-out") == 0)
			{
			if (--argc < 1) goto bad;
			outfile= *(++argv);
			}
		else if (strcmp(*argv,"-signkey") == 0)
			{
			if (--argc < 1) goto bad;
			keyfile= *(++argv);
			sign_flag= ++num;
294
			need_rand = 1;
295 296 297 298 299 300
			}
		else if (strcmp(*argv,"-CA") == 0)
			{
			if (--argc < 1) goto bad;
			CAfile= *(++argv);
			CA_flag= ++num;
301
			need_rand = 1;
302 303 304 305 306 307 308 309 310 311 312
			}
		else if (strcmp(*argv,"-CAkey") == 0)
			{
			if (--argc < 1) goto bad;
			CAkeyfile= *(++argv);
			}
		else if (strcmp(*argv,"-CAserial") == 0)
			{
			if (--argc < 1) goto bad;
			CAserial= *(++argv);
			}
313 314 315 316 317 318
		else if (strcmp(*argv,"-set_serial") == 0)
			{
			if (--argc < 1) goto bad;
			if (!(sno = s2i_ASN1_INTEGER(NULL, *(++argv))))
				goto bad;
			}
319 320 321
		else if (strcmp(*argv,"-addtrust") == 0)
			{
			if (--argc < 1) goto bad;
322 323
			if (!(objtmp = OBJ_txt2obj(*(++argv), 0)))
				{
324
				BIO_printf(bio_err,
325
					"Invalid trust object value %s\n", *argv);
326
				goto bad;
327 328
				}
			if (!trust) trust = sk_ASN1_OBJECT_new_null();
329
			sk_ASN1_OBJECT_push(trust, objtmp);
330 331
			trustout = 1;
			}
332
		else if (strcmp(*argv,"-addreject") == 0)
333 334
			{
			if (--argc < 1) goto bad;
335 336
			if (!(objtmp = OBJ_txt2obj(*(++argv), 0)))
				{
337
				BIO_printf(bio_err,
338
					"Invalid reject object value %s\n", *argv);
339
				goto bad;
340 341
				}
			if (!reject) reject = sk_ASN1_OBJECT_new_null();
342
			sk_ASN1_OBJECT_push(reject, objtmp);
343 344 345 346 347 348 349 350
			trustout = 1;
			}
		else if (strcmp(*argv,"-setalias") == 0)
			{
			if (--argc < 1) goto bad;
			alias= *(++argv);
			trustout = 1;
			}
351 352 353 354 355
		else if (strcmp(*argv,"-certopt") == 0)
			{
			if (--argc < 1) goto bad;
			if (!set_cert_ex(&certflag, *(++argv))) goto bad;
			}
D
 
Dr. Stephen Henson 已提交
356 357 358
		else if (strcmp(*argv,"-nameopt") == 0)
			{
			if (--argc < 1) goto bad;
359
			if (!set_name_ex(&nmflag, *(++argv))) goto bad;
D
 
Dr. Stephen Henson 已提交
360
			}
361
#ifndef OPENSSL_NO_ENGINE
362 363 364 365 366
		else if (strcmp(*argv,"-engine") == 0)
			{
			if (--argc < 1) goto bad;
			engine= *(++argv);
			}
367
#endif
368 369
		else if (strcmp(*argv,"-C") == 0)
			C= ++num;
370 371
		else if (strcmp(*argv,"-email") == 0)
			email= ++num;
372 373 374 375
		else if (strcmp(*argv,"-serial") == 0)
			serial= ++num;
		else if (strcmp(*argv,"-modulus") == 0)
			modulus= ++num;
376 377
		else if (strcmp(*argv,"-pubkey") == 0)
			pubkey= ++num;
378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394
		else if (strcmp(*argv,"-x509toreq") == 0)
			x509req= ++num;
		else if (strcmp(*argv,"-text") == 0)
			text= ++num;
		else if (strcmp(*argv,"-hash") == 0)
			hash= ++num;
		else if (strcmp(*argv,"-subject") == 0)
			subject= ++num;
		else if (strcmp(*argv,"-issuer") == 0)
			issuer= ++num;
		else if (strcmp(*argv,"-fingerprint") == 0)
			fingerprint= ++num;
		else if (strcmp(*argv,"-dates") == 0)
			{
			startdate= ++num;
			enddate= ++num;
			}
395 396
		else if (strcmp(*argv,"-purpose") == 0)
			pprint= ++num;
397 398 399 400
		else if (strcmp(*argv,"-startdate") == 0)
			startdate= ++num;
		else if (strcmp(*argv,"-enddate") == 0)
			enddate= ++num;
401 402 403 404 405 406
		else if (strcmp(*argv,"-checkend") == 0)
			{
			if (--argc < 1) goto bad;
			checkoffset=atoi(*(++argv));
			checkend=1;
			}
407 408
		else if (strcmp(*argv,"-noout") == 0)
			noout= ++num;
409 410 411 412
		else if (strcmp(*argv,"-trustout") == 0)
			trustout= 1;
		else if (strcmp(*argv,"-clrtrust") == 0)
			clrtrust= ++num;
413 414
		else if (strcmp(*argv,"-clrreject") == 0)
			clrreject= ++num;
415 416
		else if (strcmp(*argv,"-alias") == 0)
			aliasout= ++num;
417 418
		else if (strcmp(*argv,"-CAcreateserial") == 0)
			CA_createserial= ++num;
419 420 421
		else if (strcmp(*argv,"-clrext") == 0)
			clrext = 1;
#if 1 /* stay backwards-compatible with 0.9.5; this should go away soon */
422
		else if (strcmp(*argv,"-crlext") == 0)
423 424
			{
			BIO_printf(bio_err,"use -clrext instead of -crlext\n");
425
			clrext = 1;
426 427
			}
#endif
428 429
		else if (strcmp(*argv,"-ocspid") == 0)
			ocspid= ++num;
430
		else if ((md_alg=EVP_get_digestbyname(*argv + 1)))
431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448
			{
			/* ok */
			digest=md_alg;
			}
		else
			{
			BIO_printf(bio_err,"unknown option %s\n",*argv);
			badops=1;
			break;
			}
		argc--;
		argv++;
		}

	if (badops)
		{
bad:
		for (pp=x509_usage; (*pp != NULL); pp++)
U
Ulf Möller 已提交
449
			BIO_printf(bio_err,"%s",*pp);
450 451 452
		goto end;
		}

453
#ifndef OPENSSL_NO_ENGINE
454
        e = setup_engine(bio_err, engine, 0);
455
#endif
456

457 458 459
	if (need_rand)
		app_RAND_load_file(NULL, bio_err, 0);

460 461
	ERR_load_crypto_strings();

462 463
	if (!app_passwd(bio_err, passargin, NULL, &passin, NULL))
		{
D
Dr. Stephen Henson 已提交
464 465
		BIO_printf(bio_err, "Error getting password\n");
		goto end;
466
		}
D
Dr. Stephen Henson 已提交
467

468 469 470 471 472 473 474 475 476 477 478 479 480 481
	if (!X509_STORE_set_default_paths(ctx))
		{
		ERR_print_errors(bio_err);
		goto end;
		}

	if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM))
		{ CAkeyfile=CAfile; }
	else if ((CA_flag) && (CAkeyfile == NULL))
		{
		BIO_printf(bio_err,"need to specify a CAkey if using the CA command\n");
		goto end;
		}

482 483
	if (extfile)
		{
484
		long errorline = -1;
B
Ben Laurie 已提交
485
		X509V3_CTX ctx2;
D
 
Dr. Stephen Henson 已提交
486 487
		extconf = NCONF_new(NULL);
		if (!NCONF_load(extconf, extfile,&errorline))
488
			{
489 490 491 492 493 494 495 496 497
			if (errorline <= 0)
				BIO_printf(bio_err,
					"error loading the config file '%s'\n",
								extfile);
                	else
                        	BIO_printf(bio_err,
				       "error on line %ld of config file '%s'\n"
							,errorline,extfile);
			goto end;
498
			}
499 500
		if (!extsect)
			{
D
 
Dr. Stephen Henson 已提交
501
			extsect = NCONF_get_string(extconf, "default", "extensions");
502 503 504 505 506 507
			if (!extsect)
				{
				ERR_clear_error();
				extsect = "default";
				}
			}
B
Ben Laurie 已提交
508
		X509V3_set_ctx_test(&ctx2);
D
 
Dr. Stephen Henson 已提交
509 510
		X509V3_set_nconf(&ctx2, extconf);
		if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL))
511
			{
512 513 514 515 516
			BIO_printf(bio_err,
				"Error Loading extension section %s\n",
								 extsect);
			ERR_print_errors(bio_err);
			goto end;
517 518
			}
		}
519 520


521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539
	if (reqfile)
		{
		EVP_PKEY *pkey;
		X509_CINF *ci;
		BIO *in;

		if (!sign_flag && !CA_flag)
			{
			BIO_printf(bio_err,"We need a private key to sign with\n");
			goto end;
			}
		in=BIO_new(BIO_s_file());
		if (in == NULL)
			{
			ERR_print_errors(bio_err);
			goto end;
			}

		if (infile == NULL)
540
			BIO_set_fp(in,stdin,BIO_NOCLOSE|BIO_FP_TEXT);
541 542 543 544 545
		else
			{
			if (BIO_read_filename(in,infile) <= 0)
				{
				perror(infile);
546
				BIO_free(in);
547 548 549
				goto end;
				}
			}
550
		req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL);
551 552
		BIO_free(in);

553 554 555 556 557
		if (req == NULL)
			{
			ERR_print_errors(bio_err);
			goto end;
			}
558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573

		if (	(req->req_info == NULL) ||
			(req->req_info->pubkey == NULL) ||
			(req->req_info->pubkey->public_key == NULL) ||
			(req->req_info->pubkey->public_key->data == NULL))
			{
			BIO_printf(bio_err,"The certificate request appears to corrupted\n");
			BIO_printf(bio_err,"It does not contain a public key\n");
			goto end;
			}
		if ((pkey=X509_REQ_get_pubkey(req)) == NULL)
	                {
	                BIO_printf(bio_err,"error unpacking public key\n");
	                goto end;
	                }
		i=X509_REQ_verify(req,pkey);
574
		EVP_PKEY_free(pkey);
575 576 577 578 579 580 581 582 583 584 585 586 587
		if (i < 0)
			{
			BIO_printf(bio_err,"Signature verification error\n");
			ERR_print_errors(bio_err);
			goto end;
			}
	        if (i == 0)
			{
			BIO_printf(bio_err,"Signature did not match the certificate request\n");
			goto end;
			}
		else
			BIO_printf(bio_err,"Signature ok\n");
D
 
Dr. Stephen Henson 已提交
588 589

		print_name(bio_err, "subject=", X509_REQ_get_subject_name(req), nmflag);
590 591 592 593

		if ((x=X509_new()) == NULL) goto end;
		ci=x->cert_info;

594 595 596 597 598 599
		if (sno)
			{
			if (!X509_set_serialNumber(x, sno))
				goto end;
			}
		else if (!ASN1_INTEGER_set(X509_get_serialNumber(x),0)) goto end;
600 601 602 603 604 605
		if (!X509_set_issuer_name(x,req->req_info->subject)) goto end;
		if (!X509_set_subject_name(x,req->req_info->subject)) goto end;

		X509_gmtime_adj(X509_get_notBefore(x),0);
	        X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days);

606 607 608
		pkey = X509_REQ_get_pubkey(req);
		X509_set_pubkey(x,pkey);
		EVP_PKEY_free(pkey);
609 610
		}
	else
611
		x=load_cert(bio_err,infile,informat,NULL,e,"Certificate");
612 613 614 615

	if (x == NULL) goto end;
	if (CA_flag)
		{
616
		xca=load_cert(bio_err,CAfile,CAformat,NULL,e,"CA Certificate");
617 618 619 620 621
		if (xca == NULL) goto end;
		}

	if (!noout || text)
		{
622
		OBJ_create("2.99999.3",
623 624 625 626 627 628 629 630 631
			"SET.ex3","SET x509v3 extension 3");

		out=BIO_new(BIO_s_file());
		if (out == NULL)
			{
			ERR_print_errors(bio_err);
			goto end;
			}
		if (outfile == NULL)
632
			{
633
			BIO_set_fp(out,stdout,BIO_NOCLOSE);
634
#ifdef OPENSSL_SYS_VMS
635 636 637 638 639 640
			{
			BIO *tmpbio = BIO_new(BIO_f_linebuffer());
			out = BIO_push(tmpbio, out);
			}
#endif
			}
641 642 643 644 645 646 647 648 649 650
		else
			{
			if (BIO_write_filename(out,outfile) <= 0)
				{
				perror(outfile);
				goto end;
				}
			}
		}

651
	if (alias) X509_alias_set1(x, (unsigned char *)alias, -1);
652

653 654
	if (clrtrust) X509_trust_clear(x);
	if (clrreject) X509_reject_clear(x);
655

656 657 658 659
	if (trust)
		{
		for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++)
			{
660
			objtmp = sk_ASN1_OBJECT_value(trust, i);
661
			X509_add1_trust_object(x, objtmp);
662
			}
663 664
		}

665 666 667 668
	if (reject)
		{
		for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++)
			{
669
			objtmp = sk_ASN1_OBJECT_value(reject, i);
670
			X509_add1_reject_object(x, objtmp);
671
			}
672 673
		}

674 675 676 677 678 679
	if (num)
		{
		for (i=1; i<=num; i++)
			{
			if (issuer == i)
				{
D
 
Dr. Stephen Henson 已提交
680 681
				print_name(STDout, "issuer= ",
					X509_get_issuer_name(x), nmflag);
682 683 684
				}
			else if (subject == i) 
				{
685
				print_name(STDout, "subject= ",
D
 
Dr. Stephen Henson 已提交
686
					X509_get_subject_name(x), nmflag);
687 688 689
				}
			else if (serial == i)
				{
690
				BIO_printf(STDout,"serial=");
691
				i2a_ASN1_INTEGER(STDout,x->cert_info->serialNumber);
692
				BIO_printf(STDout,"\n");
693
				}
694 695 696 697 698
			else if (email == i) 
				{
				int j;
				STACK *emlst;
				emlst = X509_get1_email(x);
699
				for (j = 0; j < sk_num(emlst); j++)
700 701 702
					BIO_printf(STDout, "%s\n", sk_value(emlst, j));
				X509_email_free(emlst);
				}
703 704 705
			else if (aliasout == i)
				{
				unsigned char *alstr;
706
				alstr = X509_alias_get0(x, NULL);
707
				if (alstr) BIO_printf(STDout,"%s\n", alstr);
708 709
				else BIO_puts(STDout,"<No Alias>\n");
				}
710 711
			else if (hash == i)
				{
712
				BIO_printf(STDout,"%08lx\n",X509_subject_name_hash(x));
713
				}
714 715
			else if (pprint == i)
				{
716 717
				X509_PURPOSE *ptmp;
				int j;
718
				BIO_printf(STDout, "Certificate purposes:\n");
719
				for (j = 0; j < X509_PURPOSE_get_count(); j++)
720
					{
721
					ptmp = X509_PURPOSE_get0(j);
722 723
					purpose_print(STDout, x, ptmp);
					}
724
				}
725 726 727 728 729 730 731 732
			else
				if (modulus == i)
				{
				EVP_PKEY *pkey;

				pkey=X509_get_pubkey(x);
				if (pkey == NULL)
					{
733
					BIO_printf(bio_err,"Modulus=unavailable\n");
734 735 736
					ERR_print_errors(bio_err);
					goto end;
					}
737
				BIO_printf(STDout,"Modulus=");
738
#ifndef OPENSSL_NO_RSA
739 740 741
				if (pkey->type == EVP_PKEY_RSA)
					BN_print(STDout,pkey->pkey.rsa->n);
				else
742
#endif
743
#ifndef OPENSSL_NO_DSA
744 745 746 747
				if (pkey->type == EVP_PKEY_DSA)
					BN_print(STDout,pkey->pkey.dsa->pub_key);
				else
#endif
748 749
					BIO_printf(STDout,"Wrong Algorithm type");
				BIO_printf(STDout,"\n");
750
				EVP_PKEY_free(pkey);
751
				}
752 753 754 755 756 757 758 759 760 761 762 763 764 765 766
			else
				if (pubkey == i)
				{
				EVP_PKEY *pkey;

				pkey=X509_get_pubkey(x);
				if (pkey == NULL)
					{
					BIO_printf(bio_err,"Error getting public key\n");
					ERR_print_errors(bio_err);
					goto end;
					}
				PEM_write_bio_PUBKEY(STDout, pkey);
				EVP_PKEY_free(pkey);
				}
767 768 769 770 771 772 773 774
			else
				if (C == i)
				{
				unsigned char *d;
				char *m;
				int y,z;

				X509_NAME_oneline(X509_get_subject_name(x),
775
					buf,sizeof buf);
776
				BIO_printf(STDout,"/* subject:%s */\n",buf);
777
				m=X509_NAME_oneline(
778 779
					X509_get_issuer_name(x),buf,
					sizeof buf);
780
				BIO_printf(STDout,"/* issuer :%s */\n",buf);
781 782

				z=i2d_X509(x,NULL);
783
				m=OPENSSL_malloc(z);
784 785 786

				d=(unsigned char *)m;
				z=i2d_X509_NAME(X509_get_subject_name(x),&d);
787
				BIO_printf(STDout,"unsigned char XXX_subject_name[%d]={\n",z);
788 789 790
				d=(unsigned char *)m;
				for (y=0; y<z; y++)
					{
791 792
					BIO_printf(STDout,"0x%02X,",d[y]);
					if ((y & 0x0f) == 0x0f) BIO_printf(STDout,"\n");
793
					}
794 795
				if (y%16 != 0) BIO_printf(STDout,"\n");
				BIO_printf(STDout,"};\n");
796 797

				z=i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x),&d);
798
				BIO_printf(STDout,"unsigned char XXX_public_key[%d]={\n",z);
799 800 801
				d=(unsigned char *)m;
				for (y=0; y<z; y++)
					{
802 803 804
					BIO_printf(STDout,"0x%02X,",d[y]);
					if ((y & 0x0f) == 0x0f)
						BIO_printf(STDout,"\n");
805
					}
806 807
				if (y%16 != 0) BIO_printf(STDout,"\n");
				BIO_printf(STDout,"};\n");
808 809

				z=i2d_X509(x,&d);
810
				BIO_printf(STDout,"unsigned char XXX_certificate[%d]={\n",z);
811 812 813
				d=(unsigned char *)m;
				for (y=0; y<z; y++)
					{
814 815 816
					BIO_printf(STDout,"0x%02X,",d[y]);
					if ((y & 0x0f) == 0x0f)
						BIO_printf(STDout,"\n");
817
					}
818 819
				if (y%16 != 0) BIO_printf(STDout,"\n");
				BIO_printf(STDout,"};\n");
820

821
				OPENSSL_free(m);
822 823 824
				}
			else if (text == i)
				{
825
				X509_print_ex(out,x,nmflag, certflag);
826 827 828 829
				}
			else if (startdate == i)
				{
				BIO_puts(STDout,"notBefore=");
830
				ASN1_TIME_print(STDout,X509_get_notBefore(x));
831 832 833 834 835
				BIO_puts(STDout,"\n");
				}
			else if (enddate == i)
				{
				BIO_puts(STDout,"notAfter=");
836
				ASN1_TIME_print(STDout,X509_get_notAfter(x));
837 838 839 840 841 842 843 844
				BIO_puts(STDout,"\n");
				}
			else if (fingerprint == i)
				{
				int j;
				unsigned int n;
				unsigned char md[EVP_MAX_MD_SIZE];

845
				if (!X509_digest(x,digest,md,&n))
846 847 848 849
					{
					BIO_printf(bio_err,"out of memory\n");
					goto end;
					}
850 851
				BIO_printf(STDout,"%s Fingerprint=",
						OBJ_nid2sn(EVP_MD_type(digest)));
852 853
				for (j=0; j<(int)n; j++)
					{
854
					BIO_printf(STDout,"%02X%c",md[j],
855 856 857 858 859 860 861 862 863 864 865
						(j+1 == (int)n)
						?'\n':':');
					}
				}

			/* should be in the library */
			else if ((sign_flag == i) && (x509req == 0))
				{
				BIO_printf(bio_err,"Getting Private key\n");
				if (Upkey == NULL)
					{
866
					Upkey=load_key(bio_err,
867 868
						keyfile, keyformat, 0,
						passin, e, "Private key");
869 870
					if (Upkey == NULL) goto end;
					}
871
#ifndef OPENSSL_NO_DSA
872 873 874
		                if (Upkey->type == EVP_PKEY_DSA)
		                        digest=EVP_dss1();
#endif
B
Bodo Möller 已提交
875
#ifndef OPENSSL_NO_ECDSA
876
				if (Upkey->type == EVP_PKEY_EC)
B
Bodo Möller 已提交
877 878
					digest=EVP_ecdsa();
#endif
879

880
				assert(need_rand);
881
				if (!sign(x,Upkey,days,clrext,digest,
882
						 extconf, extsect)) goto end;
883 884 885 886 887 888
				}
			else if (CA_flag == i)
				{
				BIO_printf(bio_err,"Getting CA Private Key\n");
				if (CAkeyfile != NULL)
					{
889
					CApkey=load_key(bio_err,
890 891 892
						CAkeyfile, CAkeyformat,
						0, passin, e,
						"CA Private Key");
893 894
					if (CApkey == NULL) goto end;
					}
895
#ifndef OPENSSL_NO_DSA
896 897 898
		                if (CApkey->type == EVP_PKEY_DSA)
		                        digest=EVP_dss1();
#endif
B
Bodo Möller 已提交
899
#ifndef OPENSSL_NO_ECDSA
900
				if (CApkey->type == EVP_PKEY_EC)
B
Bodo Möller 已提交
901 902
					digest = EVP_ecdsa();
#endif
903
				
904
				assert(need_rand);
905
				if (!x509_certify(ctx,CAfile,digest,x,xca,
906
					CApkey, CAserial,CA_createserial,days, clrext,
907
					extconf, extsect, sno))
908 909 910 911 912 913 914 915 916 917 918 919 920 921
					goto end;
				}
			else if (x509req == i)
				{
				EVP_PKEY *pk;

				BIO_printf(bio_err,"Getting request Private Key\n");
				if (keyfile == NULL)
					{
					BIO_printf(bio_err,"no request key file specified\n");
					goto end;
					}
				else
					{
922
					pk=load_key(bio_err,
923 924
						keyfile, FORMAT_PEM, 0,
						passin, e, "request key");
925 926 927 928 929
					if (pk == NULL) goto end;
					}

				BIO_printf(bio_err,"Generating certificate request\n");

930
#ifndef OPENSSL_NO_DSA
931 932
		                if (pk->type == EVP_PKEY_DSA)
		                        digest=EVP_dss1();
933 934
#endif
#ifndef OPENSSL_NO_ECDSA
935
				if (pk->type == EVP_PKEY_EC)
B
Bodo Möller 已提交
936
					digest=EVP_ecdsa();
937
#endif
938 939

				rq=X509_to_X509_REQ(x,pk,digest);
940 941 942 943 944 945 946 947 948 949 950 951 952
				EVP_PKEY_free(pk);
				if (rq == NULL)
					{
					ERR_print_errors(bio_err);
					goto end;
					}
				if (!noout)
					{
					X509_REQ_print(out,rq);
					PEM_write_bio_X509_REQ(out,rq);
					}
				noout=1;
				}
953 954 955 956
			else if (ocspid == i)
				{
				X509_ocspid_print(out, x);
				}
957 958 959
			}
		}

960
	if (checkend)
961 962 963
		{
		time_t tnow=time(NULL);

964
		if (ASN1_UTCTIME_cmp_time_t(X509_get_notAfter(x), tnow+checkoffset) == -1)
965 966 967 968 969 970 971 972 973 974 975 976
			{
			BIO_printf(out,"Certificate will expire\n");
			ret=1;
			}
		else
			{
			BIO_printf(out,"Certificate will not expire\n");
			ret=0;
			}
		goto end;
		}

977 978 979 980 981 982 983 984
	if (noout)
		{
		ret=0;
		goto end;
		}

	if 	(outformat == FORMAT_ASN1)
		i=i2d_X509_bio(out,x);
985 986 987
	else if (outformat == FORMAT_PEM)
		{
		if (trustout) i=PEM_write_bio_X509_AUX(out,x);
988
		else i=PEM_write_bio_X509(out,x);
989 990
		}
	else if (outformat == FORMAT_NETSCAPE)
991 992 993 994
		{
		ASN1_HEADER ah;
		ASN1_OCTET_STRING os;

995 996
		os.data=(unsigned char *)NETSCAPE_CERT_HDR;
		os.length=strlen(NETSCAPE_CERT_HDR);
997 998 999 1000 1001 1002 1003 1004 1005 1006 1007
		ah.header= &os;
		ah.data=(char *)x;
		ah.meth=X509_asn1_meth();

		/* no macro for this one yet */
		i=ASN1_i2d_bio(i2d_ASN1_HEADER,out,(unsigned char *)&ah);
		}
	else	{
		BIO_printf(bio_err,"bad output format specified for outfile\n");
		goto end;
		}
1008 1009
	if (!i)
		{
1010 1011 1012 1013 1014 1015
		BIO_printf(bio_err,"unable to write certificate\n");
		ERR_print_errors(bio_err);
		goto end;
		}
	ret=0;
end:
1016 1017
	if (need_rand)
		app_RAND_write_file(NULL, bio_err);
1018
	OBJ_cleanup();
D
 
Dr. Stephen Henson 已提交
1019
	NCONF_free(extconf);
1020 1021
	BIO_free_all(out);
	BIO_free_all(STDout);
1022 1023 1024 1025 1026 1027 1028
	X509_STORE_free(ctx);
	X509_REQ_free(req);
	X509_free(x);
	X509_free(xca);
	EVP_PKEY_free(Upkey);
	EVP_PKEY_free(CApkey);
	X509_REQ_free(rq);
1029
	ASN1_INTEGER_free(sno);
1030 1031
	sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free);
	sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free);
1032
	if (passin) OPENSSL_free(passin);
1033
	apps_shutdown();
1034
	OPENSSL_EXIT(ret);
1035 1036
	}

1037
static ASN1_INTEGER *x509_load_serial(char *CAfile, char *serialfile, int create)
1038
	{
1039
	char *buf = NULL, *p;
1040
	ASN1_INTEGER *bs = NULL;
U
Ulf Möller 已提交
1041
	BIGNUM *serial = NULL;
1042

1043
	buf=OPENSSL_malloc( ((serialfile == NULL)
1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060
			?(strlen(CAfile)+strlen(POSTFIX)+1)
			:(strlen(serialfile)))+1);
	if (buf == NULL) { BIO_printf(bio_err,"out of mem\n"); goto end; }
	if (serialfile == NULL)
		{
		strcpy(buf,CAfile);
		for (p=buf; *p; p++)
			if (*p == '.')
				{
				*p='\0';
				break;
				}
		strcat(buf,POSTFIX);
		}
	else
		strcpy(buf,serialfile);

1061 1062
	serial = load_serial(buf, create, NULL);
	if (serial == NULL) goto end;
1063 1064 1065

	if (!BN_add_word(serial,1))
		{ BIO_printf(bio_err,"add_word failure\n"); goto end; }
1066

1067
	if (!save_serial(buf, serial, &bs)) goto end;
1068

1069
 end:
1070
	if (buf) OPENSSL_free(buf);
1071
	BN_free(serial);
1072
	return bs;
1073 1074 1075 1076
	}

static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
	     X509 *x, X509 *xca, EVP_PKEY *pkey, char *serialfile, int create,
D
 
Dr. Stephen Henson 已提交
1077
	     int days, int clrext, CONF *conf, char *section, ASN1_INTEGER *sno)
1078 1079 1080 1081 1082 1083 1084 1085 1086 1087
	{
	int ret=0;
	ASN1_INTEGER *bs=NULL;
	X509_STORE_CTX xsc;
	EVP_PKEY *upkey;

	upkey = X509_get_pubkey(xca);
	EVP_PKEY_copy_parameters(upkey,pkey);
	EVP_PKEY_free(upkey);

1088 1089 1090 1091 1092
	if(!X509_STORE_CTX_init(&xsc,ctx,x,NULL))
		{
		BIO_printf(bio_err,"Error initialising X509 store\n");
		goto end;
		}
1093
	if (sno) bs = sno;
1094
	else if (!(bs = x509_load_serial(CAfile, serialfile, create)))
1095 1096
		goto end;

1097 1098 1099 1100 1101 1102 1103 1104
	if (!X509_STORE_add_cert(ctx,x)) goto end;

	/* NOTE: this certificate can/should be self signed, unless it was
	 * a certificate request in which case it is not. */
	X509_STORE_CTX_set_cert(&xsc,x);
	if (!reqfile && !X509_verify_cert(&xsc))
		goto end;

1105 1106 1107 1108 1109 1110
	if (!X509_check_private_key(xca,pkey))
		{
		BIO_printf(bio_err,"CA certificate and CA private key do not match\n");
		goto end;
		}

1111 1112 1113 1114 1115 1116 1117 1118 1119 1120
	if (!X509_set_issuer_name(x,X509_get_subject_name(xca))) goto end;
	if (!X509_set_serialNumber(x,bs)) goto end;

	if (X509_gmtime_adj(X509_get_notBefore(x),0L) == NULL)
		goto end;

	/* hardwired expired */
	if (X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days) == NULL)
		goto end;

1121 1122 1123 1124
	if (clrext)
		{
		while (X509_get_ext_count(x) > 0) X509_delete_ext(x, 0);
		}
1125

1126 1127
	if (conf)
		{
B
Ben Laurie 已提交
1128
		X509V3_CTX ctx2;
1129
		X509_set_version(x,2); /* version 3 certificate */
B
Ben Laurie 已提交
1130
                X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0);
D
 
Dr. Stephen Henson 已提交
1131 1132
                X509V3_set_nconf(&ctx2, conf);
                if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x)) goto end;
1133
		}
1134

1135 1136 1137 1138 1139 1140
	if (!X509_sign(x,pkey,digest)) goto end;
	ret=1;
end:
	X509_STORE_CTX_cleanup(&xsc);
	if (!ret)
		ERR_print_errors(bio_err);
1141
	if (!sno) ASN1_INTEGER_free(bs);
1142
	return ret;
1143 1144
	}

U
Ulf Möller 已提交
1145
static int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx)
1146 1147 1148 1149 1150 1151 1152 1153 1154
	{
	int err;
	X509 *err_cert;

	/* it is ok to use a self signed certificate
	 * This case will catch both the initial ok == 0 and the
	 * final ok == 1 calls to this function */
	err=X509_STORE_CTX_get_error(ctx);
	if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)
1155
		return 1;
1156 1157 1158 1159 1160 1161

	/* BAD we should have gotten an error.  Normally if everything
	 * worked X509_STORE_CTX_get_error(ctx) will still be set to
	 * DEPTH_ZERO_SELF_.... */
	if (ok)
		{
1162
		BIO_printf(bio_err,"error with certificate to be certified - should be self signed\n");
1163
		return 0;
1164 1165 1166 1167
		}
	else
		{
		err_cert=X509_STORE_CTX_get_current_cert(ctx);
D
 
Dr. Stephen Henson 已提交
1168
		print_name(bio_err, NULL, X509_get_subject_name(err_cert),0);
1169
		BIO_printf(bio_err,"error with certificate - error %d at depth %d\n%s\n",
1170 1171
			err,X509_STORE_CTX_get_error_depth(ctx),
			X509_verify_cert_error_string(err));
1172
		return 1;
1173 1174 1175 1176
		}
	}

/* self sign */
1177
static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, const EVP_MD *digest, 
D
 
Dr. Stephen Henson 已提交
1178
						CONF *conf, char *section)
1179 1180
	{

1181 1182 1183 1184 1185 1186
	EVP_PKEY *pktmp;

	pktmp = X509_get_pubkey(x);
	EVP_PKEY_copy_parameters(pktmp,pkey);
	EVP_PKEY_save_parameters(pktmp,1);
	EVP_PKEY_free(pktmp);
1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198

	if (!X509_set_issuer_name(x,X509_get_subject_name(x))) goto err;
	if (X509_gmtime_adj(X509_get_notBefore(x),0) == NULL) goto err;

	/* Lets just make it 12:00am GMT, Jan 1 1970 */
	/* memcpy(x->cert_info->validity->notBefore,"700101120000Z",13); */
	/* 28 days to be certified */

	if (X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days) == NULL)
		goto err;

	if (!X509_set_pubkey(x,pkey)) goto err;
1199 1200 1201 1202 1203 1204
	if (clrext)
		{
		while (X509_get_ext_count(x) > 0) X509_delete_ext(x, 0);
		}
	if (conf)
		{
1205 1206 1207
		X509V3_CTX ctx;
		X509_set_version(x,2); /* version 3 certificate */
                X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0);
D
 
Dr. Stephen Henson 已提交
1208 1209
                X509V3_set_nconf(&ctx, conf);
                if (!X509V3_EXT_add_nconf(conf, &ctx, section, x)) goto err;
1210
		}
1211
	if (!X509_sign(x,pkey,digest)) goto err;
1212
	return 1;
1213 1214
err:
	ERR_print_errors(bio_err);
1215
	return 0;
1216
	}
1217

1218
static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt)
1219 1220 1221 1222
{
	int id, i, idret;
	char *pname;
	id = X509_PURPOSE_get_id(pt);
1223
	pname = X509_PURPOSE_get0_name(pt);
1224 1225
	for (i = 0; i < 2; i++)
		{
1226 1227
		idret = X509_check_purpose(cert, id, i);
		BIO_printf(bio, "%s%s : ", pname, i ? " CA" : ""); 
1228
		if (idret == 1) BIO_printf(bio, "Yes\n");
1229 1230
		else if (idret == 0) BIO_printf(bio, "No\n");
		else BIO_printf(bio, "Yes (WARNING code=%d)\n", idret);
1231
		}
1232 1233
	return 1;
}