req.c 43.6 KB
Newer Older
1
/* apps/req.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 60 61 62 63 64
/* Until the key-gen callbacks are modified to use newer prototypes, we allow
 * deprecated functions for openssl-internal code */
#ifdef OPENSSL_NO_DEPRECATED
#undef OPENSSL_NO_DEPRECATED
#endif

65 66 67 68
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
69
#ifdef OPENSSL_NO_STDIO
70 71 72
#define APPS_WIN16
#endif
#include "apps.h"
73 74 75 76 77 78 79 80 81
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/conf.h>
#include <openssl/err.h>
#include <openssl/asn1.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/objects.h>
#include <openssl/pem.h>
N
make  
Nils Larsch 已提交
82 83 84 85 86 87 88
#include <openssl/bn.h>
#ifndef OPENSSL_NO_RSA
#include <openssl/rsa.h>
#endif
#ifndef OPENSSL_NO_DSA
#include <openssl/dsa.h>
#endif
89 90 91 92 93

#define SECTION		"req"

#define BITS		"default_bits"
#define KEYFILE		"default_keyfile"
94
#define PROMPT		"prompt"
95 96
#define DISTINGUISHED_NAME	"distinguished_name"
#define ATTRIBUTES	"attributes"
97
#define V3_EXTENSIONS	"x509_extensions"
98
#define REQ_EXTENSIONS	"req_extensions"
99
#define STRING_MASK	"string_mask"
100
#define UTF8_IN		"utf8"
101 102 103 104 105 106 107

#define DEFAULT_KEY_LENGTH	512
#define MIN_KEY_LENGTH		384

#undef PROG
#define PROG	req_main

108
/* -inform arg	- input format - default PEM (DER or PEM)
109 110 111 112 113 114 115 116 117
 * -outform arg - output format - default PEM
 * -in arg	- input file - default stdin
 * -out arg	- output file - default stdout
 * -verify	- check request signature
 * -noout	- don't print stuff out.
 * -text	- print out human readable text.
 * -nodes	- no des encryption
 * -config file	- Load configuration file.
 * -key file	- make a request using key in file (or use it for verification).
R
Richard Levitte 已提交
118
 * -keyform arg	- key file format.
119
 * -rand file(s) - load the file(s) into the PRNG.
120 121
 * -newkey	- make a key and a request.
 * -modulus	- print RSA modulus.
122
 * -pubkey	- output Public Key.
123 124 125 126 127
 * -x509	- output a self signed X509 structure instead.
 * -asn1-kludge	- output new certificate request in a format that some CA's
 *		  require.  This format is wrong
 */

128 129 130 131
static int make_REQ(X509_REQ *req,EVP_PKEY *pkey,char *dn,int mutlirdn,
		int attribs,unsigned long chtype);
static int build_subject(X509_REQ *req, char *subj, unsigned long chtype,
		int multirdn);
132 133
static int prompt_info(X509_REQ *req,
		STACK_OF(CONF_VALUE) *dn_sk, char *dn_sect,
134 135
		STACK_OF(CONF_VALUE) *attr_sk, char *attr_sect, int attribs,
		unsigned long chtype);
136
static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *sk,
137 138
				STACK_OF(CONF_VALUE) *attr, int attribs,
				unsigned long chtype);
N
Nils Larsch 已提交
139 140
static int add_attribute_object(X509_REQ *req, char *text, const char *def,
				char *value, int nid, int n_min,
141
				int n_max, unsigned long chtype);
N
Nils Larsch 已提交
142
static int add_DN_object(X509_NAME *n, char *text, const char *def, char *value,
D
Dr. Stephen Henson 已提交
143
	int nid,int n_min,int n_max, unsigned long chtype, int mval);
144
static int genpkey_cb(EVP_PKEY_CTX *ctx);
D
 
Dr. Stephen Henson 已提交
145
static int req_check_len(int len,int n_min,int n_max);
N
Nils Larsch 已提交
146
static int check_end(const char *str, const char *end);
147
static EVP_PKEY_CTX *set_keygen_ctx(BIO *err, const char *gstr, int *pkey_type,
148 149
					long *pkeylen, char **palgnam,
					ENGINE *keygen_engine);
150 151 152
#ifndef MONOLITH
static char *default_config_file=NULL;
#endif
D
 
Dr. Stephen Henson 已提交
153
static CONF *req_conf=NULL;
154
static int batch=0;
155

156 157
int MAIN(int, char **);

U
Ulf Möller 已提交
158
int MAIN(int argc, char **argv)
159
	{
160
	ENGINE *e = NULL, *gen_eng = NULL;
D
 
Dr. Stephen Henson 已提交
161
	unsigned long nmflag = 0, reqflag = 0;
162 163 164
	int ex=1,x509=0,days=30;
	X509 *x509ss=NULL;
	X509_REQ *req=NULL;
165
	EVP_PKEY_CTX *genctx = NULL;
166 167
	const char *keyalg = NULL;
	char *keyalgstr = NULL;
168
	STACK_OF(OPENSSL_STRING) *pkeyopts = NULL, *sigopts = NULL;
169
	EVP_PKEY *pkey=NULL;
170
	int i=0,badops=0,newreq=0,verbose=0,pkey_type=-1;
D
 
Dr. Stephen Henson 已提交
171
	long newkey = -1;
172 173
	BIO *in=NULL,*out=NULL;
	int informat,outformat,verify=0,noout=0,text=0,keyform=FORMAT_PEM;
174
	int nodes=0,kludge=0,newhdr=0,subject=0,pubkey=0;
175
	char *infile,*outfile,*prog,*keyfile=NULL,*template=NULL,*keyout=NULL;
176
#ifndef OPENSSL_NO_ENGINE
177
	char *engine=NULL;
178
#endif
179
	char *extensions = NULL;
180
	char *req_exts = NULL;
D
 
Dr. Stephen Henson 已提交
181
	const EVP_CIPHER *cipher=NULL;
182
	ASN1_INTEGER *serial = NULL;
183
	int modulus=0;
184
	char *inrand=NULL;
D
Dr. Stephen Henson 已提交
185
	char *passargin = NULL, *passargout = NULL;
186
	char *passin = NULL, *passout = NULL;
187
	char *p;
188
	char *subj = NULL;
189
	int multirdn = 0;
190
	const EVP_MD *md_alg=NULL,*digest=NULL;
191
	unsigned long chtype = MBSTRING_ASC;
192
#ifndef MONOLITH
193
	char *to_free;
D
 
Dr. Stephen Henson 已提交
194
	long errline;
195 196
#endif

197
	req_conf = NULL;
198
#ifndef OPENSSL_NO_DES
199 200 201 202 203 204
	cipher=EVP_des_ede3_cbc();
#endif
	apps_startup();

	if (bio_err == NULL)
		if ((bio_err=BIO_new(BIO_s_file())) != NULL)
205
			BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226

	infile=NULL;
	outfile=NULL;
	informat=FORMAT_PEM;
	outformat=FORMAT_PEM;

	prog=argv[0];
	argc--;
	argv++;
	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));
			}
227
#ifndef OPENSSL_NO_ENGINE
228 229 230 231 232
		else if (strcmp(*argv,"-engine") == 0)
			{
			if (--argc < 1) goto bad;
			engine= *(++argv);
			}
233 234 235 236 237 238 239 240 241 242
		else if (strcmp(*argv,"-keygen_engine") == 0)
			{
			if (--argc < 1) goto bad;
			gen_eng = ENGINE_by_id(*(++argv));
			if (gen_eng == NULL)
				{
				BIO_printf(bio_err, "Can't find keygen engine %s\n", *argv);
				goto end;
				}
			}
243
#endif
244 245 246 247 248
		else if (strcmp(*argv,"-key") == 0)
			{
			if (--argc < 1) goto bad;
			keyfile= *(++argv);
			}
249 250 251 252
		else if (strcmp(*argv,"-pubkey") == 0)
			{
			pubkey=1;
			}
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
		else if (strcmp(*argv,"-new") == 0)
			{
			newreq=1;
			}
		else if (strcmp(*argv,"-config") == 0)
			{	
			if (--argc < 1) goto bad;
			template= *(++argv);
			}
		else if (strcmp(*argv,"-keyform") == 0)
			{
			if (--argc < 1) goto bad;
			keyform=str2fmt(*(++argv));
			}
		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,"-keyout") == 0)
			{
			if (--argc < 1) goto bad;
			keyout= *(++argv);
			}
282 283 284
		else if (strcmp(*argv,"-passin") == 0)
			{
			if (--argc < 1) goto bad;
D
Dr. Stephen Henson 已提交
285
			passargin= *(++argv);
286 287 288 289
			}
		else if (strcmp(*argv,"-passout") == 0)
			{
			if (--argc < 1) goto bad;
D
Dr. Stephen Henson 已提交
290
			passargout= *(++argv);
291
			}
292 293 294 295 296
		else if (strcmp(*argv,"-rand") == 0)
			{
			if (--argc < 1) goto bad;
			inrand= *(++argv);
			}
297 298
		else if (strcmp(*argv,"-newkey") == 0)
			{
299 300
			if (--argc < 1)
				goto bad;
301
			keyalg = *(++argv);
302 303 304 305 306 307
			newreq=1;
			}
		else if (strcmp(*argv,"-pkeyopt") == 0)
			{
			if (--argc < 1)
				goto bad;
308
			if (!pkeyopts)
D
Dr. Stephen Henson 已提交
309 310
				pkeyopts = sk_OPENSSL_STRING_new_null();
			if (!pkeyopts || !sk_OPENSSL_STRING_push(pkeyopts, *(++argv)))
311
				goto bad;
312
			}
313 314 315 316 317 318 319 320 321
		else if (strcmp(*argv,"-sigopt") == 0)
			{
			if (--argc < 1)
				goto bad;
			if (!sigopts)
				sigopts = sk_OPENSSL_STRING_new_null();
			if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv)))
				goto bad;
			}
322 323
		else if (strcmp(*argv,"-batch") == 0)
			batch=1;
324 325
		else if (strcmp(*argv,"-newhdr") == 0)
			newhdr=1;
326 327 328 329 330 331 332 333
		else if (strcmp(*argv,"-modulus") == 0)
			modulus=1;
		else if (strcmp(*argv,"-verify") == 0)
			verify=1;
		else if (strcmp(*argv,"-nodes") == 0)
			nodes=1;
		else if (strcmp(*argv,"-noout") == 0)
			noout=1;
334 335
		else if (strcmp(*argv,"-verbose") == 0)
			verbose=1;
336 337
		else if (strcmp(*argv,"-utf8") == 0)
			chtype = MBSTRING_UTF8;
338 339 340 341 342
		else if (strcmp(*argv,"-nameopt") == 0)
			{
			if (--argc < 1) goto bad;
			if (!set_name_ex(&nmflag, *(++argv))) goto bad;
			}
D
 
Dr. Stephen Henson 已提交
343 344 345 346 347
		else if (strcmp(*argv,"-reqopt") == 0)
			{
			if (--argc < 1) goto bad;
			if (!set_cert_ex(&reqflag, *(++argv))) goto bad;
			}
348 349
		else if (strcmp(*argv,"-subject") == 0)
			subject=1;
350 351 352 353 354 355 356 357
		else if (strcmp(*argv,"-text") == 0)
			text=1;
		else if (strcmp(*argv,"-x509") == 0)
			x509=1;
		else if (strcmp(*argv,"-asn1-kludge") == 0)
			kludge=1;
		else if (strcmp(*argv,"-no-asn1-kludge") == 0)
			kludge=0;
358 359 360 361 362
		else if (strcmp(*argv,"-subj") == 0)
			{
			if (--argc < 1) goto bad;
			subj= *(++argv);
			}
363 364
		else if (strcmp(*argv,"-multivalue-rdn") == 0)
			multirdn=1;
365 366 367 368 369 370
		else if (strcmp(*argv,"-days") == 0)
			{
			if (--argc < 1) goto bad;
			days= atoi(*(++argv));
			if (days == 0) days=30;
			}
371 372 373 374 375 376
		else if (strcmp(*argv,"-set_serial") == 0)
			{
			if (--argc < 1) goto bad;
			serial = s2i_ASN1_INTEGER(NULL, *(++argv));
			if (!serial) goto bad;
			}
377 378 379 380 381 382 383 384 385 386
		else if (strcmp(*argv,"-extensions") == 0)
			{
			if (--argc < 1) goto bad;
			extensions = *(++argv);
			}
		else if (strcmp(*argv,"-reqexts") == 0)
			{
			if (--argc < 1) goto bad;
			req_exts = *(++argv);
			}
D
Dr. Stephen Henson 已提交
387 388 389 390 391
		else if ((md_alg=EVP_get_digestbyname(&((*argv)[1]))) != NULL)
			{
			/* ok */
			digest=md_alg;
			}
392 393 394 395 396 397 398 399 400 401 402 403 404 405 406
		else
			{
			BIO_printf(bio_err,"unknown option %s\n",*argv);
			badops=1;
			break;
			}
		argc--;
		argv++;
		}

	if (badops)
		{
bad:
		BIO_printf(bio_err,"%s [options] <infile >outfile\n",prog);
		BIO_printf(bio_err,"where options  are\n");
407 408
		BIO_printf(bio_err," -inform arg    input format - DER or PEM\n");
		BIO_printf(bio_err," -outform arg   output format - DER or PEM\n");
409
		BIO_printf(bio_err," -in arg        input file\n");
410 411
		BIO_printf(bio_err," -out arg       output file\n");
		BIO_printf(bio_err," -text          text form of request\n");
412
		BIO_printf(bio_err," -pubkey        output public key\n");
413 414 415 416
		BIO_printf(bio_err," -noout         do not output REQ\n");
		BIO_printf(bio_err," -verify        verify signature on REQ\n");
		BIO_printf(bio_err," -modulus       RSA modulus\n");
		BIO_printf(bio_err," -nodes         don't encrypt the output key\n");
417
#ifndef OPENSSL_NO_ENGINE
418
		BIO_printf(bio_err," -engine e      use engine e, possibly a hardware device\n");
419
#endif
420 421 422
		BIO_printf(bio_err," -subject       output the request's subject\n");
		BIO_printf(bio_err," -passin        private key password source\n");
		BIO_printf(bio_err," -key file      use the private key contained in file\n");
423 424
		BIO_printf(bio_err," -keyform arg   key file format\n");
		BIO_printf(bio_err," -keyout arg    file to send the key to\n");
425 426 427
		BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
		BIO_printf(bio_err,"                load the file (or the files in the directory) into\n");
		BIO_printf(bio_err,"                the random number generator\n");
428 429
		BIO_printf(bio_err," -newkey rsa:bits generate a new RSA key of 'bits' in size\n");
		BIO_printf(bio_err," -newkey dsa:file generate a new DSA key, parameters taken from CA in 'file'\n");
B
Bodo Möller 已提交
430 431 432
#ifndef OPENSSL_NO_ECDSA
		BIO_printf(bio_err," -newkey ec:file generate a new EC key, parameters taken from CA in 'file'\n");
#endif
433
		BIO_printf(bio_err," -[digest]      Digest to sign with (md5, sha1, md2, mdc2, md4)\n");
M
Mark J. Cox 已提交
434
		BIO_printf(bio_err," -config file   request template file.\n");
435
		BIO_printf(bio_err," -subj arg      set or modify request subject\n");
436
		BIO_printf(bio_err," -multivalue-rdn enable support for multivalued RDNs\n");
437
		BIO_printf(bio_err," -new           new request.\n");
438
		BIO_printf(bio_err," -batch         do not ask anything during request generation\n");
439
		BIO_printf(bio_err," -x509          output a x509 structure instead of a cert. req.\n");
440 441
		BIO_printf(bio_err," -days          number of days a certificate generated by -x509 is valid for.\n");
		BIO_printf(bio_err," -set_serial    serial number to use for a certificate generated by -x509.\n");
442
		BIO_printf(bio_err," -newhdr        output \"NEW\" in the header lines\n");
443 444
		BIO_printf(bio_err," -asn1-kludge   Output the 'request' in a format that is wrong but some CA's\n");
		BIO_printf(bio_err,"                have been reported as requiring\n");
445 446
		BIO_printf(bio_err," -extensions .. specify certificate extension section (override value in config file)\n");
		BIO_printf(bio_err," -reqexts ..    specify request extension section (override value in config file)\n");
447
		BIO_printf(bio_err," -utf8          input characters are UTF8 (default ASCII)\n");
448
		BIO_printf(bio_err," -nameopt arg    - various certificate name options\n");
D
 
Dr. Stephen Henson 已提交
449
		BIO_printf(bio_err," -reqopt arg    - various request text options\n\n");
450 451 452 453
		goto end;
		}

	ERR_load_crypto_strings();
D
Dr. Stephen Henson 已提交
454 455 456 457
	if(!app_passwd(bio_err, passargin, passargout, &passin, &passout)) {
		BIO_printf(bio_err, "Error getting passwords\n");
		goto end;
	}
458

B
Bodo Möller 已提交
459
#ifndef MONOLITH /* else this has happened in openssl.c (global `config') */
460
	/* Lets load up our environment a little */
461 462 463
	p=getenv("OPENSSL_CONF");
	if (p == NULL)
		p=getenv("SSLEAY_CONF");
464
	if (p == NULL)
465
		p=to_free=make_config_name();
B
Bodo Möller 已提交
466
	default_config_file=p;
D
 
Dr. Stephen Henson 已提交
467
	config=NCONF_new(NULL);
D
 
Dr. Stephen Henson 已提交
468
	i=NCONF_load(config, p, &errline);
469 470 471 472
#endif

	if (template != NULL)
		{
473
		long errline = -1;
474

475 476
		if( verbose )
			BIO_printf(bio_err,"Using configuration from %s\n",template);
D
 
Dr. Stephen Henson 已提交
477 478 479
		req_conf=NCONF_new(NULL);
		i=NCONF_load(req_conf,template,&errline);
		if (i == 0)
480 481 482 483 484 485 486 487
			{
			BIO_printf(bio_err,"error on line %ld of %s\n",errline,template);
			goto end;
			}
		}
	else
		{
		req_conf=config;
488

D
 
Dr. Stephen Henson 已提交
489
		if (req_conf == NULL)
490
			{
491 492 493
			BIO_printf(bio_err,"Unable to load config info from %s\n", default_config_file);
			if (newreq)
				goto end;
494
			}
495 496 497
		else if( verbose )
			BIO_printf(bio_err,"Using configuration from %s\n",
			default_config_file);
498 499
		}

500 501
	if (req_conf != NULL)
		{
D
Dr. Stephen Henson 已提交
502 503
		if (!load_config(bio_err, req_conf))
			goto end;
D
 
Dr. Stephen Henson 已提交
504
		p=NCONF_get_string(req_conf,NULL,"oid_file");
505 506
		if (p == NULL)
			ERR_clear_error();
507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525
		if (p != NULL)
			{
			BIO *oid_bio;

			oid_bio=BIO_new_file(p,"r");
			if (oid_bio == NULL) 
				{
				/*
				BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
				ERR_print_errors(bio_err);
				*/
				}
			else
				{
				OBJ_create_objects(oid_bio);
				BIO_free(oid_bio);
				}
			}
		}
526
	if(!add_oid_section(bio_err, req_conf)) goto end;
527

528
	if (md_alg == NULL)
529
		{
D
 
Dr. Stephen Henson 已提交
530
		p=NCONF_get_string(req_conf,SECTION,"default_md");
531 532 533 534 535 536 537
		if (p == NULL)
			ERR_clear_error();
		if (p != NULL)
			{
			if ((md_alg=EVP_get_digestbyname(p)) != NULL)
				digest=md_alg;
			}
538 539
		}

540 541
	if (!extensions)
		{
D
 
Dr. Stephen Henson 已提交
542
		extensions = NCONF_get_string(req_conf, SECTION, V3_EXTENSIONS);
543 544 545 546
		if (!extensions)
			ERR_clear_error();
		}
	if (extensions) {
547
		/* Check syntax of file */
548 549
		X509V3_CTX ctx;
		X509V3_set_ctx_test(&ctx);
D
 
Dr. Stephen Henson 已提交
550 551
		X509V3_set_nconf(&ctx, req_conf);
		if(!X509V3_EXT_add_nconf(req_conf, &ctx, extensions, NULL)) {
552 553 554 555 556
			BIO_printf(bio_err,
			 "Error Loading extension section %s\n", extensions);
			goto end;
		}
	}
557

558
	if(!passin)
559
		{
D
 
Dr. Stephen Henson 已提交
560
		passin = NCONF_get_string(req_conf, SECTION, "input_password");
561 562 563 564
		if (!passin)
			ERR_clear_error();
		}
	
565
	if(!passout)
566
		{
D
 
Dr. Stephen Henson 已提交
567
		passout = NCONF_get_string(req_conf, SECTION, "output_password");
568 569 570
		if (!passout)
			ERR_clear_error();
		}
571

D
 
Dr. Stephen Henson 已提交
572
	p = NCONF_get_string(req_conf, SECTION, STRING_MASK);
573 574
	if (!p)
		ERR_clear_error();
575 576

	if(p && !ASN1_STRING_set_default_mask_asc(p)) {
577
		BIO_printf(bio_err, "Invalid global string mask setting %s\n", p);
578 579 580
		goto end;
	}

581 582 583 584 585 586 587 588 589 590
	if (chtype != MBSTRING_UTF8)
		{
		p = NCONF_get_string(req_conf, SECTION, UTF8_IN);
		if (!p)
			ERR_clear_error();
		else if (!strcmp(p, "yes"))
			chtype = MBSTRING_UTF8;
		}


591
	if(!req_exts)
592
		{
D
 
Dr. Stephen Henson 已提交
593
		req_exts = NCONF_get_string(req_conf, SECTION, REQ_EXTENSIONS);
594 595 596
		if (!req_exts)
			ERR_clear_error();
		}
597 598 599 600
	if(req_exts) {
		/* Check syntax of file */
		X509V3_CTX ctx;
		X509V3_set_ctx_test(&ctx);
D
 
Dr. Stephen Henson 已提交
601 602
		X509V3_set_nconf(&ctx, req_conf);
		if(!X509V3_EXT_add_nconf(req_conf, &ctx, req_exts, NULL)) {
603 604 605 606 607 608 609
			BIO_printf(bio_err,
			 "Error Loading request extension section %s\n",
								req_exts);
			goto end;
		}
	}

610 611 612 613 614
	in=BIO_new(BIO_s_file());
	out=BIO_new(BIO_s_file());
	if ((in == NULL) || (out == NULL))
		goto end;

615
#ifndef OPENSSL_NO_ENGINE
616
        e = setup_engine(bio_err, engine, 0);
617
#endif
618

619 620
	if (keyfile != NULL)
		{
621
		pkey = load_key(bio_err, keyfile, keyform, 0, passin, e,
622 623
			"Private Key");
		if (!pkey)
624
			{
625 626
			/* load_key() has already printed an appropriate
			   message */
627 628
			goto end;
			}
D
Dr. Stephen Henson 已提交
629
		else
D
 
Dr. Stephen Henson 已提交
630
			{
D
 
Dr. Stephen Henson 已提交
631
			char *randfile = NCONF_get_string(req_conf,SECTION,"RANDFILE");
632 633
			if (randfile == NULL)
				ERR_clear_error();
D
 
Dr. Stephen Henson 已提交
634
			app_RAND_load_file(randfile, bio_err, 0);
635
			}
636 637 638 639
		}

	if (newreq && (pkey == NULL))
		{
D
 
Dr. Stephen Henson 已提交
640
		char *randfile = NCONF_get_string(req_conf,SECTION,"RANDFILE");
641 642
		if (randfile == NULL)
			ERR_clear_error();
643
		app_RAND_load_file(randfile, bio_err, 0);
644 645
		if (inrand)
			app_RAND_load_files(inrand);
646 647 648

		if (keyalg)
			{
649
			genctx = set_keygen_ctx(bio_err, keyalg, &pkey_type, &newkey,
650
							&keyalgstr, gen_eng);
651 652 653
			if (!genctx)
				goto end;
			}
654
	
655 656
		if (newkey <= 0)
			{
D
 
Dr. Stephen Henson 已提交
657
			if (!NCONF_get_number(req_conf,SECTION,BITS, &newkey))
658 659 660
				newkey=DEFAULT_KEY_LENGTH;
			}

661
		if (newkey < MIN_KEY_LENGTH && (pkey_type == EVP_PKEY_RSA || pkey_type == EVP_PKEY_DSA))
662 663
			{
			BIO_printf(bio_err,"private key length is too short,\n");
664
			BIO_printf(bio_err,"it needs to be at least %d bits, not %ld\n",MIN_KEY_LENGTH,newkey);
665 666 667
			goto end;
			}

668
		if (!genctx)
669
			{
670
			genctx = set_keygen_ctx(bio_err, NULL, &pkey_type, &newkey,
671
							&keyalgstr, gen_eng);
672 673
			if (!genctx)
				goto end;
674
			}
675

676 677 678
		if (pkeyopts)
			{
			char *genopt;
D
Dr. Stephen Henson 已提交
679
			for (i = 0; i < sk_OPENSSL_STRING_num(pkeyopts); i++)
680
				{
D
Dr. Stephen Henson 已提交
681
				genopt = sk_OPENSSL_STRING_value(pkeyopts, i);
682 683 684 685 686 687 688 689 690 691 692
				if (pkey_ctrl_string(genctx, genopt) <= 0)
					{
					BIO_printf(bio_err,
						"parameter error \"%s\"\n",
						genopt);
					ERR_print_errors(bio_err);
					goto end;
					}
				}
			}

693 694 695 696 697 698 699
		BIO_printf(bio_err,"Generating a %ld bit %s private key\n",
				newkey, keyalgstr);

		EVP_PKEY_CTX_set_cb(genctx, genpkey_cb);
		EVP_PKEY_CTX_set_app_data(genctx, bio_err);

		if (EVP_PKEY_keygen(genctx, &pkey) <= 0)
B
Bodo Möller 已提交
700
			{
701 702
			BIO_puts(bio_err, "Error Generating Key\n");
			goto end;
B
Bodo Möller 已提交
703
			}
704 705 706

		EVP_PKEY_CTX_free(genctx);
		genctx = NULL;
707

708
		app_RAND_write_file(randfile, bio_err);
709 710

		if (keyout == NULL)
711
			{
D
 
Dr. Stephen Henson 已提交
712
			keyout=NCONF_get_string(req_conf,SECTION,KEYFILE);
713 714 715 716
			if (keyout == NULL)
				ERR_clear_error();
			}
		
717 718 719 720
		if (keyout == NULL)
			{
			BIO_printf(bio_err,"writing new private key to stdout\n");
			BIO_set_fp(out,stdout,BIO_NOCLOSE);
721
#ifdef OPENSSL_SYS_VMS
722 723 724 725 726
			{
			BIO *tmpbio = BIO_new(BIO_f_linebuffer());
			out = BIO_push(tmpbio, out);
			}
#endif
727 728 729 730 731 732 733 734 735 736 737
			}
		else
			{
			BIO_printf(bio_err,"writing new private key to '%s'\n",keyout);
			if (BIO_write_filename(out,keyout) <= 0)
				{
				perror(keyout);
				goto end;
				}
			}

D
 
Dr. Stephen Henson 已提交
738
		p=NCONF_get_string(req_conf,SECTION,"encrypt_rsa_key");
739
		if (p == NULL)
740 741
			{
			ERR_clear_error();
D
 
Dr. Stephen Henson 已提交
742
			p=NCONF_get_string(req_conf,SECTION,"encrypt_key");
743 744 745
			if (p == NULL)
				ERR_clear_error();
			}
746 747 748 749 750 751 752
		if ((p != NULL) && (strcmp(p,"no") == 0))
			cipher=NULL;
		if (nodes) cipher=NULL;
		
		i=0;
loop:
		if (!PEM_write_bio_PrivateKey(out,pkey,cipher,
D
Dr. Stephen Henson 已提交
753
			NULL,0,NULL,passout))
754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786
			{
			if ((ERR_GET_REASON(ERR_peek_error()) ==
				PEM_R_PROBLEMS_GETTING_PASSWORD) && (i < 3))
				{
				ERR_clear_error();
				i++;
				goto loop;
				}
			goto end;
			}
		BIO_printf(bio_err,"-----\n");
		}

	if (!newreq)
		{
		/* Since we are using a pre-existing certificate
		 * request, the kludge 'format' info should not be
		 * changed. */
		kludge= -1;
		if (infile == NULL)
			BIO_set_fp(in,stdin,BIO_NOCLOSE);
		else
			{
			if (BIO_read_filename(in,infile) <= 0)
				{
				perror(infile);
				goto end;
				}
			}

		if	(informat == FORMAT_ASN1)
			req=d2i_X509_REQ_bio(in,NULL);
		else if (informat == FORMAT_PEM)
787
			req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL);
788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806
		else
			{
			BIO_printf(bio_err,"bad input format specified for X509 request\n");
			goto end;
			}
		if (req == NULL)
			{
			BIO_printf(bio_err,"unable to load X509 request\n");
			goto end;
			}
		}

	if (newreq || x509)
		{
		if (pkey == NULL)
			{
			BIO_printf(bio_err,"you need to specify a private key\n");
			goto end;
			}
807

808 809 810 811 812 813 814 815
		if (req == NULL)
			{
			req=X509_REQ_new();
			if (req == NULL)
				{
				goto end;
				}

816
			i=make_REQ(req,pkey,subj,multirdn,!x509, chtype);
817
			subj=NULL; /* done processing '-subj' option */
D
 
Dr. Stephen Henson 已提交
818 819 820 821 822
			if ((kludge > 0) && !sk_X509_ATTRIBUTE_num(req->req_info->attributes))
				{
				sk_X509_ATTRIBUTE_free(req->req_info->attributes);
				req->req_info->attributes = NULL;
				}
823 824 825 826 827 828 829 830
			if (!i)
				{
				BIO_printf(bio_err,"problems making Certificate Request\n");
				goto end;
				}
			}
		if (x509)
			{
831
			EVP_PKEY *tmppkey;
832
			X509V3_CTX ext_ctx;
833 834
			if ((x509ss=X509_new()) == NULL) goto end;

835
			/* Set version to V3 */
D
Dr. Stephen Henson 已提交
836
			if(extensions && !X509_set_version(x509ss, 2)) goto end;
837
			if (serial)
B
Bodo Möller 已提交
838 839 840
				{
				if (!X509_set_serialNumber(x509ss, serial)) goto end;
				}
841
			else
B
Bodo Möller 已提交
842
				{
843 844 845
				if (!rand_serial(NULL,
					X509_get_serialNumber(x509ss)))
						goto end;
B
Bodo Möller 已提交
846 847 848 849
				}

			if (!X509_set_issuer_name(x509ss, X509_REQ_get_subject_name(req))) goto end;
			if (!X509_gmtime_adj(X509_get_notBefore(x509ss),0)) goto end;
850
			if (!X509_time_adj_ex(X509_get_notAfter(x509ss), days, 0, NULL)) goto end;
B
Bodo Möller 已提交
851
			if (!X509_set_subject_name(x509ss, X509_REQ_get_subject_name(req))) goto end;
852
			tmppkey = X509_REQ_get_pubkey(req);
B
Bodo Möller 已提交
853
			if (!tmppkey || !X509_set_pubkey(x509ss,tmppkey)) goto end;
854
			EVP_PKEY_free(tmppkey);
855

856 857
			/* Set up V3 context struct */

858
			X509V3_set_ctx(&ext_ctx, x509ss, x509ss, NULL, NULL, 0);
D
 
Dr. Stephen Henson 已提交
859
			X509V3_set_nconf(&ext_ctx, req_conf);
860 861

			/* Add extensions */
D
 
Dr. Stephen Henson 已提交
862
			if(extensions && !X509V3_EXT_add_nconf(req_conf, 
B
Ben Laurie 已提交
863
				 	&ext_ctx, extensions, x509ss))
864 865 866 867 868 869
				{
				BIO_printf(bio_err,
					"Error Loading extension section %s\n",
					extensions);
				goto end;
				}
870 871 872

			i=do_X509_sign(bio_err, x509ss, pkey, digest, sigopts);
			if (!i)
873 874
				{
				ERR_print_errors(bio_err);
875
				goto end;
876
				}
877 878 879
			}
		else
			{
880 881 882 883 884
			X509V3_CTX ext_ctx;

			/* Set up V3 context struct */

			X509V3_set_ctx(&ext_ctx, NULL, NULL, req, NULL, 0);
D
 
Dr. Stephen Henson 已提交
885
			X509V3_set_nconf(&ext_ctx, req_conf);
886 887

			/* Add extensions */
D
 
Dr. Stephen Henson 已提交
888
			if(req_exts && !X509V3_EXT_REQ_add_nconf(req_conf, 
889
				 	&ext_ctx, req_exts, req))
890 891 892 893 894 895
				{
				BIO_printf(bio_err,
					"Error Loading extension section %s\n",
					req_exts);
				goto end;
				}
896 897
			i=do_X509_REQ_sign(bio_err, req, pkey, digest, sigopts);
			if (!i)
898 899
				{
				ERR_print_errors(bio_err);
900
				goto end;
901
				}
902 903 904
			}
		}

905 906 907 908 909 910 911 912 913 914 915 916 917 918
	if (subj && x509)
		{
		BIO_printf(bio_err, "Cannot modifiy certificate subject\n");
		goto end;
		}

	if (subj && !x509)
		{
		if (verbose)
			{
			BIO_printf(bio_err, "Modifying Request's Subject\n");
			print_name(bio_err, "old subject=", X509_REQ_get_subject_name(req), nmflag);
			}

919
		if (build_subject(req, subj, chtype, multirdn) == 0)
920 921 922 923 924 925 926 927 928 929 930 931 932 933
			{
			BIO_printf(bio_err, "ERROR: cannot modify subject\n");
			ex=1;
			goto end;
			}

		req->req_info->enc.modified = 1;

		if (verbose)
			{
			print_name(bio_err, "new subject=", X509_REQ_get_subject_name(req), nmflag);
			}
		}

934 935 936 937 938 939 940 941 942 943 944 945
	if (verify && !x509)
		{
		int tmp=0;

		if (pkey == NULL)
			{
			pkey=X509_REQ_get_pubkey(req);
			tmp=1;
			if (pkey == NULL) goto end;
			}

		i=X509_REQ_verify(req,pkey);
946 947 948 949
		if (tmp) {
			EVP_PKEY_free(pkey);
			pkey=NULL;
		}
950 951 952 953 954 955 956 957

		if (i < 0)
			{
			goto end;
			}
		else if (i == 0)
			{
			BIO_printf(bio_err,"verify failure\n");
B
Ben Laurie 已提交
958
			ERR_print_errors(bio_err);
959 960 961 962 963
			}
		else /* if (i > 0) */
			BIO_printf(bio_err,"verify OK\n");
		}

964
	if (noout && !text && !modulus && !subject && !pubkey)
965 966 967 968 969 970
		{
		ex=0;
		goto end;
		}

	if (outfile == NULL)
971
		{
972
		BIO_set_fp(out,stdout,BIO_NOCLOSE);
973
#ifdef OPENSSL_SYS_VMS
974 975 976 977 978 979
		{
		BIO *tmpbio = BIO_new(BIO_f_linebuffer());
		out = BIO_push(tmpbio, out);
		}
#endif
		}
980 981 982 983 984 985 986 987 988 989 990 991 992
	else
		{
		if ((keyout != NULL) && (strcmp(outfile,keyout) == 0))
			i=(int)BIO_append_filename(out,outfile);
		else
			i=(int)BIO_write_filename(out,outfile);
		if (!i)
			{
			perror(outfile);
			goto end;
			}
		}

993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006
	if (pubkey)
		{
		EVP_PKEY *tpubkey; 
		tpubkey=X509_REQ_get_pubkey(req);
		if (tpubkey == NULL)
			{
			BIO_printf(bio_err,"Error getting public key\n");
			ERR_print_errors(bio_err);
			goto end;
			}
		PEM_write_bio_PUBKEY(out, tpubkey);
		EVP_PKEY_free(tpubkey);
		}

1007 1008 1009
	if (text)
		{
		if (x509)
D
 
Dr. Stephen Henson 已提交
1010
			X509_print_ex(out, x509ss, nmflag, reqflag);
1011
		else	
D
 
Dr. Stephen Henson 已提交
1012
			X509_REQ_print_ex(out, req, nmflag, reqflag);
1013 1014
		}

1015 1016 1017 1018 1019 1020 1021 1022
	if(subject) 
		{
		if(x509)
			print_name(out, "subject=", X509_get_subject_name(x509ss), nmflag);
		else
			print_name(out, "subject=", X509_REQ_get_subject_name(req), nmflag);
		}

1023 1024
	if (modulus)
		{
1025
		EVP_PKEY *tpubkey;
1026 1027

		if (x509)
1028
			tpubkey=X509_get_pubkey(x509ss);
1029
		else
1030 1031
			tpubkey=X509_REQ_get_pubkey(req);
		if (tpubkey == NULL)
1032 1033 1034 1035 1036
			{
			fprintf(stdout,"Modulus=unavailable\n");
			goto end; 
			}
		fprintf(stdout,"Modulus=");
1037
#ifndef OPENSSL_NO_RSA
D
Typo.  
Dr. Stephen Henson 已提交
1038
		if (EVP_PKEY_base_id(tpubkey) == EVP_PKEY_RSA)
1039
			BN_print(out,tpubkey->pkey.rsa->n);
1040
		else
1041
#endif
1042
			fprintf(stdout,"Wrong Algorithm type");
1043
		EVP_PKEY_free(tpubkey);
1044 1045 1046 1047 1048 1049 1050
		fprintf(stdout,"\n");
		}

	if (!noout && !x509)
		{
		if 	(outformat == FORMAT_ASN1)
			i=i2d_X509_REQ_bio(out,req);
1051 1052 1053 1054
		else if (outformat == FORMAT_PEM) {
			if(newhdr) i=PEM_write_bio_X509_REQ_NEW(out,req);
			else i=PEM_write_bio_X509_REQ(out,req);
		} else {
1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081
			BIO_printf(bio_err,"bad output format specified for outfile\n");
			goto end;
			}
		if (!i)
			{
			BIO_printf(bio_err,"unable to write X509 request\n");
			goto end;
			}
		}
	if (!noout && x509 && (x509ss != NULL))
		{
		if 	(outformat == FORMAT_ASN1)
			i=i2d_X509_bio(out,x509ss);
		else if (outformat == FORMAT_PEM)
			i=PEM_write_bio_X509(out,x509ss);
		else	{
			BIO_printf(bio_err,"bad output format specified for outfile\n");
			goto end;
			}
		if (!i)
			{
			BIO_printf(bio_err,"unable to write X509 certificate\n");
			goto end;
			}
		}
	ex=0;
end:
1082 1083 1084 1085
#ifndef MONOLITH
	if(to_free)
		OPENSSL_free(to_free);
#endif
1086 1087 1088 1089
	if (ex)
		{
		ERR_print_errors(bio_err);
		}
D
 
Dr. Stephen Henson 已提交
1090
	if ((req_conf != NULL) && (req_conf != config)) NCONF_free(req_conf);
1091
	BIO_free(in);
1092
	BIO_free_all(out);
1093
	EVP_PKEY_free(pkey);
1094 1095
	if (genctx)
		EVP_PKEY_CTX_free(genctx);
1096
	if (pkeyopts)
D
Dr. Stephen Henson 已提交
1097
		sk_OPENSSL_STRING_free(pkeyopts);
1098 1099
	if (sigopts)
		sk_OPENSSL_STRING_free(sigopts);
1100 1101 1102 1103 1104 1105
#ifndef OPENSSL_NO_ENGINE
	if (gen_eng)
		ENGINE_free(gen_eng);
#endif
	if (keyalgstr)
		OPENSSL_free(keyalgstr);
1106 1107
	X509_REQ_free(req);
	X509_free(x509ss);
1108
	ASN1_INTEGER_free(serial);
1109 1110
	if(passargin && passin) OPENSSL_free(passin);
	if(passargout && passout) OPENSSL_free(passout);
1111
	OBJ_cleanup();
1112
	apps_shutdown();
1113
	OPENSSL_EXIT(ex);
1114 1115
	}

1116 1117
static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *subj, int multirdn,
			int attribs, unsigned long chtype)
1118
	{
1119
	int ret=0,i;
1120 1121 1122 1123
	char no_prompt = 0;
	STACK_OF(CONF_VALUE) *dn_sk, *attr_sk = NULL;
	char *tmp, *dn_sect,*attr_sect;

D
 
Dr. Stephen Henson 已提交
1124
	tmp=NCONF_get_string(req_conf,SECTION,PROMPT);
1125 1126
	if (tmp == NULL)
		ERR_clear_error();
1127 1128
	if((tmp != NULL) && !strcmp(tmp, "no")) no_prompt = 1;

D
 
Dr. Stephen Henson 已提交
1129
	dn_sect=NCONF_get_string(req_conf,SECTION,DISTINGUISHED_NAME);
1130
	if (dn_sect == NULL)
1131 1132 1133 1134 1135
		{
		BIO_printf(bio_err,"unable to find '%s' in config\n",
			DISTINGUISHED_NAME);
		goto err;
		}
D
 
Dr. Stephen Henson 已提交
1136
	dn_sk=NCONF_get_section(req_conf,dn_sect);
1137
	if (dn_sk == NULL)
1138
		{
1139
		BIO_printf(bio_err,"unable to get '%s' section\n",dn_sect);
1140 1141 1142
		goto err;
		}

D
 
Dr. Stephen Henson 已提交
1143
	attr_sect=NCONF_get_string(req_conf,SECTION,ATTRIBUTES);
1144
	if (attr_sect == NULL)
1145 1146
		{
		ERR_clear_error();		
1147
		attr_sk=NULL;
1148
		}
1149 1150
	else
		{
D
 
Dr. Stephen Henson 已提交
1151
		attr_sk=NCONF_get_section(req_conf,attr_sect);
1152
		if (attr_sk == NULL)
1153
			{
1154
			BIO_printf(bio_err,"unable to get '%s' section\n",attr_sect);
1155 1156 1157 1158
			goto err;
			}
		}

1159
	/* setup version number */
1160
	if (!X509_REQ_set_version(req,0L)) goto err; /* version 1 */
1161

1162 1163 1164
	if (subj)
		i = build_subject(req, subj, chtype, multirdn);
	else if (no_prompt) 
1165
		i = auto_info(req, dn_sk, attr_sk, attribs, chtype);
1166 1167
	else
		i = prompt_info(req, dn_sk, dn_sect, attr_sk, attr_sect, attribs, chtype);
1168
	if(!i) goto err;
1169

B
Bodo Möller 已提交
1170
	if (!X509_REQ_set_pubkey(req,pkey)) goto err;
1171 1172 1173 1174 1175 1176

	ret=1;
err:
	return(ret);
	}

1177 1178 1179 1180
/*
 * subject is expected to be in the format /type0=value0/type1=value1/type2=...
 * where characters may be escaped by \
 */
1181
static int build_subject(X509_REQ *req, char *subject, unsigned long chtype, int multirdn)
1182
	{
D
 
Dr. Stephen Henson 已提交
1183
	X509_NAME *n;
1184

1185
	if (!(n = parse_name(subject, chtype, multirdn)))
D
 
Dr. Stephen Henson 已提交
1186
		return 0;
1187

D
 
Dr. Stephen Henson 已提交
1188
	if (!X509_REQ_set_subject_name(req, n))
1189
		{
D
 
Dr. Stephen Henson 已提交
1190 1191
		X509_NAME_free(n);
		return 0;
1192 1193 1194 1195 1196
		}
	X509_NAME_free(n);
	return 1;
}

1197 1198 1199

static int prompt_info(X509_REQ *req,
		STACK_OF(CONF_VALUE) *dn_sk, char *dn_sect,
1200 1201
		STACK_OF(CONF_VALUE) *attr_sk, char *attr_sect, int attribs,
		unsigned long chtype)
1202 1203 1204 1205
	{
	int i;
	char *p,*q;
	char buf[100];
D
Dr. Stephen Henson 已提交
1206
	int nid, mval;
D
 
Dr. Stephen Henson 已提交
1207
	long n_min,n_max;
N
Nils Larsch 已提交
1208 1209
	char *type, *value;
	const char *def;
1210 1211 1212
	CONF_VALUE *v;
	X509_NAME *subj;
	subj = X509_REQ_get_subject_name(req);
1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223

	if(!batch)
		{
		BIO_printf(bio_err,"You are about to be asked to enter information that will be incorporated\n");
		BIO_printf(bio_err,"into your certificate request.\n");
		BIO_printf(bio_err,"What you are about to enter is what is called a Distinguished Name or a DN.\n");
		BIO_printf(bio_err,"There are quite a few fields but you can leave some blank\n");
		BIO_printf(bio_err,"For some fields there will be a default value,\n");
		BIO_printf(bio_err,"If you enter '.', the field will be left blank.\n");
		BIO_printf(bio_err,"-----\n");
		}
1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249


	if (sk_CONF_VALUE_num(dn_sk))
		{
		i= -1;
start:		for (;;)
			{
			i++;
			if (sk_CONF_VALUE_num(dn_sk) <= i) break;

			v=sk_CONF_VALUE_value(dn_sk,i);
			p=q=NULL;
			type=v->name;
			if(!check_end(type,"_min") || !check_end(type,"_max") ||
				!check_end(type,"_default") ||
					 !check_end(type,"_value")) continue;
			/* Skip past any leading X. X: X, etc to allow for
			 * multiple instances 
			 */
			for(p = v->name; *p ; p++) 
				if ((*p == ':') || (*p == ',') ||
							 (*p == '.')) {
					p++;
					if(*p) type = p;
					break;
				}
D
Dr. Stephen Henson 已提交
1250 1251 1252 1253 1254 1255 1256
			if (*type == '+')
				{
				mval = -1;
				type++;
				}
			else
				mval = 0;
1257 1258
			/* If OBJ not recognised ignore it */
			if ((nid=OBJ_txt2nid(type)) == NID_undef) goto start;
1259
			if (BIO_snprintf(buf,sizeof buf,"%s_default",v->name)
1260
				>= (int)sizeof(buf))
1261 1262 1263 1264 1265
			   {
			   BIO_printf(bio_err,"Name '%s' too long\n",v->name);
			   return 0;
			   }

D
 
Dr. Stephen Henson 已提交
1266
			if ((def=NCONF_get_string(req_conf,dn_sect,buf)) == NULL)
1267 1268
				{
				ERR_clear_error();
1269
				def="";
1270
				}
1271 1272
				
			BIO_snprintf(buf,sizeof buf,"%s_value",v->name);
D
 
Dr. Stephen Henson 已提交
1273
			if ((value=NCONF_get_string(req_conf,dn_sect,buf)) == NULL)
1274 1275
				{
				ERR_clear_error();
1276
				value=NULL;
1277
				}
1278

1279
			BIO_snprintf(buf,sizeof buf,"%s_min",v->name);
D
 
Dr. Stephen Henson 已提交
1280
			if (!NCONF_get_number(req_conf,dn_sect,buf, &n_min))
1281 1282
				{
				ERR_clear_error();
D
 
Dr. Stephen Henson 已提交
1283
				n_min = -1;
1284
				}
1285

1286
			BIO_snprintf(buf,sizeof buf,"%s_max",v->name);
D
 
Dr. Stephen Henson 已提交
1287
			if (!NCONF_get_number(req_conf,dn_sect,buf, &n_max))
1288 1289
				{
				ERR_clear_error();
D
 
Dr. Stephen Henson 已提交
1290
				n_max = -1;
1291
				}
1292 1293

			if (!add_DN_object(subj,v->value,def,value,nid,
D
Dr. Stephen Henson 已提交
1294
				n_min,n_max, chtype, mval))
1295 1296 1297 1298 1299 1300 1301 1302 1303 1304
				return 0;
			}
		if (X509_NAME_entry_count(subj) == 0)
			{
			BIO_printf(bio_err,"error, no objects specified in config file\n");
			return 0;
			}

		if (attribs)
			{
1305
			if ((attr_sk != NULL) && (sk_CONF_VALUE_num(attr_sk) > 0) && (!batch))
1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323
				{
				BIO_printf(bio_err,"\nPlease enter the following 'extra' attributes\n");
				BIO_printf(bio_err,"to be sent with your certificate request\n");
				}

			i= -1;
start2:			for (;;)
				{
				i++;
				if ((attr_sk == NULL) ||
					    (sk_CONF_VALUE_num(attr_sk) <= i))
					break;

				v=sk_CONF_VALUE_value(attr_sk,i);
				type=v->name;
				if ((nid=OBJ_txt2nid(type)) == NID_undef)
					goto start2;

1324
				if (BIO_snprintf(buf,sizeof buf,"%s_default",type)
1325
					>= (int)sizeof(buf))
1326 1327 1328 1329 1330
				   {
				   BIO_printf(bio_err,"Name '%s' too long\n",v->name);
				   return 0;
				   }

D
 
Dr. Stephen Henson 已提交
1331
				if ((def=NCONF_get_string(req_conf,attr_sect,buf))
1332
					== NULL)
1333 1334
					{
					ERR_clear_error();
1335
					def="";
1336 1337
					}
				
1338
				
1339
				BIO_snprintf(buf,sizeof buf,"%s_value",type);
D
 
Dr. Stephen Henson 已提交
1340
				if ((value=NCONF_get_string(req_conf,attr_sect,buf))
1341
					== NULL)
1342 1343
					{
					ERR_clear_error();
1344
					value=NULL;
1345
					}
1346

1347
				BIO_snprintf(buf,sizeof buf,"%s_min",type);
D
 
Dr. Stephen Henson 已提交
1348
				if (!NCONF_get_number(req_conf,attr_sect,buf, &n_min))
1349 1350
					{
					ERR_clear_error();
D
 
Dr. Stephen Henson 已提交
1351
					n_min = -1;
1352
					}
1353

1354
				BIO_snprintf(buf,sizeof buf,"%s_max",type);
D
 
Dr. Stephen Henson 已提交
1355
				if (!NCONF_get_number(req_conf,attr_sect,buf, &n_max))
1356 1357
					{
					ERR_clear_error();
D
 
Dr. Stephen Henson 已提交
1358
					n_max = -1;
1359
					}
1360

1361
				if (!add_attribute_object(req,
1362
					v->value,def,value,nid,n_min,n_max, chtype))
1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377
					return 0;
				}
			}
		}
	else
		{
		BIO_printf(bio_err,"No template, please set one up.\n");
		return 0;
		}

	return 1;

	}

static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *dn_sk,
1378
			STACK_OF(CONF_VALUE) *attr_sk, int attribs, unsigned long chtype)
1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389
	{
	int i;
	char *p,*q;
	char *type;
	CONF_VALUE *v;
	X509_NAME *subj;

	subj = X509_REQ_get_subject_name(req);

	for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++)
		{
D
Dr. Stephen Henson 已提交
1390
		int mval;
1391 1392 1393 1394 1395 1396 1397
		v=sk_CONF_VALUE_value(dn_sk,i);
		p=q=NULL;
		type=v->name;
		/* Skip past any leading X. X: X, etc to allow for
		 * multiple instances 
		 */
		for(p = v->name; *p ; p++) 
1398
#ifndef CHARSET_EBCDIC
1399
			if ((*p == ':') || (*p == ',') || (*p == '.')) {
1400 1401 1402
#else
			if ((*p == os_toascii[':']) || (*p == os_toascii[',']) || (*p == os_toascii['.'])) {
#endif
1403 1404 1405 1406
				p++;
				if(*p) type = p;
				break;
			}
D
Dr. Stephen Henson 已提交
1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417
#ifndef CHARSET_EBCDIC
		if (*p == '+')
#else
		if (*p == os_toascii['+'])
#endif
			{
			p++;
			mval = -1;
			}
		else
			mval = 0;
1418
		if (!X509_NAME_add_entry_by_txt(subj,type, chtype,
D
Dr. Stephen Henson 已提交
1419
				(unsigned char *) v->value,-1,-1,mval)) return 0;
1420 1421 1422 1423 1424 1425 1426 1427 1428 1429

		}

		if (!X509_NAME_entry_count(subj))
			{
			BIO_printf(bio_err,"error, no objects specified in config file\n");
			return 0;
			}
		if (attribs)
			{
1430
			for (i = 0; i < sk_CONF_VALUE_num(attr_sk); i++)
1431 1432
				{
				v=sk_CONF_VALUE_value(attr_sk,i);
1433
				if(!X509_REQ_add1_attr_by_txt(req, v->name, chtype,
1434
					(unsigned char *)v->value, -1)) return 0;
1435 1436 1437 1438 1439 1440
				}
			}
	return 1;
	}


N
Nils Larsch 已提交
1441
static int add_DN_object(X509_NAME *n, char *text, const char *def, char *value,
D
Dr. Stephen Henson 已提交
1442
	     int nid, int n_min, int n_max, unsigned long chtype, int mval)
1443
	{
1444
	int i,ret=0;
1445
	MS_STATIC char buf[1024];
1446
start:
1447
	if (!batch) BIO_printf(bio_err,"%s [%s]:",text,def);
B
Bodo Möller 已提交
1448
	(void)BIO_flush(bio_err);
1449
	if(value != NULL)
1450
		{
1451 1452
		BUF_strlcpy(buf,value,sizeof buf);
		BUF_strlcat(buf,"\n",sizeof buf);
1453 1454 1455 1456 1457
		BIO_printf(bio_err,"%s\n",value);
		}
	else
		{
		buf[0]='\0';
1458 1459
		if (!batch)
			{
1460 1461
			if (!fgets(buf,sizeof buf,stdin))
				return 0;
1462 1463 1464 1465 1466 1467
			}
		else
			{
			buf[0] = '\n';
			buf[1] = '\0';
			}
1468 1469 1470 1471 1472 1473 1474
		}

	if (buf[0] == '\0') return(0);
	else if (buf[0] == '\n')
		{
		if ((def == NULL) || (def[0] == '\0'))
			return(1);
1475 1476
		BUF_strlcpy(buf,def,sizeof buf);
		BUF_strlcat(buf,"\n",sizeof buf);
1477 1478 1479 1480 1481 1482 1483 1484 1485 1486
		}
	else if ((buf[0] == '.') && (buf[1] == '\n')) return(1);

	i=strlen(buf);
	if (buf[i-1] != '\n')
		{
		BIO_printf(bio_err,"weird input :-(\n");
		return(0);
		}
	buf[--i]='\0';
1487 1488 1489
#ifdef CHARSET_EBCDIC
	ebcdic2ascii(buf, buf, i);
#endif
D
 
Dr. Stephen Henson 已提交
1490
	if(!req_check_len(i, n_min, n_max)) goto start;
1491
	if (!X509_NAME_add_entry_by_NID(n,nid, chtype,
D
Dr. Stephen Henson 已提交
1492
				(unsigned char *) buf, -1,-1,mval)) goto err;
1493 1494 1495 1496 1497
	ret=1;
err:
	return(ret);
	}

N
Nils Larsch 已提交
1498 1499
static int add_attribute_object(X509_REQ *req, char *text, const char *def,
				char *value, int nid, int n_min,
1500
				int n_max, unsigned long chtype)
1501
	{
1502
	int i;
1503 1504 1505
	static char buf[1024];

start:
1506
	if (!batch) BIO_printf(bio_err,"%s [%s]:",text,def);
B
Bodo Möller 已提交
1507
	(void)BIO_flush(bio_err);
1508 1509
	if (value != NULL)
		{
1510 1511
		BUF_strlcpy(buf,value,sizeof buf);
		BUF_strlcat(buf,"\n",sizeof buf);
1512 1513 1514 1515 1516
		BIO_printf(bio_err,"%s\n",value);
		}
	else
		{
		buf[0]='\0';
1517 1518
		if (!batch)
			{
1519 1520
			if (!fgets(buf,sizeof buf,stdin))
				return 0;
1521 1522 1523 1524 1525 1526
			}
		else
			{
			buf[0] = '\n';
			buf[1] = '\0';
			}
1527 1528 1529 1530 1531 1532 1533
		}

	if (buf[0] == '\0') return(0);
	else if (buf[0] == '\n')
		{
		if ((def == NULL) || (def[0] == '\0'))
			return(1);
1534 1535
		BUF_strlcpy(buf,def,sizeof buf);
		BUF_strlcat(buf,"\n",sizeof buf);
1536 1537 1538 1539 1540 1541 1542 1543 1544 1545
		}
	else if ((buf[0] == '.') && (buf[1] == '\n')) return(1);

	i=strlen(buf);
	if (buf[i-1] != '\n')
		{
		BIO_printf(bio_err,"weird input :-(\n");
		return(0);
		}
	buf[--i]='\0';
1546 1547 1548
#ifdef CHARSET_EBCDIC
	ebcdic2ascii(buf, buf, i);
#endif
D
 
Dr. Stephen Henson 已提交
1549
	if(!req_check_len(i, n_min, n_max)) goto start;
1550

1551
	if(!X509_REQ_add1_attr_by_NID(req, nid, chtype,
1552 1553 1554
					(unsigned char *)buf, -1)) {
		BIO_printf(bio_err, "Error adding attribute\n");
		ERR_print_errors(bio_err);
1555
		goto err;
1556
	}
1557 1558 1559 1560 1561 1562

	return(1);
err:
	return(0);
	}

D
 
Dr. Stephen Henson 已提交
1563
static int req_check_len(int len, int n_min, int n_max)
1564
	{
D
 
Dr. Stephen Henson 已提交
1565
	if ((n_min > 0) && (len < n_min))
1566
		{
D
 
Dr. Stephen Henson 已提交
1567
		BIO_printf(bio_err,"string is too short, it needs to be at least %d bytes long\n",n_min);
1568 1569
		return(0);
		}
D
 
Dr. Stephen Henson 已提交
1570
	if ((n_max >= 0) && (len > n_max))
1571
		{
D
 
Dr. Stephen Henson 已提交
1572
		BIO_printf(bio_err,"string is too long, it needs to be less than  %d bytes long\n",n_max);
1573 1574 1575 1576
		return(0);
		}
	return(1);
	}
1577 1578

/* Check if the end of a string matches 'end' */
N
Nils Larsch 已提交
1579
static int check_end(const char *str, const char *end)
1580 1581
{
	int elen, slen;	
N
Nils Larsch 已提交
1582
	const char *tmp;
1583 1584 1585 1586 1587 1588
	elen = strlen(end);
	slen = strlen(str);
	if(elen > slen) return 1;
	tmp = str + slen - elen;
	return strcmp(tmp, end);
}
1589

1590
static EVP_PKEY_CTX *set_keygen_ctx(BIO *err, const char *gstr, int *pkey_type,
1591 1592
					long *pkeylen, char **palgnam,
					ENGINE *keygen_engine)
1593 1594 1595 1596 1597 1598 1599 1600 1601
	{
	EVP_PKEY_CTX *gctx = NULL;
	EVP_PKEY *param = NULL;
	long keylen = -1;
	BIO *pbio = NULL;
	const char *paramfile = NULL;

	if (gstr == NULL)
		{
1602
		*pkey_type = EVP_PKEY_RSA;
1603 1604 1605 1606
		keylen = *pkeylen;
		}
	else if (gstr[0] >= '0' && gstr[0] <= '9')
		{
1607
		*pkey_type = EVP_PKEY_RSA;
1608 1609 1610 1611 1612 1613 1614 1615 1616
		keylen = atol(gstr);
		*pkeylen = keylen;
		}
	else if (!strncmp(gstr, "param:", 6))
		paramfile = gstr + 6;
	else
		{
		const char *p = strchr(gstr, ':');
		int len;
1617
		ENGINE *tmpeng;
1618 1619 1620 1621 1622 1623
		const EVP_PKEY_ASN1_METHOD *ameth;

		if (p)
			len = p - gstr;
		else
			len = strlen(gstr);
1624 1625 1626
		/* The lookup of a the string will cover all engines so
		 * keep a note of the implementation.
		 */
1627

1628
		ameth = EVP_PKEY_asn1_find_str(&tmpeng, gstr, len);
1629 1630 1631 1632 1633 1634 1635

		if (!ameth)
			{
			BIO_printf(err, "Unknown algorithm %.*s\n", len, gstr);
			return NULL;
			}

1636
		EVP_PKEY_asn1_get0_info(NULL, pkey_type, NULL, NULL, NULL,
1637 1638 1639 1640 1641
									ameth);
#ifndef OPENSSL_NO_ENGINE
		if (tmpeng)
			ENGINE_finish(tmpeng);
#endif
1642
		if (*pkey_type == EVP_PKEY_RSA)
1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667
			{
			if (p)
				{
				keylen = atol(p + 1);
				*pkeylen = keylen;
				}
			}
		else if (p)
			paramfile = p + 1;
		}

	if (paramfile)
		{
		pbio = BIO_new_file(paramfile, "r");
		if (!pbio)
			{
			BIO_printf(err, "Can't open parameter file %s\n",
					paramfile);
			return NULL;
			}
		param = PEM_read_bio_Parameters(pbio, NULL);

		if (!param)
			{
			X509 *x;
D
Dr. Stephen Henson 已提交
1668
			(void)BIO_reset(pbio);
1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684
			x = PEM_read_bio_X509(pbio, NULL, NULL, NULL);
			if (x)
				{
				param = X509_get_pubkey(x);
				X509_free(x);
				}
			}

		BIO_free(pbio);

		if (!param)
			{
			BIO_printf(err, "Error reading parameter file %s\n",
					paramfile);
			return NULL;
			}
1685 1686 1687
		if (*pkey_type == -1)
			*pkey_type = EVP_PKEY_id(param);
		else if (*pkey_type != EVP_PKEY_base_id(param))
1688 1689 1690 1691 1692 1693 1694 1695 1696 1697
			{
			BIO_printf(err, "Key Type does not match parameters\n");
			EVP_PKEY_free(param);
			return NULL;
			}
		}

	if (palgnam)
		{
		const EVP_PKEY_ASN1_METHOD *ameth;
1698 1699
		ENGINE *tmpeng;
		const char *anam;
1700
		ameth = EVP_PKEY_asn1_find(&tmpeng, *pkey_type);
1701 1702 1703 1704 1705
		if (!ameth)
			{
			BIO_puts(err, "Internal error: can't find key algorithm\n");
			return NULL;
			}
1706 1707 1708 1709 1710 1711
		EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL, &anam, ameth);
		*palgnam = BUF_strdup(anam);
#ifndef OPENSSL_NO_ENGINE
		if (tmpeng)
			ENGINE_finish(tmpeng);
#endif
1712 1713 1714 1715
		}

	if (param)
		{
1716
		gctx = EVP_PKEY_CTX_new(param, keygen_engine);
1717 1718 1719 1720
		*pkeylen = EVP_PKEY_bits(param);
		EVP_PKEY_free(param);
		}
	else
1721
		gctx = EVP_PKEY_CTX_new_id(*pkey_type, keygen_engine);
1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735

	if (!gctx)
		{
		BIO_puts(err, "Error allocating keygen context\n");
		ERR_print_errors(err);
		return NULL;
		}

	if (EVP_PKEY_keygen_init(gctx) <= 0)
		{
		BIO_puts(err, "Error initializing keygen context\n");
		ERR_print_errors(err);
		return NULL;
		}
D
Dr. Stephen Henson 已提交
1736
#ifndef OPENSSL_NO_RSA
1737
	if ((*pkey_type == EVP_PKEY_RSA) && (keylen != -1))
1738 1739 1740 1741 1742 1743 1744 1745 1746
		{
		if (EVP_PKEY_CTX_set_rsa_keygen_bits(gctx, keylen) <= 0)
			{
			BIO_puts(err, "Error setting RSA keysize\n");
			ERR_print_errors(err);
			EVP_PKEY_CTX_free(gctx);
			return NULL;
			}
		}
D
Dr. Stephen Henson 已提交
1747
#endif
1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768

	return gctx;
	}

static int genpkey_cb(EVP_PKEY_CTX *ctx)
	{
	char c='*';
	BIO *b = EVP_PKEY_CTX_get_app_data(ctx);
	int p;
	p = EVP_PKEY_CTX_get_keygen_info(ctx, 0);
	if (p == 0) c='.';
	if (p == 1) c='+';
	if (p == 2) c='*';
	if (p == 3) c='\n';
	BIO_write(b,&c,1);
	(void)BIO_flush(b);
#ifdef LINT
	p=n;
#endif
	return 1;
	}
1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818

static int do_sign_init(BIO *err, EVP_MD_CTX *ctx, EVP_PKEY *pkey,
			const EVP_MD *md, STACK_OF(OPENSSL_STRING) *sigopts)
	{
	EVP_PKEY_CTX *pkctx = NULL;
	int i;
	EVP_MD_CTX_init(ctx);
	if (!EVP_DigestSignInit(ctx, &pkctx, md, NULL, pkey))
		return 0;
	for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++)
		{
		char *sigopt = sk_OPENSSL_STRING_value(sigopts, i);
		if (pkey_ctrl_string(pkctx, sigopt) <= 0)
			{
			BIO_printf(err, "parameter error \"%s\"\n", sigopt);
			ERR_print_errors(bio_err);
			return 0;
			}
		}
	return 1;
	}

int do_X509_sign(BIO *err, X509 *x, EVP_PKEY *pkey, const EVP_MD *md,
			STACK_OF(OPENSSL_STRING) *sigopts)
	{
	int rv;
	EVP_MD_CTX mctx;
	EVP_MD_CTX_init(&mctx);
	rv = do_sign_init(err, &mctx, pkey, md, sigopts);
	if (rv > 0)
		rv = X509_sign_ctx(x, &mctx);
	EVP_MD_CTX_cleanup(&mctx);
	return rv > 0 ? 1 : 0;
	}


int do_X509_REQ_sign(BIO *err, X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md,
			STACK_OF(OPENSSL_STRING) *sigopts)
	{
	int rv;
	EVP_MD_CTX mctx;
	EVP_MD_CTX_init(&mctx);
	rv = do_sign_init(err, &mctx, pkey, md, sigopts);
	if (rv > 0)
		rv = X509_REQ_sign_ctx(x, &mctx);
	EVP_MD_CTX_cleanup(&mctx);
	return rv > 0 ? 1 : 0;
	}
		
	
1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833

int do_X509_CRL_sign(BIO *err, X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md,
			STACK_OF(OPENSSL_STRING) *sigopts)
	{
	int rv;
	EVP_MD_CTX mctx;
	EVP_MD_CTX_init(&mctx);
	rv = do_sign_init(err, &mctx, pkey, md, sigopts);
	if (rv > 0)
		rv = X509_CRL_sign_ctx(x, &mctx);
	EVP_MD_CTX_cleanup(&mctx);
	return rv > 0 ? 1 : 0;
	}