xref: /openbsd-src/usr.bin/openssl/req.c (revision 375d4fb197ee7ab7f358a72ca7a7ce87199eacc4)
1*375d4fb1Stb /* $OpenBSD: req.c,v 1.29 2024/04/17 01:24:43 tb Exp $ */
2dab3f910Sjsing /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3dab3f910Sjsing  * All rights reserved.
4dab3f910Sjsing  *
5dab3f910Sjsing  * This package is an SSL implementation written
6dab3f910Sjsing  * by Eric Young (eay@cryptsoft.com).
7dab3f910Sjsing  * The implementation was written so as to conform with Netscapes SSL.
8dab3f910Sjsing  *
9dab3f910Sjsing  * This library is free for commercial and non-commercial use as long as
10dab3f910Sjsing  * the following conditions are aheared to.  The following conditions
11dab3f910Sjsing  * apply to all code found in this distribution, be it the RC4, RSA,
12dab3f910Sjsing  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13dab3f910Sjsing  * included with this distribution is covered by the same copyright terms
14dab3f910Sjsing  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15dab3f910Sjsing  *
16dab3f910Sjsing  * Copyright remains Eric Young's, and as such any Copyright notices in
17dab3f910Sjsing  * the code are not to be removed.
18dab3f910Sjsing  * If this package is used in a product, Eric Young should be given attribution
19dab3f910Sjsing  * as the author of the parts of the library used.
20dab3f910Sjsing  * This can be in the form of a textual message at program startup or
21dab3f910Sjsing  * in documentation (online or textual) provided with the package.
22dab3f910Sjsing  *
23dab3f910Sjsing  * Redistribution and use in source and binary forms, with or without
24dab3f910Sjsing  * modification, are permitted provided that the following conditions
25dab3f910Sjsing  * are met:
26dab3f910Sjsing  * 1. Redistributions of source code must retain the copyright
27dab3f910Sjsing  *    notice, this list of conditions and the following disclaimer.
28dab3f910Sjsing  * 2. Redistributions in binary form must reproduce the above copyright
29dab3f910Sjsing  *    notice, this list of conditions and the following disclaimer in the
30dab3f910Sjsing  *    documentation and/or other materials provided with the distribution.
31dab3f910Sjsing  * 3. All advertising materials mentioning features or use of this software
32dab3f910Sjsing  *    must display the following acknowledgement:
33dab3f910Sjsing  *    "This product includes cryptographic software written by
34dab3f910Sjsing  *     Eric Young (eay@cryptsoft.com)"
35dab3f910Sjsing  *    The word 'cryptographic' can be left out if the rouines from the library
36dab3f910Sjsing  *    being used are not cryptographic related :-).
37dab3f910Sjsing  * 4. If you include any Windows specific code (or a derivative thereof) from
38dab3f910Sjsing  *    the apps directory (application code) you must include an acknowledgement:
39dab3f910Sjsing  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40dab3f910Sjsing  *
41dab3f910Sjsing  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42dab3f910Sjsing  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43dab3f910Sjsing  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44dab3f910Sjsing  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45dab3f910Sjsing  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46dab3f910Sjsing  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47dab3f910Sjsing  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48dab3f910Sjsing  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49dab3f910Sjsing  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50dab3f910Sjsing  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51dab3f910Sjsing  * SUCH DAMAGE.
52dab3f910Sjsing  *
53dab3f910Sjsing  * The licence and distribution terms for any publically available version or
54dab3f910Sjsing  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55dab3f910Sjsing  * copied and put under another distribution licence
56dab3f910Sjsing  * [including the GNU Public Licence.]
57dab3f910Sjsing  */
58dab3f910Sjsing 
59dab3f910Sjsing /* Until the key-gen callbacks are modified to use newer prototypes, we allow
60dab3f910Sjsing  * deprecated functions for openssl-internal code */
61dab3f910Sjsing #ifdef OPENSSL_NO_DEPRECATED
62dab3f910Sjsing #undef OPENSSL_NO_DEPRECATED
63dab3f910Sjsing #endif
64dab3f910Sjsing 
65a72a31a2Sinoguchi #include <ctype.h>
66a72a31a2Sinoguchi #include <limits.h>
67dab3f910Sjsing #include <stdio.h>
68dab3f910Sjsing #include <stdlib.h>
69dab3f910Sjsing #include <string.h>
70dab3f910Sjsing #include <time.h>
71dab3f910Sjsing 
72dab3f910Sjsing #include "apps.h"
73dab3f910Sjsing 
74dab3f910Sjsing #include <openssl/asn1.h>
75dab3f910Sjsing #include <openssl/bio.h>
76dab3f910Sjsing #include <openssl/bn.h>
77dab3f910Sjsing #include <openssl/conf.h>
78dab3f910Sjsing #include <openssl/err.h>
79dab3f910Sjsing #include <openssl/evp.h>
80dab3f910Sjsing #include <openssl/objects.h>
81dab3f910Sjsing #include <openssl/pem.h>
82dab3f910Sjsing #include <openssl/x509.h>
83dab3f910Sjsing #include <openssl/x509v3.h>
84dab3f910Sjsing 
85dab3f910Sjsing #include <openssl/dsa.h>
86dab3f910Sjsing 
87dab3f910Sjsing #include <openssl/rsa.h>
88dab3f910Sjsing 
89dab3f910Sjsing #define SECTION		"req"
90dab3f910Sjsing 
91dab3f910Sjsing #define BITS		"default_bits"
92dab3f910Sjsing #define KEYFILE		"default_keyfile"
93dab3f910Sjsing #define PROMPT		"prompt"
94dab3f910Sjsing #define DISTINGUISHED_NAME	"distinguished_name"
95dab3f910Sjsing #define ATTRIBUTES	"attributes"
96dab3f910Sjsing #define V3_EXTENSIONS	"x509_extensions"
97dab3f910Sjsing #define REQ_EXTENSIONS	"req_extensions"
98dab3f910Sjsing #define STRING_MASK	"string_mask"
99dab3f910Sjsing #define UTF8_IN		"utf8"
100dab3f910Sjsing 
101f25f6bcdSsthen #define DEFAULT_KEY_LENGTH	2048
102dab3f910Sjsing #define MIN_KEY_LENGTH		384
103dab3f910Sjsing 
10480772f88Smiod static int make_REQ(X509_REQ * req, EVP_PKEY * pkey, char *dn, int multirdn,
105dab3f910Sjsing     int attribs, unsigned long chtype);
106dab3f910Sjsing static int build_subject(X509_REQ * req, char *subj, unsigned long chtype,
107dab3f910Sjsing     int multirdn);
108dab3f910Sjsing static int prompt_info(X509_REQ * req,
109dab3f910Sjsing     STACK_OF(CONF_VALUE) * dn_sk, char *dn_sect,
110dab3f910Sjsing     STACK_OF(CONF_VALUE) * attr_sk, char *attr_sect, int attribs,
111dab3f910Sjsing     unsigned long chtype);
112dab3f910Sjsing static int auto_info(X509_REQ * req, STACK_OF(CONF_VALUE) * sk,
113dab3f910Sjsing     STACK_OF(CONF_VALUE) * attr, int attribs,
114dab3f910Sjsing     unsigned long chtype);
115dab3f910Sjsing static int add_attribute_object(X509_REQ * req, char *text, const char *def,
116dab3f910Sjsing     char *value, int nid, int n_min,
117dab3f910Sjsing     int n_max, unsigned long chtype);
118dab3f910Sjsing static int add_DN_object(X509_NAME * n, char *text, const char *def, char *value,
119dab3f910Sjsing     int nid, int n_min, int n_max, unsigned long chtype, int mval);
120dab3f910Sjsing static int genpkey_cb(EVP_PKEY_CTX * ctx);
121dab3f910Sjsing static int req_check_len(int len, int n_min, int n_max);
122dab3f910Sjsing static int check_end(const char *str, const char *end);
123dab3f910Sjsing static EVP_PKEY_CTX *set_keygen_ctx(BIO * err, const char *gstr, int *pkey_type,
1245284dfeaSbcook     long *pkeylen, char **palgnam);
125a72a31a2Sinoguchi static unsigned long ext_name_hash(const OPENSSL_STRING *a);
126a72a31a2Sinoguchi static int ext_name_cmp(const OPENSSL_STRING *a, const OPENSSL_STRING *b);
127a72a31a2Sinoguchi static void exts_cleanup(OPENSSL_STRING *x);
128a72a31a2Sinoguchi static int duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv);
129dab3f910Sjsing static CONF *req_conf = NULL;
130a72a31a2Sinoguchi static CONF *addext_conf = NULL;
131e451a623Sjsing 
132efc7e65fStb static struct {
133e451a623Sjsing 	LHASH_OF(OPENSSL_STRING) *addexts;
134e451a623Sjsing 	BIO *addext_bio;
135e451a623Sjsing 	int batch;
136e451a623Sjsing 	unsigned long chtype;
137e451a623Sjsing 	int days;
138e451a623Sjsing 	const EVP_MD *digest;
139e451a623Sjsing 	char *extensions;
140e451a623Sjsing 	char *infile;
141e451a623Sjsing 	int informat;
142e451a623Sjsing 	char *keyalg;
143e451a623Sjsing 	char *keyfile;
144e451a623Sjsing 	int keyform;
145e451a623Sjsing 	char *keyout;
146e451a623Sjsing 	int modulus;
147e451a623Sjsing 	int multirdn;
148e451a623Sjsing 	int newhdr;
149e451a623Sjsing 	long newkey;
150e451a623Sjsing 	int newreq;
151e451a623Sjsing 	unsigned long nmflag;
152e451a623Sjsing 	int nodes;
153e451a623Sjsing 	int noout;
154e451a623Sjsing 	char *outfile;
155e451a623Sjsing 	int outformat;
156e451a623Sjsing 	char *passargin;
157e451a623Sjsing 	char *passargout;
158e451a623Sjsing 	STACK_OF(OPENSSL_STRING) *pkeyopts;
159e451a623Sjsing 	int pubkey;
160e451a623Sjsing 	char *req_exts;
161e451a623Sjsing 	unsigned long reqflag;
162e451a623Sjsing 	ASN1_INTEGER *serial;
163e451a623Sjsing 	STACK_OF(OPENSSL_STRING) *sigopts;
164e451a623Sjsing 	char *subj;
165e451a623Sjsing 	int subject;
166e451a623Sjsing 	char *template;
167e451a623Sjsing 	int text;
168e451a623Sjsing 	int verbose;
169e451a623Sjsing 	int verify;
170e451a623Sjsing 	int x509;
171e7718adaStb } cfg;
172e451a623Sjsing 
173e451a623Sjsing static int
req_opt_addext(char * arg)174e451a623Sjsing req_opt_addext(char *arg)
175e451a623Sjsing {
176e451a623Sjsing 	int i;
177e451a623Sjsing 
178e7718adaStb 	if (cfg.addexts == NULL) {
179e7718adaStb 		cfg.addexts = (LHASH_OF(OPENSSL_STRING) *)lh_new(
180e451a623Sjsing 		    (LHASH_HASH_FN_TYPE)ext_name_hash,
181e451a623Sjsing 		    (LHASH_COMP_FN_TYPE)ext_name_cmp);
182e7718adaStb 		cfg.addext_bio = BIO_new(BIO_s_mem());
183e7718adaStb 		if (cfg.addexts == NULL ||
184e7718adaStb 		    cfg.addext_bio == NULL)
185e451a623Sjsing 			return (1);
186e451a623Sjsing 	}
187e7718adaStb 	i = duplicated(cfg.addexts, arg);
188e451a623Sjsing 	if (i == 1)
189e451a623Sjsing 		return (1);
190e7718adaStb 	if (i < 0 || BIO_printf(cfg.addext_bio, "%s\n", arg) < 0)
191e451a623Sjsing 		return (1);
192e451a623Sjsing 
193e451a623Sjsing 	return (0);
194e451a623Sjsing }
195e451a623Sjsing 
196e451a623Sjsing static int
req_opt_days(char * arg)197e451a623Sjsing req_opt_days(char *arg)
198e451a623Sjsing {
199e451a623Sjsing 	const char *errstr;
200e451a623Sjsing 
201e7718adaStb 	cfg.days = strtonum(arg, 1, INT_MAX, &errstr);
202e451a623Sjsing 	if (errstr != NULL) {
203e451a623Sjsing 		BIO_printf(bio_err, "bad -days %s, using 0: %s\n",
204e451a623Sjsing 		    arg, errstr);
205e7718adaStb 		cfg.days = 30;
206e451a623Sjsing 	}
207e451a623Sjsing 	return (0);
208e451a623Sjsing }
209e451a623Sjsing 
210e451a623Sjsing static int
req_opt_digest(int argc,char ** argv,int * argsused)211e451a623Sjsing req_opt_digest(int argc, char **argv, int *argsused)
212e451a623Sjsing {
213e451a623Sjsing 	char *name = argv[0];
214e451a623Sjsing 
215e451a623Sjsing 	if (*name++ != '-')
216e451a623Sjsing 		return (1);
217e451a623Sjsing 
218e7718adaStb 	if ((cfg.digest = EVP_get_digestbyname(name)) == NULL)
219e451a623Sjsing 		return (1);
220e451a623Sjsing 
221e451a623Sjsing 	*argsused = 1;
222e451a623Sjsing 	return (0);
223e451a623Sjsing }
224e451a623Sjsing 
225e451a623Sjsing static int
req_opt_newkey(char * arg)226e451a623Sjsing req_opt_newkey(char *arg)
227e451a623Sjsing {
228e7718adaStb 	cfg.keyalg = arg;
229e7718adaStb 	cfg.newreq = 1;
230e451a623Sjsing 	return (0);
231e451a623Sjsing }
232e451a623Sjsing 
233e451a623Sjsing static int
req_opt_nameopt(char * arg)234e451a623Sjsing req_opt_nameopt(char *arg)
235e451a623Sjsing {
236e7718adaStb 	if (!set_name_ex(&cfg.nmflag, arg))
237e451a623Sjsing 		return (1);
238e451a623Sjsing 	return (0);
239e451a623Sjsing }
240e451a623Sjsing 
241e451a623Sjsing static int
req_opt_pkeyopt(char * arg)242e451a623Sjsing req_opt_pkeyopt(char *arg)
243e451a623Sjsing {
244e7718adaStb 	if (cfg.pkeyopts == NULL)
245e7718adaStb 		cfg.pkeyopts = sk_OPENSSL_STRING_new_null();
246e7718adaStb 	if (cfg.pkeyopts == NULL)
247e451a623Sjsing 		return (1);
248e7718adaStb 	if (!sk_OPENSSL_STRING_push(cfg.pkeyopts, arg))
249e451a623Sjsing 		return (1);
250e451a623Sjsing 	return (0);
251e451a623Sjsing }
252e451a623Sjsing 
253e451a623Sjsing static int
req_opt_reqopt(char * arg)254e451a623Sjsing req_opt_reqopt(char *arg)
255e451a623Sjsing {
256e7718adaStb 	if (!set_cert_ex(&cfg.reqflag, arg))
257e451a623Sjsing 		return (1);
258e451a623Sjsing 	return (0);
259e451a623Sjsing }
260e451a623Sjsing 
261e451a623Sjsing static int
req_opt_set_serial(char * arg)262e451a623Sjsing req_opt_set_serial(char *arg)
263e451a623Sjsing {
264e7718adaStb 	cfg.serial = s2i_ASN1_INTEGER(NULL, arg);
265e7718adaStb 	if (cfg.serial == NULL)
266e451a623Sjsing 		return (1);
267e451a623Sjsing 	return (0);
268e451a623Sjsing }
269e451a623Sjsing 
270e451a623Sjsing static int
req_opt_sigopt(char * arg)271e451a623Sjsing req_opt_sigopt(char *arg)
272e451a623Sjsing {
273e7718adaStb 	if (cfg.sigopts == NULL)
274e7718adaStb 		cfg.sigopts = sk_OPENSSL_STRING_new_null();
275e7718adaStb 	if (cfg.sigopts == NULL)
276e451a623Sjsing 		return (1);
277e7718adaStb 	if (!sk_OPENSSL_STRING_push(cfg.sigopts, arg))
278e451a623Sjsing 		return (1);
279e451a623Sjsing 	return (0);
280e451a623Sjsing }
281e451a623Sjsing 
282e451a623Sjsing static int
req_opt_utf8(void)283e451a623Sjsing req_opt_utf8(void)
284e451a623Sjsing {
285e7718adaStb 	cfg.chtype = MBSTRING_UTF8;
286e451a623Sjsing 	return (0);
287e451a623Sjsing }
288e451a623Sjsing 
289e451a623Sjsing static const struct option req_options[] = {
290e451a623Sjsing 	{
291e451a623Sjsing 		.name = "addext",
292e451a623Sjsing 		.argname = "key=value",
293e451a623Sjsing 		.desc = "Additional certificate extension (may be repeated)",
294e451a623Sjsing 		.type = OPTION_ARG_FUNC,
295e451a623Sjsing 		.opt.argfunc = req_opt_addext,
296e451a623Sjsing 	},
297e451a623Sjsing 	{
298e451a623Sjsing 		.name = "batch",
299e451a623Sjsing 		.desc = "Operate in batch mode",
300e451a623Sjsing 		.type = OPTION_FLAG,
301e7718adaStb 		.opt.flag = &cfg.batch,
302e451a623Sjsing 	},
303e451a623Sjsing 	{
304e451a623Sjsing 		.name = "config",
305e451a623Sjsing 		.argname = "file",
306e451a623Sjsing 		.desc = "Configuration file to use as request template",
307e451a623Sjsing 		.type = OPTION_ARG,
308e7718adaStb 		.opt.arg = &cfg.template,
309e451a623Sjsing 	},
310e451a623Sjsing 	{
311e451a623Sjsing 		.name = "days",
312e451a623Sjsing 		.argname = "number",
313e451a623Sjsing 		.desc = "Number of days generated certificate is valid for",
314e451a623Sjsing 		.type = OPTION_ARG_FUNC,
315e451a623Sjsing 		.opt.argfunc = req_opt_days,
316e451a623Sjsing 	},
317e451a623Sjsing 	{
318e451a623Sjsing 		.name = "extensions",
319e451a623Sjsing 		.argname = "section",
320e451a623Sjsing 		.desc = "Config section to use for certificate extensions",
321e451a623Sjsing 		.type = OPTION_ARG,
322e7718adaStb 		.opt.arg = &cfg.extensions,
323e451a623Sjsing 	},
324e451a623Sjsing 	{
325e451a623Sjsing 		.name = "in",
326e451a623Sjsing 		.argname = "file",
327e451a623Sjsing 		.desc = "Input file (default stdin)",
328e451a623Sjsing 		.type = OPTION_ARG,
329e7718adaStb 		.opt.arg = &cfg.infile,
330e451a623Sjsing 	},
331e451a623Sjsing 	{
332e451a623Sjsing 		.name = "inform",
333e451a623Sjsing 		.argname = "format",
334e451a623Sjsing 		.desc = "Input format (DER or PEM (default))",
335e451a623Sjsing 		.type = OPTION_ARG_FORMAT,
336e7718adaStb 		.opt.value = &cfg.informat,
337e451a623Sjsing 	},
338e451a623Sjsing 	{
339e451a623Sjsing 		.name = "key",
340e451a623Sjsing 		.argname = "file",
341e451a623Sjsing 		.desc = "Private key file",
342e451a623Sjsing 		.type = OPTION_ARG,
343e7718adaStb 		.opt.arg = &cfg.keyfile,
344e451a623Sjsing 	},
345e451a623Sjsing 	{
346e451a623Sjsing 		.name = "keyform",
347e451a623Sjsing 		.argname = "format",
348e451a623Sjsing 		.desc = "Private key format (DER or PEM (default))",
349e451a623Sjsing 		.type = OPTION_ARG_FORMAT,
350e7718adaStb 		.opt.value = &cfg.keyform,
351e451a623Sjsing 	},
352e451a623Sjsing 	{
353e451a623Sjsing 		.name = "keyout",
354e451a623Sjsing 		.argname = "file",
355e451a623Sjsing 		.desc = "Private key output file",
356e451a623Sjsing 		.type = OPTION_ARG,
357e7718adaStb 		.opt.arg = &cfg.keyout,
358e451a623Sjsing 	},
359e451a623Sjsing 	{
360e451a623Sjsing 		.name = "modulus",
361e451a623Sjsing 		.desc = "Print RSA modulus",
362e451a623Sjsing 		.type = OPTION_FLAG,
363e7718adaStb 		.opt.flag = &cfg.modulus,
364e451a623Sjsing 	},
365e451a623Sjsing 	{
366e451a623Sjsing 		.name = "multivalue-rdn",
367e451a623Sjsing 		.desc = "Enable support for multivalued RDNs",
368e451a623Sjsing 		.type = OPTION_FLAG,
369e7718adaStb 		.opt.flag = &cfg.multirdn,
370e451a623Sjsing 	},
371e451a623Sjsing 	{
372e451a623Sjsing 		.name = "nameopt",
373e451a623Sjsing 		.argname = "arg",
374e451a623Sjsing 		.desc = "Certificate name options",
375e451a623Sjsing 		.type = OPTION_ARG_FUNC,
376e451a623Sjsing 		.opt.argfunc = req_opt_nameopt,
377e451a623Sjsing 	},
378e451a623Sjsing 	{
379e451a623Sjsing 		.name = "new",
380e451a623Sjsing 		.desc = "New request",
381e451a623Sjsing 		.type = OPTION_FLAG,
382e7718adaStb 		.opt.flag = &cfg.newreq,
383e451a623Sjsing 	},
384e451a623Sjsing 	{
385e451a623Sjsing 		.name = "newhdr",
386e451a623Sjsing 		.desc = "Include 'NEW' in header lines",
387e451a623Sjsing 		.type = OPTION_FLAG,
388e7718adaStb 		.opt.flag = &cfg.newhdr,
389e451a623Sjsing 	},
390e451a623Sjsing 	{
391e451a623Sjsing 		.name = "newkey",
392e451a623Sjsing 		.argname = "param",
393e451a623Sjsing 		.desc = "Generate a new key using given parameters",
394e451a623Sjsing 		.type = OPTION_ARG_FUNC,
395e451a623Sjsing 		.opt.argfunc = req_opt_newkey,
396e451a623Sjsing 	},
397e451a623Sjsing 	{
398e451a623Sjsing 		.name = "nodes",
399e451a623Sjsing 		.desc = "Do not encrypt output private key",
400e451a623Sjsing 		.type = OPTION_FLAG,
401e7718adaStb 		.opt.flag = &cfg.nodes,
402e451a623Sjsing 	},
403e451a623Sjsing 	{
404e451a623Sjsing 		.name = "noout",
405e451a623Sjsing 		.desc = "Do not output request",
406e451a623Sjsing 		.type = OPTION_FLAG,
407e7718adaStb 		.opt.flag = &cfg.noout,
408e451a623Sjsing 	},
409e451a623Sjsing 	{
410e451a623Sjsing 		.name = "out",
411e451a623Sjsing 		.argname = "file",
412e451a623Sjsing 		.desc = "Output file (default stdout)",
413e451a623Sjsing 		.type = OPTION_ARG,
414e7718adaStb 		.opt.arg = &cfg.outfile,
415e451a623Sjsing 	},
416e451a623Sjsing 	{
417e451a623Sjsing 		.name = "outform",
418e451a623Sjsing 		.argname = "format",
419e451a623Sjsing 		.desc = "Output format (DER or PEM (default))",
420e451a623Sjsing 		.type = OPTION_ARG_FORMAT,
421e7718adaStb 		.opt.value = &cfg.outformat,
422e451a623Sjsing 	},
423e451a623Sjsing 	{
424e451a623Sjsing 		.name = "passin",
425e451a623Sjsing 		.argname = "source",
426e451a623Sjsing 		.desc = "Private key input password source",
427e451a623Sjsing 		.type = OPTION_ARG,
428e7718adaStb 		.opt.arg = &cfg.passargin,
429e451a623Sjsing 	},
430e451a623Sjsing 	{
431e451a623Sjsing 		.name = "passout",
432e451a623Sjsing 		.argname = "source",
433e451a623Sjsing 		.desc = "Private key output password source",
434e451a623Sjsing 		.type = OPTION_ARG,
435e7718adaStb 		.opt.arg = &cfg.passargout,
436e451a623Sjsing 	},
437e451a623Sjsing 	{
438e451a623Sjsing 		.name = "pkeyopt",
439e451a623Sjsing 		.argname = "opt:val",
440e451a623Sjsing 		.desc = "Set the public key algorithm option opt to val",
441e451a623Sjsing 		.type = OPTION_ARG_FUNC,
442e451a623Sjsing 		.opt.argfunc = req_opt_pkeyopt,
443e451a623Sjsing 	},
444e451a623Sjsing 	{
445e451a623Sjsing 		.name = "pubkey",
446e451a623Sjsing 		.desc = "Output the public key",
447e451a623Sjsing 		.type = OPTION_FLAG,
448e7718adaStb 		.opt.flag = &cfg.pubkey,
449e451a623Sjsing 	},
450e451a623Sjsing 	{
451e451a623Sjsing 		.name = "reqexts",
452e451a623Sjsing 		.argname = "section",
453e451a623Sjsing 		.desc = "Config section to use for request extensions",
454e451a623Sjsing 		.type = OPTION_ARG,
455e7718adaStb 		.opt.arg = &cfg.req_exts,
456e451a623Sjsing 	},
457e451a623Sjsing 	{
458e451a623Sjsing 		.name = "reqopt",
459e451a623Sjsing 		.argname = "option",
460e451a623Sjsing 		.desc = "Request text options",
461e451a623Sjsing 		.type = OPTION_ARG_FUNC,
462e451a623Sjsing 		.opt.argfunc = req_opt_reqopt,
463e451a623Sjsing 	},
464e451a623Sjsing 	{
465e451a623Sjsing 		.name = "set_serial",
466e451a623Sjsing 		.argname = "serial",
467e451a623Sjsing 		.desc = "Serial number to use for generated certificate",
468e451a623Sjsing 		.type = OPTION_ARG_FUNC,
469e451a623Sjsing 		.opt.argfunc = req_opt_set_serial,
470e451a623Sjsing 	},
471e451a623Sjsing 	{
472e451a623Sjsing 		.name = "sigopt",
473e451a623Sjsing 		.argname = "name:val",
474e451a623Sjsing 		.desc = "Signature options",
475e451a623Sjsing 		.type = OPTION_ARG_FUNC,
476e451a623Sjsing 		.opt.argfunc = req_opt_sigopt,
477e451a623Sjsing 	},
478e451a623Sjsing 	{
479e451a623Sjsing 		.name = "subj",
480e451a623Sjsing 		.argname = "name",
481e451a623Sjsing 		.desc = "Set or modify the request subject",
482e451a623Sjsing 		.type = OPTION_ARG,
483e7718adaStb 		.opt.arg = &cfg.subj,
484e451a623Sjsing 	},
485e451a623Sjsing 	{
486e451a623Sjsing 		.name = "subject",
487e451a623Sjsing 		.desc = "Output the subject of the request",
488e451a623Sjsing 		.type = OPTION_FLAG,
489e7718adaStb 		.opt.flag = &cfg.subject,
490e451a623Sjsing 	},
491e451a623Sjsing 	{
492e451a623Sjsing 		.name = "text",
493e451a623Sjsing 		.desc = "Print request in text form",
494e451a623Sjsing 		.type = OPTION_FLAG,
495e7718adaStb 		.opt.flag = &cfg.text,
496e451a623Sjsing 	},
497e451a623Sjsing 	{
498e451a623Sjsing 		.name = "utf8",
499e451a623Sjsing 		.desc = "Input characters are in UTF-8 (default ASCII)",
500e451a623Sjsing 		.type = OPTION_FUNC,
501e451a623Sjsing 		.opt.func = req_opt_utf8,
502e451a623Sjsing 	},
503e451a623Sjsing 	{
504e451a623Sjsing 		.name = "verbose",
505e451a623Sjsing 		.desc = "Verbose",
506e451a623Sjsing 		.type = OPTION_FLAG,
507e7718adaStb 		.opt.flag = &cfg.verbose,
508e451a623Sjsing 	},
509e451a623Sjsing 	{
510e451a623Sjsing 		.name = "verify",
511e451a623Sjsing 		.desc = "Verify signature on request",
512e451a623Sjsing 		.type = OPTION_FLAG,
513e7718adaStb 		.opt.flag = &cfg.verify,
514e451a623Sjsing 	},
515e451a623Sjsing 	{
516e451a623Sjsing 		.name = "x509",
517e451a623Sjsing 		.desc = "Output an X.509 structure instead of a certificate request",
518e451a623Sjsing 		.type = OPTION_FLAG,
519e7718adaStb 		.opt.flag = &cfg.x509,
520e451a623Sjsing 	},
521e451a623Sjsing 	{
522e451a623Sjsing 		.name = NULL,
523e451a623Sjsing 		.desc = "",
524e451a623Sjsing 		.type = OPTION_ARGV_FUNC,
525e451a623Sjsing 		.opt.argvfunc = req_opt_digest,
526e451a623Sjsing 	},
527e451a623Sjsing 	{ NULL },
528e451a623Sjsing };
529e451a623Sjsing 
530e451a623Sjsing static void
req_usage(void)531e451a623Sjsing req_usage(void)
532e451a623Sjsing {
533e451a623Sjsing 	fprintf(stderr,
5346869ac5cStb 	    "usage: req [-addext ext] [-batch] [-config file]\n"
535e451a623Sjsing 	    "    [-days n] [-extensions section] [-in file]\n"
536e451a623Sjsing 	    "    [-inform der | pem] [-key keyfile] [-keyform der | pem]\n"
537e451a623Sjsing 	    "    [-keyout file] [-md4 | -md5 | -sha1] [-modulus]\n"
538e451a623Sjsing 	    "    [-multivalue-rdn] [-nameopt option] [-new] [-newhdr]\n"
5396869ac5cStb 	    "    [-newkey arg] [-nodes] [-noout]\n"
540e451a623Sjsing 	    "    [-out file] [-outform der | pem] [-passin arg]\n"
541e451a623Sjsing 	    "    [-passout arg] [-pkeyopt opt:value] [-pubkey]\n"
542e451a623Sjsing 	    "    [-reqexts section] [-reqopt option] [-set_serial n]\n"
543e451a623Sjsing 	    "    [-sigopt nm:v] [-subj arg] [-subject] [-text] [-utf8]\n"
544e451a623Sjsing 	    "    [-verbose] [-verify] [-x509]\n\n");
545e451a623Sjsing 
546e451a623Sjsing 	options_usage(req_options);
547e451a623Sjsing 	fprintf(stderr, "\n");
548e451a623Sjsing }
549dab3f910Sjsing 
550dab3f910Sjsing int
req_main(int argc,char ** argv)551dab3f910Sjsing req_main(int argc, char **argv)
552dab3f910Sjsing {
553e451a623Sjsing 	int ex = 1;
554dab3f910Sjsing 	X509 *x509ss = NULL;
555dab3f910Sjsing 	X509_REQ *req = NULL;
556dab3f910Sjsing 	EVP_PKEY_CTX *genctx = NULL;
557dab3f910Sjsing 	char *keyalgstr = NULL;
558dab3f910Sjsing 	const EVP_CIPHER *cipher = NULL;
559e451a623Sjsing 	EVP_PKEY *pkey = NULL;
560e451a623Sjsing 	int i = 0, pkey_type = -1;
561e451a623Sjsing 	BIO *in = NULL, *out = NULL;
562dab3f910Sjsing 	char *passin = NULL, *passout = NULL;
563e451a623Sjsing 	const EVP_MD *md_alg = NULL;
564dab3f910Sjsing 	char *p;
565dab3f910Sjsing 
56651811eadSderaadt 	if (pledge("stdio cpath wpath rpath tty", NULL) == -1) {
5679bc487adSdoug 		perror("pledge");
568e370f0eeSdoug 		exit(1);
569e370f0eeSdoug 	}
5709bc487adSdoug 
571e7718adaStb 	memset(&cfg, 0, sizeof(cfg));
572e451a623Sjsing 
573e7718adaStb 	cfg.chtype = MBSTRING_ASC;
574e7718adaStb 	cfg.days = 30;
575e7718adaStb 	cfg.digest = EVP_sha256();
576e7718adaStb 	cfg.newkey = -1;
577e7718adaStb 	cfg.informat = FORMAT_PEM;
578e7718adaStb 	cfg.keyform = FORMAT_PEM;
579e7718adaStb 	cfg.outformat = FORMAT_PEM;
580e451a623Sjsing 
581e451a623Sjsing 	if (options_parse(argc, argv, req_options, NULL, NULL) != 0) {
582e451a623Sjsing 		req_usage();
583e451a623Sjsing 		return (1);
584e451a623Sjsing 	}
585e451a623Sjsing 
586dab3f910Sjsing 	req_conf = NULL;
587f25f6bcdSsthen 	cipher = EVP_aes_256_cbc();
588dab3f910Sjsing 
589e7718adaStb 	if (!app_passwd(bio_err, cfg.passargin, cfg.passargout, &passin, &passout)) {
590dab3f910Sjsing 		BIO_printf(bio_err, "Error getting passwords\n");
591dab3f910Sjsing 		goto end;
592dab3f910Sjsing 	}
593e7718adaStb 	if (cfg.template != NULL) {
594dab3f910Sjsing 		long errline = -1;
595dab3f910Sjsing 
596e7718adaStb 		if (cfg.verbose)
597e7718adaStb 			BIO_printf(bio_err, "Using configuration from %s\n", cfg.template);
598efc1006dSinoguchi 		if ((req_conf = NCONF_new(NULL)) == NULL)
599efc1006dSinoguchi 			goto end;
600e7718adaStb 		if(!NCONF_load(req_conf, cfg.template, &errline)) {
601e7718adaStb 			BIO_printf(bio_err, "error on line %ld of %s\n", errline, cfg.template);
602dab3f910Sjsing 			goto end;
603dab3f910Sjsing 		}
604dab3f910Sjsing 	} else {
605dab3f910Sjsing 		req_conf = config;
606dab3f910Sjsing 
607dab3f910Sjsing 		if (req_conf == NULL) {
608dab3f910Sjsing 			BIO_printf(bio_err, "Unable to load config info from %s\n", default_config_file);
609e7718adaStb 			if (cfg.newreq)
610dab3f910Sjsing 				goto end;
611e7718adaStb 		} else if (cfg.verbose)
612dab3f910Sjsing 			BIO_printf(bio_err, "Using configuration from %s\n",
613dab3f910Sjsing 			    default_config_file);
614dab3f910Sjsing 	}
615dab3f910Sjsing 
616e7718adaStb 	if (cfg.addext_bio != NULL) {
617a72a31a2Sinoguchi 		long errline = -1;
618e7718adaStb 		if (cfg.verbose)
619a72a31a2Sinoguchi 			BIO_printf(bio_err,
620a72a31a2Sinoguchi 			    "Using additional configuration from command line\n");
621efc1006dSinoguchi 		if ((addext_conf = NCONF_new(NULL)) == NULL)
622efc1006dSinoguchi 			goto end;
623e7718adaStb 		if (!NCONF_load_bio(addext_conf, cfg.addext_bio, &errline)) {
624a72a31a2Sinoguchi 			BIO_printf(bio_err,
625a72a31a2Sinoguchi 			    "req: Error on line %ld of config input\n",
626a72a31a2Sinoguchi 			    errline);
627a72a31a2Sinoguchi 			goto end;
628a72a31a2Sinoguchi 		}
629a72a31a2Sinoguchi 	}
630a72a31a2Sinoguchi 
631dab3f910Sjsing 	if (req_conf != NULL) {
632dab3f910Sjsing 		if (!load_config(bio_err, req_conf))
633dab3f910Sjsing 			goto end;
634dab3f910Sjsing 		p = NCONF_get_string(req_conf, NULL, "oid_file");
635dab3f910Sjsing 		if (p == NULL)
636dab3f910Sjsing 			ERR_clear_error();
637dab3f910Sjsing 		if (p != NULL) {
638dab3f910Sjsing 			BIO *oid_bio;
639dab3f910Sjsing 
640dab3f910Sjsing 			oid_bio = BIO_new_file(p, "r");
641dab3f910Sjsing 			if (oid_bio == NULL) {
642dab3f910Sjsing 				/*
643dab3f910Sjsing 				BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
644dab3f910Sjsing 				ERR_print_errors(bio_err);
645dab3f910Sjsing 				*/
646dab3f910Sjsing 			} else {
647dab3f910Sjsing 				OBJ_create_objects(oid_bio);
648dab3f910Sjsing 				BIO_free(oid_bio);
649dab3f910Sjsing 			}
650dab3f910Sjsing 		}
651dab3f910Sjsing 	}
652dab3f910Sjsing 	if (!add_oid_section(bio_err, req_conf))
653dab3f910Sjsing 		goto end;
654dab3f910Sjsing 
655dab3f910Sjsing 	if (md_alg == NULL) {
656dab3f910Sjsing 		p = NCONF_get_string(req_conf, SECTION, "default_md");
657dab3f910Sjsing 		if (p == NULL)
658dab3f910Sjsing 			ERR_clear_error();
659dab3f910Sjsing 		if (p != NULL) {
660dab3f910Sjsing 			if ((md_alg = EVP_get_digestbyname(p)) != NULL)
661e7718adaStb 				cfg.digest = md_alg;
662dab3f910Sjsing 		}
663dab3f910Sjsing 	}
664e7718adaStb 	if (!cfg.extensions) {
665e7718adaStb 		cfg.extensions = NCONF_get_string(req_conf, SECTION, V3_EXTENSIONS);
666e7718adaStb 		if (!cfg.extensions)
667dab3f910Sjsing 			ERR_clear_error();
668dab3f910Sjsing 	}
669e7718adaStb 	if (cfg.extensions) {
670dab3f910Sjsing 		/* Check syntax of file */
671dab3f910Sjsing 		X509V3_CTX ctx;
672dab3f910Sjsing 		X509V3_set_ctx_test(&ctx);
673dab3f910Sjsing 		X509V3_set_nconf(&ctx, req_conf);
674e7718adaStb 		if (!X509V3_EXT_add_nconf(req_conf, &ctx, cfg.extensions, NULL)) {
675dab3f910Sjsing 			BIO_printf(bio_err,
676e7718adaStb 			    "Error Loading extension section %s\n", cfg.extensions);
677dab3f910Sjsing 			goto end;
678dab3f910Sjsing 		}
679dab3f910Sjsing 	}
680a72a31a2Sinoguchi 	if (addext_conf != NULL) {
681a72a31a2Sinoguchi 		/* Check syntax of command line extensions */
682a72a31a2Sinoguchi 		X509V3_CTX ctx;
683a72a31a2Sinoguchi 		X509V3_set_ctx_test(&ctx);
684a72a31a2Sinoguchi 		X509V3_set_nconf(&ctx, addext_conf);
685a72a31a2Sinoguchi 		if (!X509V3_EXT_add_nconf(addext_conf, &ctx, "default", NULL)) {
686a72a31a2Sinoguchi 			BIO_printf(bio_err,
687a72a31a2Sinoguchi 			    "Error Loading command line extensions\n");
688a72a31a2Sinoguchi 			goto end;
689a72a31a2Sinoguchi 		}
690a72a31a2Sinoguchi 	}
691dab3f910Sjsing 	if (!passin) {
692dab3f910Sjsing 		passin = NCONF_get_string(req_conf, SECTION, "input_password");
693dab3f910Sjsing 		if (!passin)
694dab3f910Sjsing 			ERR_clear_error();
695dab3f910Sjsing 	}
696dab3f910Sjsing 	if (!passout) {
697dab3f910Sjsing 		passout = NCONF_get_string(req_conf, SECTION, "output_password");
698dab3f910Sjsing 		if (!passout)
699dab3f910Sjsing 			ERR_clear_error();
700dab3f910Sjsing 	}
701dab3f910Sjsing 	p = NCONF_get_string(req_conf, SECTION, STRING_MASK);
702dab3f910Sjsing 	if (!p)
703dab3f910Sjsing 		ERR_clear_error();
704dab3f910Sjsing 
705dab3f910Sjsing 	if (p && !ASN1_STRING_set_default_mask_asc(p)) {
706dab3f910Sjsing 		BIO_printf(bio_err, "Invalid global string mask setting %s\n", p);
707dab3f910Sjsing 		goto end;
708dab3f910Sjsing 	}
709e7718adaStb 	if (cfg.chtype != MBSTRING_UTF8) {
710dab3f910Sjsing 		p = NCONF_get_string(req_conf, SECTION, UTF8_IN);
711dab3f910Sjsing 		if (!p)
712dab3f910Sjsing 			ERR_clear_error();
713dab3f910Sjsing 		else if (!strcmp(p, "yes"))
714e7718adaStb 			cfg.chtype = MBSTRING_UTF8;
715dab3f910Sjsing 	}
716e7718adaStb 	if (!cfg.req_exts) {
717e7718adaStb 		cfg.req_exts = NCONF_get_string(req_conf, SECTION, REQ_EXTENSIONS);
718e7718adaStb 		if (!cfg.req_exts)
719dab3f910Sjsing 			ERR_clear_error();
720dab3f910Sjsing 	}
721e7718adaStb 	if (cfg.req_exts) {
722dab3f910Sjsing 		/* Check syntax of file */
723dab3f910Sjsing 		X509V3_CTX ctx;
724dab3f910Sjsing 		X509V3_set_ctx_test(&ctx);
725dab3f910Sjsing 		X509V3_set_nconf(&ctx, req_conf);
726e7718adaStb 		if (!X509V3_EXT_add_nconf(req_conf, &ctx, cfg.req_exts, NULL)) {
727dab3f910Sjsing 			BIO_printf(bio_err,
728dab3f910Sjsing 			    "Error Loading request extension section %s\n",
729e7718adaStb 			    cfg.req_exts);
730dab3f910Sjsing 			goto end;
731dab3f910Sjsing 		}
732dab3f910Sjsing 	}
733dab3f910Sjsing 	in = BIO_new(BIO_s_file());
734dab3f910Sjsing 	out = BIO_new(BIO_s_file());
735dab3f910Sjsing 	if ((in == NULL) || (out == NULL))
736dab3f910Sjsing 		goto end;
737dab3f910Sjsing 
738e7718adaStb 	if (cfg.keyfile != NULL) {
739e7718adaStb 		pkey = load_key(bio_err, cfg.keyfile, cfg.keyform, 0, passin,
740dab3f910Sjsing 		    "Private Key");
741dab3f910Sjsing 		if (!pkey) {
742dab3f910Sjsing 			/*
743dab3f910Sjsing 			 * load_key() has already printed an appropriate
744dab3f910Sjsing 			 * message
745dab3f910Sjsing 			 */
746dab3f910Sjsing 			goto end;
747dab3f910Sjsing 		}
748dab3f910Sjsing 	}
749e7718adaStb 	if (cfg.newreq && (pkey == NULL)) {
750e7718adaStb 		if (!NCONF_get_number(req_conf, SECTION, BITS, &cfg.newkey)) {
751e7718adaStb 			cfg.newkey = DEFAULT_KEY_LENGTH;
752dab3f910Sjsing 		}
753e7718adaStb 		if (cfg.keyalg) {
754e7718adaStb 			genctx = set_keygen_ctx(bio_err, cfg.keyalg, &pkey_type, &cfg.newkey,
7555284dfeaSbcook 			    &keyalgstr);
756dab3f910Sjsing 			if (!genctx)
757dab3f910Sjsing 				goto end;
758dab3f910Sjsing 		}
759e7718adaStb 		if (cfg.newkey < MIN_KEY_LENGTH && (pkey_type == EVP_PKEY_RSA || pkey_type == EVP_PKEY_DSA)) {
760dab3f910Sjsing 			BIO_printf(bio_err, "private key length is too short,\n");
761e7718adaStb 			BIO_printf(bio_err, "it needs to be at least %d bits, not %ld\n", MIN_KEY_LENGTH, cfg.newkey);
762dab3f910Sjsing 			goto end;
763dab3f910Sjsing 		}
764dab3f910Sjsing 		if (!genctx) {
765e7718adaStb 			genctx = set_keygen_ctx(bio_err, NULL, &pkey_type, &cfg.newkey,
7665284dfeaSbcook 			    &keyalgstr);
767dab3f910Sjsing 			if (!genctx)
768dab3f910Sjsing 				goto end;
769dab3f910Sjsing 		}
770e7718adaStb 		if (cfg.pkeyopts) {
771dab3f910Sjsing 			char *genopt;
772e7718adaStb 			for (i = 0; i < sk_OPENSSL_STRING_num(cfg.pkeyopts); i++) {
773e7718adaStb 				genopt = sk_OPENSSL_STRING_value(cfg.pkeyopts, i);
774dab3f910Sjsing 				if (pkey_ctrl_string(genctx, genopt) <= 0) {
775dab3f910Sjsing 					BIO_printf(bio_err,
776dab3f910Sjsing 					    "parameter error \"%s\"\n",
777dab3f910Sjsing 					    genopt);
778dab3f910Sjsing 					ERR_print_errors(bio_err);
779dab3f910Sjsing 					goto end;
780dab3f910Sjsing 				}
781dab3f910Sjsing 			}
782dab3f910Sjsing 		}
783dab3f910Sjsing 		BIO_printf(bio_err, "Generating a %ld bit %s private key\n",
784e7718adaStb 		    cfg.newkey, keyalgstr);
785dab3f910Sjsing 
786dab3f910Sjsing 		EVP_PKEY_CTX_set_cb(genctx, genpkey_cb);
787dab3f910Sjsing 		EVP_PKEY_CTX_set_app_data(genctx, bio_err);
788dab3f910Sjsing 
789dab3f910Sjsing 		if (EVP_PKEY_keygen(genctx, &pkey) <= 0) {
790dab3f910Sjsing 			BIO_puts(bio_err, "Error Generating Key\n");
791dab3f910Sjsing 			goto end;
792dab3f910Sjsing 		}
793dab3f910Sjsing 		EVP_PKEY_CTX_free(genctx);
794dab3f910Sjsing 		genctx = NULL;
795dab3f910Sjsing 
796e7718adaStb 		if (cfg.keyout == NULL) {
797e7718adaStb 			cfg.keyout = NCONF_get_string(req_conf, SECTION, KEYFILE);
798e7718adaStb 			if (cfg.keyout == NULL)
799dab3f910Sjsing 				ERR_clear_error();
800dab3f910Sjsing 		}
801e7718adaStb 		if (cfg.keyout == NULL) {
802dab3f910Sjsing 			BIO_printf(bio_err, "writing new private key to stdout\n");
803dab3f910Sjsing 			BIO_set_fp(out, stdout, BIO_NOCLOSE);
804dab3f910Sjsing 		} else {
805e7718adaStb 			BIO_printf(bio_err, "writing new private key to '%s'\n", cfg.keyout);
806e7718adaStb 			if (BIO_write_filename(out, cfg.keyout) <= 0) {
807e7718adaStb 				perror(cfg.keyout);
808dab3f910Sjsing 				goto end;
809dab3f910Sjsing 			}
810dab3f910Sjsing 		}
811dab3f910Sjsing 
812dab3f910Sjsing 		p = NCONF_get_string(req_conf, SECTION, "encrypt_rsa_key");
813dab3f910Sjsing 		if (p == NULL) {
814dab3f910Sjsing 			ERR_clear_error();
815dab3f910Sjsing 			p = NCONF_get_string(req_conf, SECTION, "encrypt_key");
816dab3f910Sjsing 			if (p == NULL)
817dab3f910Sjsing 				ERR_clear_error();
818dab3f910Sjsing 		}
819dab3f910Sjsing 		if ((p != NULL) && (strcmp(p, "no") == 0))
820dab3f910Sjsing 			cipher = NULL;
821e7718adaStb 		if (cfg.nodes)
822dab3f910Sjsing 			cipher = NULL;
823dab3f910Sjsing 
824dab3f910Sjsing 		i = 0;
825dab3f910Sjsing  loop:
826dab3f910Sjsing 		if (!PEM_write_bio_PrivateKey(out, pkey, cipher,
827dab3f910Sjsing 			NULL, 0, NULL, passout)) {
828dab3f910Sjsing 			if ((ERR_GET_REASON(ERR_peek_error()) ==
829dab3f910Sjsing 				PEM_R_PROBLEMS_GETTING_PASSWORD) && (i < 3)) {
830dab3f910Sjsing 				ERR_clear_error();
831dab3f910Sjsing 				i++;
832dab3f910Sjsing 				goto loop;
833dab3f910Sjsing 			}
834dab3f910Sjsing 			goto end;
835dab3f910Sjsing 		}
836dab3f910Sjsing 		BIO_printf(bio_err, "-----\n");
837dab3f910Sjsing 	}
838e7718adaStb 	if (!cfg.newreq) {
839e7718adaStb 		if (cfg.infile == NULL)
840dab3f910Sjsing 			BIO_set_fp(in, stdin, BIO_NOCLOSE);
841dab3f910Sjsing 		else {
842e7718adaStb 			if (BIO_read_filename(in, cfg.infile) <= 0) {
843e7718adaStb 				perror(cfg.infile);
844dab3f910Sjsing 				goto end;
845dab3f910Sjsing 			}
846dab3f910Sjsing 		}
847dab3f910Sjsing 
848e7718adaStb 		if (cfg.informat == FORMAT_ASN1)
849dab3f910Sjsing 			req = d2i_X509_REQ_bio(in, NULL);
850e7718adaStb 		else if (cfg.informat == FORMAT_PEM)
851dab3f910Sjsing 			req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
852dab3f910Sjsing 		else {
853dab3f910Sjsing 			BIO_printf(bio_err, "bad input format specified for X509 request\n");
854dab3f910Sjsing 			goto end;
855dab3f910Sjsing 		}
856dab3f910Sjsing 		if (req == NULL) {
857dab3f910Sjsing 			BIO_printf(bio_err, "unable to load X509 request\n");
858dab3f910Sjsing 			goto end;
859dab3f910Sjsing 		}
860dab3f910Sjsing 	}
861e7718adaStb 	if (cfg.newreq || cfg.x509) {
862dab3f910Sjsing 		if (pkey == NULL) {
863dab3f910Sjsing 			BIO_printf(bio_err, "you need to specify a private key\n");
864dab3f910Sjsing 			goto end;
865dab3f910Sjsing 		}
866dab3f910Sjsing 		if (req == NULL) {
867dab3f910Sjsing 			req = X509_REQ_new();
868dab3f910Sjsing 			if (req == NULL) {
869dab3f910Sjsing 				goto end;
870dab3f910Sjsing 			}
871e7718adaStb 			i = make_REQ(req, pkey, cfg.subj, cfg.multirdn, !cfg.x509, cfg.chtype);
872e7718adaStb 			cfg.subj = NULL;	/* done processing '-subj' option */
873dab3f910Sjsing 			if (!i) {
874dab3f910Sjsing 				BIO_printf(bio_err, "problems making Certificate Request\n");
875dab3f910Sjsing 				goto end;
876dab3f910Sjsing 			}
877dab3f910Sjsing 		}
878e7718adaStb 		if (cfg.x509) {
879dab3f910Sjsing 			EVP_PKEY *tmppkey;
88084dd6e9aStb 
881dab3f910Sjsing 			X509V3_CTX ext_ctx;
882dab3f910Sjsing 			if ((x509ss = X509_new()) == NULL)
883dab3f910Sjsing 				goto end;
884dab3f910Sjsing 
885dab3f910Sjsing 			/* Set version to V3 */
886e7718adaStb 			if ((cfg.extensions != NULL || addext_conf != NULL) &&
887a72a31a2Sinoguchi 			    !X509_set_version(x509ss, 2))
888dab3f910Sjsing 				goto end;
889e7718adaStb 			if (cfg.serial) {
890e7718adaStb 				if (!X509_set_serialNumber(x509ss, cfg.serial))
891dab3f910Sjsing 					goto end;
892dab3f910Sjsing 			} else {
893dab3f910Sjsing 				if (!rand_serial(NULL,
894dab3f910Sjsing 					X509_get_serialNumber(x509ss)))
895dab3f910Sjsing 					goto end;
896dab3f910Sjsing 			}
897dab3f910Sjsing 
898dab3f910Sjsing 			if (!X509_set_issuer_name(x509ss, X509_REQ_get_subject_name(req)))
899dab3f910Sjsing 				goto end;
900dab3f910Sjsing 			if (!X509_gmtime_adj(X509_get_notBefore(x509ss), 0))
901dab3f910Sjsing 				goto end;
902e7718adaStb 			if (!X509_time_adj_ex(X509_get_notAfter(x509ss), cfg.days, 0, NULL))
903dab3f910Sjsing 				goto end;
904dab3f910Sjsing 			if (!X509_set_subject_name(x509ss, X509_REQ_get_subject_name(req)))
905dab3f910Sjsing 				goto end;
90684dd6e9aStb 			if ((tmppkey = X509_REQ_get0_pubkey(req)) == NULL)
907dab3f910Sjsing 				goto end;
90884dd6e9aStb 			if (!X509_set_pubkey(x509ss, tmppkey))
90984dd6e9aStb 				goto end;
910dab3f910Sjsing 
911dab3f910Sjsing 			/* Set up V3 context struct */
912dab3f910Sjsing 
913dab3f910Sjsing 			X509V3_set_ctx(&ext_ctx, x509ss, x509ss, NULL, NULL, 0);
914dab3f910Sjsing 			X509V3_set_nconf(&ext_ctx, req_conf);
915dab3f910Sjsing 
916dab3f910Sjsing 			/* Add extensions */
917e7718adaStb 			if (cfg.extensions && !X509V3_EXT_add_nconf(req_conf,
918e7718adaStb 				&ext_ctx, cfg.extensions, x509ss)) {
919dab3f910Sjsing 				BIO_printf(bio_err,
920dab3f910Sjsing 				    "Error Loading extension section %s\n",
921e7718adaStb 				    cfg.extensions);
922dab3f910Sjsing 				goto end;
923dab3f910Sjsing 			}
924a72a31a2Sinoguchi 			if (addext_conf != NULL &&
925a72a31a2Sinoguchi 			    !X509V3_EXT_add_nconf(addext_conf, &ext_ctx,
926a72a31a2Sinoguchi 				    "default", x509ss)) {
927a72a31a2Sinoguchi 				BIO_printf(bio_err,
928a72a31a2Sinoguchi 				    "Error Loading command line extensions\n");
929a72a31a2Sinoguchi 				goto end;
930a72a31a2Sinoguchi 			}
931e7718adaStb 			i = do_X509_sign(bio_err, x509ss, pkey, cfg.digest, cfg.sigopts);
932dab3f910Sjsing 			if (!i) {
933dab3f910Sjsing 				ERR_print_errors(bio_err);
934dab3f910Sjsing 				goto end;
935dab3f910Sjsing 			}
936dab3f910Sjsing 		} else {
937dab3f910Sjsing 			X509V3_CTX ext_ctx;
938dab3f910Sjsing 
939dab3f910Sjsing 			/* Set up V3 context struct */
940dab3f910Sjsing 
941dab3f910Sjsing 			X509V3_set_ctx(&ext_ctx, NULL, NULL, req, NULL, 0);
942dab3f910Sjsing 			X509V3_set_nconf(&ext_ctx, req_conf);
943dab3f910Sjsing 
944dab3f910Sjsing 			/* Add extensions */
945e7718adaStb 			if (cfg.req_exts && !X509V3_EXT_REQ_add_nconf(req_conf,
946e7718adaStb 				&ext_ctx, cfg.req_exts, req)) {
947dab3f910Sjsing 				BIO_printf(bio_err,
948dab3f910Sjsing 				    "Error Loading extension section %s\n",
949e7718adaStb 				    cfg.req_exts);
950dab3f910Sjsing 				goto end;
951dab3f910Sjsing 			}
952a72a31a2Sinoguchi 			if (addext_conf != NULL &&
953a72a31a2Sinoguchi 			    !X509V3_EXT_REQ_add_nconf(addext_conf, &ext_ctx,
954a72a31a2Sinoguchi 				    "default", req)) {
955a72a31a2Sinoguchi 				BIO_printf(bio_err,
956a72a31a2Sinoguchi 				    "Error Loading command line extensions\n");
957a72a31a2Sinoguchi 				goto end;
958a72a31a2Sinoguchi 			}
959e7718adaStb 			i = do_X509_REQ_sign(bio_err, req, pkey, cfg.digest, cfg.sigopts);
960dab3f910Sjsing 			if (!i) {
961dab3f910Sjsing 				ERR_print_errors(bio_err);
962dab3f910Sjsing 				goto end;
963dab3f910Sjsing 			}
964dab3f910Sjsing 		}
965dab3f910Sjsing 	}
966e7718adaStb 	if (cfg.subj && cfg.x509) {
967e451a623Sjsing 		BIO_printf(bio_err, "Cannot modify certificate subject\n");
968dab3f910Sjsing 		goto end;
969dab3f910Sjsing 	}
970e7718adaStb 	if (cfg.subj && !cfg.x509) {
971e7718adaStb 		if (cfg.verbose) {
972dab3f910Sjsing 			BIO_printf(bio_err, "Modifying Request's Subject\n");
973e7718adaStb 			print_name(bio_err, "old subject=", X509_REQ_get_subject_name(req), cfg.nmflag);
974dab3f910Sjsing 		}
975e7718adaStb 		if (build_subject(req, cfg.subj, cfg.chtype, cfg.multirdn) == 0) {
976dab3f910Sjsing 			BIO_printf(bio_err, "ERROR: cannot modify subject\n");
977dab3f910Sjsing 			ex = 1;
978dab3f910Sjsing 			goto end;
979dab3f910Sjsing 		}
980dab3f910Sjsing 
981e7718adaStb 		if (cfg.verbose) {
982e7718adaStb 			print_name(bio_err, "new subject=", X509_REQ_get_subject_name(req), cfg.nmflag);
983dab3f910Sjsing 		}
984dab3f910Sjsing 	}
985e7718adaStb 	if (cfg.verify && !cfg.x509) {
98684dd6e9aStb 		EVP_PKEY *pubkey = pkey;
987dab3f910Sjsing 
98884dd6e9aStb 		if (pubkey == NULL)
98984dd6e9aStb 			pubkey = X509_REQ_get0_pubkey(req);
99084dd6e9aStb 		if (pubkey == NULL)
991dab3f910Sjsing 			goto end;
99284dd6e9aStb 		i = X509_REQ_verify(req, pubkey);
993dab3f910Sjsing 		if (i < 0) {
994dab3f910Sjsing 			goto end;
995dab3f910Sjsing 		} else if (i == 0) {
996dab3f910Sjsing 			BIO_printf(bio_err, "verify failure\n");
997dab3f910Sjsing 			ERR_print_errors(bio_err);
998dab3f910Sjsing 		} else		/* if (i > 0) */
999dab3f910Sjsing 			BIO_printf(bio_err, "verify OK\n");
1000dab3f910Sjsing 	}
1001e7718adaStb 	if (cfg.noout && !cfg.text && !cfg.modulus && !cfg.subject && !cfg.pubkey) {
1002dab3f910Sjsing 		ex = 0;
1003dab3f910Sjsing 		goto end;
1004dab3f910Sjsing 	}
1005e7718adaStb 	if (cfg.outfile == NULL) {
1006dab3f910Sjsing 		BIO_set_fp(out, stdout, BIO_NOCLOSE);
1007dab3f910Sjsing 	} else {
1008e7718adaStb 		if ((cfg.keyout != NULL) && (strcmp(cfg.outfile, cfg.keyout) == 0))
1009e7718adaStb 			i = (int) BIO_append_filename(out, cfg.outfile);
1010dab3f910Sjsing 		else
1011e7718adaStb 			i = (int) BIO_write_filename(out, cfg.outfile);
1012dab3f910Sjsing 		if (!i) {
1013e7718adaStb 			perror(cfg.outfile);
1014dab3f910Sjsing 			goto end;
1015dab3f910Sjsing 		}
1016dab3f910Sjsing 	}
1017dab3f910Sjsing 
1018e7718adaStb 	if (cfg.pubkey) {
1019dab3f910Sjsing 		EVP_PKEY *tpubkey;
102084dd6e9aStb 
102184dd6e9aStb 		if ((tpubkey = X509_REQ_get0_pubkey(req)) == NULL) {
1022dab3f910Sjsing 			BIO_printf(bio_err, "Error getting public key\n");
1023dab3f910Sjsing 			ERR_print_errors(bio_err);
1024dab3f910Sjsing 			goto end;
1025dab3f910Sjsing 		}
1026dab3f910Sjsing 		PEM_write_bio_PUBKEY(out, tpubkey);
1027dab3f910Sjsing 	}
1028e7718adaStb 	if (cfg.text) {
1029e7718adaStb 		if (cfg.x509)
1030e7718adaStb 			X509_print_ex(out, x509ss, cfg.nmflag, cfg.reqflag);
1031dab3f910Sjsing 		else
1032e7718adaStb 			X509_REQ_print_ex(out, req, cfg.nmflag, cfg.reqflag);
1033dab3f910Sjsing 	}
1034e7718adaStb 	if (cfg.subject) {
1035e7718adaStb 		if (cfg.x509)
1036e7718adaStb 			print_name(out, "subject=", X509_get_subject_name(x509ss), cfg.nmflag);
1037dab3f910Sjsing 		else
1038e7718adaStb 			print_name(out, "subject=", X509_REQ_get_subject_name(req), cfg.nmflag);
1039dab3f910Sjsing 	}
1040e7718adaStb 	if (cfg.modulus) {
1041dab3f910Sjsing 		EVP_PKEY *tpubkey;
1042dab3f910Sjsing 
1043e7718adaStb 		if (cfg.x509)
1044d13925e1Stb 			tpubkey = X509_get0_pubkey(x509ss);
1045dab3f910Sjsing 		else
1046d13925e1Stb 			tpubkey = X509_REQ_get0_pubkey(req);
1047dab3f910Sjsing 		if (tpubkey == NULL) {
1048dab3f910Sjsing 			fprintf(stdout, "Modulus=unavailable\n");
1049dab3f910Sjsing 			goto end;
1050dab3f910Sjsing 		}
1051dab3f910Sjsing 		fprintf(stdout, "Modulus=");
1052d13925e1Stb 		if (EVP_PKEY_base_id(tpubkey) == EVP_PKEY_RSA) {
1053d13925e1Stb 			const BIGNUM *n = NULL;
1054d13925e1Stb 
1055d13925e1Stb 			RSA_get0_key(EVP_PKEY_get0_RSA(tpubkey), &n, NULL, NULL);
1056d13925e1Stb 
1057d13925e1Stb 			BN_print(out, n);
1058d13925e1Stb 		} else
1059dab3f910Sjsing 			fprintf(stdout, "Wrong Algorithm type");
1060dab3f910Sjsing 		fprintf(stdout, "\n");
1061dab3f910Sjsing 	}
1062e7718adaStb 	if (!cfg.noout && !cfg.x509) {
1063e7718adaStb 		if (cfg.outformat == FORMAT_ASN1)
1064dab3f910Sjsing 			i = i2d_X509_REQ_bio(out, req);
1065e7718adaStb 		else if (cfg.outformat == FORMAT_PEM) {
1066e7718adaStb 			if (cfg.newhdr)
1067dab3f910Sjsing 				i = PEM_write_bio_X509_REQ_NEW(out, req);
1068dab3f910Sjsing 			else
1069dab3f910Sjsing 				i = PEM_write_bio_X509_REQ(out, req);
1070dab3f910Sjsing 		} else {
1071dab3f910Sjsing 			BIO_printf(bio_err, "bad output format specified for outfile\n");
1072dab3f910Sjsing 			goto end;
1073dab3f910Sjsing 		}
1074dab3f910Sjsing 		if (!i) {
1075dab3f910Sjsing 			BIO_printf(bio_err, "unable to write X509 request\n");
1076dab3f910Sjsing 			goto end;
1077dab3f910Sjsing 		}
1078dab3f910Sjsing 	}
1079e7718adaStb 	if (!cfg.noout && cfg.x509 && (x509ss != NULL)) {
1080e7718adaStb 		if (cfg.outformat == FORMAT_ASN1)
1081dab3f910Sjsing 			i = i2d_X509_bio(out, x509ss);
1082e7718adaStb 		else if (cfg.outformat == FORMAT_PEM)
1083dab3f910Sjsing 			i = PEM_write_bio_X509(out, x509ss);
1084dab3f910Sjsing 		else {
1085dab3f910Sjsing 			BIO_printf(bio_err, "bad output format specified for outfile\n");
1086dab3f910Sjsing 			goto end;
1087dab3f910Sjsing 		}
1088dab3f910Sjsing 		if (!i) {
1089dab3f910Sjsing 			BIO_printf(bio_err, "unable to write X509 certificate\n");
1090dab3f910Sjsing 			goto end;
1091dab3f910Sjsing 		}
1092dab3f910Sjsing 	}
1093dab3f910Sjsing 	ex = 0;
1094dab3f910Sjsing  end:
1095dab3f910Sjsing 	if (ex) {
1096dab3f910Sjsing 		ERR_print_errors(bio_err);
1097dab3f910Sjsing 	}
1098dab3f910Sjsing 	if ((req_conf != NULL) && (req_conf != config))
1099dab3f910Sjsing 		NCONF_free(req_conf);
1100a72a31a2Sinoguchi 	NCONF_free(addext_conf);
1101e7718adaStb 	BIO_free(cfg.addext_bio);
1102dab3f910Sjsing 	BIO_free(in);
1103dab3f910Sjsing 	BIO_free_all(out);
1104dab3f910Sjsing 	EVP_PKEY_free(pkey);
1105dab3f910Sjsing 	if (genctx)
1106dab3f910Sjsing 		EVP_PKEY_CTX_free(genctx);
1107e7718adaStb 	if (cfg.pkeyopts)
1108e7718adaStb 		sk_OPENSSL_STRING_free(cfg.pkeyopts);
1109e7718adaStb 	if (cfg.sigopts)
1110e7718adaStb 		sk_OPENSSL_STRING_free(cfg.sigopts);
1111e7718adaStb 	lh_OPENSSL_STRING_doall(cfg.addexts, (LHASH_DOALL_FN_TYPE)exts_cleanup);
1112e7718adaStb 	lh_OPENSSL_STRING_free(cfg.addexts);
1113dab3f910Sjsing 	free(keyalgstr);
1114dab3f910Sjsing 	X509_REQ_free(req);
1115dab3f910Sjsing 	X509_free(x509ss);
1116e7718adaStb 	ASN1_INTEGER_free(cfg.serial);
1117e7718adaStb 	if (cfg.passargin && passin)
1118dab3f910Sjsing 		free(passin);
1119e7718adaStb 	if (cfg.passargout && passout)
1120dab3f910Sjsing 		free(passout);
1121dab3f910Sjsing 	OBJ_cleanup();
1122dab3f910Sjsing 
1123dab3f910Sjsing 	return (ex);
1124dab3f910Sjsing }
1125dab3f910Sjsing 
1126dab3f910Sjsing static int
make_REQ(X509_REQ * req,EVP_PKEY * pkey,char * subj,int multirdn,int attribs,unsigned long chtype)1127dab3f910Sjsing make_REQ(X509_REQ * req, EVP_PKEY * pkey, char *subj, int multirdn,
1128dab3f910Sjsing     int attribs, unsigned long chtype)
1129dab3f910Sjsing {
1130dab3f910Sjsing 	int ret = 0, i;
1131dab3f910Sjsing 	char no_prompt = 0;
1132dab3f910Sjsing 	STACK_OF(CONF_VALUE) * dn_sk, *attr_sk = NULL;
1133dab3f910Sjsing 	char *tmp, *dn_sect, *attr_sect;
1134dab3f910Sjsing 
1135dab3f910Sjsing 	tmp = NCONF_get_string(req_conf, SECTION, PROMPT);
1136dab3f910Sjsing 	if (tmp == NULL)
1137dab3f910Sjsing 		ERR_clear_error();
1138dab3f910Sjsing 	if ((tmp != NULL) && !strcmp(tmp, "no"))
1139dab3f910Sjsing 		no_prompt = 1;
1140dab3f910Sjsing 
1141dab3f910Sjsing 	dn_sect = NCONF_get_string(req_conf, SECTION, DISTINGUISHED_NAME);
1142dab3f910Sjsing 	if (dn_sect == NULL) {
1143dab3f910Sjsing 		BIO_printf(bio_err, "unable to find '%s' in config\n",
1144dab3f910Sjsing 		    DISTINGUISHED_NAME);
1145dab3f910Sjsing 		goto err;
1146dab3f910Sjsing 	}
1147dab3f910Sjsing 	dn_sk = NCONF_get_section(req_conf, dn_sect);
1148dab3f910Sjsing 	if (dn_sk == NULL) {
1149dab3f910Sjsing 		BIO_printf(bio_err, "unable to get '%s' section\n", dn_sect);
1150dab3f910Sjsing 		goto err;
1151dab3f910Sjsing 	}
1152dab3f910Sjsing 	attr_sect = NCONF_get_string(req_conf, SECTION, ATTRIBUTES);
1153dab3f910Sjsing 	if (attr_sect == NULL) {
1154dab3f910Sjsing 		ERR_clear_error();
1155dab3f910Sjsing 		attr_sk = NULL;
1156dab3f910Sjsing 	} else {
1157dab3f910Sjsing 		attr_sk = NCONF_get_section(req_conf, attr_sect);
1158dab3f910Sjsing 		if (attr_sk == NULL) {
1159dab3f910Sjsing 			BIO_printf(bio_err, "unable to get '%s' section\n", attr_sect);
1160dab3f910Sjsing 			goto err;
1161dab3f910Sjsing 		}
1162dab3f910Sjsing 	}
1163dab3f910Sjsing 
1164dab3f910Sjsing 	/* setup version number */
1165dab3f910Sjsing 	if (!X509_REQ_set_version(req, 0L))
1166dab3f910Sjsing 		goto err;	/* version 1 */
1167dab3f910Sjsing 
1168dab3f910Sjsing 	if (no_prompt)
1169dab3f910Sjsing 		i = auto_info(req, dn_sk, attr_sk, attribs, chtype);
1170dab3f910Sjsing 	else {
1171dab3f910Sjsing 		if (subj)
1172dab3f910Sjsing 			i = build_subject(req, subj, chtype, multirdn);
1173dab3f910Sjsing 		else
1174dab3f910Sjsing 			i = prompt_info(req, dn_sk, dn_sect, attr_sk, attr_sect, attribs, chtype);
1175dab3f910Sjsing 	}
1176dab3f910Sjsing 	if (!i)
1177dab3f910Sjsing 		goto err;
1178dab3f910Sjsing 
1179dab3f910Sjsing 	if (!X509_REQ_set_pubkey(req, pkey))
1180dab3f910Sjsing 		goto err;
1181dab3f910Sjsing 
1182dab3f910Sjsing 	ret = 1;
1183dab3f910Sjsing  err:
1184dab3f910Sjsing 	return (ret);
1185dab3f910Sjsing }
1186dab3f910Sjsing 
1187dab3f910Sjsing /*
1188dab3f910Sjsing  * subject is expected to be in the format /type0=value0/type1=value1/type2=...
1189dab3f910Sjsing  * where characters may be escaped by \
1190dab3f910Sjsing  */
1191dab3f910Sjsing static int
build_subject(X509_REQ * req,char * subject,unsigned long chtype,int multirdn)1192dab3f910Sjsing build_subject(X509_REQ * req, char *subject, unsigned long chtype, int multirdn)
1193dab3f910Sjsing {
1194dab3f910Sjsing 	X509_NAME *n;
1195dab3f910Sjsing 
1196dab3f910Sjsing 	if (!(n = parse_name(subject, chtype, multirdn)))
1197dab3f910Sjsing 		return 0;
1198dab3f910Sjsing 
1199dab3f910Sjsing 	if (!X509_REQ_set_subject_name(req, n)) {
1200dab3f910Sjsing 		X509_NAME_free(n);
1201dab3f910Sjsing 		return 0;
1202dab3f910Sjsing 	}
1203dab3f910Sjsing 	X509_NAME_free(n);
1204dab3f910Sjsing 	return 1;
1205dab3f910Sjsing }
1206dab3f910Sjsing 
1207dab3f910Sjsing 
1208dab3f910Sjsing static int
prompt_info(X509_REQ * req,STACK_OF (CONF_VALUE)* dn_sk,char * dn_sect,STACK_OF (CONF_VALUE)* attr_sk,char * attr_sect,int attribs,unsigned long chtype)1209dab3f910Sjsing prompt_info(X509_REQ * req,
1210dab3f910Sjsing     STACK_OF(CONF_VALUE) * dn_sk, char *dn_sect,
1211dab3f910Sjsing     STACK_OF(CONF_VALUE) * attr_sk, char *attr_sect, int attribs,
1212dab3f910Sjsing     unsigned long chtype)
1213dab3f910Sjsing {
1214dab3f910Sjsing 	int i;
1215dab3f910Sjsing 	char *p, *q;
1216dab3f910Sjsing 	char buf[100];
1217dab3f910Sjsing 	int nid, mval;
1218dab3f910Sjsing 	long n_min, n_max;
1219dab3f910Sjsing 	char *type, *value;
1220dab3f910Sjsing 	const char *def;
1221dab3f910Sjsing 	CONF_VALUE *v;
1222dab3f910Sjsing 	X509_NAME *subj;
1223dab3f910Sjsing 	subj = X509_REQ_get_subject_name(req);
1224dab3f910Sjsing 
1225e7718adaStb 	if (!cfg.batch) {
1226dab3f910Sjsing 		BIO_printf(bio_err, "You are about to be asked to enter information that will be incorporated\n");
1227dab3f910Sjsing 		BIO_printf(bio_err, "into your certificate request.\n");
1228dab3f910Sjsing 		BIO_printf(bio_err, "What you are about to enter is what is called a Distinguished Name or a DN.\n");
1229dab3f910Sjsing 		BIO_printf(bio_err, "There are quite a few fields but you can leave some blank\n");
1230dab3f910Sjsing 		BIO_printf(bio_err, "For some fields there will be a default value,\n");
1231dab3f910Sjsing 		BIO_printf(bio_err, "If you enter '.', the field will be left blank.\n");
1232dab3f910Sjsing 		BIO_printf(bio_err, "-----\n");
1233dab3f910Sjsing 	}
1234dab3f910Sjsing 	if (sk_CONF_VALUE_num(dn_sk)) {
1235dab3f910Sjsing 		i = -1;
1236dab3f910Sjsing  start:		for (;;) {
1237dab3f910Sjsing 			int ret;
1238dab3f910Sjsing 			i++;
1239dab3f910Sjsing 			if (sk_CONF_VALUE_num(dn_sk) <= i)
1240dab3f910Sjsing 				break;
1241dab3f910Sjsing 
1242dab3f910Sjsing 			v = sk_CONF_VALUE_value(dn_sk, i);
1243dab3f910Sjsing 			p = q = NULL;
1244dab3f910Sjsing 			type = v->name;
1245dab3f910Sjsing 			if (!check_end(type, "_min") || !check_end(type, "_max") ||
1246dab3f910Sjsing 			    !check_end(type, "_default") ||
1247dab3f910Sjsing 			    !check_end(type, "_value"))
1248dab3f910Sjsing 				continue;
1249dab3f910Sjsing 			/*
1250dab3f910Sjsing 			 * Skip past any leading X. X: X, etc to allow for
1251dab3f910Sjsing 			 * multiple instances
1252dab3f910Sjsing 			 */
1253dab3f910Sjsing 			for (p = v->name; *p; p++)
1254dab3f910Sjsing 				if ((*p == ':') || (*p == ',') ||
1255dab3f910Sjsing 				    (*p == '.')) {
1256dab3f910Sjsing 					p++;
1257dab3f910Sjsing 					if (*p)
1258dab3f910Sjsing 						type = p;
1259dab3f910Sjsing 					break;
1260dab3f910Sjsing 				}
1261dab3f910Sjsing 			if (*type == '+') {
1262dab3f910Sjsing 				mval = -1;
1263dab3f910Sjsing 				type++;
1264dab3f910Sjsing 			} else
1265dab3f910Sjsing 				mval = 0;
1266dab3f910Sjsing 			/* If OBJ not recognised ignore it */
1267dab3f910Sjsing 			if ((nid = OBJ_txt2nid(type)) == NID_undef)
1268dab3f910Sjsing 				goto start;
1269dab3f910Sjsing 			ret = snprintf(buf, sizeof buf, "%s_default", v->name);
1270515e489cSderaadt 			if (ret < 0 || ret >= sizeof(buf)) {
1271dab3f910Sjsing 				BIO_printf(bio_err, "Name '%s' too long for default\n",
1272dab3f910Sjsing 				    v->name);
1273dab3f910Sjsing 				return 0;
1274dab3f910Sjsing 			}
1275dab3f910Sjsing 			if ((def = NCONF_get_string(req_conf, dn_sect, buf)) == NULL) {
1276dab3f910Sjsing 				ERR_clear_error();
1277dab3f910Sjsing 				def = "";
1278dab3f910Sjsing 			}
1279dab3f910Sjsing 			ret = snprintf(buf, sizeof buf, "%s_value", v->name);
1280515e489cSderaadt 			if (ret < 0 || ret >= sizeof(buf)) {
1281dab3f910Sjsing 				BIO_printf(bio_err, "Name '%s' too long for value\n",
1282dab3f910Sjsing 				    v->name);
1283dab3f910Sjsing 				return 0;
1284dab3f910Sjsing 			}
1285dab3f910Sjsing 			if ((value = NCONF_get_string(req_conf, dn_sect, buf)) == NULL) {
1286dab3f910Sjsing 				ERR_clear_error();
1287dab3f910Sjsing 				value = NULL;
1288dab3f910Sjsing 			}
1289dab3f910Sjsing 			ret = snprintf(buf, sizeof buf, "%s_min", v->name);
1290515e489cSderaadt 			if (ret < 0 || ret >= sizeof(buf)) {
1291dab3f910Sjsing 				BIO_printf(bio_err, "Name '%s' too long for min\n",
1292dab3f910Sjsing 				    v->name);
1293dab3f910Sjsing 				return 0;
1294dab3f910Sjsing 			}
1295dab3f910Sjsing 			if (!NCONF_get_number(req_conf, dn_sect, buf, &n_min)) {
1296dab3f910Sjsing 				ERR_clear_error();
1297dab3f910Sjsing 				n_min = -1;
1298dab3f910Sjsing 			}
1299dab3f910Sjsing 			ret = snprintf(buf, sizeof buf, "%s_max", v->name);
1300515e489cSderaadt 			if (ret < 0 || ret >= sizeof(buf)) {
1301dab3f910Sjsing 				BIO_printf(bio_err, "Name '%s' too long for max\n",
1302dab3f910Sjsing 				    v->name);
1303dab3f910Sjsing 				return 0;
1304dab3f910Sjsing 			}
1305dab3f910Sjsing 			if (!NCONF_get_number(req_conf, dn_sect, buf, &n_max)) {
1306dab3f910Sjsing 				ERR_clear_error();
1307dab3f910Sjsing 				n_max = -1;
1308dab3f910Sjsing 			}
1309dab3f910Sjsing 			if (!add_DN_object(subj, v->value, def, value, nid,
1310dab3f910Sjsing 				n_min, n_max, chtype, mval))
1311dab3f910Sjsing 				return 0;
1312dab3f910Sjsing 		}
1313dab3f910Sjsing 		if (X509_NAME_entry_count(subj) == 0) {
1314dab3f910Sjsing 			BIO_printf(bio_err, "error, no objects specified in config file\n");
1315dab3f910Sjsing 			return 0;
1316dab3f910Sjsing 		}
1317dab3f910Sjsing 		if (attribs) {
1318dab3f910Sjsing 			if ((attr_sk != NULL) && (sk_CONF_VALUE_num(attr_sk) > 0) &&
1319e7718adaStb 			    (!cfg.batch)) {
1320dab3f910Sjsing 				BIO_printf(bio_err,
1321dab3f910Sjsing 				    "\nPlease enter the following 'extra' attributes\n");
1322dab3f910Sjsing 				BIO_printf(bio_err,
1323dab3f910Sjsing 				    "to be sent with your certificate request\n");
1324dab3f910Sjsing 			}
1325dab3f910Sjsing 			i = -1;
1326dab3f910Sjsing start2:			for (;;) {
1327dab3f910Sjsing 				int ret;
1328dab3f910Sjsing 				i++;
1329dab3f910Sjsing 				if ((attr_sk == NULL) ||
1330dab3f910Sjsing 				    (sk_CONF_VALUE_num(attr_sk) <= i))
1331dab3f910Sjsing 					break;
1332dab3f910Sjsing 
1333dab3f910Sjsing 				v = sk_CONF_VALUE_value(attr_sk, i);
1334dab3f910Sjsing 				type = v->name;
1335dab3f910Sjsing 				if ((nid = OBJ_txt2nid(type)) == NID_undef)
1336dab3f910Sjsing 					goto start2;
1337dab3f910Sjsing 				ret = snprintf(buf, sizeof buf, "%s_default", type);
1338515e489cSderaadt 				if (ret < 0 || ret >= sizeof(buf)) {
1339dab3f910Sjsing 					BIO_printf(bio_err, "Name '%s' too long for default\n",
1340dab3f910Sjsing 					    v->name);
1341dab3f910Sjsing 					return 0;
1342dab3f910Sjsing 				}
1343dab3f910Sjsing 				if ((def = NCONF_get_string(req_conf, attr_sect, buf))
1344dab3f910Sjsing 				    == NULL) {
1345dab3f910Sjsing 					ERR_clear_error();
1346dab3f910Sjsing 					def = "";
1347dab3f910Sjsing 				}
1348dab3f910Sjsing 				ret = snprintf(buf, sizeof buf, "%s_value", type);
1349515e489cSderaadt 				if (ret < 0 || ret >= sizeof(buf)) {
1350dab3f910Sjsing 					BIO_printf(bio_err, "Name '%s' too long for value\n",
1351dab3f910Sjsing 					    v->name);
1352dab3f910Sjsing 					return 0;
1353dab3f910Sjsing 				}
1354dab3f910Sjsing 				if ((value = NCONF_get_string(req_conf, attr_sect, buf))
1355dab3f910Sjsing 				    == NULL) {
1356dab3f910Sjsing 					ERR_clear_error();
1357dab3f910Sjsing 					value = NULL;
1358dab3f910Sjsing 				}
1359dab3f910Sjsing 				ret = snprintf(buf, sizeof buf, "%s_min", type);
1360515e489cSderaadt 				if (ret < 0 || ret >= sizeof(buf)) {
1361dab3f910Sjsing 					BIO_printf(bio_err, "Name '%s' too long for min\n",
1362dab3f910Sjsing 					    v->name);
1363dab3f910Sjsing 					return 0;
1364dab3f910Sjsing 				}
1365dab3f910Sjsing 				if (!NCONF_get_number(req_conf, attr_sect, buf, &n_min)) {
1366dab3f910Sjsing 					ERR_clear_error();
1367dab3f910Sjsing 					n_min = -1;
1368dab3f910Sjsing 				}
1369dab3f910Sjsing 				ret = snprintf(buf, sizeof buf, "%s_max", type);
1370515e489cSderaadt 				if (ret < 0 || ret >= sizeof(buf)) {
1371dab3f910Sjsing 					BIO_printf(bio_err, "Name '%s' too long for max\n",
1372dab3f910Sjsing 					    v->name);
1373dab3f910Sjsing 					return 0;
1374dab3f910Sjsing 				}
1375dab3f910Sjsing 				if (!NCONF_get_number(req_conf, attr_sect, buf, &n_max)) {
1376dab3f910Sjsing 					ERR_clear_error();
1377dab3f910Sjsing 					n_max = -1;
1378dab3f910Sjsing 				}
1379dab3f910Sjsing 				if (!add_attribute_object(req,
1380dab3f910Sjsing 					v->value, def, value, nid, n_min, n_max, chtype))
1381dab3f910Sjsing 					return 0;
1382dab3f910Sjsing 			}
1383dab3f910Sjsing 		}
1384dab3f910Sjsing 	} else {
1385dab3f910Sjsing 		BIO_printf(bio_err, "No template, please set one up.\n");
1386dab3f910Sjsing 		return 0;
1387dab3f910Sjsing 	}
1388dab3f910Sjsing 
1389dab3f910Sjsing 	return 1;
1390dab3f910Sjsing 
1391dab3f910Sjsing }
1392dab3f910Sjsing 
1393dab3f910Sjsing static int
auto_info(X509_REQ * req,STACK_OF (CONF_VALUE)* dn_sk,STACK_OF (CONF_VALUE)* attr_sk,int attribs,unsigned long chtype)1394dab3f910Sjsing auto_info(X509_REQ * req, STACK_OF(CONF_VALUE) * dn_sk,
1395dab3f910Sjsing     STACK_OF(CONF_VALUE) * attr_sk, int attribs, unsigned long chtype)
1396dab3f910Sjsing {
1397dab3f910Sjsing 	int i;
1398dab3f910Sjsing 	char *p, *q;
1399dab3f910Sjsing 	char *type;
1400dab3f910Sjsing 	CONF_VALUE *v;
1401dab3f910Sjsing 	X509_NAME *subj;
1402dab3f910Sjsing 
1403dab3f910Sjsing 	subj = X509_REQ_get_subject_name(req);
1404dab3f910Sjsing 
1405dab3f910Sjsing 	for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) {
1406dab3f910Sjsing 		int mval;
1407dab3f910Sjsing 		v = sk_CONF_VALUE_value(dn_sk, i);
1408dab3f910Sjsing 		p = q = NULL;
1409dab3f910Sjsing 		type = v->name;
1410dab3f910Sjsing 		/*
1411dab3f910Sjsing 		 * Skip past any leading X. X: X, etc to allow for multiple
1412dab3f910Sjsing 		 * instances
1413dab3f910Sjsing 		 */
1414dab3f910Sjsing 		for (p = v->name; *p; p++)
1415dab3f910Sjsing 			if ((*p == ':') || (*p == ',') || (*p == '.')) {
1416dab3f910Sjsing 				p++;
1417dab3f910Sjsing 				if (*p)
1418dab3f910Sjsing 					type = p;
1419dab3f910Sjsing 				break;
1420dab3f910Sjsing 			}
1421dab3f910Sjsing 		if (*p == '+') {
1422dab3f910Sjsing 			p++;
1423dab3f910Sjsing 			mval = -1;
1424dab3f910Sjsing 		} else
1425dab3f910Sjsing 			mval = 0;
1426dab3f910Sjsing 		if (!X509_NAME_add_entry_by_txt(subj, type, chtype,
1427dab3f910Sjsing 			(unsigned char *) v->value, -1, -1, mval))
1428dab3f910Sjsing 			return 0;
1429dab3f910Sjsing 
1430dab3f910Sjsing 	}
1431dab3f910Sjsing 
1432dab3f910Sjsing 	if (!X509_NAME_entry_count(subj)) {
1433dab3f910Sjsing 		BIO_printf(bio_err, "error, no objects specified in config file\n");
1434dab3f910Sjsing 		return 0;
1435dab3f910Sjsing 	}
1436dab3f910Sjsing 	if (attribs) {
1437dab3f910Sjsing 		for (i = 0; i < sk_CONF_VALUE_num(attr_sk); i++) {
1438dab3f910Sjsing 			v = sk_CONF_VALUE_value(attr_sk, i);
1439dab3f910Sjsing 			if (!X509_REQ_add1_attr_by_txt(req, v->name, chtype,
1440dab3f910Sjsing 				(unsigned char *) v->value, -1))
1441dab3f910Sjsing 				return 0;
1442dab3f910Sjsing 		}
1443dab3f910Sjsing 	}
1444dab3f910Sjsing 	return 1;
1445dab3f910Sjsing }
1446dab3f910Sjsing 
1447dab3f910Sjsing 
1448dab3f910Sjsing static int
add_DN_object(X509_NAME * n,char * text,const char * def,char * value,int nid,int n_min,int n_max,unsigned long chtype,int mval)1449dab3f910Sjsing add_DN_object(X509_NAME * n, char *text, const char *def, char *value,
1450dab3f910Sjsing     int nid, int n_min, int n_max, unsigned long chtype, int mval)
1451dab3f910Sjsing {
1452dab3f910Sjsing 	int i, ret = 0;
1453dab3f910Sjsing 	char buf[1024];
1454dab3f910Sjsing  start:
1455e7718adaStb 	if (!cfg.batch)
1456dab3f910Sjsing 		BIO_printf(bio_err, "%s [%s]:", text, def);
1457dab3f910Sjsing 	(void) BIO_flush(bio_err);
1458dab3f910Sjsing 	if (value != NULL) {
1459dab3f910Sjsing 		strlcpy(buf, value, sizeof buf);
1460dab3f910Sjsing 		strlcat(buf, "\n", sizeof buf);
1461dab3f910Sjsing 		BIO_printf(bio_err, "%s\n", value);
1462dab3f910Sjsing 	} else {
1463dab3f910Sjsing 		buf[0] = '\0';
1464e7718adaStb 		if (!cfg.batch) {
1465dab3f910Sjsing 			if (!fgets(buf, sizeof buf, stdin))
1466dab3f910Sjsing 				return 0;
1467dab3f910Sjsing 		} else {
1468dab3f910Sjsing 			buf[0] = '\n';
1469dab3f910Sjsing 			buf[1] = '\0';
1470dab3f910Sjsing 		}
1471dab3f910Sjsing 	}
1472dab3f910Sjsing 
1473dab3f910Sjsing 	if (buf[0] == '\0')
1474dab3f910Sjsing 		return (0);
1475dab3f910Sjsing 	else if (buf[0] == '\n') {
1476dab3f910Sjsing 		if ((def == NULL) || (def[0] == '\0'))
1477dab3f910Sjsing 			return (1);
1478dab3f910Sjsing 		strlcpy(buf, def, sizeof buf);
1479dab3f910Sjsing 		strlcat(buf, "\n", sizeof buf);
1480dab3f910Sjsing 	} else if ((buf[0] == '.') && (buf[1] == '\n'))
1481dab3f910Sjsing 		return (1);
1482dab3f910Sjsing 
1483dab3f910Sjsing 	i = strlen(buf);
1484dab3f910Sjsing 	if (buf[i - 1] != '\n') {
1485dab3f910Sjsing 		BIO_printf(bio_err, "weird input :-(\n");
1486dab3f910Sjsing 		return (0);
1487dab3f910Sjsing 	}
1488dab3f910Sjsing 	buf[--i] = '\0';
1489dab3f910Sjsing 	if (!req_check_len(i, n_min, n_max))
1490dab3f910Sjsing 		goto start;
1491dab3f910Sjsing 	if (!X509_NAME_add_entry_by_NID(n, nid, chtype,
1492dab3f910Sjsing 		(unsigned char *) buf, -1, -1, mval))
1493dab3f910Sjsing 		goto err;
1494dab3f910Sjsing 	ret = 1;
1495dab3f910Sjsing  err:
1496dab3f910Sjsing 	return (ret);
1497dab3f910Sjsing }
1498dab3f910Sjsing 
1499dab3f910Sjsing static int
add_attribute_object(X509_REQ * req,char * text,const char * def,char * value,int nid,int n_min,int n_max,unsigned long chtype)1500dab3f910Sjsing add_attribute_object(X509_REQ * req, char *text, const char *def,
1501dab3f910Sjsing     char *value, int nid, int n_min,
1502dab3f910Sjsing     int n_max, unsigned long chtype)
1503dab3f910Sjsing {
1504dab3f910Sjsing 	int i;
1505dab3f910Sjsing 	static char buf[1024];
1506dab3f910Sjsing 
1507dab3f910Sjsing  start:
1508e7718adaStb 	if (!cfg.batch)
1509dab3f910Sjsing 		BIO_printf(bio_err, "%s [%s]:", text, def);
1510dab3f910Sjsing 	(void) BIO_flush(bio_err);
1511dab3f910Sjsing 	if (value != NULL) {
1512dab3f910Sjsing 		strlcpy(buf, value, sizeof buf);
1513dab3f910Sjsing 		strlcat(buf, "\n", sizeof buf);
1514dab3f910Sjsing 		BIO_printf(bio_err, "%s\n", value);
1515dab3f910Sjsing 	} else {
1516dab3f910Sjsing 		buf[0] = '\0';
1517e7718adaStb 		if (!cfg.batch) {
1518dab3f910Sjsing 			if (!fgets(buf, sizeof buf, stdin))
1519dab3f910Sjsing 				return 0;
1520dab3f910Sjsing 		} else {
1521dab3f910Sjsing 			buf[0] = '\n';
1522dab3f910Sjsing 			buf[1] = '\0';
1523dab3f910Sjsing 		}
1524dab3f910Sjsing 	}
1525dab3f910Sjsing 
1526dab3f910Sjsing 	if (buf[0] == '\0')
1527dab3f910Sjsing 		return (0);
1528dab3f910Sjsing 	else if (buf[0] == '\n') {
1529dab3f910Sjsing 		if ((def == NULL) || (def[0] == '\0'))
1530dab3f910Sjsing 			return (1);
1531dab3f910Sjsing 		strlcpy(buf, def, sizeof buf);
1532dab3f910Sjsing 		strlcat(buf, "\n", sizeof buf);
1533dab3f910Sjsing 	} else if ((buf[0] == '.') && (buf[1] == '\n'))
1534dab3f910Sjsing 		return (1);
1535dab3f910Sjsing 
1536dab3f910Sjsing 	i = strlen(buf);
1537dab3f910Sjsing 	if (buf[i - 1] != '\n') {
1538dab3f910Sjsing 		BIO_printf(bio_err, "weird input :-(\n");
1539dab3f910Sjsing 		return (0);
1540dab3f910Sjsing 	}
1541dab3f910Sjsing 	buf[--i] = '\0';
1542dab3f910Sjsing 	if (!req_check_len(i, n_min, n_max))
1543dab3f910Sjsing 		goto start;
1544dab3f910Sjsing 
1545dab3f910Sjsing 	if (!X509_REQ_add1_attr_by_NID(req, nid, chtype,
1546dab3f910Sjsing 		(unsigned char *) buf, -1)) {
1547dab3f910Sjsing 		BIO_printf(bio_err, "Error adding attribute\n");
1548dab3f910Sjsing 		ERR_print_errors(bio_err);
1549dab3f910Sjsing 		goto err;
1550dab3f910Sjsing 	}
1551dab3f910Sjsing 	return (1);
1552dab3f910Sjsing  err:
1553dab3f910Sjsing 	return (0);
1554dab3f910Sjsing }
1555dab3f910Sjsing 
1556dab3f910Sjsing static int
req_check_len(int len,int n_min,int n_max)1557dab3f910Sjsing req_check_len(int len, int n_min, int n_max)
1558dab3f910Sjsing {
1559dab3f910Sjsing 	if ((n_min > 0) && (len < n_min)) {
1560dab3f910Sjsing 		BIO_printf(bio_err, "string is too short, it needs to be at least %d bytes long\n", n_min);
1561dab3f910Sjsing 		return (0);
1562dab3f910Sjsing 	}
1563dab3f910Sjsing 	if ((n_max >= 0) && (len > n_max)) {
1564dab3f910Sjsing 		BIO_printf(bio_err, "string is too long, it needs to be less than  %d bytes long\n", n_max);
1565dab3f910Sjsing 		return (0);
1566dab3f910Sjsing 	}
1567dab3f910Sjsing 	return (1);
1568dab3f910Sjsing }
1569dab3f910Sjsing 
1570dab3f910Sjsing /* Check if the end of a string matches 'end' */
1571dab3f910Sjsing static int
check_end(const char * str,const char * end)1572dab3f910Sjsing check_end(const char *str, const char *end)
1573dab3f910Sjsing {
1574dab3f910Sjsing 	int elen, slen;
1575dab3f910Sjsing 	const char *tmp;
1576dab3f910Sjsing 	elen = strlen(end);
1577dab3f910Sjsing 	slen = strlen(str);
1578dab3f910Sjsing 	if (elen > slen)
1579dab3f910Sjsing 		return 1;
1580dab3f910Sjsing 	tmp = str + slen - elen;
1581dab3f910Sjsing 	return strcmp(tmp, end);
1582dab3f910Sjsing }
1583dab3f910Sjsing 
1584dab3f910Sjsing static EVP_PKEY_CTX *
set_keygen_ctx(BIO * err,const char * gstr,int * pkey_type,long * pkeylen,char ** palgnam)1585dab3f910Sjsing set_keygen_ctx(BIO * err, const char *gstr, int *pkey_type,
15865284dfeaSbcook     long *pkeylen, char **palgnam)
1587dab3f910Sjsing {
1588dab3f910Sjsing 	EVP_PKEY_CTX *gctx = NULL;
1589dab3f910Sjsing 	EVP_PKEY *param = NULL;
1590dab3f910Sjsing 	long keylen = -1;
1591dab3f910Sjsing 	BIO *pbio = NULL;
1592dab3f910Sjsing 	const char *paramfile = NULL;
1593dab3f910Sjsing 	const char *errstr;
1594dab3f910Sjsing 
1595dab3f910Sjsing 	if (gstr == NULL) {
1596dab3f910Sjsing 		*pkey_type = EVP_PKEY_RSA;
1597dab3f910Sjsing 		keylen = *pkeylen;
1598dab3f910Sjsing 	} else if (gstr[0] >= '0' && gstr[0] <= '9') {
1599dab3f910Sjsing 		*pkey_type = EVP_PKEY_RSA;
1600dab3f910Sjsing 		keylen = strtonum(gstr, 0, LONG_MAX, &errstr);
1601dab3f910Sjsing 		if (errstr) {
1602dab3f910Sjsing 			BIO_printf(err, "bad algorithm %s: %s\n", gstr, errstr);
1603dab3f910Sjsing 			return NULL;
1604dab3f910Sjsing 		}
1605dab3f910Sjsing 		*pkeylen = keylen;
1606dab3f910Sjsing 	} else if (!strncmp(gstr, "param:", 6))
1607dab3f910Sjsing 		paramfile = gstr + 6;
1608dab3f910Sjsing 	else {
1609dab3f910Sjsing 		const char *p = strchr(gstr, ':');
1610dab3f910Sjsing 		int len;
1611dab3f910Sjsing 		const EVP_PKEY_ASN1_METHOD *ameth;
1612dab3f910Sjsing 
1613dab3f910Sjsing 		if (p)
1614dab3f910Sjsing 			len = p - gstr;
1615dab3f910Sjsing 		else
1616dab3f910Sjsing 			len = strlen(gstr);
1617dab3f910Sjsing 
16185284dfeaSbcook 		ameth = EVP_PKEY_asn1_find_str(NULL, gstr, len);
1619dab3f910Sjsing 
1620dab3f910Sjsing 		if (!ameth) {
1621dab3f910Sjsing 			BIO_printf(err, "Unknown algorithm %.*s\n", len, gstr);
1622dab3f910Sjsing 			return NULL;
1623dab3f910Sjsing 		}
1624dab3f910Sjsing 		EVP_PKEY_asn1_get0_info(NULL, pkey_type, NULL, NULL, NULL,
1625dab3f910Sjsing 		    ameth);
1626dab3f910Sjsing 		if (*pkey_type == EVP_PKEY_RSA) {
1627dab3f910Sjsing 			if (p) {
1628dab3f910Sjsing 				keylen = strtonum(p + 1, 0, LONG_MAX, &errstr);
1629dab3f910Sjsing 				if (errstr) {
1630dab3f910Sjsing 					BIO_printf(err, "bad algorithm %s: %s\n",
1631dab3f910Sjsing 					    p + 1, errstr);
1632dab3f910Sjsing 					return NULL;
1633dab3f910Sjsing 				}
1634dab3f910Sjsing 				*pkeylen = keylen;
1635dab3f910Sjsing 			} else
1636dab3f910Sjsing 				keylen = *pkeylen;
1637dab3f910Sjsing 		} else if (p)
1638dab3f910Sjsing 			paramfile = p + 1;
1639dab3f910Sjsing 	}
1640dab3f910Sjsing 
1641dab3f910Sjsing 	if (paramfile) {
1642dab3f910Sjsing 		pbio = BIO_new_file(paramfile, "r");
1643dab3f910Sjsing 		if (!pbio) {
1644dab3f910Sjsing 			BIO_printf(err, "Can't open parameter file %s\n",
1645dab3f910Sjsing 			    paramfile);
1646dab3f910Sjsing 			return NULL;
1647dab3f910Sjsing 		}
1648dab3f910Sjsing 		param = PEM_read_bio_Parameters(pbio, NULL);
1649dab3f910Sjsing 
1650dab3f910Sjsing 		if (!param) {
1651dab3f910Sjsing 			X509 *x;
1652dab3f910Sjsing 			(void) BIO_reset(pbio);
1653dab3f910Sjsing 			x = PEM_read_bio_X509(pbio, NULL, NULL, NULL);
1654dab3f910Sjsing 			if (x) {
1655dab3f910Sjsing 				param = X509_get_pubkey(x);
1656dab3f910Sjsing 				X509_free(x);
1657dab3f910Sjsing 			}
1658dab3f910Sjsing 		}
1659dab3f910Sjsing 		BIO_free(pbio);
1660dab3f910Sjsing 
1661dab3f910Sjsing 		if (!param) {
1662dab3f910Sjsing 			BIO_printf(err, "Error reading parameter file %s\n",
1663dab3f910Sjsing 			    paramfile);
1664dab3f910Sjsing 			return NULL;
1665dab3f910Sjsing 		}
1666dab3f910Sjsing 		if (*pkey_type == -1)
1667dab3f910Sjsing 			*pkey_type = EVP_PKEY_id(param);
1668dab3f910Sjsing 		else if (*pkey_type != EVP_PKEY_base_id(param)) {
1669dab3f910Sjsing 			BIO_printf(err, "Key Type does not match parameters\n");
1670dab3f910Sjsing 			EVP_PKEY_free(param);
1671dab3f910Sjsing 			return NULL;
1672dab3f910Sjsing 		}
1673dab3f910Sjsing 	}
1674dab3f910Sjsing 	if (palgnam) {
1675dab3f910Sjsing 		const EVP_PKEY_ASN1_METHOD *ameth;
1676dab3f910Sjsing 		const char *anam;
16775284dfeaSbcook 		ameth = EVP_PKEY_asn1_find(NULL, *pkey_type);
1678dab3f910Sjsing 		if (!ameth) {
1679dab3f910Sjsing 			BIO_puts(err, "Internal error: can't find key algorithm\n");
1680dab3f910Sjsing 			return NULL;
1681dab3f910Sjsing 		}
1682dab3f910Sjsing 		EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL, &anam, ameth);
16838e315e4cSjsing 		*palgnam = strdup(anam);
1684dab3f910Sjsing 	}
1685dab3f910Sjsing 	if (param) {
16865284dfeaSbcook 		gctx = EVP_PKEY_CTX_new(param, NULL);
1687dab3f910Sjsing 		*pkeylen = EVP_PKEY_bits(param);
1688dab3f910Sjsing 		EVP_PKEY_free(param);
1689dab3f910Sjsing 	} else
16905284dfeaSbcook 		gctx = EVP_PKEY_CTX_new_id(*pkey_type, NULL);
1691dab3f910Sjsing 
1692dab3f910Sjsing 	if (!gctx) {
1693dab3f910Sjsing 		BIO_puts(err, "Error allocating keygen context\n");
1694dab3f910Sjsing 		ERR_print_errors(err);
1695dab3f910Sjsing 		return NULL;
1696dab3f910Sjsing 	}
1697dab3f910Sjsing 	if (EVP_PKEY_keygen_init(gctx) <= 0) {
1698dab3f910Sjsing 		BIO_puts(err, "Error initializing keygen context\n");
1699dab3f910Sjsing 		ERR_print_errors(err);
1700*375d4fb1Stb 		EVP_PKEY_CTX_free(gctx);
1701dab3f910Sjsing 		return NULL;
1702dab3f910Sjsing 	}
1703dab3f910Sjsing 	if ((*pkey_type == EVP_PKEY_RSA) && (keylen != -1)) {
1704dab3f910Sjsing 		if (EVP_PKEY_CTX_set_rsa_keygen_bits(gctx, keylen) <= 0) {
1705dab3f910Sjsing 			BIO_puts(err, "Error setting RSA keysize\n");
1706dab3f910Sjsing 			ERR_print_errors(err);
1707dab3f910Sjsing 			EVP_PKEY_CTX_free(gctx);
1708dab3f910Sjsing 			return NULL;
1709dab3f910Sjsing 		}
1710dab3f910Sjsing 	}
1711dab3f910Sjsing 
1712dab3f910Sjsing 	return gctx;
1713dab3f910Sjsing }
1714dab3f910Sjsing 
1715dab3f910Sjsing static int
genpkey_cb(EVP_PKEY_CTX * ctx)1716dab3f910Sjsing genpkey_cb(EVP_PKEY_CTX * ctx)
1717dab3f910Sjsing {
1718dab3f910Sjsing 	char c = '*';
1719dab3f910Sjsing 	BIO *b = EVP_PKEY_CTX_get_app_data(ctx);
1720dab3f910Sjsing 	int p;
1721dab3f910Sjsing 	p = EVP_PKEY_CTX_get_keygen_info(ctx, 0);
1722dab3f910Sjsing 	if (p == 0)
1723dab3f910Sjsing 		c = '.';
1724dab3f910Sjsing 	if (p == 1)
1725dab3f910Sjsing 		c = '+';
1726dab3f910Sjsing 	if (p == 2)
1727dab3f910Sjsing 		c = '*';
1728dab3f910Sjsing 	if (p == 3)
1729dab3f910Sjsing 		c = '\n';
1730dab3f910Sjsing 	BIO_write(b, &c, 1);
1731dab3f910Sjsing 	(void) BIO_flush(b);
1732dab3f910Sjsing 	return 1;
1733dab3f910Sjsing }
1734dab3f910Sjsing 
1735dab3f910Sjsing static int
do_sign_init(BIO * err,EVP_MD_CTX * ctx,EVP_PKEY * pkey,const EVP_MD * md,STACK_OF (OPENSSL_STRING)* sigopts)1736dab3f910Sjsing do_sign_init(BIO * err, EVP_MD_CTX * ctx, EVP_PKEY * pkey,
1737dab3f910Sjsing     const EVP_MD * md, STACK_OF(OPENSSL_STRING) * sigopts)
1738dab3f910Sjsing {
1739dab3f910Sjsing 	EVP_PKEY_CTX *pkctx = NULL;
1740d348a60aStb 	int default_nid;
1741dab3f910Sjsing 	int i;
174216954431Stb 
1743d348a60aStb 	if (EVP_PKEY_get_default_digest_nid(pkey, &default_nid) == 2 &&
1744d348a60aStb 	    default_nid == NID_undef) {
1745d348a60aStb 		/* The digest is required to be EVP_md_null() (EdDSA). */
1746d348a60aStb 		md = EVP_md_null();
1747d348a60aStb 	}
1748d348a60aStb 
1749dab3f910Sjsing 	if (!EVP_DigestSignInit(ctx, &pkctx, md, NULL, pkey))
1750dab3f910Sjsing 		return 0;
1751dab3f910Sjsing 	for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) {
1752dab3f910Sjsing 		char *sigopt = sk_OPENSSL_STRING_value(sigopts, i);
1753dab3f910Sjsing 		if (pkey_ctrl_string(pkctx, sigopt) <= 0) {
1754dab3f910Sjsing 			BIO_printf(err, "parameter error \"%s\"\n", sigopt);
1755dab3f910Sjsing 			ERR_print_errors(bio_err);
1756dab3f910Sjsing 			return 0;
1757dab3f910Sjsing 		}
1758dab3f910Sjsing 	}
1759dab3f910Sjsing 	return 1;
1760dab3f910Sjsing }
1761dab3f910Sjsing 
1762dab3f910Sjsing int
do_X509_sign(BIO * err,X509 * x,EVP_PKEY * pkey,const EVP_MD * md,STACK_OF (OPENSSL_STRING)* sigopts)1763dab3f910Sjsing do_X509_sign(BIO * err, X509 * x, EVP_PKEY * pkey, const EVP_MD * md,
1764dab3f910Sjsing     STACK_OF(OPENSSL_STRING) * sigopts)
1765dab3f910Sjsing {
1766d13925e1Stb 	EVP_MD_CTX *mctx;
1767dab3f910Sjsing 	int rv;
1768d13925e1Stb 
1769d13925e1Stb 	if ((mctx = EVP_MD_CTX_new()) == NULL)
1770d13925e1Stb 		return 0;
1771d13925e1Stb 
1772d13925e1Stb 	rv = do_sign_init(err, mctx, pkey, md, sigopts);
1773dab3f910Sjsing 	if (rv > 0)
1774d13925e1Stb 		rv = X509_sign_ctx(x, mctx);
1775d13925e1Stb 
1776d13925e1Stb 	EVP_MD_CTX_free(mctx);
1777d13925e1Stb 
1778d13925e1Stb 	return rv > 0;
1779dab3f910Sjsing }
1780dab3f910Sjsing 
1781dab3f910Sjsing 
1782dab3f910Sjsing int
do_X509_REQ_sign(BIO * err,X509_REQ * x,EVP_PKEY * pkey,const EVP_MD * md,STACK_OF (OPENSSL_STRING)* sigopts)1783dab3f910Sjsing do_X509_REQ_sign(BIO * err, X509_REQ * x, EVP_PKEY * pkey, const EVP_MD * md,
1784dab3f910Sjsing     STACK_OF(OPENSSL_STRING) * sigopts)
1785dab3f910Sjsing {
1786d13925e1Stb 	EVP_MD_CTX *mctx;
1787dab3f910Sjsing 	int rv;
1788d13925e1Stb 
1789d13925e1Stb 	if ((mctx = EVP_MD_CTX_new()) == NULL)
1790d13925e1Stb 		return 0;
1791d13925e1Stb 
1792d13925e1Stb 	rv = do_sign_init(err, mctx, pkey, md, sigopts);
1793dab3f910Sjsing 	if (rv > 0)
1794d13925e1Stb 		rv = X509_REQ_sign_ctx(x, mctx);
1795d13925e1Stb 
1796d13925e1Stb 	EVP_MD_CTX_free(mctx);
1797d13925e1Stb 
1798d13925e1Stb 	return rv > 0;
1799dab3f910Sjsing }
1800dab3f910Sjsing 
1801dab3f910Sjsing 
1802dab3f910Sjsing 
1803dab3f910Sjsing int
do_X509_CRL_sign(BIO * err,X509_CRL * x,EVP_PKEY * pkey,const EVP_MD * md,STACK_OF (OPENSSL_STRING)* sigopts)1804dab3f910Sjsing do_X509_CRL_sign(BIO * err, X509_CRL * x, EVP_PKEY * pkey, const EVP_MD * md,
1805dab3f910Sjsing     STACK_OF(OPENSSL_STRING) * sigopts)
1806dab3f910Sjsing {
1807dab3f910Sjsing 	int rv;
1808d13925e1Stb 	EVP_MD_CTX *mctx;
1809d13925e1Stb 
1810d13925e1Stb 	if ((mctx = EVP_MD_CTX_new()) == NULL)
1811d13925e1Stb 		return 0;
1812d13925e1Stb 
1813d13925e1Stb 	rv = do_sign_init(err, mctx, pkey, md, sigopts);
1814dab3f910Sjsing 	if (rv > 0)
1815d13925e1Stb 		rv = X509_CRL_sign_ctx(x, mctx);
1816d13925e1Stb 
1817d13925e1Stb 	EVP_MD_CTX_free(mctx);
1818d13925e1Stb 
1819d13925e1Stb 	return rv > 0;
1820dab3f910Sjsing }
1821a72a31a2Sinoguchi 
1822a72a31a2Sinoguchi static unsigned long
ext_name_hash(const OPENSSL_STRING * a)1823a72a31a2Sinoguchi ext_name_hash(const OPENSSL_STRING *a)
1824a72a31a2Sinoguchi {
1825a72a31a2Sinoguchi 	return lh_strhash((const char *)a);
1826a72a31a2Sinoguchi }
1827a72a31a2Sinoguchi 
1828a72a31a2Sinoguchi static int
ext_name_cmp(const OPENSSL_STRING * a,const OPENSSL_STRING * b)1829a72a31a2Sinoguchi ext_name_cmp(const OPENSSL_STRING *a, const OPENSSL_STRING *b)
1830a72a31a2Sinoguchi {
1831a72a31a2Sinoguchi 	return strcmp((const char *)a, (const char *)b);
1832a72a31a2Sinoguchi }
1833a72a31a2Sinoguchi 
1834a72a31a2Sinoguchi static void
exts_cleanup(OPENSSL_STRING * x)1835a72a31a2Sinoguchi exts_cleanup(OPENSSL_STRING *x)
1836a72a31a2Sinoguchi {
1837a72a31a2Sinoguchi 	free((char *)x);
1838a72a31a2Sinoguchi }
1839a72a31a2Sinoguchi 
1840a72a31a2Sinoguchi /*
1841a72a31a2Sinoguchi  * Is the |kv| key already duplicated ? This is remarkably tricky to get right.
1842a72a31a2Sinoguchi  * Return 0 if unique, -1 on runtime error; 1 if found or a syntax error.
1843a72a31a2Sinoguchi  */
1844a72a31a2Sinoguchi static int
duplicated(LHASH_OF (OPENSSL_STRING)* addexts,char * kv)1845a72a31a2Sinoguchi duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv)
1846a72a31a2Sinoguchi {
1847a72a31a2Sinoguchi 	char *p;
1848a72a31a2Sinoguchi 	size_t off;
1849a72a31a2Sinoguchi 
1850a72a31a2Sinoguchi 	/* Check syntax. */
1851a72a31a2Sinoguchi 	/* Skip leading whitespace, make a copy. */
1852a72a31a2Sinoguchi 	while (*kv && isspace(*kv))
1853a72a31a2Sinoguchi 		if (*++kv == '\0')
1854a72a31a2Sinoguchi 			return 1;
1855a72a31a2Sinoguchi 	if ((p = strchr(kv, '=')) == NULL)
1856a72a31a2Sinoguchi 		return 1;
1857a72a31a2Sinoguchi 	off = p - kv;
1858a72a31a2Sinoguchi 	if ((kv = strdup(kv)) == NULL)
1859a72a31a2Sinoguchi 		return -1;
1860a72a31a2Sinoguchi 
1861a72a31a2Sinoguchi 	/* Skip trailing space before the equal sign. */
1862a72a31a2Sinoguchi 	for (p = kv + off; p > kv; --p)
1863a72a31a2Sinoguchi 		if (!isspace(p[-1]))
1864a72a31a2Sinoguchi 			break;
1865a72a31a2Sinoguchi 	if (p == kv) {
1866a72a31a2Sinoguchi 		free(kv);
1867a72a31a2Sinoguchi 		return 1;
1868a72a31a2Sinoguchi 	}
1869a72a31a2Sinoguchi 	*p = '\0';
1870a72a31a2Sinoguchi 
1871a72a31a2Sinoguchi 	/* See if "key" is there by attempting to add it. */
1872a72a31a2Sinoguchi 	if ((p = (char *)lh_OPENSSL_STRING_insert(addexts, (OPENSSL_STRING*)kv))
1873a72a31a2Sinoguchi 	    != NULL || lh_OPENSSL_STRING_error(addexts)) {
1874a72a31a2Sinoguchi 		free(p != NULL ? p : kv);
1875a72a31a2Sinoguchi 		return -1;
1876a72a31a2Sinoguchi 	}
1877a72a31a2Sinoguchi 
1878a72a31a2Sinoguchi 	return 0;
1879a72a31a2Sinoguchi }
1880