xref: /dflybsd-src/crypto/libressl/apps/openssl/req.c (revision 961e30ea7dc61d1112b778ea4981eac68129fb86)
1*de0e0e4dSAntonio Huete Jimenez /* $OpenBSD: req.c,v 1.23 2022/02/03 17:44:04 tb Exp $ */
2f5b1c8a1SJohn Marino /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3f5b1c8a1SJohn Marino  * All rights reserved.
4f5b1c8a1SJohn Marino  *
5f5b1c8a1SJohn Marino  * This package is an SSL implementation written
6f5b1c8a1SJohn Marino  * by Eric Young (eay@cryptsoft.com).
7f5b1c8a1SJohn Marino  * The implementation was written so as to conform with Netscapes SSL.
8f5b1c8a1SJohn Marino  *
9f5b1c8a1SJohn Marino  * This library is free for commercial and non-commercial use as long as
10f5b1c8a1SJohn Marino  * the following conditions are aheared to.  The following conditions
11f5b1c8a1SJohn Marino  * apply to all code found in this distribution, be it the RC4, RSA,
12f5b1c8a1SJohn Marino  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13f5b1c8a1SJohn Marino  * included with this distribution is covered by the same copyright terms
14f5b1c8a1SJohn Marino  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15f5b1c8a1SJohn Marino  *
16f5b1c8a1SJohn Marino  * Copyright remains Eric Young's, and as such any Copyright notices in
17f5b1c8a1SJohn Marino  * the code are not to be removed.
18f5b1c8a1SJohn Marino  * If this package is used in a product, Eric Young should be given attribution
19f5b1c8a1SJohn Marino  * as the author of the parts of the library used.
20f5b1c8a1SJohn Marino  * This can be in the form of a textual message at program startup or
21f5b1c8a1SJohn Marino  * in documentation (online or textual) provided with the package.
22f5b1c8a1SJohn Marino  *
23f5b1c8a1SJohn Marino  * Redistribution and use in source and binary forms, with or without
24f5b1c8a1SJohn Marino  * modification, are permitted provided that the following conditions
25f5b1c8a1SJohn Marino  * are met:
26f5b1c8a1SJohn Marino  * 1. Redistributions of source code must retain the copyright
27f5b1c8a1SJohn Marino  *    notice, this list of conditions and the following disclaimer.
28f5b1c8a1SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
29f5b1c8a1SJohn Marino  *    notice, this list of conditions and the following disclaimer in the
30f5b1c8a1SJohn Marino  *    documentation and/or other materials provided with the distribution.
31f5b1c8a1SJohn Marino  * 3. All advertising materials mentioning features or use of this software
32f5b1c8a1SJohn Marino  *    must display the following acknowledgement:
33f5b1c8a1SJohn Marino  *    "This product includes cryptographic software written by
34f5b1c8a1SJohn Marino  *     Eric Young (eay@cryptsoft.com)"
35f5b1c8a1SJohn Marino  *    The word 'cryptographic' can be left out if the rouines from the library
36f5b1c8a1SJohn Marino  *    being used are not cryptographic related :-).
37f5b1c8a1SJohn Marino  * 4. If you include any Windows specific code (or a derivative thereof) from
38f5b1c8a1SJohn Marino  *    the apps directory (application code) you must include an acknowledgement:
39f5b1c8a1SJohn Marino  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40f5b1c8a1SJohn Marino  *
41f5b1c8a1SJohn Marino  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42f5b1c8a1SJohn Marino  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43f5b1c8a1SJohn Marino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44f5b1c8a1SJohn Marino  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45f5b1c8a1SJohn Marino  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46f5b1c8a1SJohn Marino  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47f5b1c8a1SJohn Marino  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48f5b1c8a1SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49f5b1c8a1SJohn Marino  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50f5b1c8a1SJohn Marino  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51f5b1c8a1SJohn Marino  * SUCH DAMAGE.
52f5b1c8a1SJohn Marino  *
53f5b1c8a1SJohn Marino  * The licence and distribution terms for any publically available version or
54f5b1c8a1SJohn Marino  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55f5b1c8a1SJohn Marino  * copied and put under another distribution licence
56f5b1c8a1SJohn Marino  * [including the GNU Public Licence.]
57f5b1c8a1SJohn Marino  */
58f5b1c8a1SJohn Marino 
59f5b1c8a1SJohn Marino /* Until the key-gen callbacks are modified to use newer prototypes, we allow
60f5b1c8a1SJohn Marino  * deprecated functions for openssl-internal code */
61f5b1c8a1SJohn Marino #ifdef OPENSSL_NO_DEPRECATED
62f5b1c8a1SJohn Marino #undef OPENSSL_NO_DEPRECATED
63f5b1c8a1SJohn Marino #endif
64f5b1c8a1SJohn Marino 
65cca6fc52SDaniel Fojt #include <ctype.h>
66cca6fc52SDaniel Fojt #include <limits.h>
67f5b1c8a1SJohn Marino #include <stdio.h>
68f5b1c8a1SJohn Marino #include <stdlib.h>
69f5b1c8a1SJohn Marino #include <string.h>
70f5b1c8a1SJohn Marino #include <time.h>
71f5b1c8a1SJohn Marino 
72f5b1c8a1SJohn Marino #include "apps.h"
73f5b1c8a1SJohn Marino 
74f5b1c8a1SJohn Marino #include <openssl/asn1.h>
75f5b1c8a1SJohn Marino #include <openssl/bio.h>
76f5b1c8a1SJohn Marino #include <openssl/bn.h>
77f5b1c8a1SJohn Marino #include <openssl/conf.h>
78f5b1c8a1SJohn Marino #include <openssl/err.h>
79f5b1c8a1SJohn Marino #include <openssl/evp.h>
80f5b1c8a1SJohn Marino #include <openssl/objects.h>
81f5b1c8a1SJohn Marino #include <openssl/pem.h>
82f5b1c8a1SJohn Marino #include <openssl/x509.h>
83f5b1c8a1SJohn Marino #include <openssl/x509v3.h>
84f5b1c8a1SJohn Marino 
85f5b1c8a1SJohn Marino #include <openssl/dsa.h>
86f5b1c8a1SJohn Marino 
87f5b1c8a1SJohn Marino #include <openssl/rsa.h>
88f5b1c8a1SJohn Marino 
89f5b1c8a1SJohn Marino #define SECTION		"req"
90f5b1c8a1SJohn Marino 
91f5b1c8a1SJohn Marino #define BITS		"default_bits"
92f5b1c8a1SJohn Marino #define KEYFILE		"default_keyfile"
93f5b1c8a1SJohn Marino #define PROMPT		"prompt"
94f5b1c8a1SJohn Marino #define DISTINGUISHED_NAME	"distinguished_name"
95f5b1c8a1SJohn Marino #define ATTRIBUTES	"attributes"
96f5b1c8a1SJohn Marino #define V3_EXTENSIONS	"x509_extensions"
97f5b1c8a1SJohn Marino #define REQ_EXTENSIONS	"req_extensions"
98f5b1c8a1SJohn Marino #define STRING_MASK	"string_mask"
99f5b1c8a1SJohn Marino #define UTF8_IN		"utf8"
100f5b1c8a1SJohn Marino 
101f5b1c8a1SJohn Marino #define DEFAULT_KEY_LENGTH	2048
102f5b1c8a1SJohn Marino #define MIN_KEY_LENGTH		384
103f5b1c8a1SJohn Marino 
104f5b1c8a1SJohn Marino static int make_REQ(X509_REQ * req, EVP_PKEY * pkey, char *dn, int multirdn,
105f5b1c8a1SJohn Marino     int attribs, unsigned long chtype);
106f5b1c8a1SJohn Marino static int build_subject(X509_REQ * req, char *subj, unsigned long chtype,
107f5b1c8a1SJohn Marino     int multirdn);
108f5b1c8a1SJohn Marino static int prompt_info(X509_REQ * req,
109f5b1c8a1SJohn Marino     STACK_OF(CONF_VALUE) * dn_sk, char *dn_sect,
110f5b1c8a1SJohn Marino     STACK_OF(CONF_VALUE) * attr_sk, char *attr_sect, int attribs,
111f5b1c8a1SJohn Marino     unsigned long chtype);
112f5b1c8a1SJohn Marino static int auto_info(X509_REQ * req, STACK_OF(CONF_VALUE) * sk,
113f5b1c8a1SJohn Marino     STACK_OF(CONF_VALUE) * attr, int attribs,
114f5b1c8a1SJohn Marino     unsigned long chtype);
115f5b1c8a1SJohn Marino static int add_attribute_object(X509_REQ * req, char *text, const char *def,
116f5b1c8a1SJohn Marino     char *value, int nid, int n_min,
117f5b1c8a1SJohn Marino     int n_max, unsigned long chtype);
118f5b1c8a1SJohn Marino static int add_DN_object(X509_NAME * n, char *text, const char *def, char *value,
119f5b1c8a1SJohn Marino     int nid, int n_min, int n_max, unsigned long chtype, int mval);
120f5b1c8a1SJohn Marino static int genpkey_cb(EVP_PKEY_CTX * ctx);
121f5b1c8a1SJohn Marino static int req_check_len(int len, int n_min, int n_max);
122f5b1c8a1SJohn Marino static int check_end(const char *str, const char *end);
123f5b1c8a1SJohn Marino static EVP_PKEY_CTX *set_keygen_ctx(BIO * err, const char *gstr, int *pkey_type,
124f5b1c8a1SJohn Marino     long *pkeylen, char **palgnam);
125cca6fc52SDaniel Fojt static unsigned long ext_name_hash(const OPENSSL_STRING *a);
126cca6fc52SDaniel Fojt static int ext_name_cmp(const OPENSSL_STRING *a, const OPENSSL_STRING *b);
127cca6fc52SDaniel Fojt static void exts_cleanup(OPENSSL_STRING *x);
128cca6fc52SDaniel Fojt static int duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv);
129f5b1c8a1SJohn Marino static CONF *req_conf = NULL;
130cca6fc52SDaniel Fojt static CONF *addext_conf = NULL;
1318edacedfSDaniel Fojt 
1328edacedfSDaniel Fojt struct {
1338edacedfSDaniel Fojt 	LHASH_OF(OPENSSL_STRING) *addexts;
1348edacedfSDaniel Fojt 	BIO *addext_bio;
1358edacedfSDaniel Fojt 	int batch;
1368edacedfSDaniel Fojt 	unsigned long chtype;
1378edacedfSDaniel Fojt 	int days;
1388edacedfSDaniel Fojt 	const EVP_MD *digest;
1398edacedfSDaniel Fojt 	char *extensions;
1408edacedfSDaniel Fojt 	char *infile;
1418edacedfSDaniel Fojt 	int informat;
1428edacedfSDaniel Fojt 	char *keyalg;
1438edacedfSDaniel Fojt 	char *keyfile;
1448edacedfSDaniel Fojt 	int keyform;
1458edacedfSDaniel Fojt 	char *keyout;
1468edacedfSDaniel Fojt 	int modulus;
1478edacedfSDaniel Fojt 	int multirdn;
1488edacedfSDaniel Fojt 	int newhdr;
1498edacedfSDaniel Fojt 	long newkey;
1508edacedfSDaniel Fojt 	int newreq;
1518edacedfSDaniel Fojt 	unsigned long nmflag;
1528edacedfSDaniel Fojt 	int nodes;
1538edacedfSDaniel Fojt 	int noout;
1548edacedfSDaniel Fojt 	char *outfile;
1558edacedfSDaniel Fojt 	int outformat;
1568edacedfSDaniel Fojt 	char *passargin;
1578edacedfSDaniel Fojt 	char *passargout;
1588edacedfSDaniel Fojt 	STACK_OF(OPENSSL_STRING) *pkeyopts;
1598edacedfSDaniel Fojt 	int pubkey;
1608edacedfSDaniel Fojt 	char *req_exts;
1618edacedfSDaniel Fojt 	unsigned long reqflag;
1628edacedfSDaniel Fojt 	ASN1_INTEGER *serial;
1638edacedfSDaniel Fojt 	STACK_OF(OPENSSL_STRING) *sigopts;
1648edacedfSDaniel Fojt 	char *subj;
1658edacedfSDaniel Fojt 	int subject;
1668edacedfSDaniel Fojt 	char *template;
1678edacedfSDaniel Fojt 	int text;
1688edacedfSDaniel Fojt 	int verbose;
1698edacedfSDaniel Fojt 	int verify;
1708edacedfSDaniel Fojt 	int x509;
1718edacedfSDaniel Fojt } req_config;
1728edacedfSDaniel Fojt 
1738edacedfSDaniel Fojt static int
req_opt_addext(char * arg)1748edacedfSDaniel Fojt req_opt_addext(char *arg)
1758edacedfSDaniel Fojt {
1768edacedfSDaniel Fojt 	int i;
1778edacedfSDaniel Fojt 
1788edacedfSDaniel Fojt 	if (req_config.addexts == NULL) {
1798edacedfSDaniel Fojt 		req_config.addexts = (LHASH_OF(OPENSSL_STRING) *)lh_new(
1808edacedfSDaniel Fojt 		    (LHASH_HASH_FN_TYPE)ext_name_hash,
1818edacedfSDaniel Fojt 		    (LHASH_COMP_FN_TYPE)ext_name_cmp);
1828edacedfSDaniel Fojt 		req_config.addext_bio = BIO_new(BIO_s_mem());
1838edacedfSDaniel Fojt 		if (req_config.addexts == NULL ||
1848edacedfSDaniel Fojt 		    req_config.addext_bio == NULL)
1858edacedfSDaniel Fojt 			return (1);
1868edacedfSDaniel Fojt 	}
1878edacedfSDaniel Fojt 	i = duplicated(req_config.addexts, arg);
1888edacedfSDaniel Fojt 	if (i == 1)
1898edacedfSDaniel Fojt 		return (1);
1908edacedfSDaniel Fojt 	if (i < 0 || BIO_printf(req_config.addext_bio, "%s\n", arg) < 0)
1918edacedfSDaniel Fojt 		return (1);
1928edacedfSDaniel Fojt 
1938edacedfSDaniel Fojt 	return (0);
1948edacedfSDaniel Fojt }
1958edacedfSDaniel Fojt 
1968edacedfSDaniel Fojt static int
req_opt_days(char * arg)1978edacedfSDaniel Fojt req_opt_days(char *arg)
1988edacedfSDaniel Fojt {
1998edacedfSDaniel Fojt 	const char *errstr;
2008edacedfSDaniel Fojt 
2018edacedfSDaniel Fojt 	req_config.days = strtonum(arg, 1, INT_MAX, &errstr);
2028edacedfSDaniel Fojt 	if (errstr != NULL) {
2038edacedfSDaniel Fojt 		BIO_printf(bio_err, "bad -days %s, using 0: %s\n",
2048edacedfSDaniel Fojt 		    arg, errstr);
2058edacedfSDaniel Fojt 		req_config.days = 30;
2068edacedfSDaniel Fojt 	}
2078edacedfSDaniel Fojt 	return (0);
2088edacedfSDaniel Fojt }
2098edacedfSDaniel Fojt 
2108edacedfSDaniel Fojt static int
req_opt_digest(int argc,char ** argv,int * argsused)2118edacedfSDaniel Fojt req_opt_digest(int argc, char **argv, int *argsused)
2128edacedfSDaniel Fojt {
2138edacedfSDaniel Fojt 	char *name = argv[0];
2148edacedfSDaniel Fojt 
2158edacedfSDaniel Fojt 	if (*name++ != '-')
2168edacedfSDaniel Fojt 		return (1);
2178edacedfSDaniel Fojt 
2188edacedfSDaniel Fojt 	if ((req_config.digest = EVP_get_digestbyname(name)) == NULL)
2198edacedfSDaniel Fojt 		return (1);
2208edacedfSDaniel Fojt 
2218edacedfSDaniel Fojt 	*argsused = 1;
2228edacedfSDaniel Fojt 	return (0);
2238edacedfSDaniel Fojt }
2248edacedfSDaniel Fojt 
2258edacedfSDaniel Fojt static int
req_opt_newkey(char * arg)2268edacedfSDaniel Fojt req_opt_newkey(char *arg)
2278edacedfSDaniel Fojt {
2288edacedfSDaniel Fojt 	req_config.keyalg = arg;
2298edacedfSDaniel Fojt 	req_config.newreq = 1;
2308edacedfSDaniel Fojt 	return (0);
2318edacedfSDaniel Fojt }
2328edacedfSDaniel Fojt 
2338edacedfSDaniel Fojt static int
req_opt_nameopt(char * arg)2348edacedfSDaniel Fojt req_opt_nameopt(char *arg)
2358edacedfSDaniel Fojt {
2368edacedfSDaniel Fojt 	if (!set_name_ex(&req_config.nmflag, arg))
2378edacedfSDaniel Fojt 		return (1);
2388edacedfSDaniel Fojt 	return (0);
2398edacedfSDaniel Fojt }
2408edacedfSDaniel Fojt 
2418edacedfSDaniel Fojt static int
req_opt_pkeyopt(char * arg)2428edacedfSDaniel Fojt req_opt_pkeyopt(char *arg)
2438edacedfSDaniel Fojt {
2448edacedfSDaniel Fojt 	if (req_config.pkeyopts == NULL)
2458edacedfSDaniel Fojt 		req_config.pkeyopts = sk_OPENSSL_STRING_new_null();
2468edacedfSDaniel Fojt 	if (req_config.pkeyopts == NULL)
2478edacedfSDaniel Fojt 		return (1);
2488edacedfSDaniel Fojt 	if (!sk_OPENSSL_STRING_push(req_config.pkeyopts, arg))
2498edacedfSDaniel Fojt 		return (1);
2508edacedfSDaniel Fojt 	return (0);
2518edacedfSDaniel Fojt }
2528edacedfSDaniel Fojt 
2538edacedfSDaniel Fojt static int
req_opt_reqopt(char * arg)2548edacedfSDaniel Fojt req_opt_reqopt(char *arg)
2558edacedfSDaniel Fojt {
2568edacedfSDaniel Fojt 	if (!set_cert_ex(&req_config.reqflag, arg))
2578edacedfSDaniel Fojt 		return (1);
2588edacedfSDaniel Fojt 	return (0);
2598edacedfSDaniel Fojt }
2608edacedfSDaniel Fojt 
2618edacedfSDaniel Fojt static int
req_opt_set_serial(char * arg)2628edacedfSDaniel Fojt req_opt_set_serial(char *arg)
2638edacedfSDaniel Fojt {
2648edacedfSDaniel Fojt 	req_config.serial = s2i_ASN1_INTEGER(NULL, arg);
2658edacedfSDaniel Fojt 	if (req_config.serial == NULL)
2668edacedfSDaniel Fojt 		return (1);
2678edacedfSDaniel Fojt 	return (0);
2688edacedfSDaniel Fojt }
2698edacedfSDaniel Fojt 
2708edacedfSDaniel Fojt static int
req_opt_sigopt(char * arg)2718edacedfSDaniel Fojt req_opt_sigopt(char *arg)
2728edacedfSDaniel Fojt {
2738edacedfSDaniel Fojt 	if (req_config.sigopts == NULL)
2748edacedfSDaniel Fojt 		req_config.sigopts = sk_OPENSSL_STRING_new_null();
2758edacedfSDaniel Fojt 	if (req_config.sigopts == NULL)
2768edacedfSDaniel Fojt 		return (1);
2778edacedfSDaniel Fojt 	if (!sk_OPENSSL_STRING_push(req_config.sigopts, arg))
2788edacedfSDaniel Fojt 		return (1);
2798edacedfSDaniel Fojt 	return (0);
2808edacedfSDaniel Fojt }
2818edacedfSDaniel Fojt 
2828edacedfSDaniel Fojt static int
req_opt_utf8(void)2838edacedfSDaniel Fojt req_opt_utf8(void)
2848edacedfSDaniel Fojt {
2858edacedfSDaniel Fojt 	req_config.chtype = MBSTRING_UTF8;
2868edacedfSDaniel Fojt 	return (0);
2878edacedfSDaniel Fojt }
2888edacedfSDaniel Fojt 
2898edacedfSDaniel Fojt static const struct option req_options[] = {
2908edacedfSDaniel Fojt 	{
2918edacedfSDaniel Fojt 		.name = "addext",
2928edacedfSDaniel Fojt 		.argname = "key=value",
2938edacedfSDaniel Fojt 		.desc = "Additional certificate extension (may be repeated)",
2948edacedfSDaniel Fojt 		.type = OPTION_ARG_FUNC,
2958edacedfSDaniel Fojt 		.opt.argfunc = req_opt_addext,
2968edacedfSDaniel Fojt 	},
2978edacedfSDaniel Fojt 	{
2988edacedfSDaniel Fojt 		.name = "batch",
2998edacedfSDaniel Fojt 		.desc = "Operate in batch mode",
3008edacedfSDaniel Fojt 		.type = OPTION_FLAG,
3018edacedfSDaniel Fojt 		.opt.flag = &req_config.batch,
3028edacedfSDaniel Fojt 	},
3038edacedfSDaniel Fojt 	{
3048edacedfSDaniel Fojt 		.name = "config",
3058edacedfSDaniel Fojt 		.argname = "file",
3068edacedfSDaniel Fojt 		.desc = "Configuration file to use as request template",
3078edacedfSDaniel Fojt 		.type = OPTION_ARG,
3088edacedfSDaniel Fojt 		.opt.arg = &req_config.template,
3098edacedfSDaniel Fojt 	},
3108edacedfSDaniel Fojt 	{
3118edacedfSDaniel Fojt 		.name = "days",
3128edacedfSDaniel Fojt 		.argname = "number",
3138edacedfSDaniel Fojt 		.desc = "Number of days generated certificate is valid for",
3148edacedfSDaniel Fojt 		.type = OPTION_ARG_FUNC,
3158edacedfSDaniel Fojt 		.opt.argfunc = req_opt_days,
3168edacedfSDaniel Fojt 	},
3178edacedfSDaniel Fojt 	{
3188edacedfSDaniel Fojt 		.name = "extensions",
3198edacedfSDaniel Fojt 		.argname = "section",
3208edacedfSDaniel Fojt 		.desc = "Config section to use for certificate extensions",
3218edacedfSDaniel Fojt 		.type = OPTION_ARG,
3228edacedfSDaniel Fojt 		.opt.arg = &req_config.extensions,
3238edacedfSDaniel Fojt 	},
3248edacedfSDaniel Fojt 	{
3258edacedfSDaniel Fojt 		.name = "in",
3268edacedfSDaniel Fojt 		.argname = "file",
3278edacedfSDaniel Fojt 		.desc = "Input file (default stdin)",
3288edacedfSDaniel Fojt 		.type = OPTION_ARG,
3298edacedfSDaniel Fojt 		.opt.arg = &req_config.infile,
3308edacedfSDaniel Fojt 	},
3318edacedfSDaniel Fojt 	{
3328edacedfSDaniel Fojt 		.name = "inform",
3338edacedfSDaniel Fojt 		.argname = "format",
3348edacedfSDaniel Fojt 		.desc = "Input format (DER or PEM (default))",
3358edacedfSDaniel Fojt 		.type = OPTION_ARG_FORMAT,
3368edacedfSDaniel Fojt 		.opt.value = &req_config.informat,
3378edacedfSDaniel Fojt 	},
3388edacedfSDaniel Fojt 	{
3398edacedfSDaniel Fojt 		.name = "key",
3408edacedfSDaniel Fojt 		.argname = "file",
3418edacedfSDaniel Fojt 		.desc = "Private key file",
3428edacedfSDaniel Fojt 		.type = OPTION_ARG,
3438edacedfSDaniel Fojt 		.opt.arg = &req_config.keyfile,
3448edacedfSDaniel Fojt 	},
3458edacedfSDaniel Fojt 	{
3468edacedfSDaniel Fojt 		.name = "keyform",
3478edacedfSDaniel Fojt 		.argname = "format",
3488edacedfSDaniel Fojt 		.desc = "Private key format (DER or PEM (default))",
3498edacedfSDaniel Fojt 		.type = OPTION_ARG_FORMAT,
3508edacedfSDaniel Fojt 		.opt.value = &req_config.keyform,
3518edacedfSDaniel Fojt 	},
3528edacedfSDaniel Fojt 	{
3538edacedfSDaniel Fojt 		.name = "keyout",
3548edacedfSDaniel Fojt 		.argname = "file",
3558edacedfSDaniel Fojt 		.desc = "Private key output file",
3568edacedfSDaniel Fojt 		.type = OPTION_ARG,
3578edacedfSDaniel Fojt 		.opt.arg = &req_config.keyout,
3588edacedfSDaniel Fojt 	},
3598edacedfSDaniel Fojt 	{
3608edacedfSDaniel Fojt 		.name = "modulus",
3618edacedfSDaniel Fojt 		.desc = "Print RSA modulus",
3628edacedfSDaniel Fojt 		.type = OPTION_FLAG,
3638edacedfSDaniel Fojt 		.opt.flag = &req_config.modulus,
3648edacedfSDaniel Fojt 	},
3658edacedfSDaniel Fojt 	{
3668edacedfSDaniel Fojt 		.name = "multivalue-rdn",
3678edacedfSDaniel Fojt 		.desc = "Enable support for multivalued RDNs",
3688edacedfSDaniel Fojt 		.type = OPTION_FLAG,
3698edacedfSDaniel Fojt 		.opt.flag = &req_config.multirdn,
3708edacedfSDaniel Fojt 	},
3718edacedfSDaniel Fojt 	{
3728edacedfSDaniel Fojt 		.name = "nameopt",
3738edacedfSDaniel Fojt 		.argname = "arg",
3748edacedfSDaniel Fojt 		.desc = "Certificate name options",
3758edacedfSDaniel Fojt 		.type = OPTION_ARG_FUNC,
3768edacedfSDaniel Fojt 		.opt.argfunc = req_opt_nameopt,
3778edacedfSDaniel Fojt 	},
3788edacedfSDaniel Fojt 	{
3798edacedfSDaniel Fojt 		.name = "new",
3808edacedfSDaniel Fojt 		.desc = "New request",
3818edacedfSDaniel Fojt 		.type = OPTION_FLAG,
3828edacedfSDaniel Fojt 		.opt.flag = &req_config.newreq,
3838edacedfSDaniel Fojt 	},
3848edacedfSDaniel Fojt 	{
3858edacedfSDaniel Fojt 		.name = "newhdr",
3868edacedfSDaniel Fojt 		.desc = "Include 'NEW' in header lines",
3878edacedfSDaniel Fojt 		.type = OPTION_FLAG,
3888edacedfSDaniel Fojt 		.opt.flag = &req_config.newhdr,
3898edacedfSDaniel Fojt 	},
3908edacedfSDaniel Fojt 	{
3918edacedfSDaniel Fojt 		.name = "newkey",
3928edacedfSDaniel Fojt 		.argname = "param",
3938edacedfSDaniel Fojt 		.desc = "Generate a new key using given parameters",
3948edacedfSDaniel Fojt 		.type = OPTION_ARG_FUNC,
3958edacedfSDaniel Fojt 		.opt.argfunc = req_opt_newkey,
3968edacedfSDaniel Fojt 	},
3978edacedfSDaniel Fojt 	{
3988edacedfSDaniel Fojt 		.name = "nodes",
3998edacedfSDaniel Fojt 		.desc = "Do not encrypt output private key",
4008edacedfSDaniel Fojt 		.type = OPTION_FLAG,
4018edacedfSDaniel Fojt 		.opt.flag = &req_config.nodes,
4028edacedfSDaniel Fojt 	},
4038edacedfSDaniel Fojt 	{
4048edacedfSDaniel Fojt 		.name = "noout",
4058edacedfSDaniel Fojt 		.desc = "Do not output request",
4068edacedfSDaniel Fojt 		.type = OPTION_FLAG,
4078edacedfSDaniel Fojt 		.opt.flag = &req_config.noout,
4088edacedfSDaniel Fojt 	},
4098edacedfSDaniel Fojt 	{
4108edacedfSDaniel Fojt 		.name = "out",
4118edacedfSDaniel Fojt 		.argname = "file",
4128edacedfSDaniel Fojt 		.desc = "Output file (default stdout)",
4138edacedfSDaniel Fojt 		.type = OPTION_ARG,
4148edacedfSDaniel Fojt 		.opt.arg = &req_config.outfile,
4158edacedfSDaniel Fojt 	},
4168edacedfSDaniel Fojt 	{
4178edacedfSDaniel Fojt 		.name = "outform",
4188edacedfSDaniel Fojt 		.argname = "format",
4198edacedfSDaniel Fojt 		.desc = "Output format (DER or PEM (default))",
4208edacedfSDaniel Fojt 		.type = OPTION_ARG_FORMAT,
4218edacedfSDaniel Fojt 		.opt.value = &req_config.outformat,
4228edacedfSDaniel Fojt 	},
4238edacedfSDaniel Fojt 	{
4248edacedfSDaniel Fojt 		.name = "passin",
4258edacedfSDaniel Fojt 		.argname = "source",
4268edacedfSDaniel Fojt 		.desc = "Private key input password source",
4278edacedfSDaniel Fojt 		.type = OPTION_ARG,
4288edacedfSDaniel Fojt 		.opt.arg = &req_config.passargin,
4298edacedfSDaniel Fojt 	},
4308edacedfSDaniel Fojt 	{
4318edacedfSDaniel Fojt 		.name = "passout",
4328edacedfSDaniel Fojt 		.argname = "source",
4338edacedfSDaniel Fojt 		.desc = "Private key output password source",
4348edacedfSDaniel Fojt 		.type = OPTION_ARG,
4358edacedfSDaniel Fojt 		.opt.arg = &req_config.passargout,
4368edacedfSDaniel Fojt 	},
4378edacedfSDaniel Fojt 	{
4388edacedfSDaniel Fojt 		.name = "pkeyopt",
4398edacedfSDaniel Fojt 		.argname = "opt:val",
4408edacedfSDaniel Fojt 		.desc = "Set the public key algorithm option opt to val",
4418edacedfSDaniel Fojt 		.type = OPTION_ARG_FUNC,
4428edacedfSDaniel Fojt 		.opt.argfunc = req_opt_pkeyopt,
4438edacedfSDaniel Fojt 	},
4448edacedfSDaniel Fojt 	{
4458edacedfSDaniel Fojt 		.name = "pubkey",
4468edacedfSDaniel Fojt 		.desc = "Output the public key",
4478edacedfSDaniel Fojt 		.type = OPTION_FLAG,
4488edacedfSDaniel Fojt 		.opt.flag = &req_config.pubkey,
4498edacedfSDaniel Fojt 	},
4508edacedfSDaniel Fojt 	{
4518edacedfSDaniel Fojt 		.name = "reqexts",
4528edacedfSDaniel Fojt 		.argname = "section",
4538edacedfSDaniel Fojt 		.desc = "Config section to use for request extensions",
4548edacedfSDaniel Fojt 		.type = OPTION_ARG,
4558edacedfSDaniel Fojt 		.opt.arg = &req_config.req_exts,
4568edacedfSDaniel Fojt 	},
4578edacedfSDaniel Fojt 	{
4588edacedfSDaniel Fojt 		.name = "reqopt",
4598edacedfSDaniel Fojt 		.argname = "option",
4608edacedfSDaniel Fojt 		.desc = "Request text options",
4618edacedfSDaniel Fojt 		.type = OPTION_ARG_FUNC,
4628edacedfSDaniel Fojt 		.opt.argfunc = req_opt_reqopt,
4638edacedfSDaniel Fojt 	},
4648edacedfSDaniel Fojt 	{
4658edacedfSDaniel Fojt 		.name = "set_serial",
4668edacedfSDaniel Fojt 		.argname = "serial",
4678edacedfSDaniel Fojt 		.desc = "Serial number to use for generated certificate",
4688edacedfSDaniel Fojt 		.type = OPTION_ARG_FUNC,
4698edacedfSDaniel Fojt 		.opt.argfunc = req_opt_set_serial,
4708edacedfSDaniel Fojt 	},
4718edacedfSDaniel Fojt 	{
4728edacedfSDaniel Fojt 		.name = "sigopt",
4738edacedfSDaniel Fojt 		.argname = "name:val",
4748edacedfSDaniel Fojt 		.desc = "Signature options",
4758edacedfSDaniel Fojt 		.type = OPTION_ARG_FUNC,
4768edacedfSDaniel Fojt 		.opt.argfunc = req_opt_sigopt,
4778edacedfSDaniel Fojt 	},
4788edacedfSDaniel Fojt 	{
4798edacedfSDaniel Fojt 		.name = "subj",
4808edacedfSDaniel Fojt 		.argname = "name",
4818edacedfSDaniel Fojt 		.desc = "Set or modify the request subject",
4828edacedfSDaniel Fojt 		.type = OPTION_ARG,
4838edacedfSDaniel Fojt 		.opt.arg = &req_config.subj,
4848edacedfSDaniel Fojt 	},
4858edacedfSDaniel Fojt 	{
4868edacedfSDaniel Fojt 		.name = "subject",
4878edacedfSDaniel Fojt 		.desc = "Output the subject of the request",
4888edacedfSDaniel Fojt 		.type = OPTION_FLAG,
4898edacedfSDaniel Fojt 		.opt.flag = &req_config.subject,
4908edacedfSDaniel Fojt 	},
4918edacedfSDaniel Fojt 	{
4928edacedfSDaniel Fojt 		.name = "text",
4938edacedfSDaniel Fojt 		.desc = "Print request in text form",
4948edacedfSDaniel Fojt 		.type = OPTION_FLAG,
4958edacedfSDaniel Fojt 		.opt.flag = &req_config.text,
4968edacedfSDaniel Fojt 	},
4978edacedfSDaniel Fojt 	{
4988edacedfSDaniel Fojt 		.name = "utf8",
4998edacedfSDaniel Fojt 		.desc = "Input characters are in UTF-8 (default ASCII)",
5008edacedfSDaniel Fojt 		.type = OPTION_FUNC,
5018edacedfSDaniel Fojt 		.opt.func = req_opt_utf8,
5028edacedfSDaniel Fojt 	},
5038edacedfSDaniel Fojt 	{
5048edacedfSDaniel Fojt 		.name = "verbose",
5058edacedfSDaniel Fojt 		.desc = "Verbose",
5068edacedfSDaniel Fojt 		.type = OPTION_FLAG,
5078edacedfSDaniel Fojt 		.opt.flag = &req_config.verbose,
5088edacedfSDaniel Fojt 	},
5098edacedfSDaniel Fojt 	{
5108edacedfSDaniel Fojt 		.name = "verify",
5118edacedfSDaniel Fojt 		.desc = "Verify signature on request",
5128edacedfSDaniel Fojt 		.type = OPTION_FLAG,
5138edacedfSDaniel Fojt 		.opt.flag = &req_config.verify,
5148edacedfSDaniel Fojt 	},
5158edacedfSDaniel Fojt 	{
5168edacedfSDaniel Fojt 		.name = "x509",
5178edacedfSDaniel Fojt 		.desc = "Output an X.509 structure instead of a certificate request",
5188edacedfSDaniel Fojt 		.type = OPTION_FLAG,
5198edacedfSDaniel Fojt 		.opt.flag = &req_config.x509,
5208edacedfSDaniel Fojt 	},
5218edacedfSDaniel Fojt 	{
5228edacedfSDaniel Fojt 		.name = NULL,
5238edacedfSDaniel Fojt 		.desc = "",
5248edacedfSDaniel Fojt 		.type = OPTION_ARGV_FUNC,
5258edacedfSDaniel Fojt 		.opt.argvfunc = req_opt_digest,
5268edacedfSDaniel Fojt 	},
5278edacedfSDaniel Fojt 	{ NULL },
5288edacedfSDaniel Fojt };
5298edacedfSDaniel Fojt 
5308edacedfSDaniel Fojt static void
req_usage(void)5318edacedfSDaniel Fojt req_usage(void)
5328edacedfSDaniel Fojt {
5338edacedfSDaniel Fojt 	fprintf(stderr,
534*de0e0e4dSAntonio Huete Jimenez 	    "usage: req [-addext ext] [-batch] [-config file]\n"
5358edacedfSDaniel Fojt 	    "    [-days n] [-extensions section] [-in file]\n"
5368edacedfSDaniel Fojt 	    "    [-inform der | pem] [-key keyfile] [-keyform der | pem]\n"
5378edacedfSDaniel Fojt 	    "    [-keyout file] [-md4 | -md5 | -sha1] [-modulus]\n"
5388edacedfSDaniel Fojt 	    "    [-multivalue-rdn] [-nameopt option] [-new] [-newhdr]\n"
539*de0e0e4dSAntonio Huete Jimenez 	    "    [-newkey arg] [-nodes] [-noout]\n"
5408edacedfSDaniel Fojt 	    "    [-out file] [-outform der | pem] [-passin arg]\n"
5418edacedfSDaniel Fojt 	    "    [-passout arg] [-pkeyopt opt:value] [-pubkey]\n"
5428edacedfSDaniel Fojt 	    "    [-reqexts section] [-reqopt option] [-set_serial n]\n"
5438edacedfSDaniel Fojt 	    "    [-sigopt nm:v] [-subj arg] [-subject] [-text] [-utf8]\n"
5448edacedfSDaniel Fojt 	    "    [-verbose] [-verify] [-x509]\n\n");
5458edacedfSDaniel Fojt 
5468edacedfSDaniel Fojt 	options_usage(req_options);
5478edacedfSDaniel Fojt 	fprintf(stderr, "\n");
5488edacedfSDaniel Fojt }
549f5b1c8a1SJohn Marino 
550f5b1c8a1SJohn Marino int
req_main(int argc,char ** argv)551f5b1c8a1SJohn Marino req_main(int argc, char **argv)
552f5b1c8a1SJohn Marino {
5538edacedfSDaniel Fojt 	int ex = 1;
554f5b1c8a1SJohn Marino 	X509 *x509ss = NULL;
555f5b1c8a1SJohn Marino 	X509_REQ *req = NULL;
556f5b1c8a1SJohn Marino 	EVP_PKEY_CTX *genctx = NULL;
557f5b1c8a1SJohn Marino 	char *keyalgstr = NULL;
558f5b1c8a1SJohn Marino 	const EVP_CIPHER *cipher = NULL;
5598edacedfSDaniel Fojt 	EVP_PKEY *pkey = NULL;
5608edacedfSDaniel Fojt 	int i = 0, pkey_type = -1;
5618edacedfSDaniel Fojt 	BIO *in = NULL, *out = NULL;
562f5b1c8a1SJohn Marino 	char *passin = NULL, *passout = NULL;
5638edacedfSDaniel Fojt 	const EVP_MD *md_alg = NULL;
564f5b1c8a1SJohn Marino 	char *p;
565f5b1c8a1SJohn Marino 
566f5b1c8a1SJohn Marino 	if (single_execution) {
56772c33676SMaxim Ag 		if (pledge("stdio cpath wpath rpath tty", NULL) == -1) {
568f5b1c8a1SJohn Marino 			perror("pledge");
569f5b1c8a1SJohn Marino 			exit(1);
570f5b1c8a1SJohn Marino 		}
571f5b1c8a1SJohn Marino 	}
572f5b1c8a1SJohn Marino 
5738edacedfSDaniel Fojt 	memset(&req_config, 0, sizeof(req_config));
5748edacedfSDaniel Fojt 
5758edacedfSDaniel Fojt 	req_config.chtype = MBSTRING_ASC;
5768edacedfSDaniel Fojt 	req_config.days = 30;
5778edacedfSDaniel Fojt 	req_config.digest = EVP_sha256();
5788edacedfSDaniel Fojt 	req_config.newkey = -1;
5798edacedfSDaniel Fojt 	req_config.informat = FORMAT_PEM;
5808edacedfSDaniel Fojt 	req_config.keyform = FORMAT_PEM;
5818edacedfSDaniel Fojt 	req_config.outformat = FORMAT_PEM;
5828edacedfSDaniel Fojt 
5838edacedfSDaniel Fojt 	if (options_parse(argc, argv, req_options, NULL, NULL) != 0) {
5848edacedfSDaniel Fojt 		req_usage();
5858edacedfSDaniel Fojt 		return (1);
5868edacedfSDaniel Fojt 	}
5878edacedfSDaniel Fojt 
588f5b1c8a1SJohn Marino 	req_conf = NULL;
589f5b1c8a1SJohn Marino 	cipher = EVP_aes_256_cbc();
590f5b1c8a1SJohn Marino 
5918edacedfSDaniel Fojt 	if (!app_passwd(bio_err, req_config.passargin, req_config.passargout, &passin, &passout)) {
592f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "Error getting passwords\n");
593f5b1c8a1SJohn Marino 		goto end;
594f5b1c8a1SJohn Marino 	}
5958edacedfSDaniel Fojt 	if (req_config.template != NULL) {
596f5b1c8a1SJohn Marino 		long errline = -1;
597f5b1c8a1SJohn Marino 
5988edacedfSDaniel Fojt 		if (req_config.verbose)
5998edacedfSDaniel Fojt 			BIO_printf(bio_err, "Using configuration from %s\n", req_config.template);
600cca6fc52SDaniel Fojt 		if ((req_conf = NCONF_new(NULL)) == NULL)
601cca6fc52SDaniel Fojt 			goto end;
6028edacedfSDaniel Fojt 		if(!NCONF_load(req_conf, req_config.template, &errline)) {
6038edacedfSDaniel Fojt 			BIO_printf(bio_err, "error on line %ld of %s\n", errline, req_config.template);
604f5b1c8a1SJohn Marino 			goto end;
605f5b1c8a1SJohn Marino 		}
606f5b1c8a1SJohn Marino 	} else {
607f5b1c8a1SJohn Marino 		req_conf = config;
608f5b1c8a1SJohn Marino 
609f5b1c8a1SJohn Marino 		if (req_conf == NULL) {
610f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "Unable to load config info from %s\n", default_config_file);
6118edacedfSDaniel Fojt 			if (req_config.newreq)
612f5b1c8a1SJohn Marino 				goto end;
6138edacedfSDaniel Fojt 		} else if (req_config.verbose)
614f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "Using configuration from %s\n",
615f5b1c8a1SJohn Marino 			    default_config_file);
616f5b1c8a1SJohn Marino 	}
617f5b1c8a1SJohn Marino 
6188edacedfSDaniel Fojt 	if (req_config.addext_bio != NULL) {
619cca6fc52SDaniel Fojt 		long errline = -1;
6208edacedfSDaniel Fojt 		if (req_config.verbose)
621cca6fc52SDaniel Fojt 			BIO_printf(bio_err,
622cca6fc52SDaniel Fojt 			    "Using additional configuration from command line\n");
623cca6fc52SDaniel Fojt 		if ((addext_conf = NCONF_new(NULL)) == NULL)
624cca6fc52SDaniel Fojt 			goto end;
6258edacedfSDaniel Fojt 		if (!NCONF_load_bio(addext_conf, req_config.addext_bio, &errline)) {
626cca6fc52SDaniel Fojt 			BIO_printf(bio_err,
627cca6fc52SDaniel Fojt 			    "req: Error on line %ld of config input\n",
628cca6fc52SDaniel Fojt 			    errline);
629cca6fc52SDaniel Fojt 			goto end;
630cca6fc52SDaniel Fojt 		}
631cca6fc52SDaniel Fojt 	}
632cca6fc52SDaniel Fojt 
633f5b1c8a1SJohn Marino 	if (req_conf != NULL) {
634f5b1c8a1SJohn Marino 		if (!load_config(bio_err, req_conf))
635f5b1c8a1SJohn Marino 			goto end;
636f5b1c8a1SJohn Marino 		p = NCONF_get_string(req_conf, NULL, "oid_file");
637f5b1c8a1SJohn Marino 		if (p == NULL)
638f5b1c8a1SJohn Marino 			ERR_clear_error();
639f5b1c8a1SJohn Marino 		if (p != NULL) {
640f5b1c8a1SJohn Marino 			BIO *oid_bio;
641f5b1c8a1SJohn Marino 
642f5b1c8a1SJohn Marino 			oid_bio = BIO_new_file(p, "r");
643f5b1c8a1SJohn Marino 			if (oid_bio == NULL) {
644f5b1c8a1SJohn Marino 				/*
645f5b1c8a1SJohn Marino 				BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
646f5b1c8a1SJohn Marino 				ERR_print_errors(bio_err);
647f5b1c8a1SJohn Marino 				*/
648f5b1c8a1SJohn Marino 			} else {
649f5b1c8a1SJohn Marino 				OBJ_create_objects(oid_bio);
650f5b1c8a1SJohn Marino 				BIO_free(oid_bio);
651f5b1c8a1SJohn Marino 			}
652f5b1c8a1SJohn Marino 		}
653f5b1c8a1SJohn Marino 	}
654f5b1c8a1SJohn Marino 	if (!add_oid_section(bio_err, req_conf))
655f5b1c8a1SJohn Marino 		goto end;
656f5b1c8a1SJohn Marino 
657f5b1c8a1SJohn Marino 	if (md_alg == NULL) {
658f5b1c8a1SJohn Marino 		p = NCONF_get_string(req_conf, SECTION, "default_md");
659f5b1c8a1SJohn Marino 		if (p == NULL)
660f5b1c8a1SJohn Marino 			ERR_clear_error();
661f5b1c8a1SJohn Marino 		if (p != NULL) {
662f5b1c8a1SJohn Marino 			if ((md_alg = EVP_get_digestbyname(p)) != NULL)
6638edacedfSDaniel Fojt 				req_config.digest = md_alg;
664f5b1c8a1SJohn Marino 		}
665f5b1c8a1SJohn Marino 	}
6668edacedfSDaniel Fojt 	if (!req_config.extensions) {
6678edacedfSDaniel Fojt 		req_config.extensions = NCONF_get_string(req_conf, SECTION, V3_EXTENSIONS);
6688edacedfSDaniel Fojt 		if (!req_config.extensions)
669f5b1c8a1SJohn Marino 			ERR_clear_error();
670f5b1c8a1SJohn Marino 	}
6718edacedfSDaniel Fojt 	if (req_config.extensions) {
672f5b1c8a1SJohn Marino 		/* Check syntax of file */
673f5b1c8a1SJohn Marino 		X509V3_CTX ctx;
674f5b1c8a1SJohn Marino 		X509V3_set_ctx_test(&ctx);
675f5b1c8a1SJohn Marino 		X509V3_set_nconf(&ctx, req_conf);
6768edacedfSDaniel Fojt 		if (!X509V3_EXT_add_nconf(req_conf, &ctx, req_config.extensions, NULL)) {
677f5b1c8a1SJohn Marino 			BIO_printf(bio_err,
6788edacedfSDaniel Fojt 			    "Error Loading extension section %s\n", req_config.extensions);
679f5b1c8a1SJohn Marino 			goto end;
680f5b1c8a1SJohn Marino 		}
681f5b1c8a1SJohn Marino 	}
682cca6fc52SDaniel Fojt 	if (addext_conf != NULL) {
683cca6fc52SDaniel Fojt 		/* Check syntax of command line extensions */
684cca6fc52SDaniel Fojt 		X509V3_CTX ctx;
685cca6fc52SDaniel Fojt 		X509V3_set_ctx_test(&ctx);
686cca6fc52SDaniel Fojt 		X509V3_set_nconf(&ctx, addext_conf);
687cca6fc52SDaniel Fojt 		if (!X509V3_EXT_add_nconf(addext_conf, &ctx, "default", NULL)) {
688cca6fc52SDaniel Fojt 			BIO_printf(bio_err,
689cca6fc52SDaniel Fojt 			    "Error Loading command line extensions\n");
690cca6fc52SDaniel Fojt 			goto end;
691cca6fc52SDaniel Fojt 		}
692cca6fc52SDaniel Fojt 	}
693f5b1c8a1SJohn Marino 	if (!passin) {
694f5b1c8a1SJohn Marino 		passin = NCONF_get_string(req_conf, SECTION, "input_password");
695f5b1c8a1SJohn Marino 		if (!passin)
696f5b1c8a1SJohn Marino 			ERR_clear_error();
697f5b1c8a1SJohn Marino 	}
698f5b1c8a1SJohn Marino 	if (!passout) {
699f5b1c8a1SJohn Marino 		passout = NCONF_get_string(req_conf, SECTION, "output_password");
700f5b1c8a1SJohn Marino 		if (!passout)
701f5b1c8a1SJohn Marino 			ERR_clear_error();
702f5b1c8a1SJohn Marino 	}
703f5b1c8a1SJohn Marino 	p = NCONF_get_string(req_conf, SECTION, STRING_MASK);
704f5b1c8a1SJohn Marino 	if (!p)
705f5b1c8a1SJohn Marino 		ERR_clear_error();
706f5b1c8a1SJohn Marino 
707f5b1c8a1SJohn Marino 	if (p && !ASN1_STRING_set_default_mask_asc(p)) {
708f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "Invalid global string mask setting %s\n", p);
709f5b1c8a1SJohn Marino 		goto end;
710f5b1c8a1SJohn Marino 	}
7118edacedfSDaniel Fojt 	if (req_config.chtype != MBSTRING_UTF8) {
712f5b1c8a1SJohn Marino 		p = NCONF_get_string(req_conf, SECTION, UTF8_IN);
713f5b1c8a1SJohn Marino 		if (!p)
714f5b1c8a1SJohn Marino 			ERR_clear_error();
715f5b1c8a1SJohn Marino 		else if (!strcmp(p, "yes"))
7168edacedfSDaniel Fojt 			req_config.chtype = MBSTRING_UTF8;
717f5b1c8a1SJohn Marino 	}
7188edacedfSDaniel Fojt 	if (!req_config.req_exts) {
7198edacedfSDaniel Fojt 		req_config.req_exts = NCONF_get_string(req_conf, SECTION, REQ_EXTENSIONS);
7208edacedfSDaniel Fojt 		if (!req_config.req_exts)
721f5b1c8a1SJohn Marino 			ERR_clear_error();
722f5b1c8a1SJohn Marino 	}
7238edacedfSDaniel Fojt 	if (req_config.req_exts) {
724f5b1c8a1SJohn Marino 		/* Check syntax of file */
725f5b1c8a1SJohn Marino 		X509V3_CTX ctx;
726f5b1c8a1SJohn Marino 		X509V3_set_ctx_test(&ctx);
727f5b1c8a1SJohn Marino 		X509V3_set_nconf(&ctx, req_conf);
7288edacedfSDaniel Fojt 		if (!X509V3_EXT_add_nconf(req_conf, &ctx, req_config.req_exts, NULL)) {
729f5b1c8a1SJohn Marino 			BIO_printf(bio_err,
730f5b1c8a1SJohn Marino 			    "Error Loading request extension section %s\n",
7318edacedfSDaniel Fojt 			    req_config.req_exts);
732f5b1c8a1SJohn Marino 			goto end;
733f5b1c8a1SJohn Marino 		}
734f5b1c8a1SJohn Marino 	}
735f5b1c8a1SJohn Marino 	in = BIO_new(BIO_s_file());
736f5b1c8a1SJohn Marino 	out = BIO_new(BIO_s_file());
737f5b1c8a1SJohn Marino 	if ((in == NULL) || (out == NULL))
738f5b1c8a1SJohn Marino 		goto end;
739f5b1c8a1SJohn Marino 
7408edacedfSDaniel Fojt 	if (req_config.keyfile != NULL) {
7418edacedfSDaniel Fojt 		pkey = load_key(bio_err, req_config.keyfile, req_config.keyform, 0, passin,
742f5b1c8a1SJohn Marino 		    "Private Key");
743f5b1c8a1SJohn Marino 		if (!pkey) {
744f5b1c8a1SJohn Marino 			/*
745f5b1c8a1SJohn Marino 			 * load_key() has already printed an appropriate
746f5b1c8a1SJohn Marino 			 * message
747f5b1c8a1SJohn Marino 			 */
748f5b1c8a1SJohn Marino 			goto end;
749f5b1c8a1SJohn Marino 		}
750f5b1c8a1SJohn Marino 	}
7518edacedfSDaniel Fojt 	if (req_config.newreq && (pkey == NULL)) {
7528edacedfSDaniel Fojt 		if (!NCONF_get_number(req_conf, SECTION, BITS, &req_config.newkey)) {
7538edacedfSDaniel Fojt 			req_config.newkey = DEFAULT_KEY_LENGTH;
754f5b1c8a1SJohn Marino 		}
7558edacedfSDaniel Fojt 		if (req_config.keyalg) {
7568edacedfSDaniel Fojt 			genctx = set_keygen_ctx(bio_err, req_config.keyalg, &pkey_type, &req_config.newkey,
757f5b1c8a1SJohn Marino 			    &keyalgstr);
758f5b1c8a1SJohn Marino 			if (!genctx)
759f5b1c8a1SJohn Marino 				goto end;
760f5b1c8a1SJohn Marino 		}
7618edacedfSDaniel Fojt 		if (req_config.newkey < MIN_KEY_LENGTH && (pkey_type == EVP_PKEY_RSA || pkey_type == EVP_PKEY_DSA)) {
762f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "private key length is too short,\n");
7638edacedfSDaniel Fojt 			BIO_printf(bio_err, "it needs to be at least %d bits, not %ld\n", MIN_KEY_LENGTH, req_config.newkey);
764f5b1c8a1SJohn Marino 			goto end;
765f5b1c8a1SJohn Marino 		}
766f5b1c8a1SJohn Marino 		if (!genctx) {
7678edacedfSDaniel Fojt 			genctx = set_keygen_ctx(bio_err, NULL, &pkey_type, &req_config.newkey,
768f5b1c8a1SJohn Marino 			    &keyalgstr);
769f5b1c8a1SJohn Marino 			if (!genctx)
770f5b1c8a1SJohn Marino 				goto end;
771f5b1c8a1SJohn Marino 		}
7728edacedfSDaniel Fojt 		if (req_config.pkeyopts) {
773f5b1c8a1SJohn Marino 			char *genopt;
7748edacedfSDaniel Fojt 			for (i = 0; i < sk_OPENSSL_STRING_num(req_config.pkeyopts); i++) {
7758edacedfSDaniel Fojt 				genopt = sk_OPENSSL_STRING_value(req_config.pkeyopts, i);
776f5b1c8a1SJohn Marino 				if (pkey_ctrl_string(genctx, genopt) <= 0) {
777f5b1c8a1SJohn Marino 					BIO_printf(bio_err,
778f5b1c8a1SJohn Marino 					    "parameter error \"%s\"\n",
779f5b1c8a1SJohn Marino 					    genopt);
780f5b1c8a1SJohn Marino 					ERR_print_errors(bio_err);
781f5b1c8a1SJohn Marino 					goto end;
782f5b1c8a1SJohn Marino 				}
783f5b1c8a1SJohn Marino 			}
784f5b1c8a1SJohn Marino 		}
785f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "Generating a %ld bit %s private key\n",
7868edacedfSDaniel Fojt 		    req_config.newkey, keyalgstr);
787f5b1c8a1SJohn Marino 
788f5b1c8a1SJohn Marino 		EVP_PKEY_CTX_set_cb(genctx, genpkey_cb);
789f5b1c8a1SJohn Marino 		EVP_PKEY_CTX_set_app_data(genctx, bio_err);
790f5b1c8a1SJohn Marino 
791f5b1c8a1SJohn Marino 		if (EVP_PKEY_keygen(genctx, &pkey) <= 0) {
792f5b1c8a1SJohn Marino 			BIO_puts(bio_err, "Error Generating Key\n");
793f5b1c8a1SJohn Marino 			goto end;
794f5b1c8a1SJohn Marino 		}
795f5b1c8a1SJohn Marino 		EVP_PKEY_CTX_free(genctx);
796f5b1c8a1SJohn Marino 		genctx = NULL;
797f5b1c8a1SJohn Marino 
7988edacedfSDaniel Fojt 		if (req_config.keyout == NULL) {
7998edacedfSDaniel Fojt 			req_config.keyout = NCONF_get_string(req_conf, SECTION, KEYFILE);
8008edacedfSDaniel Fojt 			if (req_config.keyout == NULL)
801f5b1c8a1SJohn Marino 				ERR_clear_error();
802f5b1c8a1SJohn Marino 		}
8038edacedfSDaniel Fojt 		if (req_config.keyout == NULL) {
804f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "writing new private key to stdout\n");
805f5b1c8a1SJohn Marino 			BIO_set_fp(out, stdout, BIO_NOCLOSE);
806f5b1c8a1SJohn Marino 		} else {
8078edacedfSDaniel Fojt 			BIO_printf(bio_err, "writing new private key to '%s'\n", req_config.keyout);
8088edacedfSDaniel Fojt 			if (BIO_write_filename(out, req_config.keyout) <= 0) {
8098edacedfSDaniel Fojt 				perror(req_config.keyout);
810f5b1c8a1SJohn Marino 				goto end;
811f5b1c8a1SJohn Marino 			}
812f5b1c8a1SJohn Marino 		}
813f5b1c8a1SJohn Marino 
814f5b1c8a1SJohn Marino 		p = NCONF_get_string(req_conf, SECTION, "encrypt_rsa_key");
815f5b1c8a1SJohn Marino 		if (p == NULL) {
816f5b1c8a1SJohn Marino 			ERR_clear_error();
817f5b1c8a1SJohn Marino 			p = NCONF_get_string(req_conf, SECTION, "encrypt_key");
818f5b1c8a1SJohn Marino 			if (p == NULL)
819f5b1c8a1SJohn Marino 				ERR_clear_error();
820f5b1c8a1SJohn Marino 		}
821f5b1c8a1SJohn Marino 		if ((p != NULL) && (strcmp(p, "no") == 0))
822f5b1c8a1SJohn Marino 			cipher = NULL;
8238edacedfSDaniel Fojt 		if (req_config.nodes)
824f5b1c8a1SJohn Marino 			cipher = NULL;
825f5b1c8a1SJohn Marino 
826f5b1c8a1SJohn Marino 		i = 0;
827f5b1c8a1SJohn Marino  loop:
828f5b1c8a1SJohn Marino 		if (!PEM_write_bio_PrivateKey(out, pkey, cipher,
829f5b1c8a1SJohn Marino 			NULL, 0, NULL, passout)) {
830f5b1c8a1SJohn Marino 			if ((ERR_GET_REASON(ERR_peek_error()) ==
831f5b1c8a1SJohn Marino 				PEM_R_PROBLEMS_GETTING_PASSWORD) && (i < 3)) {
832f5b1c8a1SJohn Marino 				ERR_clear_error();
833f5b1c8a1SJohn Marino 				i++;
834f5b1c8a1SJohn Marino 				goto loop;
835f5b1c8a1SJohn Marino 			}
836f5b1c8a1SJohn Marino 			goto end;
837f5b1c8a1SJohn Marino 		}
838f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "-----\n");
839f5b1c8a1SJohn Marino 	}
8408edacedfSDaniel Fojt 	if (!req_config.newreq) {
8418edacedfSDaniel Fojt 		if (req_config.infile == NULL)
842f5b1c8a1SJohn Marino 			BIO_set_fp(in, stdin, BIO_NOCLOSE);
843f5b1c8a1SJohn Marino 		else {
8448edacedfSDaniel Fojt 			if (BIO_read_filename(in, req_config.infile) <= 0) {
8458edacedfSDaniel Fojt 				perror(req_config.infile);
846f5b1c8a1SJohn Marino 				goto end;
847f5b1c8a1SJohn Marino 			}
848f5b1c8a1SJohn Marino 		}
849f5b1c8a1SJohn Marino 
8508edacedfSDaniel Fojt 		if (req_config.informat == FORMAT_ASN1)
851f5b1c8a1SJohn Marino 			req = d2i_X509_REQ_bio(in, NULL);
8528edacedfSDaniel Fojt 		else if (req_config.informat == FORMAT_PEM)
853f5b1c8a1SJohn Marino 			req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
854f5b1c8a1SJohn Marino 		else {
855f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "bad input format specified for X509 request\n");
856f5b1c8a1SJohn Marino 			goto end;
857f5b1c8a1SJohn Marino 		}
858f5b1c8a1SJohn Marino 		if (req == NULL) {
859f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "unable to load X509 request\n");
860f5b1c8a1SJohn Marino 			goto end;
861f5b1c8a1SJohn Marino 		}
862f5b1c8a1SJohn Marino 	}
8638edacedfSDaniel Fojt 	if (req_config.newreq || req_config.x509) {
864f5b1c8a1SJohn Marino 		if (pkey == NULL) {
865f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "you need to specify a private key\n");
866f5b1c8a1SJohn Marino 			goto end;
867f5b1c8a1SJohn Marino 		}
868f5b1c8a1SJohn Marino 		if (req == NULL) {
869f5b1c8a1SJohn Marino 			req = X509_REQ_new();
870f5b1c8a1SJohn Marino 			if (req == NULL) {
871f5b1c8a1SJohn Marino 				goto end;
872f5b1c8a1SJohn Marino 			}
8738edacedfSDaniel Fojt 			i = make_REQ(req, pkey, req_config.subj, req_config.multirdn, !req_config.x509, req_config.chtype);
8748edacedfSDaniel Fojt 			req_config.subj = NULL;	/* done processing '-subj' option */
875f5b1c8a1SJohn Marino 			if (!i) {
876f5b1c8a1SJohn Marino 				BIO_printf(bio_err, "problems making Certificate Request\n");
877f5b1c8a1SJohn Marino 				goto end;
878f5b1c8a1SJohn Marino 			}
879f5b1c8a1SJohn Marino 		}
8808edacedfSDaniel Fojt 		if (req_config.x509) {
881f5b1c8a1SJohn Marino 			EVP_PKEY *tmppkey;
882*de0e0e4dSAntonio Huete Jimenez 
883f5b1c8a1SJohn Marino 			X509V3_CTX ext_ctx;
884f5b1c8a1SJohn Marino 			if ((x509ss = X509_new()) == NULL)
885f5b1c8a1SJohn Marino 				goto end;
886f5b1c8a1SJohn Marino 
887f5b1c8a1SJohn Marino 			/* Set version to V3 */
8888edacedfSDaniel Fojt 			if ((req_config.extensions != NULL || addext_conf != NULL) &&
889cca6fc52SDaniel Fojt 			    !X509_set_version(x509ss, 2))
890f5b1c8a1SJohn Marino 				goto end;
8918edacedfSDaniel Fojt 			if (req_config.serial) {
8928edacedfSDaniel Fojt 				if (!X509_set_serialNumber(x509ss, req_config.serial))
893f5b1c8a1SJohn Marino 					goto end;
894f5b1c8a1SJohn Marino 			} else {
895f5b1c8a1SJohn Marino 				if (!rand_serial(NULL,
896f5b1c8a1SJohn Marino 					X509_get_serialNumber(x509ss)))
897f5b1c8a1SJohn Marino 					goto end;
898f5b1c8a1SJohn Marino 			}
899f5b1c8a1SJohn Marino 
900f5b1c8a1SJohn Marino 			if (!X509_set_issuer_name(x509ss, X509_REQ_get_subject_name(req)))
901f5b1c8a1SJohn Marino 				goto end;
902f5b1c8a1SJohn Marino 			if (!X509_gmtime_adj(X509_get_notBefore(x509ss), 0))
903f5b1c8a1SJohn Marino 				goto end;
9048edacedfSDaniel Fojt 			if (!X509_time_adj_ex(X509_get_notAfter(x509ss), req_config.days, 0, NULL))
905f5b1c8a1SJohn Marino 				goto end;
906f5b1c8a1SJohn Marino 			if (!X509_set_subject_name(x509ss, X509_REQ_get_subject_name(req)))
907f5b1c8a1SJohn Marino 				goto end;
908*de0e0e4dSAntonio Huete Jimenez 			if ((tmppkey = X509_REQ_get0_pubkey(req)) == NULL)
909f5b1c8a1SJohn Marino 				goto end;
910*de0e0e4dSAntonio Huete Jimenez 			if (!X509_set_pubkey(x509ss, tmppkey))
911*de0e0e4dSAntonio Huete Jimenez 				goto end;
912f5b1c8a1SJohn Marino 
913f5b1c8a1SJohn Marino 			/* Set up V3 context struct */
914f5b1c8a1SJohn Marino 
915f5b1c8a1SJohn Marino 			X509V3_set_ctx(&ext_ctx, x509ss, x509ss, NULL, NULL, 0);
916f5b1c8a1SJohn Marino 			X509V3_set_nconf(&ext_ctx, req_conf);
917f5b1c8a1SJohn Marino 
918f5b1c8a1SJohn Marino 			/* Add extensions */
9198edacedfSDaniel Fojt 			if (req_config.extensions && !X509V3_EXT_add_nconf(req_conf,
9208edacedfSDaniel Fojt 				&ext_ctx, req_config.extensions, x509ss)) {
921f5b1c8a1SJohn Marino 				BIO_printf(bio_err,
922f5b1c8a1SJohn Marino 				    "Error Loading extension section %s\n",
9238edacedfSDaniel Fojt 				    req_config.extensions);
924f5b1c8a1SJohn Marino 				goto end;
925f5b1c8a1SJohn Marino 			}
926cca6fc52SDaniel Fojt 			if (addext_conf != NULL &&
927cca6fc52SDaniel Fojt 			    !X509V3_EXT_add_nconf(addext_conf, &ext_ctx,
928cca6fc52SDaniel Fojt 				    "default", x509ss)) {
929cca6fc52SDaniel Fojt 				BIO_printf(bio_err,
930cca6fc52SDaniel Fojt 				    "Error Loading command line extensions\n");
931cca6fc52SDaniel Fojt 				goto end;
932cca6fc52SDaniel Fojt 			}
9338edacedfSDaniel Fojt 			i = do_X509_sign(bio_err, x509ss, pkey, req_config.digest, req_config.sigopts);
934f5b1c8a1SJohn Marino 			if (!i) {
935f5b1c8a1SJohn Marino 				ERR_print_errors(bio_err);
936f5b1c8a1SJohn Marino 				goto end;
937f5b1c8a1SJohn Marino 			}
938f5b1c8a1SJohn Marino 		} else {
939f5b1c8a1SJohn Marino 			X509V3_CTX ext_ctx;
940f5b1c8a1SJohn Marino 
941f5b1c8a1SJohn Marino 			/* Set up V3 context struct */
942f5b1c8a1SJohn Marino 
943f5b1c8a1SJohn Marino 			X509V3_set_ctx(&ext_ctx, NULL, NULL, req, NULL, 0);
944f5b1c8a1SJohn Marino 			X509V3_set_nconf(&ext_ctx, req_conf);
945f5b1c8a1SJohn Marino 
946f5b1c8a1SJohn Marino 			/* Add extensions */
9478edacedfSDaniel Fojt 			if (req_config.req_exts && !X509V3_EXT_REQ_add_nconf(req_conf,
9488edacedfSDaniel Fojt 				&ext_ctx, req_config.req_exts, req)) {
949f5b1c8a1SJohn Marino 				BIO_printf(bio_err,
950f5b1c8a1SJohn Marino 				    "Error Loading extension section %s\n",
9518edacedfSDaniel Fojt 				    req_config.req_exts);
952f5b1c8a1SJohn Marino 				goto end;
953f5b1c8a1SJohn Marino 			}
954cca6fc52SDaniel Fojt 			if (addext_conf != NULL &&
955cca6fc52SDaniel Fojt 			    !X509V3_EXT_REQ_add_nconf(addext_conf, &ext_ctx,
956cca6fc52SDaniel Fojt 				    "default", req)) {
957cca6fc52SDaniel Fojt 				BIO_printf(bio_err,
958cca6fc52SDaniel Fojt 				    "Error Loading command line extensions\n");
959cca6fc52SDaniel Fojt 				goto end;
960cca6fc52SDaniel Fojt 			}
9618edacedfSDaniel Fojt 			i = do_X509_REQ_sign(bio_err, req, pkey, req_config.digest, req_config.sigopts);
962f5b1c8a1SJohn Marino 			if (!i) {
963f5b1c8a1SJohn Marino 				ERR_print_errors(bio_err);
964f5b1c8a1SJohn Marino 				goto end;
965f5b1c8a1SJohn Marino 			}
966f5b1c8a1SJohn Marino 		}
967f5b1c8a1SJohn Marino 	}
9688edacedfSDaniel Fojt 	if (req_config.subj && req_config.x509) {
9698edacedfSDaniel Fojt 		BIO_printf(bio_err, "Cannot modify certificate subject\n");
970f5b1c8a1SJohn Marino 		goto end;
971f5b1c8a1SJohn Marino 	}
9728edacedfSDaniel Fojt 	if (req_config.subj && !req_config.x509) {
9738edacedfSDaniel Fojt 		if (req_config.verbose) {
974f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "Modifying Request's Subject\n");
9758edacedfSDaniel Fojt 			print_name(bio_err, "old subject=", X509_REQ_get_subject_name(req), req_config.nmflag);
976f5b1c8a1SJohn Marino 		}
9778edacedfSDaniel Fojt 		if (build_subject(req, req_config.subj, req_config.chtype, req_config.multirdn) == 0) {
978f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "ERROR: cannot modify subject\n");
979f5b1c8a1SJohn Marino 			ex = 1;
980f5b1c8a1SJohn Marino 			goto end;
981f5b1c8a1SJohn Marino 		}
982f5b1c8a1SJohn Marino 
9838edacedfSDaniel Fojt 		if (req_config.verbose) {
9848edacedfSDaniel Fojt 			print_name(bio_err, "new subject=", X509_REQ_get_subject_name(req), req_config.nmflag);
985f5b1c8a1SJohn Marino 		}
986f5b1c8a1SJohn Marino 	}
9878edacedfSDaniel Fojt 	if (req_config.verify && !req_config.x509) {
988*de0e0e4dSAntonio Huete Jimenez 		EVP_PKEY *pubkey = pkey;
989f5b1c8a1SJohn Marino 
990*de0e0e4dSAntonio Huete Jimenez 		if (pubkey == NULL)
991*de0e0e4dSAntonio Huete Jimenez 			pubkey = X509_REQ_get0_pubkey(req);
992*de0e0e4dSAntonio Huete Jimenez 		if (pubkey == NULL)
993f5b1c8a1SJohn Marino 			goto end;
994*de0e0e4dSAntonio Huete Jimenez 		i = X509_REQ_verify(req, pubkey);
995f5b1c8a1SJohn Marino 		if (i < 0) {
996f5b1c8a1SJohn Marino 			goto end;
997f5b1c8a1SJohn Marino 		} else if (i == 0) {
998f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "verify failure\n");
999f5b1c8a1SJohn Marino 			ERR_print_errors(bio_err);
1000f5b1c8a1SJohn Marino 		} else		/* if (i > 0) */
1001f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "verify OK\n");
1002f5b1c8a1SJohn Marino 	}
10038edacedfSDaniel Fojt 	if (req_config.noout && !req_config.text && !req_config.modulus && !req_config.subject && !req_config.pubkey) {
1004f5b1c8a1SJohn Marino 		ex = 0;
1005f5b1c8a1SJohn Marino 		goto end;
1006f5b1c8a1SJohn Marino 	}
10078edacedfSDaniel Fojt 	if (req_config.outfile == NULL) {
1008f5b1c8a1SJohn Marino 		BIO_set_fp(out, stdout, BIO_NOCLOSE);
1009f5b1c8a1SJohn Marino 	} else {
10108edacedfSDaniel Fojt 		if ((req_config.keyout != NULL) && (strcmp(req_config.outfile, req_config.keyout) == 0))
10118edacedfSDaniel Fojt 			i = (int) BIO_append_filename(out, req_config.outfile);
1012f5b1c8a1SJohn Marino 		else
10138edacedfSDaniel Fojt 			i = (int) BIO_write_filename(out, req_config.outfile);
1014f5b1c8a1SJohn Marino 		if (!i) {
10158edacedfSDaniel Fojt 			perror(req_config.outfile);
1016f5b1c8a1SJohn Marino 			goto end;
1017f5b1c8a1SJohn Marino 		}
1018f5b1c8a1SJohn Marino 	}
1019f5b1c8a1SJohn Marino 
10208edacedfSDaniel Fojt 	if (req_config.pubkey) {
1021f5b1c8a1SJohn Marino 		EVP_PKEY *tpubkey;
1022*de0e0e4dSAntonio Huete Jimenez 
1023*de0e0e4dSAntonio Huete Jimenez 		if ((tpubkey = X509_REQ_get0_pubkey(req)) == NULL) {
1024f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "Error getting public key\n");
1025f5b1c8a1SJohn Marino 			ERR_print_errors(bio_err);
1026f5b1c8a1SJohn Marino 			goto end;
1027f5b1c8a1SJohn Marino 		}
1028f5b1c8a1SJohn Marino 		PEM_write_bio_PUBKEY(out, tpubkey);
1029f5b1c8a1SJohn Marino 	}
10308edacedfSDaniel Fojt 	if (req_config.text) {
10318edacedfSDaniel Fojt 		if (req_config.x509)
10328edacedfSDaniel Fojt 			X509_print_ex(out, x509ss, req_config.nmflag, req_config.reqflag);
1033f5b1c8a1SJohn Marino 		else
10348edacedfSDaniel Fojt 			X509_REQ_print_ex(out, req, req_config.nmflag, req_config.reqflag);
1035f5b1c8a1SJohn Marino 	}
10368edacedfSDaniel Fojt 	if (req_config.subject) {
10378edacedfSDaniel Fojt 		if (req_config.x509)
10388edacedfSDaniel Fojt 			print_name(out, "subject=", X509_get_subject_name(x509ss), req_config.nmflag);
1039f5b1c8a1SJohn Marino 		else
10408edacedfSDaniel Fojt 			print_name(out, "subject=", X509_REQ_get_subject_name(req), req_config.nmflag);
1041f5b1c8a1SJohn Marino 	}
10428edacedfSDaniel Fojt 	if (req_config.modulus) {
1043f5b1c8a1SJohn Marino 		EVP_PKEY *tpubkey;
1044f5b1c8a1SJohn Marino 
10458edacedfSDaniel Fojt 		if (req_config.x509)
1046*de0e0e4dSAntonio Huete Jimenez 			tpubkey = X509_get0_pubkey(x509ss);
1047f5b1c8a1SJohn Marino 		else
1048*de0e0e4dSAntonio Huete Jimenez 			tpubkey = X509_REQ_get0_pubkey(req);
1049f5b1c8a1SJohn Marino 		if (tpubkey == NULL) {
1050f5b1c8a1SJohn Marino 			fprintf(stdout, "Modulus=unavailable\n");
1051f5b1c8a1SJohn Marino 			goto end;
1052f5b1c8a1SJohn Marino 		}
1053f5b1c8a1SJohn Marino 		fprintf(stdout, "Modulus=");
1054*de0e0e4dSAntonio Huete Jimenez 		if (EVP_PKEY_base_id(tpubkey) == EVP_PKEY_RSA) {
1055*de0e0e4dSAntonio Huete Jimenez 			const BIGNUM *n = NULL;
1056*de0e0e4dSAntonio Huete Jimenez 
1057*de0e0e4dSAntonio Huete Jimenez 			RSA_get0_key(EVP_PKEY_get0_RSA(tpubkey), &n, NULL, NULL);
1058*de0e0e4dSAntonio Huete Jimenez 
1059*de0e0e4dSAntonio Huete Jimenez 			BN_print(out, n);
1060*de0e0e4dSAntonio Huete Jimenez 		} else
1061f5b1c8a1SJohn Marino 			fprintf(stdout, "Wrong Algorithm type");
1062f5b1c8a1SJohn Marino 		fprintf(stdout, "\n");
1063f5b1c8a1SJohn Marino 	}
10648edacedfSDaniel Fojt 	if (!req_config.noout && !req_config.x509) {
10658edacedfSDaniel Fojt 		if (req_config.outformat == FORMAT_ASN1)
1066f5b1c8a1SJohn Marino 			i = i2d_X509_REQ_bio(out, req);
10678edacedfSDaniel Fojt 		else if (req_config.outformat == FORMAT_PEM) {
10688edacedfSDaniel Fojt 			if (req_config.newhdr)
1069f5b1c8a1SJohn Marino 				i = PEM_write_bio_X509_REQ_NEW(out, req);
1070f5b1c8a1SJohn Marino 			else
1071f5b1c8a1SJohn Marino 				i = PEM_write_bio_X509_REQ(out, req);
1072f5b1c8a1SJohn Marino 		} else {
1073f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "bad output format specified for outfile\n");
1074f5b1c8a1SJohn Marino 			goto end;
1075f5b1c8a1SJohn Marino 		}
1076f5b1c8a1SJohn Marino 		if (!i) {
1077f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "unable to write X509 request\n");
1078f5b1c8a1SJohn Marino 			goto end;
1079f5b1c8a1SJohn Marino 		}
1080f5b1c8a1SJohn Marino 	}
10818edacedfSDaniel Fojt 	if (!req_config.noout && req_config.x509 && (x509ss != NULL)) {
10828edacedfSDaniel Fojt 		if (req_config.outformat == FORMAT_ASN1)
1083f5b1c8a1SJohn Marino 			i = i2d_X509_bio(out, x509ss);
10848edacedfSDaniel Fojt 		else if (req_config.outformat == FORMAT_PEM)
1085f5b1c8a1SJohn Marino 			i = PEM_write_bio_X509(out, x509ss);
1086f5b1c8a1SJohn Marino 		else {
1087f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "bad output format specified for outfile\n");
1088f5b1c8a1SJohn Marino 			goto end;
1089f5b1c8a1SJohn Marino 		}
1090f5b1c8a1SJohn Marino 		if (!i) {
1091f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "unable to write X509 certificate\n");
1092f5b1c8a1SJohn Marino 			goto end;
1093f5b1c8a1SJohn Marino 		}
1094f5b1c8a1SJohn Marino 	}
1095f5b1c8a1SJohn Marino 	ex = 0;
1096f5b1c8a1SJohn Marino  end:
1097f5b1c8a1SJohn Marino 	if (ex) {
1098f5b1c8a1SJohn Marino 		ERR_print_errors(bio_err);
1099f5b1c8a1SJohn Marino 	}
1100f5b1c8a1SJohn Marino 	if ((req_conf != NULL) && (req_conf != config))
1101f5b1c8a1SJohn Marino 		NCONF_free(req_conf);
1102cca6fc52SDaniel Fojt 	NCONF_free(addext_conf);
11038edacedfSDaniel Fojt 	BIO_free(req_config.addext_bio);
1104f5b1c8a1SJohn Marino 	BIO_free(in);
1105f5b1c8a1SJohn Marino 	BIO_free_all(out);
1106f5b1c8a1SJohn Marino 	EVP_PKEY_free(pkey);
1107f5b1c8a1SJohn Marino 	if (genctx)
1108f5b1c8a1SJohn Marino 		EVP_PKEY_CTX_free(genctx);
11098edacedfSDaniel Fojt 	if (req_config.pkeyopts)
11108edacedfSDaniel Fojt 		sk_OPENSSL_STRING_free(req_config.pkeyopts);
11118edacedfSDaniel Fojt 	if (req_config.sigopts)
11128edacedfSDaniel Fojt 		sk_OPENSSL_STRING_free(req_config.sigopts);
11138edacedfSDaniel Fojt 	lh_OPENSSL_STRING_doall(req_config.addexts, (LHASH_DOALL_FN_TYPE)exts_cleanup);
11148edacedfSDaniel Fojt 	lh_OPENSSL_STRING_free(req_config.addexts);
1115f5b1c8a1SJohn Marino 	free(keyalgstr);
1116f5b1c8a1SJohn Marino 	X509_REQ_free(req);
1117f5b1c8a1SJohn Marino 	X509_free(x509ss);
11188edacedfSDaniel Fojt 	ASN1_INTEGER_free(req_config.serial);
11198edacedfSDaniel Fojt 	if (req_config.passargin && passin)
1120f5b1c8a1SJohn Marino 		free(passin);
11218edacedfSDaniel Fojt 	if (req_config.passargout && passout)
1122f5b1c8a1SJohn Marino 		free(passout);
1123f5b1c8a1SJohn Marino 	OBJ_cleanup();
1124f5b1c8a1SJohn Marino 
1125f5b1c8a1SJohn Marino 	return (ex);
1126f5b1c8a1SJohn Marino }
1127f5b1c8a1SJohn Marino 
1128f5b1c8a1SJohn Marino static int
make_REQ(X509_REQ * req,EVP_PKEY * pkey,char * subj,int multirdn,int attribs,unsigned long chtype)1129f5b1c8a1SJohn Marino make_REQ(X509_REQ * req, EVP_PKEY * pkey, char *subj, int multirdn,
1130f5b1c8a1SJohn Marino     int attribs, unsigned long chtype)
1131f5b1c8a1SJohn Marino {
1132f5b1c8a1SJohn Marino 	int ret = 0, i;
1133f5b1c8a1SJohn Marino 	char no_prompt = 0;
1134f5b1c8a1SJohn Marino 	STACK_OF(CONF_VALUE) * dn_sk, *attr_sk = NULL;
1135f5b1c8a1SJohn Marino 	char *tmp, *dn_sect, *attr_sect;
1136f5b1c8a1SJohn Marino 
1137f5b1c8a1SJohn Marino 	tmp = NCONF_get_string(req_conf, SECTION, PROMPT);
1138f5b1c8a1SJohn Marino 	if (tmp == NULL)
1139f5b1c8a1SJohn Marino 		ERR_clear_error();
1140f5b1c8a1SJohn Marino 	if ((tmp != NULL) && !strcmp(tmp, "no"))
1141f5b1c8a1SJohn Marino 		no_prompt = 1;
1142f5b1c8a1SJohn Marino 
1143f5b1c8a1SJohn Marino 	dn_sect = NCONF_get_string(req_conf, SECTION, DISTINGUISHED_NAME);
1144f5b1c8a1SJohn Marino 	if (dn_sect == NULL) {
1145f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "unable to find '%s' in config\n",
1146f5b1c8a1SJohn Marino 		    DISTINGUISHED_NAME);
1147f5b1c8a1SJohn Marino 		goto err;
1148f5b1c8a1SJohn Marino 	}
1149f5b1c8a1SJohn Marino 	dn_sk = NCONF_get_section(req_conf, dn_sect);
1150f5b1c8a1SJohn Marino 	if (dn_sk == NULL) {
1151f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "unable to get '%s' section\n", dn_sect);
1152f5b1c8a1SJohn Marino 		goto err;
1153f5b1c8a1SJohn Marino 	}
1154f5b1c8a1SJohn Marino 	attr_sect = NCONF_get_string(req_conf, SECTION, ATTRIBUTES);
1155f5b1c8a1SJohn Marino 	if (attr_sect == NULL) {
1156f5b1c8a1SJohn Marino 		ERR_clear_error();
1157f5b1c8a1SJohn Marino 		attr_sk = NULL;
1158f5b1c8a1SJohn Marino 	} else {
1159f5b1c8a1SJohn Marino 		attr_sk = NCONF_get_section(req_conf, attr_sect);
1160f5b1c8a1SJohn Marino 		if (attr_sk == NULL) {
1161f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "unable to get '%s' section\n", attr_sect);
1162f5b1c8a1SJohn Marino 			goto err;
1163f5b1c8a1SJohn Marino 		}
1164f5b1c8a1SJohn Marino 	}
1165f5b1c8a1SJohn Marino 
1166f5b1c8a1SJohn Marino 	/* setup version number */
1167f5b1c8a1SJohn Marino 	if (!X509_REQ_set_version(req, 0L))
1168f5b1c8a1SJohn Marino 		goto err;	/* version 1 */
1169f5b1c8a1SJohn Marino 
1170f5b1c8a1SJohn Marino 	if (no_prompt)
1171f5b1c8a1SJohn Marino 		i = auto_info(req, dn_sk, attr_sk, attribs, chtype);
1172f5b1c8a1SJohn Marino 	else {
1173f5b1c8a1SJohn Marino 		if (subj)
1174f5b1c8a1SJohn Marino 			i = build_subject(req, subj, chtype, multirdn);
1175f5b1c8a1SJohn Marino 		else
1176f5b1c8a1SJohn Marino 			i = prompt_info(req, dn_sk, dn_sect, attr_sk, attr_sect, attribs, chtype);
1177f5b1c8a1SJohn Marino 	}
1178f5b1c8a1SJohn Marino 	if (!i)
1179f5b1c8a1SJohn Marino 		goto err;
1180f5b1c8a1SJohn Marino 
1181f5b1c8a1SJohn Marino 	if (!X509_REQ_set_pubkey(req, pkey))
1182f5b1c8a1SJohn Marino 		goto err;
1183f5b1c8a1SJohn Marino 
1184f5b1c8a1SJohn Marino 	ret = 1;
1185f5b1c8a1SJohn Marino  err:
1186f5b1c8a1SJohn Marino 	return (ret);
1187f5b1c8a1SJohn Marino }
1188f5b1c8a1SJohn Marino 
1189f5b1c8a1SJohn Marino /*
1190f5b1c8a1SJohn Marino  * subject is expected to be in the format /type0=value0/type1=value1/type2=...
1191f5b1c8a1SJohn Marino  * where characters may be escaped by \
1192f5b1c8a1SJohn Marino  */
1193f5b1c8a1SJohn Marino static int
build_subject(X509_REQ * req,char * subject,unsigned long chtype,int multirdn)1194f5b1c8a1SJohn Marino build_subject(X509_REQ * req, char *subject, unsigned long chtype, int multirdn)
1195f5b1c8a1SJohn Marino {
1196f5b1c8a1SJohn Marino 	X509_NAME *n;
1197f5b1c8a1SJohn Marino 
1198f5b1c8a1SJohn Marino 	if (!(n = parse_name(subject, chtype, multirdn)))
1199f5b1c8a1SJohn Marino 		return 0;
1200f5b1c8a1SJohn Marino 
1201f5b1c8a1SJohn Marino 	if (!X509_REQ_set_subject_name(req, n)) {
1202f5b1c8a1SJohn Marino 		X509_NAME_free(n);
1203f5b1c8a1SJohn Marino 		return 0;
1204f5b1c8a1SJohn Marino 	}
1205f5b1c8a1SJohn Marino 	X509_NAME_free(n);
1206f5b1c8a1SJohn Marino 	return 1;
1207f5b1c8a1SJohn Marino }
1208f5b1c8a1SJohn Marino 
1209f5b1c8a1SJohn Marino 
1210f5b1c8a1SJohn Marino 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)1211f5b1c8a1SJohn Marino prompt_info(X509_REQ * req,
1212f5b1c8a1SJohn Marino     STACK_OF(CONF_VALUE) * dn_sk, char *dn_sect,
1213f5b1c8a1SJohn Marino     STACK_OF(CONF_VALUE) * attr_sk, char *attr_sect, int attribs,
1214f5b1c8a1SJohn Marino     unsigned long chtype)
1215f5b1c8a1SJohn Marino {
1216f5b1c8a1SJohn Marino 	int i;
1217f5b1c8a1SJohn Marino 	char *p, *q;
1218f5b1c8a1SJohn Marino 	char buf[100];
1219f5b1c8a1SJohn Marino 	int nid, mval;
1220f5b1c8a1SJohn Marino 	long n_min, n_max;
1221f5b1c8a1SJohn Marino 	char *type, *value;
1222f5b1c8a1SJohn Marino 	const char *def;
1223f5b1c8a1SJohn Marino 	CONF_VALUE *v;
1224f5b1c8a1SJohn Marino 	X509_NAME *subj;
1225f5b1c8a1SJohn Marino 	subj = X509_REQ_get_subject_name(req);
1226f5b1c8a1SJohn Marino 
12278edacedfSDaniel Fojt 	if (!req_config.batch) {
1228f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "You are about to be asked to enter information that will be incorporated\n");
1229f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "into your certificate request.\n");
1230f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "What you are about to enter is what is called a Distinguished Name or a DN.\n");
1231f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "There are quite a few fields but you can leave some blank\n");
1232f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "For some fields there will be a default value,\n");
1233f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "If you enter '.', the field will be left blank.\n");
1234f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "-----\n");
1235f5b1c8a1SJohn Marino 	}
1236f5b1c8a1SJohn Marino 	if (sk_CONF_VALUE_num(dn_sk)) {
1237f5b1c8a1SJohn Marino 		i = -1;
1238f5b1c8a1SJohn Marino  start:		for (;;) {
1239f5b1c8a1SJohn Marino 			int ret;
1240f5b1c8a1SJohn Marino 			i++;
1241f5b1c8a1SJohn Marino 			if (sk_CONF_VALUE_num(dn_sk) <= i)
1242f5b1c8a1SJohn Marino 				break;
1243f5b1c8a1SJohn Marino 
1244f5b1c8a1SJohn Marino 			v = sk_CONF_VALUE_value(dn_sk, i);
1245f5b1c8a1SJohn Marino 			p = q = NULL;
1246f5b1c8a1SJohn Marino 			type = v->name;
1247f5b1c8a1SJohn Marino 			if (!check_end(type, "_min") || !check_end(type, "_max") ||
1248f5b1c8a1SJohn Marino 			    !check_end(type, "_default") ||
1249f5b1c8a1SJohn Marino 			    !check_end(type, "_value"))
1250f5b1c8a1SJohn Marino 				continue;
1251f5b1c8a1SJohn Marino 			/*
1252f5b1c8a1SJohn Marino 			 * Skip past any leading X. X: X, etc to allow for
1253f5b1c8a1SJohn Marino 			 * multiple instances
1254f5b1c8a1SJohn Marino 			 */
1255f5b1c8a1SJohn Marino 			for (p = v->name; *p; p++)
1256f5b1c8a1SJohn Marino 				if ((*p == ':') || (*p == ',') ||
1257f5b1c8a1SJohn Marino 				    (*p == '.')) {
1258f5b1c8a1SJohn Marino 					p++;
1259f5b1c8a1SJohn Marino 					if (*p)
1260f5b1c8a1SJohn Marino 						type = p;
1261f5b1c8a1SJohn Marino 					break;
1262f5b1c8a1SJohn Marino 				}
1263f5b1c8a1SJohn Marino 			if (*type == '+') {
1264f5b1c8a1SJohn Marino 				mval = -1;
1265f5b1c8a1SJohn Marino 				type++;
1266f5b1c8a1SJohn Marino 			} else
1267f5b1c8a1SJohn Marino 				mval = 0;
1268f5b1c8a1SJohn Marino 			/* If OBJ not recognised ignore it */
1269f5b1c8a1SJohn Marino 			if ((nid = OBJ_txt2nid(type)) == NID_undef)
1270f5b1c8a1SJohn Marino 				goto start;
1271f5b1c8a1SJohn Marino 			ret = snprintf(buf, sizeof buf, "%s_default", v->name);
1272cca6fc52SDaniel Fojt 			if (ret < 0 || ret >= sizeof(buf)) {
1273f5b1c8a1SJohn Marino 				BIO_printf(bio_err, "Name '%s' too long for default\n",
1274f5b1c8a1SJohn Marino 				    v->name);
1275f5b1c8a1SJohn Marino 				return 0;
1276f5b1c8a1SJohn Marino 			}
1277f5b1c8a1SJohn Marino 			if ((def = NCONF_get_string(req_conf, dn_sect, buf)) == NULL) {
1278f5b1c8a1SJohn Marino 				ERR_clear_error();
1279f5b1c8a1SJohn Marino 				def = "";
1280f5b1c8a1SJohn Marino 			}
1281f5b1c8a1SJohn Marino 			ret = snprintf(buf, sizeof buf, "%s_value", v->name);
1282cca6fc52SDaniel Fojt 			if (ret < 0 || ret >= sizeof(buf)) {
1283f5b1c8a1SJohn Marino 				BIO_printf(bio_err, "Name '%s' too long for value\n",
1284f5b1c8a1SJohn Marino 				    v->name);
1285f5b1c8a1SJohn Marino 				return 0;
1286f5b1c8a1SJohn Marino 			}
1287f5b1c8a1SJohn Marino 			if ((value = NCONF_get_string(req_conf, dn_sect, buf)) == NULL) {
1288f5b1c8a1SJohn Marino 				ERR_clear_error();
1289f5b1c8a1SJohn Marino 				value = NULL;
1290f5b1c8a1SJohn Marino 			}
1291f5b1c8a1SJohn Marino 			ret = snprintf(buf, sizeof buf, "%s_min", v->name);
1292cca6fc52SDaniel Fojt 			if (ret < 0 || ret >= sizeof(buf)) {
1293f5b1c8a1SJohn Marino 				BIO_printf(bio_err, "Name '%s' too long for min\n",
1294f5b1c8a1SJohn Marino 				    v->name);
1295f5b1c8a1SJohn Marino 				return 0;
1296f5b1c8a1SJohn Marino 			}
1297f5b1c8a1SJohn Marino 			if (!NCONF_get_number(req_conf, dn_sect, buf, &n_min)) {
1298f5b1c8a1SJohn Marino 				ERR_clear_error();
1299f5b1c8a1SJohn Marino 				n_min = -1;
1300f5b1c8a1SJohn Marino 			}
1301f5b1c8a1SJohn Marino 			ret = snprintf(buf, sizeof buf, "%s_max", v->name);
1302cca6fc52SDaniel Fojt 			if (ret < 0 || ret >= sizeof(buf)) {
1303f5b1c8a1SJohn Marino 				BIO_printf(bio_err, "Name '%s' too long for max\n",
1304f5b1c8a1SJohn Marino 				    v->name);
1305f5b1c8a1SJohn Marino 				return 0;
1306f5b1c8a1SJohn Marino 			}
1307f5b1c8a1SJohn Marino 			if (!NCONF_get_number(req_conf, dn_sect, buf, &n_max)) {
1308f5b1c8a1SJohn Marino 				ERR_clear_error();
1309f5b1c8a1SJohn Marino 				n_max = -1;
1310f5b1c8a1SJohn Marino 			}
1311f5b1c8a1SJohn Marino 			if (!add_DN_object(subj, v->value, def, value, nid,
1312f5b1c8a1SJohn Marino 				n_min, n_max, chtype, mval))
1313f5b1c8a1SJohn Marino 				return 0;
1314f5b1c8a1SJohn Marino 		}
1315f5b1c8a1SJohn Marino 		if (X509_NAME_entry_count(subj) == 0) {
1316f5b1c8a1SJohn Marino 			BIO_printf(bio_err, "error, no objects specified in config file\n");
1317f5b1c8a1SJohn Marino 			return 0;
1318f5b1c8a1SJohn Marino 		}
1319f5b1c8a1SJohn Marino 		if (attribs) {
1320f5b1c8a1SJohn Marino 			if ((attr_sk != NULL) && (sk_CONF_VALUE_num(attr_sk) > 0) &&
13218edacedfSDaniel Fojt 			    (!req_config.batch)) {
1322f5b1c8a1SJohn Marino 				BIO_printf(bio_err,
1323f5b1c8a1SJohn Marino 				    "\nPlease enter the following 'extra' attributes\n");
1324f5b1c8a1SJohn Marino 				BIO_printf(bio_err,
1325f5b1c8a1SJohn Marino 				    "to be sent with your certificate request\n");
1326f5b1c8a1SJohn Marino 			}
1327f5b1c8a1SJohn Marino 			i = -1;
1328f5b1c8a1SJohn Marino start2:			for (;;) {
1329f5b1c8a1SJohn Marino 				int ret;
1330f5b1c8a1SJohn Marino 				i++;
1331f5b1c8a1SJohn Marino 				if ((attr_sk == NULL) ||
1332f5b1c8a1SJohn Marino 				    (sk_CONF_VALUE_num(attr_sk) <= i))
1333f5b1c8a1SJohn Marino 					break;
1334f5b1c8a1SJohn Marino 
1335f5b1c8a1SJohn Marino 				v = sk_CONF_VALUE_value(attr_sk, i);
1336f5b1c8a1SJohn Marino 				type = v->name;
1337f5b1c8a1SJohn Marino 				if ((nid = OBJ_txt2nid(type)) == NID_undef)
1338f5b1c8a1SJohn Marino 					goto start2;
1339f5b1c8a1SJohn Marino 				ret = snprintf(buf, sizeof buf, "%s_default", type);
1340cca6fc52SDaniel Fojt 				if (ret < 0 || ret >= sizeof(buf)) {
1341f5b1c8a1SJohn Marino 					BIO_printf(bio_err, "Name '%s' too long for default\n",
1342f5b1c8a1SJohn Marino 					    v->name);
1343f5b1c8a1SJohn Marino 					return 0;
1344f5b1c8a1SJohn Marino 				}
1345f5b1c8a1SJohn Marino 				if ((def = NCONF_get_string(req_conf, attr_sect, buf))
1346f5b1c8a1SJohn Marino 				    == NULL) {
1347f5b1c8a1SJohn Marino 					ERR_clear_error();
1348f5b1c8a1SJohn Marino 					def = "";
1349f5b1c8a1SJohn Marino 				}
1350f5b1c8a1SJohn Marino 				ret = snprintf(buf, sizeof buf, "%s_value", type);
1351cca6fc52SDaniel Fojt 				if (ret < 0 || ret >= sizeof(buf)) {
1352f5b1c8a1SJohn Marino 					BIO_printf(bio_err, "Name '%s' too long for value\n",
1353f5b1c8a1SJohn Marino 					    v->name);
1354f5b1c8a1SJohn Marino 					return 0;
1355f5b1c8a1SJohn Marino 				}
1356f5b1c8a1SJohn Marino 				if ((value = NCONF_get_string(req_conf, attr_sect, buf))
1357f5b1c8a1SJohn Marino 				    == NULL) {
1358f5b1c8a1SJohn Marino 					ERR_clear_error();
1359f5b1c8a1SJohn Marino 					value = NULL;
1360f5b1c8a1SJohn Marino 				}
1361f5b1c8a1SJohn Marino 				ret = snprintf(buf, sizeof buf, "%s_min", type);
1362cca6fc52SDaniel Fojt 				if (ret < 0 || ret >= sizeof(buf)) {
1363f5b1c8a1SJohn Marino 					BIO_printf(bio_err, "Name '%s' too long for min\n",
1364f5b1c8a1SJohn Marino 					    v->name);
1365f5b1c8a1SJohn Marino 					return 0;
1366f5b1c8a1SJohn Marino 				}
1367f5b1c8a1SJohn Marino 				if (!NCONF_get_number(req_conf, attr_sect, buf, &n_min)) {
1368f5b1c8a1SJohn Marino 					ERR_clear_error();
1369f5b1c8a1SJohn Marino 					n_min = -1;
1370f5b1c8a1SJohn Marino 				}
1371f5b1c8a1SJohn Marino 				ret = snprintf(buf, sizeof buf, "%s_max", type);
1372cca6fc52SDaniel Fojt 				if (ret < 0 || ret >= sizeof(buf)) {
1373f5b1c8a1SJohn Marino 					BIO_printf(bio_err, "Name '%s' too long for max\n",
1374f5b1c8a1SJohn Marino 					    v->name);
1375f5b1c8a1SJohn Marino 					return 0;
1376f5b1c8a1SJohn Marino 				}
1377f5b1c8a1SJohn Marino 				if (!NCONF_get_number(req_conf, attr_sect, buf, &n_max)) {
1378f5b1c8a1SJohn Marino 					ERR_clear_error();
1379f5b1c8a1SJohn Marino 					n_max = -1;
1380f5b1c8a1SJohn Marino 				}
1381f5b1c8a1SJohn Marino 				if (!add_attribute_object(req,
1382f5b1c8a1SJohn Marino 					v->value, def, value, nid, n_min, n_max, chtype))
1383f5b1c8a1SJohn Marino 					return 0;
1384f5b1c8a1SJohn Marino 			}
1385f5b1c8a1SJohn Marino 		}
1386f5b1c8a1SJohn Marino 	} else {
1387f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "No template, please set one up.\n");
1388f5b1c8a1SJohn Marino 		return 0;
1389f5b1c8a1SJohn Marino 	}
1390f5b1c8a1SJohn Marino 
1391f5b1c8a1SJohn Marino 	return 1;
1392f5b1c8a1SJohn Marino 
1393f5b1c8a1SJohn Marino }
1394f5b1c8a1SJohn Marino 
1395f5b1c8a1SJohn Marino static int
auto_info(X509_REQ * req,STACK_OF (CONF_VALUE)* dn_sk,STACK_OF (CONF_VALUE)* attr_sk,int attribs,unsigned long chtype)1396f5b1c8a1SJohn Marino auto_info(X509_REQ * req, STACK_OF(CONF_VALUE) * dn_sk,
1397f5b1c8a1SJohn Marino     STACK_OF(CONF_VALUE) * attr_sk, int attribs, unsigned long chtype)
1398f5b1c8a1SJohn Marino {
1399f5b1c8a1SJohn Marino 	int i;
1400f5b1c8a1SJohn Marino 	char *p, *q;
1401f5b1c8a1SJohn Marino 	char *type;
1402f5b1c8a1SJohn Marino 	CONF_VALUE *v;
1403f5b1c8a1SJohn Marino 	X509_NAME *subj;
1404f5b1c8a1SJohn Marino 
1405f5b1c8a1SJohn Marino 	subj = X509_REQ_get_subject_name(req);
1406f5b1c8a1SJohn Marino 
1407f5b1c8a1SJohn Marino 	for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) {
1408f5b1c8a1SJohn Marino 		int mval;
1409f5b1c8a1SJohn Marino 		v = sk_CONF_VALUE_value(dn_sk, i);
1410f5b1c8a1SJohn Marino 		p = q = NULL;
1411f5b1c8a1SJohn Marino 		type = v->name;
1412f5b1c8a1SJohn Marino 		/*
1413f5b1c8a1SJohn Marino 		 * Skip past any leading X. X: X, etc to allow for multiple
1414f5b1c8a1SJohn Marino 		 * instances
1415f5b1c8a1SJohn Marino 		 */
1416f5b1c8a1SJohn Marino 		for (p = v->name; *p; p++)
1417f5b1c8a1SJohn Marino 			if ((*p == ':') || (*p == ',') || (*p == '.')) {
1418f5b1c8a1SJohn Marino 				p++;
1419f5b1c8a1SJohn Marino 				if (*p)
1420f5b1c8a1SJohn Marino 					type = p;
1421f5b1c8a1SJohn Marino 				break;
1422f5b1c8a1SJohn Marino 			}
1423f5b1c8a1SJohn Marino 		if (*p == '+') {
1424f5b1c8a1SJohn Marino 			p++;
1425f5b1c8a1SJohn Marino 			mval = -1;
1426f5b1c8a1SJohn Marino 		} else
1427f5b1c8a1SJohn Marino 			mval = 0;
1428f5b1c8a1SJohn Marino 		if (!X509_NAME_add_entry_by_txt(subj, type, chtype,
1429f5b1c8a1SJohn Marino 			(unsigned char *) v->value, -1, -1, mval))
1430f5b1c8a1SJohn Marino 			return 0;
1431f5b1c8a1SJohn Marino 
1432f5b1c8a1SJohn Marino 	}
1433f5b1c8a1SJohn Marino 
1434f5b1c8a1SJohn Marino 	if (!X509_NAME_entry_count(subj)) {
1435f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "error, no objects specified in config file\n");
1436f5b1c8a1SJohn Marino 		return 0;
1437f5b1c8a1SJohn Marino 	}
1438f5b1c8a1SJohn Marino 	if (attribs) {
1439f5b1c8a1SJohn Marino 		for (i = 0; i < sk_CONF_VALUE_num(attr_sk); i++) {
1440f5b1c8a1SJohn Marino 			v = sk_CONF_VALUE_value(attr_sk, i);
1441f5b1c8a1SJohn Marino 			if (!X509_REQ_add1_attr_by_txt(req, v->name, chtype,
1442f5b1c8a1SJohn Marino 				(unsigned char *) v->value, -1))
1443f5b1c8a1SJohn Marino 				return 0;
1444f5b1c8a1SJohn Marino 		}
1445f5b1c8a1SJohn Marino 	}
1446f5b1c8a1SJohn Marino 	return 1;
1447f5b1c8a1SJohn Marino }
1448f5b1c8a1SJohn Marino 
1449f5b1c8a1SJohn Marino 
1450f5b1c8a1SJohn Marino 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)1451f5b1c8a1SJohn Marino add_DN_object(X509_NAME * n, char *text, const char *def, char *value,
1452f5b1c8a1SJohn Marino     int nid, int n_min, int n_max, unsigned long chtype, int mval)
1453f5b1c8a1SJohn Marino {
1454f5b1c8a1SJohn Marino 	int i, ret = 0;
1455f5b1c8a1SJohn Marino 	char buf[1024];
1456f5b1c8a1SJohn Marino  start:
14578edacedfSDaniel Fojt 	if (!req_config.batch)
1458f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "%s [%s]:", text, def);
1459f5b1c8a1SJohn Marino 	(void) BIO_flush(bio_err);
1460f5b1c8a1SJohn Marino 	if (value != NULL) {
1461f5b1c8a1SJohn Marino 		strlcpy(buf, value, sizeof buf);
1462f5b1c8a1SJohn Marino 		strlcat(buf, "\n", sizeof buf);
1463f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "%s\n", value);
1464f5b1c8a1SJohn Marino 	} else {
1465f5b1c8a1SJohn Marino 		buf[0] = '\0';
14668edacedfSDaniel Fojt 		if (!req_config.batch) {
1467f5b1c8a1SJohn Marino 			if (!fgets(buf, sizeof buf, stdin))
1468f5b1c8a1SJohn Marino 				return 0;
1469f5b1c8a1SJohn Marino 		} else {
1470f5b1c8a1SJohn Marino 			buf[0] = '\n';
1471f5b1c8a1SJohn Marino 			buf[1] = '\0';
1472f5b1c8a1SJohn Marino 		}
1473f5b1c8a1SJohn Marino 	}
1474f5b1c8a1SJohn Marino 
1475f5b1c8a1SJohn Marino 	if (buf[0] == '\0')
1476f5b1c8a1SJohn Marino 		return (0);
1477f5b1c8a1SJohn Marino 	else if (buf[0] == '\n') {
1478f5b1c8a1SJohn Marino 		if ((def == NULL) || (def[0] == '\0'))
1479f5b1c8a1SJohn Marino 			return (1);
1480f5b1c8a1SJohn Marino 		strlcpy(buf, def, sizeof buf);
1481f5b1c8a1SJohn Marino 		strlcat(buf, "\n", sizeof buf);
1482f5b1c8a1SJohn Marino 	} else if ((buf[0] == '.') && (buf[1] == '\n'))
1483f5b1c8a1SJohn Marino 		return (1);
1484f5b1c8a1SJohn Marino 
1485f5b1c8a1SJohn Marino 	i = strlen(buf);
1486f5b1c8a1SJohn Marino 	if (buf[i - 1] != '\n') {
1487f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "weird input :-(\n");
1488f5b1c8a1SJohn Marino 		return (0);
1489f5b1c8a1SJohn Marino 	}
1490f5b1c8a1SJohn Marino 	buf[--i] = '\0';
1491f5b1c8a1SJohn Marino 	if (!req_check_len(i, n_min, n_max))
1492f5b1c8a1SJohn Marino 		goto start;
1493f5b1c8a1SJohn Marino 	if (!X509_NAME_add_entry_by_NID(n, nid, chtype,
1494f5b1c8a1SJohn Marino 		(unsigned char *) buf, -1, -1, mval))
1495f5b1c8a1SJohn Marino 		goto err;
1496f5b1c8a1SJohn Marino 	ret = 1;
1497f5b1c8a1SJohn Marino  err:
1498f5b1c8a1SJohn Marino 	return (ret);
1499f5b1c8a1SJohn Marino }
1500f5b1c8a1SJohn Marino 
1501f5b1c8a1SJohn Marino 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)1502f5b1c8a1SJohn Marino add_attribute_object(X509_REQ * req, char *text, const char *def,
1503f5b1c8a1SJohn Marino     char *value, int nid, int n_min,
1504f5b1c8a1SJohn Marino     int n_max, unsigned long chtype)
1505f5b1c8a1SJohn Marino {
1506f5b1c8a1SJohn Marino 	int i;
1507f5b1c8a1SJohn Marino 	static char buf[1024];
1508f5b1c8a1SJohn Marino 
1509f5b1c8a1SJohn Marino  start:
15108edacedfSDaniel Fojt 	if (!req_config.batch)
1511f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "%s [%s]:", text, def);
1512f5b1c8a1SJohn Marino 	(void) BIO_flush(bio_err);
1513f5b1c8a1SJohn Marino 	if (value != NULL) {
1514f5b1c8a1SJohn Marino 		strlcpy(buf, value, sizeof buf);
1515f5b1c8a1SJohn Marino 		strlcat(buf, "\n", sizeof buf);
1516f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "%s\n", value);
1517f5b1c8a1SJohn Marino 	} else {
1518f5b1c8a1SJohn Marino 		buf[0] = '\0';
15198edacedfSDaniel Fojt 		if (!req_config.batch) {
1520f5b1c8a1SJohn Marino 			if (!fgets(buf, sizeof buf, stdin))
1521f5b1c8a1SJohn Marino 				return 0;
1522f5b1c8a1SJohn Marino 		} else {
1523f5b1c8a1SJohn Marino 			buf[0] = '\n';
1524f5b1c8a1SJohn Marino 			buf[1] = '\0';
1525f5b1c8a1SJohn Marino 		}
1526f5b1c8a1SJohn Marino 	}
1527f5b1c8a1SJohn Marino 
1528f5b1c8a1SJohn Marino 	if (buf[0] == '\0')
1529f5b1c8a1SJohn Marino 		return (0);
1530f5b1c8a1SJohn Marino 	else if (buf[0] == '\n') {
1531f5b1c8a1SJohn Marino 		if ((def == NULL) || (def[0] == '\0'))
1532f5b1c8a1SJohn Marino 			return (1);
1533f5b1c8a1SJohn Marino 		strlcpy(buf, def, sizeof buf);
1534f5b1c8a1SJohn Marino 		strlcat(buf, "\n", sizeof buf);
1535f5b1c8a1SJohn Marino 	} else if ((buf[0] == '.') && (buf[1] == '\n'))
1536f5b1c8a1SJohn Marino 		return (1);
1537f5b1c8a1SJohn Marino 
1538f5b1c8a1SJohn Marino 	i = strlen(buf);
1539f5b1c8a1SJohn Marino 	if (buf[i - 1] != '\n') {
1540f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "weird input :-(\n");
1541f5b1c8a1SJohn Marino 		return (0);
1542f5b1c8a1SJohn Marino 	}
1543f5b1c8a1SJohn Marino 	buf[--i] = '\0';
1544f5b1c8a1SJohn Marino 	if (!req_check_len(i, n_min, n_max))
1545f5b1c8a1SJohn Marino 		goto start;
1546f5b1c8a1SJohn Marino 
1547f5b1c8a1SJohn Marino 	if (!X509_REQ_add1_attr_by_NID(req, nid, chtype,
1548f5b1c8a1SJohn Marino 		(unsigned char *) buf, -1)) {
1549f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "Error adding attribute\n");
1550f5b1c8a1SJohn Marino 		ERR_print_errors(bio_err);
1551f5b1c8a1SJohn Marino 		goto err;
1552f5b1c8a1SJohn Marino 	}
1553f5b1c8a1SJohn Marino 	return (1);
1554f5b1c8a1SJohn Marino  err:
1555f5b1c8a1SJohn Marino 	return (0);
1556f5b1c8a1SJohn Marino }
1557f5b1c8a1SJohn Marino 
1558f5b1c8a1SJohn Marino static int
req_check_len(int len,int n_min,int n_max)1559f5b1c8a1SJohn Marino req_check_len(int len, int n_min, int n_max)
1560f5b1c8a1SJohn Marino {
1561f5b1c8a1SJohn Marino 	if ((n_min > 0) && (len < n_min)) {
1562f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "string is too short, it needs to be at least %d bytes long\n", n_min);
1563f5b1c8a1SJohn Marino 		return (0);
1564f5b1c8a1SJohn Marino 	}
1565f5b1c8a1SJohn Marino 	if ((n_max >= 0) && (len > n_max)) {
1566f5b1c8a1SJohn Marino 		BIO_printf(bio_err, "string is too long, it needs to be less than  %d bytes long\n", n_max);
1567f5b1c8a1SJohn Marino 		return (0);
1568f5b1c8a1SJohn Marino 	}
1569f5b1c8a1SJohn Marino 	return (1);
1570f5b1c8a1SJohn Marino }
1571f5b1c8a1SJohn Marino 
1572f5b1c8a1SJohn Marino /* Check if the end of a string matches 'end' */
1573f5b1c8a1SJohn Marino static int
check_end(const char * str,const char * end)1574f5b1c8a1SJohn Marino check_end(const char *str, const char *end)
1575f5b1c8a1SJohn Marino {
1576f5b1c8a1SJohn Marino 	int elen, slen;
1577f5b1c8a1SJohn Marino 	const char *tmp;
1578f5b1c8a1SJohn Marino 	elen = strlen(end);
1579f5b1c8a1SJohn Marino 	slen = strlen(str);
1580f5b1c8a1SJohn Marino 	if (elen > slen)
1581f5b1c8a1SJohn Marino 		return 1;
1582f5b1c8a1SJohn Marino 	tmp = str + slen - elen;
1583f5b1c8a1SJohn Marino 	return strcmp(tmp, end);
1584f5b1c8a1SJohn Marino }
1585f5b1c8a1SJohn Marino 
1586f5b1c8a1SJohn Marino static EVP_PKEY_CTX *
set_keygen_ctx(BIO * err,const char * gstr,int * pkey_type,long * pkeylen,char ** palgnam)1587f5b1c8a1SJohn Marino set_keygen_ctx(BIO * err, const char *gstr, int *pkey_type,
1588f5b1c8a1SJohn Marino     long *pkeylen, char **palgnam)
1589f5b1c8a1SJohn Marino {
1590f5b1c8a1SJohn Marino 	EVP_PKEY_CTX *gctx = NULL;
1591f5b1c8a1SJohn Marino 	EVP_PKEY *param = NULL;
1592f5b1c8a1SJohn Marino 	long keylen = -1;
1593f5b1c8a1SJohn Marino 	BIO *pbio = NULL;
1594f5b1c8a1SJohn Marino 	const char *paramfile = NULL;
1595f5b1c8a1SJohn Marino 	const char *errstr;
1596f5b1c8a1SJohn Marino 
1597f5b1c8a1SJohn Marino 	if (gstr == NULL) {
1598f5b1c8a1SJohn Marino 		*pkey_type = EVP_PKEY_RSA;
1599f5b1c8a1SJohn Marino 		keylen = *pkeylen;
1600f5b1c8a1SJohn Marino 	} else if (gstr[0] >= '0' && gstr[0] <= '9') {
1601f5b1c8a1SJohn Marino 		*pkey_type = EVP_PKEY_RSA;
1602f5b1c8a1SJohn Marino 		keylen = strtonum(gstr, 0, LONG_MAX, &errstr);
1603f5b1c8a1SJohn Marino 		if (errstr) {
1604f5b1c8a1SJohn Marino 			BIO_printf(err, "bad algorithm %s: %s\n", gstr, errstr);
1605f5b1c8a1SJohn Marino 			return NULL;
1606f5b1c8a1SJohn Marino 		}
1607f5b1c8a1SJohn Marino 		*pkeylen = keylen;
1608f5b1c8a1SJohn Marino 	} else if (!strncmp(gstr, "param:", 6))
1609f5b1c8a1SJohn Marino 		paramfile = gstr + 6;
1610f5b1c8a1SJohn Marino 	else {
1611f5b1c8a1SJohn Marino 		const char *p = strchr(gstr, ':');
1612f5b1c8a1SJohn Marino 		int len;
1613f5b1c8a1SJohn Marino 		const EVP_PKEY_ASN1_METHOD *ameth;
1614f5b1c8a1SJohn Marino 
1615f5b1c8a1SJohn Marino 		if (p)
1616f5b1c8a1SJohn Marino 			len = p - gstr;
1617f5b1c8a1SJohn Marino 		else
1618f5b1c8a1SJohn Marino 			len = strlen(gstr);
1619f5b1c8a1SJohn Marino 
1620f5b1c8a1SJohn Marino 		ameth = EVP_PKEY_asn1_find_str(NULL, gstr, len);
1621f5b1c8a1SJohn Marino 
1622f5b1c8a1SJohn Marino 		if (!ameth) {
1623f5b1c8a1SJohn Marino 			BIO_printf(err, "Unknown algorithm %.*s\n", len, gstr);
1624f5b1c8a1SJohn Marino 			return NULL;
1625f5b1c8a1SJohn Marino 		}
1626f5b1c8a1SJohn Marino 		EVP_PKEY_asn1_get0_info(NULL, pkey_type, NULL, NULL, NULL,
1627f5b1c8a1SJohn Marino 		    ameth);
1628f5b1c8a1SJohn Marino 		if (*pkey_type == EVP_PKEY_RSA) {
1629f5b1c8a1SJohn Marino 			if (p) {
1630f5b1c8a1SJohn Marino 				keylen = strtonum(p + 1, 0, LONG_MAX, &errstr);
1631f5b1c8a1SJohn Marino 				if (errstr) {
1632f5b1c8a1SJohn Marino 					BIO_printf(err, "bad algorithm %s: %s\n",
1633f5b1c8a1SJohn Marino 					    p + 1, errstr);
1634f5b1c8a1SJohn Marino 					return NULL;
1635f5b1c8a1SJohn Marino 				}
1636f5b1c8a1SJohn Marino 				*pkeylen = keylen;
1637f5b1c8a1SJohn Marino 			} else
1638f5b1c8a1SJohn Marino 				keylen = *pkeylen;
1639f5b1c8a1SJohn Marino 		} else if (p)
1640f5b1c8a1SJohn Marino 			paramfile = p + 1;
1641f5b1c8a1SJohn Marino 	}
1642f5b1c8a1SJohn Marino 
1643f5b1c8a1SJohn Marino 	if (paramfile) {
1644f5b1c8a1SJohn Marino 		pbio = BIO_new_file(paramfile, "r");
1645f5b1c8a1SJohn Marino 		if (!pbio) {
1646f5b1c8a1SJohn Marino 			BIO_printf(err, "Can't open parameter file %s\n",
1647f5b1c8a1SJohn Marino 			    paramfile);
1648f5b1c8a1SJohn Marino 			return NULL;
1649f5b1c8a1SJohn Marino 		}
1650f5b1c8a1SJohn Marino 		param = PEM_read_bio_Parameters(pbio, NULL);
1651f5b1c8a1SJohn Marino 
1652f5b1c8a1SJohn Marino 		if (!param) {
1653f5b1c8a1SJohn Marino 			X509 *x;
1654f5b1c8a1SJohn Marino 			(void) BIO_reset(pbio);
1655f5b1c8a1SJohn Marino 			x = PEM_read_bio_X509(pbio, NULL, NULL, NULL);
1656f5b1c8a1SJohn Marino 			if (x) {
1657f5b1c8a1SJohn Marino 				param = X509_get_pubkey(x);
1658f5b1c8a1SJohn Marino 				X509_free(x);
1659f5b1c8a1SJohn Marino 			}
1660f5b1c8a1SJohn Marino 		}
1661f5b1c8a1SJohn Marino 		BIO_free(pbio);
1662f5b1c8a1SJohn Marino 
1663f5b1c8a1SJohn Marino 		if (!param) {
1664f5b1c8a1SJohn Marino 			BIO_printf(err, "Error reading parameter file %s\n",
1665f5b1c8a1SJohn Marino 			    paramfile);
1666f5b1c8a1SJohn Marino 			return NULL;
1667f5b1c8a1SJohn Marino 		}
1668f5b1c8a1SJohn Marino 		if (*pkey_type == -1)
1669f5b1c8a1SJohn Marino 			*pkey_type = EVP_PKEY_id(param);
1670f5b1c8a1SJohn Marino 		else if (*pkey_type != EVP_PKEY_base_id(param)) {
1671f5b1c8a1SJohn Marino 			BIO_printf(err, "Key Type does not match parameters\n");
1672f5b1c8a1SJohn Marino 			EVP_PKEY_free(param);
1673f5b1c8a1SJohn Marino 			return NULL;
1674f5b1c8a1SJohn Marino 		}
1675f5b1c8a1SJohn Marino 	}
1676f5b1c8a1SJohn Marino 	if (palgnam) {
1677f5b1c8a1SJohn Marino 		const EVP_PKEY_ASN1_METHOD *ameth;
1678f5b1c8a1SJohn Marino 		const char *anam;
1679f5b1c8a1SJohn Marino 		ameth = EVP_PKEY_asn1_find(NULL, *pkey_type);
1680f5b1c8a1SJohn Marino 		if (!ameth) {
1681f5b1c8a1SJohn Marino 			BIO_puts(err, "Internal error: can't find key algorithm\n");
1682f5b1c8a1SJohn Marino 			return NULL;
1683f5b1c8a1SJohn Marino 		}
1684f5b1c8a1SJohn Marino 		EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL, &anam, ameth);
1685f5b1c8a1SJohn Marino 		*palgnam = strdup(anam);
1686f5b1c8a1SJohn Marino 	}
1687f5b1c8a1SJohn Marino 	if (param) {
1688f5b1c8a1SJohn Marino 		gctx = EVP_PKEY_CTX_new(param, NULL);
1689f5b1c8a1SJohn Marino 		*pkeylen = EVP_PKEY_bits(param);
1690f5b1c8a1SJohn Marino 		EVP_PKEY_free(param);
1691f5b1c8a1SJohn Marino 	} else
1692f5b1c8a1SJohn Marino 		gctx = EVP_PKEY_CTX_new_id(*pkey_type, NULL);
1693f5b1c8a1SJohn Marino 
1694f5b1c8a1SJohn Marino 	if (!gctx) {
1695f5b1c8a1SJohn Marino 		BIO_puts(err, "Error allocating keygen context\n");
1696f5b1c8a1SJohn Marino 		ERR_print_errors(err);
1697f5b1c8a1SJohn Marino 		return NULL;
1698f5b1c8a1SJohn Marino 	}
1699f5b1c8a1SJohn Marino 	if (EVP_PKEY_keygen_init(gctx) <= 0) {
1700f5b1c8a1SJohn Marino 		BIO_puts(err, "Error initializing keygen context\n");
1701f5b1c8a1SJohn Marino 		ERR_print_errors(err);
1702f5b1c8a1SJohn Marino 		return NULL;
1703f5b1c8a1SJohn Marino 	}
1704f5b1c8a1SJohn Marino 	if ((*pkey_type == EVP_PKEY_RSA) && (keylen != -1)) {
1705f5b1c8a1SJohn Marino 		if (EVP_PKEY_CTX_set_rsa_keygen_bits(gctx, keylen) <= 0) {
1706f5b1c8a1SJohn Marino 			BIO_puts(err, "Error setting RSA keysize\n");
1707f5b1c8a1SJohn Marino 			ERR_print_errors(err);
1708f5b1c8a1SJohn Marino 			EVP_PKEY_CTX_free(gctx);
1709f5b1c8a1SJohn Marino 			return NULL;
1710f5b1c8a1SJohn Marino 		}
1711f5b1c8a1SJohn Marino 	}
1712f5b1c8a1SJohn Marino 
1713f5b1c8a1SJohn Marino 	return gctx;
1714f5b1c8a1SJohn Marino }
1715f5b1c8a1SJohn Marino 
1716f5b1c8a1SJohn Marino static int
genpkey_cb(EVP_PKEY_CTX * ctx)1717f5b1c8a1SJohn Marino genpkey_cb(EVP_PKEY_CTX * ctx)
1718f5b1c8a1SJohn Marino {
1719f5b1c8a1SJohn Marino 	char c = '*';
1720f5b1c8a1SJohn Marino 	BIO *b = EVP_PKEY_CTX_get_app_data(ctx);
1721f5b1c8a1SJohn Marino 	int p;
1722f5b1c8a1SJohn Marino 	p = EVP_PKEY_CTX_get_keygen_info(ctx, 0);
1723f5b1c8a1SJohn Marino 	if (p == 0)
1724f5b1c8a1SJohn Marino 		c = '.';
1725f5b1c8a1SJohn Marino 	if (p == 1)
1726f5b1c8a1SJohn Marino 		c = '+';
1727f5b1c8a1SJohn Marino 	if (p == 2)
1728f5b1c8a1SJohn Marino 		c = '*';
1729f5b1c8a1SJohn Marino 	if (p == 3)
1730f5b1c8a1SJohn Marino 		c = '\n';
1731f5b1c8a1SJohn Marino 	BIO_write(b, &c, 1);
1732f5b1c8a1SJohn Marino 	(void) BIO_flush(b);
1733f5b1c8a1SJohn Marino 	return 1;
1734f5b1c8a1SJohn Marino }
1735f5b1c8a1SJohn Marino 
1736f5b1c8a1SJohn Marino static int
do_sign_init(BIO * err,EVP_MD_CTX * ctx,EVP_PKEY * pkey,const EVP_MD * md,STACK_OF (OPENSSL_STRING)* sigopts)1737f5b1c8a1SJohn Marino do_sign_init(BIO * err, EVP_MD_CTX * ctx, EVP_PKEY * pkey,
1738f5b1c8a1SJohn Marino     const EVP_MD * md, STACK_OF(OPENSSL_STRING) * sigopts)
1739f5b1c8a1SJohn Marino {
1740f5b1c8a1SJohn Marino 	EVP_PKEY_CTX *pkctx = NULL;
1741f5b1c8a1SJohn Marino 	int i;
1742f5b1c8a1SJohn Marino 	EVP_MD_CTX_init(ctx);
1743f5b1c8a1SJohn Marino 	if (!EVP_DigestSignInit(ctx, &pkctx, md, NULL, pkey))
1744f5b1c8a1SJohn Marino 		return 0;
1745f5b1c8a1SJohn Marino 	for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) {
1746f5b1c8a1SJohn Marino 		char *sigopt = sk_OPENSSL_STRING_value(sigopts, i);
1747f5b1c8a1SJohn Marino 		if (pkey_ctrl_string(pkctx, sigopt) <= 0) {
1748f5b1c8a1SJohn Marino 			BIO_printf(err, "parameter error \"%s\"\n", sigopt);
1749f5b1c8a1SJohn Marino 			ERR_print_errors(bio_err);
1750f5b1c8a1SJohn Marino 			return 0;
1751f5b1c8a1SJohn Marino 		}
1752f5b1c8a1SJohn Marino 	}
1753f5b1c8a1SJohn Marino 	return 1;
1754f5b1c8a1SJohn Marino }
1755f5b1c8a1SJohn Marino 
1756f5b1c8a1SJohn Marino int
do_X509_sign(BIO * err,X509 * x,EVP_PKEY * pkey,const EVP_MD * md,STACK_OF (OPENSSL_STRING)* sigopts)1757f5b1c8a1SJohn Marino do_X509_sign(BIO * err, X509 * x, EVP_PKEY * pkey, const EVP_MD * md,
1758f5b1c8a1SJohn Marino     STACK_OF(OPENSSL_STRING) * sigopts)
1759f5b1c8a1SJohn Marino {
1760*de0e0e4dSAntonio Huete Jimenez 	EVP_MD_CTX *mctx;
1761f5b1c8a1SJohn Marino 	int rv;
1762*de0e0e4dSAntonio Huete Jimenez 
1763*de0e0e4dSAntonio Huete Jimenez 	if ((mctx = EVP_MD_CTX_new()) == NULL)
1764*de0e0e4dSAntonio Huete Jimenez 		return 0;
1765*de0e0e4dSAntonio Huete Jimenez 
1766*de0e0e4dSAntonio Huete Jimenez 	rv = do_sign_init(err, mctx, pkey, md, sigopts);
1767f5b1c8a1SJohn Marino 	if (rv > 0)
1768*de0e0e4dSAntonio Huete Jimenez 		rv = X509_sign_ctx(x, mctx);
1769*de0e0e4dSAntonio Huete Jimenez 
1770*de0e0e4dSAntonio Huete Jimenez 	EVP_MD_CTX_free(mctx);
1771*de0e0e4dSAntonio Huete Jimenez 
1772*de0e0e4dSAntonio Huete Jimenez 	return rv > 0;
1773f5b1c8a1SJohn Marino }
1774f5b1c8a1SJohn Marino 
1775f5b1c8a1SJohn Marino 
1776f5b1c8a1SJohn Marino int
do_X509_REQ_sign(BIO * err,X509_REQ * x,EVP_PKEY * pkey,const EVP_MD * md,STACK_OF (OPENSSL_STRING)* sigopts)1777f5b1c8a1SJohn Marino do_X509_REQ_sign(BIO * err, X509_REQ * x, EVP_PKEY * pkey, const EVP_MD * md,
1778f5b1c8a1SJohn Marino     STACK_OF(OPENSSL_STRING) * sigopts)
1779f5b1c8a1SJohn Marino {
1780*de0e0e4dSAntonio Huete Jimenez 	EVP_MD_CTX *mctx;
1781f5b1c8a1SJohn Marino 	int rv;
1782*de0e0e4dSAntonio Huete Jimenez 
1783*de0e0e4dSAntonio Huete Jimenez 	if ((mctx = EVP_MD_CTX_new()) == NULL)
1784*de0e0e4dSAntonio Huete Jimenez 		return 0;
1785*de0e0e4dSAntonio Huete Jimenez 
1786*de0e0e4dSAntonio Huete Jimenez 	rv = do_sign_init(err, mctx, pkey, md, sigopts);
1787f5b1c8a1SJohn Marino 	if (rv > 0)
1788*de0e0e4dSAntonio Huete Jimenez 		rv = X509_REQ_sign_ctx(x, mctx);
1789*de0e0e4dSAntonio Huete Jimenez 
1790*de0e0e4dSAntonio Huete Jimenez 	EVP_MD_CTX_free(mctx);
1791*de0e0e4dSAntonio Huete Jimenez 
1792*de0e0e4dSAntonio Huete Jimenez 	return rv > 0;
1793f5b1c8a1SJohn Marino }
1794f5b1c8a1SJohn Marino 
1795f5b1c8a1SJohn Marino 
1796f5b1c8a1SJohn Marino 
1797f5b1c8a1SJohn Marino int
do_X509_CRL_sign(BIO * err,X509_CRL * x,EVP_PKEY * pkey,const EVP_MD * md,STACK_OF (OPENSSL_STRING)* sigopts)1798f5b1c8a1SJohn Marino do_X509_CRL_sign(BIO * err, X509_CRL * x, EVP_PKEY * pkey, const EVP_MD * md,
1799f5b1c8a1SJohn Marino     STACK_OF(OPENSSL_STRING) * sigopts)
1800f5b1c8a1SJohn Marino {
1801f5b1c8a1SJohn Marino 	int rv;
1802*de0e0e4dSAntonio Huete Jimenez 	EVP_MD_CTX *mctx;
1803*de0e0e4dSAntonio Huete Jimenez 
1804*de0e0e4dSAntonio Huete Jimenez 	if ((mctx = EVP_MD_CTX_new()) == NULL)
1805*de0e0e4dSAntonio Huete Jimenez 		return 0;
1806*de0e0e4dSAntonio Huete Jimenez 
1807*de0e0e4dSAntonio Huete Jimenez 	rv = do_sign_init(err, mctx, pkey, md, sigopts);
1808f5b1c8a1SJohn Marino 	if (rv > 0)
1809*de0e0e4dSAntonio Huete Jimenez 		rv = X509_CRL_sign_ctx(x, mctx);
1810*de0e0e4dSAntonio Huete Jimenez 
1811*de0e0e4dSAntonio Huete Jimenez 	EVP_MD_CTX_free(mctx);
1812*de0e0e4dSAntonio Huete Jimenez 
1813*de0e0e4dSAntonio Huete Jimenez 	return rv > 0;
1814f5b1c8a1SJohn Marino }
1815cca6fc52SDaniel Fojt 
1816cca6fc52SDaniel Fojt static unsigned long
ext_name_hash(const OPENSSL_STRING * a)1817cca6fc52SDaniel Fojt ext_name_hash(const OPENSSL_STRING *a)
1818cca6fc52SDaniel Fojt {
1819cca6fc52SDaniel Fojt 	return lh_strhash((const char *)a);
1820cca6fc52SDaniel Fojt }
1821cca6fc52SDaniel Fojt 
1822cca6fc52SDaniel Fojt static int
ext_name_cmp(const OPENSSL_STRING * a,const OPENSSL_STRING * b)1823cca6fc52SDaniel Fojt ext_name_cmp(const OPENSSL_STRING *a, const OPENSSL_STRING *b)
1824cca6fc52SDaniel Fojt {
1825cca6fc52SDaniel Fojt 	return strcmp((const char *)a, (const char *)b);
1826cca6fc52SDaniel Fojt }
1827cca6fc52SDaniel Fojt 
1828cca6fc52SDaniel Fojt static void
exts_cleanup(OPENSSL_STRING * x)1829cca6fc52SDaniel Fojt exts_cleanup(OPENSSL_STRING *x)
1830cca6fc52SDaniel Fojt {
1831cca6fc52SDaniel Fojt 	free((char *)x);
1832cca6fc52SDaniel Fojt }
1833cca6fc52SDaniel Fojt 
1834cca6fc52SDaniel Fojt /*
1835cca6fc52SDaniel Fojt  * Is the |kv| key already duplicated ? This is remarkably tricky to get right.
1836cca6fc52SDaniel Fojt  * Return 0 if unique, -1 on runtime error; 1 if found or a syntax error.
1837cca6fc52SDaniel Fojt  */
1838cca6fc52SDaniel Fojt static int
duplicated(LHASH_OF (OPENSSL_STRING)* addexts,char * kv)1839cca6fc52SDaniel Fojt duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv)
1840cca6fc52SDaniel Fojt {
1841cca6fc52SDaniel Fojt 	char *p;
1842cca6fc52SDaniel Fojt 	size_t off;
1843cca6fc52SDaniel Fojt 
1844cca6fc52SDaniel Fojt 	/* Check syntax. */
1845cca6fc52SDaniel Fojt 	/* Skip leading whitespace, make a copy. */
1846cca6fc52SDaniel Fojt 	while (*kv && isspace(*kv))
1847cca6fc52SDaniel Fojt 		if (*++kv == '\0')
1848cca6fc52SDaniel Fojt 			return 1;
1849cca6fc52SDaniel Fojt 	if ((p = strchr(kv, '=')) == NULL)
1850cca6fc52SDaniel Fojt 		return 1;
1851cca6fc52SDaniel Fojt 	off = p - kv;
1852cca6fc52SDaniel Fojt 	if ((kv = strdup(kv)) == NULL)
1853cca6fc52SDaniel Fojt 		return -1;
1854cca6fc52SDaniel Fojt 
1855cca6fc52SDaniel Fojt 	/* Skip trailing space before the equal sign. */
1856cca6fc52SDaniel Fojt 	for (p = kv + off; p > kv; --p)
1857cca6fc52SDaniel Fojt 		if (!isspace(p[-1]))
1858cca6fc52SDaniel Fojt 			break;
1859cca6fc52SDaniel Fojt 	if (p == kv) {
1860cca6fc52SDaniel Fojt 		free(kv);
1861cca6fc52SDaniel Fojt 		return 1;
1862cca6fc52SDaniel Fojt 	}
1863cca6fc52SDaniel Fojt 	*p = '\0';
1864cca6fc52SDaniel Fojt 
1865cca6fc52SDaniel Fojt 	/* See if "key" is there by attempting to add it. */
1866cca6fc52SDaniel Fojt 	if ((p = (char *)lh_OPENSSL_STRING_insert(addexts, (OPENSSL_STRING*)kv))
1867cca6fc52SDaniel Fojt 	    != NULL || lh_OPENSSL_STRING_error(addexts)) {
1868cca6fc52SDaniel Fojt 		free(p != NULL ? p : kv);
1869cca6fc52SDaniel Fojt 		return -1;
1870cca6fc52SDaniel Fojt 	}
1871cca6fc52SDaniel Fojt 
1872cca6fc52SDaniel Fojt 	return 0;
1873cca6fc52SDaniel Fojt }
1874