xref: /freebsd/crypto/openssl/apps/req.c (revision 44096ebd22ddd0081a357011714eff8963614b65)
16f9291ceSJung-uk Kim /*
2e0c4386eSCy Schubert  * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
3e71b7053SJung-uk Kim  *
4b077aed3SPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5e71b7053SJung-uk Kim  * this file except in compliance with the License.  You can obtain a copy
6e71b7053SJung-uk Kim  * in the file LICENSE in the source distribution or at
7e71b7053SJung-uk Kim  * https://www.openssl.org/source/license.html
86f9291ceSJung-uk Kim  */
93b4e3dcbSSimon L. B. Nielsen 
1074664626SKris Kennaway #include <stdio.h>
1174664626SKris Kennaway #include <stdlib.h>
1274664626SKris Kennaway #include <time.h>
1374664626SKris Kennaway #include <string.h>
14e71b7053SJung-uk Kim #include <ctype.h>
1574664626SKris Kennaway #include "apps.h"
16e71b7053SJung-uk Kim #include "progs.h"
17b077aed3SPierre Pronchery #include <openssl/core_names.h>
1874664626SKris Kennaway #include <openssl/bio.h>
1974664626SKris Kennaway #include <openssl/evp.h>
2074664626SKris Kennaway #include <openssl/conf.h>
2174664626SKris Kennaway #include <openssl/err.h>
2274664626SKris Kennaway #include <openssl/asn1.h>
2374664626SKris Kennaway #include <openssl/x509.h>
2474664626SKris Kennaway #include <openssl/x509v3.h>
2574664626SKris Kennaway #include <openssl/objects.h>
2674664626SKris Kennaway #include <openssl/pem.h>
273b4e3dcbSSimon L. B. Nielsen #include <openssl/bn.h>
28e71b7053SJung-uk Kim #include <openssl/lhash.h>
293b4e3dcbSSimon L. B. Nielsen #include <openssl/rsa.h>
303b4e3dcbSSimon L. B. Nielsen #ifndef OPENSSL_NO_DSA
313b4e3dcbSSimon L. B. Nielsen # include <openssl/dsa.h>
323b4e3dcbSSimon L. B. Nielsen #endif
3374664626SKris Kennaway 
3474664626SKris Kennaway #define BITS               "default_bits"
3574664626SKris Kennaway #define KEYFILE            "default_keyfile"
36f579bf8eSKris Kennaway #define PROMPT             "prompt"
3774664626SKris Kennaway #define DISTINGUISHED_NAME "distinguished_name"
3874664626SKris Kennaway #define ATTRIBUTES         "attributes"
3974664626SKris Kennaway #define V3_EXTENSIONS      "x509_extensions"
40f579bf8eSKris Kennaway #define REQ_EXTENSIONS     "req_extensions"
41f579bf8eSKris Kennaway #define STRING_MASK        "string_mask"
425c87c606SMark Murray #define UTF8_IN            "utf8"
4374664626SKris Kennaway 
444c6a0400SJung-uk Kim #define DEFAULT_KEY_LENGTH 2048
454c6a0400SJung-uk Kim #define MIN_KEY_LENGTH     512
46b077aed3SPierre Pronchery #define DEFAULT_DAYS       30 /* default cert validity period in days */
47b077aed3SPierre Pronchery #define UNSET_DAYS         -2 /* -1 may be used for testing expiration checks */
48b077aed3SPierre Pronchery #define EXT_COPY_UNSET     -1
4974664626SKris Kennaway 
50b077aed3SPierre Pronchery static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, X509_NAME *fsubj,
51b077aed3SPierre Pronchery                     int mutlirdn, int attribs, unsigned long chtype);
52f579bf8eSKris Kennaway static int prompt_info(X509_REQ *req,
53e71b7053SJung-uk Kim                        STACK_OF(CONF_VALUE) *dn_sk, const char *dn_sect,
54e71b7053SJung-uk Kim                        STACK_OF(CONF_VALUE) *attr_sk, const char *attr_sect,
556f9291ceSJung-uk Kim                        int attribs, unsigned long chtype);
56f579bf8eSKris Kennaway static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *sk,
575c87c606SMark Murray                      STACK_OF(CONF_VALUE) *attr, int attribs,
585c87c606SMark Murray                      unsigned long chtype);
593b4e3dcbSSimon L. B. Nielsen static int add_attribute_object(X509_REQ *req, char *text, const char *def,
606f9291ceSJung-uk Kim                                 char *value, int nid, int n_min, int n_max,
616f9291ceSJung-uk Kim                                 unsigned long chtype);
626f9291ceSJung-uk Kim static int add_DN_object(X509_NAME *n, char *text, const char *def,
636f9291ceSJung-uk Kim                          char *value, int nid, int n_min, int n_max,
646f9291ceSJung-uk Kim                          unsigned long chtype, int mval);
651f13597dSJung-uk Kim static int genpkey_cb(EVP_PKEY_CTX *ctx);
66b077aed3SPierre Pronchery static int build_data(char *text, const char *def, char *value,
67b077aed3SPierre Pronchery                       int n_min, int n_max, char *buf, const int buf_size,
68b077aed3SPierre Pronchery                       const char *desc1, const char *desc2);
695c87c606SMark Murray static int req_check_len(int len, int n_min, int n_max);
703b4e3dcbSSimon L. B. Nielsen static int check_end(const char *str, const char *end);
71e71b7053SJung-uk Kim static int join(char buf[], size_t buf_size, const char *name,
72e71b7053SJung-uk Kim                 const char *tail, const char *desc);
73e71b7053SJung-uk Kim static EVP_PKEY_CTX *set_keygen_ctx(const char *gstr,
74b077aed3SPierre Pronchery                                     char **pkeytype, long *pkeylen,
75b077aed3SPierre Pronchery                                     ENGINE *keygen_engine);
76b077aed3SPierre Pronchery 
77b077aed3SPierre Pronchery static const char *section = "req";
785c87c606SMark Murray static CONF *req_conf = NULL;
79e71b7053SJung-uk Kim static CONF *addext_conf = NULL;
805c87c606SMark Murray static int batch = 0;
8174664626SKris Kennaway 
82e71b7053SJung-uk Kim typedef enum OPTION_choice {
83b077aed3SPierre Pronchery     OPT_COMMON,
84e71b7053SJung-uk Kim     OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_KEYGEN_ENGINE, OPT_KEY,
85e71b7053SJung-uk Kim     OPT_PUBKEY, OPT_NEW, OPT_CONFIG, OPT_KEYFORM, OPT_IN, OPT_OUT,
86e71b7053SJung-uk Kim     OPT_KEYOUT, OPT_PASSIN, OPT_PASSOUT, OPT_NEWKEY,
87b077aed3SPierre Pronchery     OPT_PKEYOPT, OPT_SIGOPT, OPT_VFYOPT, OPT_BATCH, OPT_NEWHDR, OPT_MODULUS,
88b077aed3SPierre Pronchery     OPT_VERIFY, OPT_NOENC, OPT_NODES, OPT_NOOUT, OPT_VERBOSE, OPT_UTF8,
89e71b7053SJung-uk Kim     OPT_NAMEOPT, OPT_REQOPT, OPT_SUBJ, OPT_SUBJECT, OPT_TEXT, OPT_X509,
90b077aed3SPierre Pronchery     OPT_CA, OPT_CAKEY,
91b077aed3SPierre Pronchery     OPT_MULTIVALUE_RDN, OPT_DAYS, OPT_SET_SERIAL,
92b077aed3SPierre Pronchery     OPT_COPY_EXTENSIONS, OPT_ADDEXT, OPT_EXTENSIONS,
93e71b7053SJung-uk Kim     OPT_REQEXTS, OPT_PRECERT, OPT_MD,
94b077aed3SPierre Pronchery     OPT_SECTION,
95b077aed3SPierre Pronchery     OPT_R_ENUM, OPT_PROV_ENUM
96e71b7053SJung-uk Kim } OPTION_CHOICE;
97f579bf8eSKris Kennaway 
98e71b7053SJung-uk Kim const OPTIONS req_options[] = {
99b077aed3SPierre Pronchery     OPT_SECTION("General"),
100e71b7053SJung-uk Kim     {"help", OPT_HELP, '-', "Display this summary"},
101b077aed3SPierre Pronchery #ifndef OPENSSL_NO_ENGINE
102b077aed3SPierre Pronchery     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
103b077aed3SPierre Pronchery     {"keygen_engine", OPT_KEYGEN_ENGINE, 's',
104b077aed3SPierre Pronchery      "Specify engine to be used for key generation operations"},
105b077aed3SPierre Pronchery #endif
106b077aed3SPierre Pronchery     {"in", OPT_IN, '<', "X.509 request input file (default stdin)"},
107e71b7053SJung-uk Kim     {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"},
108b077aed3SPierre Pronchery     {"verify", OPT_VERIFY, '-', "Verify self-signature on the request"},
109b077aed3SPierre Pronchery 
110b077aed3SPierre Pronchery     OPT_SECTION("Certificate"),
111e71b7053SJung-uk Kim     {"new", OPT_NEW, '-', "New request"},
112e71b7053SJung-uk Kim     {"config", OPT_CONFIG, '<', "Request template file"},
113b077aed3SPierre Pronchery     {"section", OPT_SECTION, 's', "Config section to use (default \"req\")"},
114e71b7053SJung-uk Kim     {"utf8", OPT_UTF8, '-', "Input characters are UTF8 (default ASCII)"},
115b077aed3SPierre Pronchery     {"nameopt", OPT_NAMEOPT, 's', "Certificate subject/issuer name printing options"},
116e71b7053SJung-uk Kim     {"reqopt", OPT_REQOPT, 's', "Various request text options"},
117e71b7053SJung-uk Kim     {"text", OPT_TEXT, '-', "Text form of request"},
118e71b7053SJung-uk Kim     {"x509", OPT_X509, '-',
119b077aed3SPierre Pronchery      "Output an X.509 certificate structure instead of a cert request"},
120b077aed3SPierre Pronchery     {"CA", OPT_CA, '<', "Issuer cert to use for signing a cert, implies -x509"},
121b077aed3SPierre Pronchery     {"CAkey", OPT_CAKEY, 's',
122b077aed3SPierre Pronchery      "Issuer private key to use with -CA; default is -CA arg"},
123e71b7053SJung-uk Kim     {OPT_MORE_STR, 1, 1, "(Required by some CA's)"},
124b077aed3SPierre Pronchery     {"subj", OPT_SUBJ, 's', "Set or modify subject of request or cert"},
125b077aed3SPierre Pronchery     {"subject", OPT_SUBJECT, '-',
126b077aed3SPierre Pronchery      "Print the subject of the output request or cert"},
127e71b7053SJung-uk Kim     {"multivalue-rdn", OPT_MULTIVALUE_RDN, '-',
128b077aed3SPierre Pronchery      "Deprecated; multi-valued RDNs support is always on."},
129e71b7053SJung-uk Kim     {"days", OPT_DAYS, 'p', "Number of days cert is valid for"},
130e71b7053SJung-uk Kim     {"set_serial", OPT_SET_SERIAL, 's', "Serial number to use"},
131b077aed3SPierre Pronchery     {"copy_extensions", OPT_COPY_EXTENSIONS, 's',
132b077aed3SPierre Pronchery      "copy extensions from request when using -x509"},
133e71b7053SJung-uk Kim     {"addext", OPT_ADDEXT, 's',
134e71b7053SJung-uk Kim      "Additional cert extension key=value pair (may be given more than once)"},
135e71b7053SJung-uk Kim     {"extensions", OPT_EXTENSIONS, 's',
136e71b7053SJung-uk Kim      "Cert extension section (override value in config file)"},
137e71b7053SJung-uk Kim     {"reqexts", OPT_REQEXTS, 's',
138e71b7053SJung-uk Kim      "Request extension section (override value in config file)"},
139b077aed3SPierre Pronchery     {"precert", OPT_PRECERT, '-',
140b077aed3SPierre Pronchery      "Add a poison extension to the generated cert (implies -new)"},
141b077aed3SPierre Pronchery 
142b077aed3SPierre Pronchery     OPT_SECTION("Keys and Signing"),
143b077aed3SPierre Pronchery     {"key", OPT_KEY, 's', "Key for signing, and to include unless -in given"},
144b077aed3SPierre Pronchery     {"keyform", OPT_KEYFORM, 'f', "Key file format (ENGINE, other values ignored)"},
145b077aed3SPierre Pronchery     {"pubkey", OPT_PUBKEY, '-', "Output public key"},
146b077aed3SPierre Pronchery     {"keyout", OPT_KEYOUT, '>', "File to write private key to"},
147b077aed3SPierre Pronchery     {"passin", OPT_PASSIN, 's', "Private key and certificate password source"},
148b077aed3SPierre Pronchery     {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
149b077aed3SPierre Pronchery     {"newkey", OPT_NEWKEY, 's',
150b077aed3SPierre Pronchery      "Generate new key with [<alg>:]<nbits> or <alg>[:<file>] or param:<file>"},
151b077aed3SPierre Pronchery     {"pkeyopt", OPT_PKEYOPT, 's', "Public key options as opt:value"},
152b077aed3SPierre Pronchery     {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"},
153b077aed3SPierre Pronchery     {"vfyopt", OPT_VFYOPT, 's', "Verification parameter in n:v form"},
154e71b7053SJung-uk Kim     {"", OPT_MD, '-', "Any supported digest"},
155b077aed3SPierre Pronchery 
156b077aed3SPierre Pronchery     OPT_SECTION("Output"),
157b077aed3SPierre Pronchery     {"out", OPT_OUT, '>', "Output file"},
158b077aed3SPierre Pronchery     {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"},
159b077aed3SPierre Pronchery     {"batch", OPT_BATCH, '-',
160b077aed3SPierre Pronchery      "Do not ask anything during request generation"},
161b077aed3SPierre Pronchery     {"verbose", OPT_VERBOSE, '-', "Verbose output"},
162b077aed3SPierre Pronchery     {"noenc", OPT_NOENC, '-', "Don't encrypt private keys"},
163b077aed3SPierre Pronchery     {"nodes", OPT_NODES, '-', "Don't encrypt private keys; deprecated"},
164b077aed3SPierre Pronchery     {"noout", OPT_NOOUT, '-', "Do not output REQ"},
165b077aed3SPierre Pronchery     {"newhdr", OPT_NEWHDR, '-', "Output \"NEW\" in the header lines"},
166b077aed3SPierre Pronchery     {"modulus", OPT_MODULUS, '-', "RSA modulus"},
167b077aed3SPierre Pronchery 
168b077aed3SPierre Pronchery     OPT_R_OPTIONS,
169b077aed3SPierre Pronchery     OPT_PROV_OPTIONS,
170e71b7053SJung-uk Kim     {NULL}
171e71b7053SJung-uk Kim };
172e71b7053SJung-uk Kim 
173e71b7053SJung-uk Kim /*
174e71b7053SJung-uk Kim  * An LHASH of strings, where each string is an extension name.
175e71b7053SJung-uk Kim  */
176e71b7053SJung-uk Kim static unsigned long ext_name_hash(const OPENSSL_STRING *a)
17774664626SKris Kennaway {
178e71b7053SJung-uk Kim     return OPENSSL_LH_strhash((const char *)a);
179e71b7053SJung-uk Kim }
180e71b7053SJung-uk Kim 
181e71b7053SJung-uk Kim static int ext_name_cmp(const OPENSSL_STRING *a, const OPENSSL_STRING *b)
182e71b7053SJung-uk Kim {
183e71b7053SJung-uk Kim     return strcmp((const char *)a, (const char *)b);
184e71b7053SJung-uk Kim }
185e71b7053SJung-uk Kim 
186e71b7053SJung-uk Kim static void exts_cleanup(OPENSSL_STRING *x)
187e71b7053SJung-uk Kim {
188e71b7053SJung-uk Kim     OPENSSL_free((char *)x);
189e71b7053SJung-uk Kim }
190e71b7053SJung-uk Kim 
191e71b7053SJung-uk Kim /*
192b077aed3SPierre Pronchery  * Is the |kv| key already duplicated? This is remarkably tricky to get right.
193b077aed3SPierre Pronchery  * Return 0 if unique, -1 on runtime error; 1 if found or a syntax error.
194e71b7053SJung-uk Kim  */
195e71b7053SJung-uk Kim static int duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv)
196e71b7053SJung-uk Kim {
197e71b7053SJung-uk Kim     char *p;
198e71b7053SJung-uk Kim     size_t off;
199e71b7053SJung-uk Kim 
200e71b7053SJung-uk Kim     /* Check syntax. */
201e71b7053SJung-uk Kim     /* Skip leading whitespace, make a copy. */
202aa795734SPierre Pronchery     while (*kv && isspace(_UC(*kv)))
203e71b7053SJung-uk Kim         if (*++kv == '\0')
204e71b7053SJung-uk Kim             return 1;
205e71b7053SJung-uk Kim     if ((p = strchr(kv, '=')) == NULL)
206e71b7053SJung-uk Kim         return 1;
207e71b7053SJung-uk Kim     off = p - kv;
208e71b7053SJung-uk Kim     if ((kv = OPENSSL_strdup(kv)) == NULL)
209e71b7053SJung-uk Kim         return -1;
210e71b7053SJung-uk Kim 
211e71b7053SJung-uk Kim     /* Skip trailing space before the equal sign. */
212e71b7053SJung-uk Kim     for (p = kv + off; p > kv; --p)
213aa795734SPierre Pronchery         if (!isspace(_UC(p[-1])))
214e71b7053SJung-uk Kim             break;
215e71b7053SJung-uk Kim     if (p == kv) {
216e71b7053SJung-uk Kim         OPENSSL_free(kv);
217e71b7053SJung-uk Kim         return 1;
218e71b7053SJung-uk Kim     }
219e71b7053SJung-uk Kim     *p = '\0';
220e71b7053SJung-uk Kim 
221e71b7053SJung-uk Kim     /* Finally have a clean "key"; see if it's there [by attempt to add it]. */
22217f01e99SJung-uk Kim     p = (char *)lh_OPENSSL_STRING_insert(addexts, (OPENSSL_STRING *)kv);
22317f01e99SJung-uk Kim     if (p != NULL) {
22417f01e99SJung-uk Kim         OPENSSL_free(p);
22517f01e99SJung-uk Kim         return 1;
22617f01e99SJung-uk Kim     } else if (lh_OPENSSL_STRING_error(addexts)) {
22717f01e99SJung-uk Kim         OPENSSL_free(kv);
228e71b7053SJung-uk Kim         return -1;
229e71b7053SJung-uk Kim     }
230e71b7053SJung-uk Kim 
231e71b7053SJung-uk Kim     return 0;
232e71b7053SJung-uk Kim }
233e71b7053SJung-uk Kim 
234e71b7053SJung-uk Kim int req_main(int argc, char **argv)
235e71b7053SJung-uk Kim {
236e71b7053SJung-uk Kim     ASN1_INTEGER *serial = NULL;
237b077aed3SPierre Pronchery     BIO *out = NULL;
2381f13597dSJung-uk Kim     ENGINE *e = NULL, *gen_eng = NULL;
239b077aed3SPierre Pronchery     EVP_PKEY *pkey = NULL, *CAkey = NULL;
240e71b7053SJung-uk Kim     EVP_PKEY_CTX *genctx = NULL;
241b077aed3SPierre Pronchery     STACK_OF(OPENSSL_STRING) *pkeyopts = NULL, *sigopts = NULL, *vfyopts = NULL;
242e71b7053SJung-uk Kim     LHASH_OF(OPENSSL_STRING) *addexts = NULL;
243b077aed3SPierre Pronchery     X509 *new_x509 = NULL, *CAcert = NULL;
24474664626SKris Kennaway     X509_REQ *req = NULL;
245b077aed3SPierre Pronchery     EVP_CIPHER *cipher = NULL;
246b077aed3SPierre Pronchery     EVP_MD *md = NULL;
247b077aed3SPierre Pronchery     int ext_copy = EXT_COPY_UNSET;
248e71b7053SJung-uk Kim     BIO *addext_bio = NULL;
249b077aed3SPierre Pronchery     char *extensions = NULL;
250b077aed3SPierre Pronchery     const char *infile = NULL, *CAfile = NULL, *CAkeyfile = NULL;
251b077aed3SPierre Pronchery     char *outfile = NULL, *keyfile = NULL, *digest = NULL;
252e71b7053SJung-uk Kim     char *keyalgstr = NULL, *p, *prog, *passargin = NULL, *passargout = NULL;
253e71b7053SJung-uk Kim     char *passin = NULL, *passout = NULL;
254e71b7053SJung-uk Kim     char *nofree_passin = NULL, *nofree_passout = NULL;
255e71b7053SJung-uk Kim     char *req_exts = NULL, *subj = NULL;
256b077aed3SPierre Pronchery     X509_NAME *fsubj = NULL;
257e71b7053SJung-uk Kim     char *template = default_config_file, *keyout = NULL;
258e71b7053SJung-uk Kim     const char *keyalg = NULL;
259e71b7053SJung-uk Kim     OPTION_CHOICE o;
260b077aed3SPierre Pronchery     int days = UNSET_DAYS;
261b077aed3SPierre Pronchery     int ret = 1, gen_x509 = 0, i = 0, newreq = 0, verbose = 0;
262b077aed3SPierre Pronchery     int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, keyform = FORMAT_UNDEF;
263b077aed3SPierre Pronchery     int modulus = 0, multirdn = 1, verify = 0, noout = 0, text = 0;
264b077aed3SPierre Pronchery     int noenc = 0, newhdr = 0, subject = 0, pubkey = 0, precert = 0;
265b077aed3SPierre Pronchery     long newkey_len = -1;
266e71b7053SJung-uk Kim     unsigned long chtype = MBSTRING_ASC, reqflag = 0;
26774664626SKris Kennaway 
2685c87c606SMark Murray #ifndef OPENSSL_NO_DES
269b077aed3SPierre Pronchery     cipher = (EVP_CIPHER *)EVP_des_ede3_cbc();
27074664626SKris Kennaway #endif
27174664626SKris Kennaway 
272e71b7053SJung-uk Kim     prog = opt_init(argc, argv, req_options);
273e71b7053SJung-uk Kim     while ((o = opt_next()) != OPT_EOF) {
274e71b7053SJung-uk Kim         switch (o) {
275e71b7053SJung-uk Kim         case OPT_EOF:
276e71b7053SJung-uk Kim         case OPT_ERR:
277e71b7053SJung-uk Kim  opthelp:
278e71b7053SJung-uk Kim             BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
279e71b7053SJung-uk Kim             goto end;
280e71b7053SJung-uk Kim         case OPT_HELP:
281e71b7053SJung-uk Kim             opt_help(req_options);
282e71b7053SJung-uk Kim             ret = 0;
283e71b7053SJung-uk Kim             goto end;
284e71b7053SJung-uk Kim         case OPT_INFORM:
285e71b7053SJung-uk Kim             if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
286e71b7053SJung-uk Kim                 goto opthelp;
287e71b7053SJung-uk Kim             break;
288e71b7053SJung-uk Kim         case OPT_OUTFORM:
289e71b7053SJung-uk Kim             if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat))
290e71b7053SJung-uk Kim                 goto opthelp;
291e71b7053SJung-uk Kim             break;
292e71b7053SJung-uk Kim         case OPT_ENGINE:
293e71b7053SJung-uk Kim             e = setup_engine(opt_arg(), 0);
294e71b7053SJung-uk Kim             break;
295e71b7053SJung-uk Kim         case OPT_KEYGEN_ENGINE:
296fceca8a3SJacques Vidrine #ifndef OPENSSL_NO_ENGINE
297b077aed3SPierre Pronchery             gen_eng = setup_engine(opt_arg(), 0);
2986f9291ceSJung-uk Kim             if (gen_eng == NULL) {
2991f13597dSJung-uk Kim                 BIO_printf(bio_err, "Can't find keygen engine %s\n", *argv);
300e71b7053SJung-uk Kim                 goto opthelp;
3011f13597dSJung-uk Kim             }
302fceca8a3SJacques Vidrine #endif
303e71b7053SJung-uk Kim             break;
304e71b7053SJung-uk Kim         case OPT_KEY:
305e71b7053SJung-uk Kim             keyfile = opt_arg();
306e71b7053SJung-uk Kim             break;
307e71b7053SJung-uk Kim         case OPT_PUBKEY:
3085c87c606SMark Murray             pubkey = 1;
309e71b7053SJung-uk Kim             break;
310e71b7053SJung-uk Kim         case OPT_NEW:
31174664626SKris Kennaway             newreq = 1;
312e71b7053SJung-uk Kim             break;
313e71b7053SJung-uk Kim         case OPT_CONFIG:
314e71b7053SJung-uk Kim             template = opt_arg();
315e71b7053SJung-uk Kim             break;
316b077aed3SPierre Pronchery         case OPT_SECTION:
317b077aed3SPierre Pronchery             section = opt_arg();
318b077aed3SPierre Pronchery             break;
319e71b7053SJung-uk Kim         case OPT_KEYFORM:
320e71b7053SJung-uk Kim             if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform))
321e71b7053SJung-uk Kim                 goto opthelp;
322e71b7053SJung-uk Kim             break;
323e71b7053SJung-uk Kim         case OPT_IN:
324e71b7053SJung-uk Kim             infile = opt_arg();
325e71b7053SJung-uk Kim             break;
326e71b7053SJung-uk Kim         case OPT_OUT:
327e71b7053SJung-uk Kim             outfile = opt_arg();
328e71b7053SJung-uk Kim             break;
329e71b7053SJung-uk Kim         case OPT_KEYOUT:
330e71b7053SJung-uk Kim             keyout = opt_arg();
331e71b7053SJung-uk Kim             break;
332e71b7053SJung-uk Kim         case OPT_PASSIN:
333e71b7053SJung-uk Kim             passargin = opt_arg();
334e71b7053SJung-uk Kim             break;
335e71b7053SJung-uk Kim         case OPT_PASSOUT:
336e71b7053SJung-uk Kim             passargout = opt_arg();
337e71b7053SJung-uk Kim             break;
338e71b7053SJung-uk Kim         case OPT_R_CASES:
339e71b7053SJung-uk Kim             if (!opt_rand(o))
340e71b7053SJung-uk Kim                 goto end;
341e71b7053SJung-uk Kim             break;
342b077aed3SPierre Pronchery         case OPT_PROV_CASES:
343b077aed3SPierre Pronchery             if (!opt_provider(o))
344b077aed3SPierre Pronchery                 goto end;
345b077aed3SPierre Pronchery             break;
346e71b7053SJung-uk Kim         case OPT_NEWKEY:
347e71b7053SJung-uk Kim             keyalg = opt_arg();
3481f13597dSJung-uk Kim             newreq = 1;
349e71b7053SJung-uk Kim             break;
350e71b7053SJung-uk Kim         case OPT_PKEYOPT:
351b077aed3SPierre Pronchery             if (pkeyopts == NULL)
3521f13597dSJung-uk Kim                 pkeyopts = sk_OPENSSL_STRING_new_null();
353b077aed3SPierre Pronchery             if (pkeyopts == NULL
354b077aed3SPierre Pronchery                     || !sk_OPENSSL_STRING_push(pkeyopts, opt_arg()))
355e71b7053SJung-uk Kim                 goto opthelp;
356e71b7053SJung-uk Kim             break;
357e71b7053SJung-uk Kim         case OPT_SIGOPT:
3581f13597dSJung-uk Kim             if (!sigopts)
3591f13597dSJung-uk Kim                 sigopts = sk_OPENSSL_STRING_new_null();
360e71b7053SJung-uk Kim             if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg()))
361e71b7053SJung-uk Kim                 goto opthelp;
36274664626SKris Kennaway             break;
363b077aed3SPierre Pronchery         case OPT_VFYOPT:
364b077aed3SPierre Pronchery             if (!vfyopts)
365b077aed3SPierre Pronchery                 vfyopts = sk_OPENSSL_STRING_new_null();
366b077aed3SPierre Pronchery             if (!vfyopts || !sk_OPENSSL_STRING_push(vfyopts, opt_arg()))
367b077aed3SPierre Pronchery                 goto opthelp;
368b077aed3SPierre Pronchery             break;
369e71b7053SJung-uk Kim         case OPT_BATCH:
370e71b7053SJung-uk Kim             batch = 1;
371e71b7053SJung-uk Kim             break;
372e71b7053SJung-uk Kim         case OPT_NEWHDR:
373e71b7053SJung-uk Kim             newhdr = 1;
374e71b7053SJung-uk Kim             break;
375e71b7053SJung-uk Kim         case OPT_MODULUS:
376e71b7053SJung-uk Kim             modulus = 1;
377e71b7053SJung-uk Kim             break;
378e71b7053SJung-uk Kim         case OPT_VERIFY:
379e71b7053SJung-uk Kim             verify = 1;
380e71b7053SJung-uk Kim             break;
381e71b7053SJung-uk Kim         case OPT_NODES:
382b077aed3SPierre Pronchery         case OPT_NOENC:
383b077aed3SPierre Pronchery             noenc = 1;
384e71b7053SJung-uk Kim             break;
385e71b7053SJung-uk Kim         case OPT_NOOUT:
386e71b7053SJung-uk Kim             noout = 1;
387e71b7053SJung-uk Kim             break;
388e71b7053SJung-uk Kim         case OPT_VERBOSE:
389e71b7053SJung-uk Kim             verbose = 1;
390e71b7053SJung-uk Kim             break;
391e71b7053SJung-uk Kim         case OPT_UTF8:
392e71b7053SJung-uk Kim             chtype = MBSTRING_UTF8;
393e71b7053SJung-uk Kim             break;
394e71b7053SJung-uk Kim         case OPT_NAMEOPT:
395e71b7053SJung-uk Kim             if (!set_nameopt(opt_arg()))
396e71b7053SJung-uk Kim                 goto opthelp;
397e71b7053SJung-uk Kim             break;
398e71b7053SJung-uk Kim         case OPT_REQOPT:
399e71b7053SJung-uk Kim             if (!set_cert_ex(&reqflag, opt_arg()))
400e71b7053SJung-uk Kim                 goto opthelp;
401e71b7053SJung-uk Kim             break;
402e71b7053SJung-uk Kim         case OPT_TEXT:
403e71b7053SJung-uk Kim             text = 1;
404e71b7053SJung-uk Kim             break;
405e71b7053SJung-uk Kim         case OPT_X509:
406b077aed3SPierre Pronchery             gen_x509 = 1;
407b077aed3SPierre Pronchery             break;
408b077aed3SPierre Pronchery         case OPT_CA:
409b077aed3SPierre Pronchery             CAfile = opt_arg();
410b077aed3SPierre Pronchery             gen_x509 = 1;
411b077aed3SPierre Pronchery             break;
412b077aed3SPierre Pronchery         case OPT_CAKEY:
413b077aed3SPierre Pronchery             CAkeyfile = opt_arg();
414e71b7053SJung-uk Kim             break;
415e71b7053SJung-uk Kim         case OPT_DAYS:
416e71b7053SJung-uk Kim             days = atoi(opt_arg());
417b077aed3SPierre Pronchery             if (days < -1) {
418b077aed3SPierre Pronchery                 BIO_printf(bio_err, "%s: -days parameter arg must be >= -1\n",
419b077aed3SPierre Pronchery                            prog);
420b077aed3SPierre Pronchery                 goto end;
421b077aed3SPierre Pronchery             }
422e71b7053SJung-uk Kim             break;
423e71b7053SJung-uk Kim         case OPT_SET_SERIAL:
424e71b7053SJung-uk Kim             if (serial != NULL) {
425e71b7053SJung-uk Kim                 BIO_printf(bio_err, "Serial number supplied twice\n");
426e71b7053SJung-uk Kim                 goto opthelp;
42774664626SKris Kennaway             }
428e71b7053SJung-uk Kim             serial = s2i_ASN1_INTEGER(NULL, opt_arg());
429e71b7053SJung-uk Kim             if (serial == NULL)
430e71b7053SJung-uk Kim                 goto opthelp;
431e71b7053SJung-uk Kim             break;
432e71b7053SJung-uk Kim         case OPT_SUBJECT:
433e71b7053SJung-uk Kim             subject = 1;
434e71b7053SJung-uk Kim             break;
435e71b7053SJung-uk Kim         case OPT_SUBJ:
436e71b7053SJung-uk Kim             subj = opt_arg();
437e71b7053SJung-uk Kim             break;
438e71b7053SJung-uk Kim         case OPT_MULTIVALUE_RDN:
439b077aed3SPierre Pronchery             /* obsolete */
440b077aed3SPierre Pronchery             break;
441b077aed3SPierre Pronchery         case OPT_COPY_EXTENSIONS:
442b077aed3SPierre Pronchery             if (!set_ext_copy(&ext_copy, opt_arg())) {
443b077aed3SPierre Pronchery                 BIO_printf(bio_err, "Invalid extension copy option: \"%s\"\n",
444b077aed3SPierre Pronchery                            opt_arg());
445b077aed3SPierre Pronchery                 goto end;
446b077aed3SPierre Pronchery             }
447e71b7053SJung-uk Kim             break;
448e71b7053SJung-uk Kim         case OPT_ADDEXT:
449e71b7053SJung-uk Kim             p = opt_arg();
450e71b7053SJung-uk Kim             if (addexts == NULL) {
451e71b7053SJung-uk Kim                 addexts = lh_OPENSSL_STRING_new(ext_name_hash, ext_name_cmp);
452e71b7053SJung-uk Kim                 addext_bio = BIO_new(BIO_s_mem());
453e71b7053SJung-uk Kim                 if (addexts == NULL || addext_bio == NULL)
45474664626SKris Kennaway                     goto end;
45574664626SKris Kennaway             }
456e71b7053SJung-uk Kim             i = duplicated(addexts, p);
457b077aed3SPierre Pronchery             if (i == 1) {
458b077aed3SPierre Pronchery                 BIO_printf(bio_err, "Duplicate extension: %s\n", p);
459e71b7053SJung-uk Kim                 goto opthelp;
460b077aed3SPierre Pronchery             }
461b077aed3SPierre Pronchery             if (i < 0 || BIO_printf(addext_bio, "%s\n", p) < 0)
462e71b7053SJung-uk Kim                 goto end;
463e71b7053SJung-uk Kim             break;
464e71b7053SJung-uk Kim         case OPT_EXTENSIONS:
465e71b7053SJung-uk Kim             extensions = opt_arg();
466e71b7053SJung-uk Kim             break;
467e71b7053SJung-uk Kim         case OPT_REQEXTS:
468e71b7053SJung-uk Kim             req_exts = opt_arg();
469e71b7053SJung-uk Kim             break;
470e71b7053SJung-uk Kim         case OPT_PRECERT:
471e71b7053SJung-uk Kim             newreq = precert = 1;
472e71b7053SJung-uk Kim             break;
473e71b7053SJung-uk Kim         case OPT_MD:
474b077aed3SPierre Pronchery             digest = opt_unknown();
475e71b7053SJung-uk Kim             break;
476e71b7053SJung-uk Kim         }
477e71b7053SJung-uk Kim     }
478b077aed3SPierre Pronchery 
479b077aed3SPierre Pronchery     /* No extra arguments. */
480e71b7053SJung-uk Kim     argc = opt_num_rest();
481e71b7053SJung-uk Kim     if (argc != 0)
482e71b7053SJung-uk Kim         goto opthelp;
48374664626SKris Kennaway 
484b077aed3SPierre Pronchery     if (!app_RAND_load())
485b077aed3SPierre Pronchery         goto end;
486ed7112f0SJung-uk Kim 
487b077aed3SPierre Pronchery     if (!gen_x509) {
488b077aed3SPierre Pronchery         if (days != UNSET_DAYS)
489b077aed3SPierre Pronchery             BIO_printf(bio_err, "Ignoring -days without -x509; not generating a certificate\n");
490b077aed3SPierre Pronchery         if (ext_copy == EXT_COPY_NONE)
491b077aed3SPierre Pronchery             BIO_printf(bio_err, "Ignoring -copy_extensions 'none' when -x509 is not given\n");
492b077aed3SPierre Pronchery     }
493b077aed3SPierre Pronchery     if (gen_x509 && infile == NULL)
494b077aed3SPierre Pronchery         newreq = 1;
495e71b7053SJung-uk Kim 
496e71b7053SJung-uk Kim     if (!app_passwd(passargin, passargout, &passin, &passout)) {
497f579bf8eSKris Kennaway         BIO_printf(bio_err, "Error getting passwords\n");
498f579bf8eSKris Kennaway         goto end;
499f579bf8eSKris Kennaway     }
50074664626SKris Kennaway 
501b077aed3SPierre Pronchery     if ((req_conf = app_load_config_verbose(template, verbose)) == NULL)
50217f01e99SJung-uk Kim         goto end;
503b077aed3SPierre Pronchery     if (addext_bio != NULL) {
504e71b7053SJung-uk Kim         if (verbose)
505e71b7053SJung-uk Kim             BIO_printf(bio_err,
506b077aed3SPierre Pronchery                        "Using additional configuration from -addext options\n");
50717f01e99SJung-uk Kim         if ((addext_conf = app_load_config_bio(addext_bio, NULL)) == NULL)
50817f01e99SJung-uk Kim             goto end;
50974664626SKris Kennaway     }
510e71b7053SJung-uk Kim     if (template != default_config_file && !app_load_modules(req_conf))
5113b4e3dcbSSimon L. B. Nielsen         goto end;
51274664626SKris Kennaway 
5136f9291ceSJung-uk Kim     if (req_conf != NULL) {
5145c87c606SMark Murray         p = NCONF_get_string(req_conf, NULL, "oid_file");
5155c87c606SMark Murray         if (p == NULL)
5165c87c606SMark Murray             ERR_clear_error();
5176f9291ceSJung-uk Kim         if (p != NULL) {
518b077aed3SPierre Pronchery             BIO *oid_bio = BIO_new_file(p, "r");
51974664626SKris Kennaway 
5206f9291ceSJung-uk Kim             if (oid_bio == NULL) {
521b077aed3SPierre Pronchery                 if (verbose)
522b077aed3SPierre Pronchery                     BIO_printf(bio_err,
523b077aed3SPierre Pronchery                                "Problems opening '%s' for extra OIDs\n", p);
5246f9291ceSJung-uk Kim             } else {
52574664626SKris Kennaway                 OBJ_create_objects(oid_bio);
52674664626SKris Kennaway                 BIO_free(oid_bio);
52774664626SKris Kennaway             }
52874664626SKris Kennaway         }
52974664626SKris Kennaway     }
530e71b7053SJung-uk Kim     if (!add_oid_section(req_conf))
5316f9291ceSJung-uk Kim         goto end;
53274664626SKris Kennaway 
533b077aed3SPierre Pronchery     /* Check that any specified digest is fetchable */
534b077aed3SPierre Pronchery     if (digest != NULL) {
535b077aed3SPierre Pronchery         if (!opt_md(digest, &md)) {
5365c87c606SMark Murray             ERR_clear_error();
537e71b7053SJung-uk Kim             goto opthelp;
53874664626SKris Kennaway         }
539b077aed3SPierre Pronchery         EVP_MD_free(md);
540b077aed3SPierre Pronchery     } else {
541b077aed3SPierre Pronchery         /* No digest specified, default to configuration */
542b077aed3SPierre Pronchery         p = NCONF_get_string(req_conf, section, "default_md");
543b077aed3SPierre Pronchery         if (p == NULL)
544b077aed3SPierre Pronchery             ERR_clear_error();
545b077aed3SPierre Pronchery         else
546b077aed3SPierre Pronchery             digest = p;
5475c87c606SMark Murray     }
54874664626SKris Kennaway 
549e71b7053SJung-uk Kim     if (extensions == NULL) {
550b077aed3SPierre Pronchery         extensions = NCONF_get_string(req_conf, section, V3_EXTENSIONS);
551e71b7053SJung-uk Kim         if (extensions == NULL)
5525c87c606SMark Murray             ERR_clear_error();
5535c87c606SMark Murray     }
554e71b7053SJung-uk Kim     if (extensions != NULL) {
55574664626SKris Kennaway         /* Check syntax of file */
55674664626SKris Kennaway         X509V3_CTX ctx;
557b077aed3SPierre Pronchery 
55874664626SKris Kennaway         X509V3_set_ctx_test(&ctx);
5595c87c606SMark Murray         X509V3_set_nconf(&ctx, req_conf);
5605c87c606SMark Murray         if (!X509V3_EXT_add_nconf(req_conf, &ctx, extensions, NULL)) {
56174664626SKris Kennaway             BIO_printf(bio_err,
562b077aed3SPierre Pronchery                        "Error checking x509 extension section %s\n",
563b077aed3SPierre Pronchery                        extensions);
56474664626SKris Kennaway             goto end;
56574664626SKris Kennaway         }
56674664626SKris Kennaway     }
567e71b7053SJung-uk Kim     if (addext_conf != NULL) {
568e71b7053SJung-uk Kim         /* Check syntax of command line extensions */
569e71b7053SJung-uk Kim         X509V3_CTX ctx;
570b077aed3SPierre Pronchery 
571e71b7053SJung-uk Kim         X509V3_set_ctx_test(&ctx);
572*44096ebdSEnji Cooper         X509V3_set_nconf(&ctx, req_conf);
573e71b7053SJung-uk Kim         if (!X509V3_EXT_add_nconf(addext_conf, &ctx, "default", NULL)) {
574b077aed3SPierre Pronchery             BIO_printf(bio_err, "Error checking extensions defined using -addext\n");
575e71b7053SJung-uk Kim             goto end;
576e71b7053SJung-uk Kim         }
577e71b7053SJung-uk Kim     }
57874664626SKris Kennaway 
579e71b7053SJung-uk Kim     if (passin == NULL) {
580e71b7053SJung-uk Kim         passin = nofree_passin =
581b077aed3SPierre Pronchery             NCONF_get_string(req_conf, section, "input_password");
582e71b7053SJung-uk Kim         if (passin == NULL)
5835c87c606SMark Murray             ERR_clear_error();
5845c87c606SMark Murray     }
585f579bf8eSKris Kennaway 
586e71b7053SJung-uk Kim     if (passout == NULL) {
587e71b7053SJung-uk Kim         passout = nofree_passout =
588b077aed3SPierre Pronchery             NCONF_get_string(req_conf, section, "output_password");
589e71b7053SJung-uk Kim         if (passout == NULL)
5905c87c606SMark Murray             ERR_clear_error();
5915c87c606SMark Murray     }
592f579bf8eSKris Kennaway 
593b077aed3SPierre Pronchery     p = NCONF_get_string(req_conf, section, STRING_MASK);
594e71b7053SJung-uk Kim     if (p == NULL)
5955c87c606SMark Murray         ERR_clear_error();
596f579bf8eSKris Kennaway 
597e71b7053SJung-uk Kim     if (p != NULL && !ASN1_STRING_set_default_mask_asc(p)) {
598f579bf8eSKris Kennaway         BIO_printf(bio_err, "Invalid global string mask setting %s\n", p);
599f579bf8eSKris Kennaway         goto end;
600f579bf8eSKris Kennaway     }
601f579bf8eSKris Kennaway 
6026f9291ceSJung-uk Kim     if (chtype != MBSTRING_UTF8) {
603b077aed3SPierre Pronchery         p = NCONF_get_string(req_conf, section, UTF8_IN);
604e71b7053SJung-uk Kim         if (p == NULL)
6055c87c606SMark Murray             ERR_clear_error();
606e71b7053SJung-uk Kim         else if (strcmp(p, "yes") == 0)
6075c87c606SMark Murray             chtype = MBSTRING_UTF8;
6085c87c606SMark Murray     }
6095c87c606SMark Murray 
610e71b7053SJung-uk Kim     if (req_exts == NULL) {
611b077aed3SPierre Pronchery         req_exts = NCONF_get_string(req_conf, section, REQ_EXTENSIONS);
612e71b7053SJung-uk Kim         if (req_exts == NULL)
6135c87c606SMark Murray             ERR_clear_error();
6145c87c606SMark Murray     }
615e71b7053SJung-uk Kim     if (req_exts != NULL) {
616f579bf8eSKris Kennaway         /* Check syntax of file */
617f579bf8eSKris Kennaway         X509V3_CTX ctx;
618b077aed3SPierre Pronchery 
619f579bf8eSKris Kennaway         X509V3_set_ctx_test(&ctx);
6205c87c606SMark Murray         X509V3_set_nconf(&ctx, req_conf);
6215c87c606SMark Murray         if (!X509V3_EXT_add_nconf(req_conf, &ctx, req_exts, NULL)) {
622f579bf8eSKris Kennaway             BIO_printf(bio_err,
623b077aed3SPierre Pronchery                        "Error checking request extension section %s\n",
624f579bf8eSKris Kennaway                        req_exts);
625f579bf8eSKris Kennaway             goto end;
626f579bf8eSKris Kennaway         }
627f579bf8eSKris Kennaway     }
628f579bf8eSKris Kennaway 
6296f9291ceSJung-uk Kim     if (keyfile != NULL) {
630b077aed3SPierre Pronchery         pkey = load_key(keyfile, keyform, 0, passin, e, "private key");
631b077aed3SPierre Pronchery         if (pkey == NULL)
63274664626SKris Kennaway             goto end;
633b077aed3SPierre Pronchery         app_RAND_load_conf(req_conf, section);
634ddd58736SKris Kennaway     }
635b077aed3SPierre Pronchery     if (newreq && pkey == NULL) {
636b077aed3SPierre Pronchery         app_RAND_load_conf(req_conf, section);
63774664626SKris Kennaway 
638aa795734SPierre Pronchery         if (!NCONF_get_number(req_conf, section, BITS, &newkey_len)) {
639aa795734SPierre Pronchery             ERR_clear_error();
640b077aed3SPierre Pronchery             newkey_len = DEFAULT_KEY_LENGTH;
641aa795734SPierre Pronchery         }
64274664626SKris Kennaway 
643b077aed3SPierre Pronchery         genctx = set_keygen_ctx(keyalg, &keyalgstr, &newkey_len, gen_eng);
644e71b7053SJung-uk Kim         if (genctx == NULL)
6451f13597dSJung-uk Kim             goto end;
6461f13597dSJung-uk Kim 
647b077aed3SPierre Pronchery         if (newkey_len < MIN_KEY_LENGTH
648b077aed3SPierre Pronchery             && (EVP_PKEY_CTX_is_a(genctx, "RSA")
649b077aed3SPierre Pronchery                 || EVP_PKEY_CTX_is_a(genctx, "RSA-PSS")
650b077aed3SPierre Pronchery                 || EVP_PKEY_CTX_is_a(genctx, "DSA"))) {
651b077aed3SPierre Pronchery             BIO_printf(bio_err, "Private key length too short, needs to be at least %d bits, not %ld.\n",
652b077aed3SPierre Pronchery                        MIN_KEY_LENGTH, newkey_len);
65374664626SKris Kennaway             goto end;
65474664626SKris Kennaway         }
6551f13597dSJung-uk Kim 
656b077aed3SPierre Pronchery         if (newkey_len > OPENSSL_RSA_MAX_MODULUS_BITS
657b077aed3SPierre Pronchery             && (EVP_PKEY_CTX_is_a(genctx, "RSA")
658b077aed3SPierre Pronchery                 || EVP_PKEY_CTX_is_a(genctx, "RSA-PSS")))
659e71b7053SJung-uk Kim             BIO_printf(bio_err,
660e71b7053SJung-uk Kim                        "Warning: It is not recommended to use more than %d bit for RSA keys.\n"
661e71b7053SJung-uk Kim                        "         Your key size is %ld! Larger key size may behave not as expected.\n",
662b077aed3SPierre Pronchery                        OPENSSL_RSA_MAX_MODULUS_BITS, newkey_len);
663e71b7053SJung-uk Kim 
664e71b7053SJung-uk Kim #ifndef OPENSSL_NO_DSA
665b077aed3SPierre Pronchery         if (EVP_PKEY_CTX_is_a(genctx, "DSA")
666b077aed3SPierre Pronchery                 && newkey_len > OPENSSL_DSA_MAX_MODULUS_BITS)
667e71b7053SJung-uk Kim             BIO_printf(bio_err,
668e71b7053SJung-uk Kim                        "Warning: It is not recommended to use more than %d bit for DSA keys.\n"
669e71b7053SJung-uk Kim                        "         Your key size is %ld! Larger key size may behave not as expected.\n",
670b077aed3SPierre Pronchery                        OPENSSL_DSA_MAX_MODULUS_BITS, newkey_len);
671e71b7053SJung-uk Kim #endif
672e71b7053SJung-uk Kim 
673e71b7053SJung-uk Kim         if (pkeyopts != NULL) {
6741f13597dSJung-uk Kim             char *genopt;
6756f9291ceSJung-uk Kim             for (i = 0; i < sk_OPENSSL_STRING_num(pkeyopts); i++) {
6761f13597dSJung-uk Kim                 genopt = sk_OPENSSL_STRING_value(pkeyopts, i);
6776f9291ceSJung-uk Kim                 if (pkey_ctrl_string(genctx, genopt) <= 0) {
678b077aed3SPierre Pronchery                     BIO_printf(bio_err, "Key parameter error \"%s\"\n", genopt);
6791f13597dSJung-uk Kim                     goto end;
6801f13597dSJung-uk Kim                 }
6811f13597dSJung-uk Kim             }
6821f13597dSJung-uk Kim         }
6831f13597dSJung-uk Kim 
6841f13597dSJung-uk Kim         EVP_PKEY_CTX_set_cb(genctx, genpkey_cb);
6851f13597dSJung-uk Kim         EVP_PKEY_CTX_set_app_data(genctx, bio_err);
68674664626SKris Kennaway 
687b077aed3SPierre Pronchery         pkey = app_keygen(genctx, keyalgstr, newkey_len, verbose);
688ad991e4cSEd Maste         if (pkey == NULL)
689ad991e4cSEd Maste             goto end;
6901f13597dSJung-uk Kim 
6911f13597dSJung-uk Kim         EVP_PKEY_CTX_free(genctx);
6921f13597dSJung-uk Kim         genctx = NULL;
693b077aed3SPierre Pronchery     }
694b077aed3SPierre Pronchery     if (keyout == NULL && keyfile == NULL) {
695b077aed3SPierre Pronchery         keyout = NCONF_get_string(req_conf, section, KEYFILE);
6965c87c606SMark Murray         if (keyout == NULL)
6975c87c606SMark Murray             ERR_clear_error();
6985c87c606SMark Murray     }
69974664626SKris Kennaway 
700b077aed3SPierre Pronchery     if (pkey != NULL && (keyfile == NULL || keyout != NULL)) {
701b077aed3SPierre Pronchery         if (verbose) {
702b077aed3SPierre Pronchery             BIO_printf(bio_err, "Writing private key to ");
703e71b7053SJung-uk Kim             if (keyout == NULL)
704b077aed3SPierre Pronchery                 BIO_printf(bio_err, "stdout\n");
705e71b7053SJung-uk Kim             else
706b077aed3SPierre Pronchery                 BIO_printf(bio_err, "'%s'\n", keyout);
707b077aed3SPierre Pronchery         }
708b077aed3SPierre Pronchery         out = bio_open_owner(keyout, outformat, newreq);
709e71b7053SJung-uk Kim         if (out == NULL)
71074664626SKris Kennaway             goto end;
71174664626SKris Kennaway 
712b077aed3SPierre Pronchery         p = NCONF_get_string(req_conf, section, "encrypt_rsa_key");
7136f9291ceSJung-uk Kim         if (p == NULL) {
7145c87c606SMark Murray             ERR_clear_error();
715b077aed3SPierre Pronchery             p = NCONF_get_string(req_conf, section, "encrypt_key");
7165c87c606SMark Murray             if (p == NULL)
7175c87c606SMark Murray                 ERR_clear_error();
7185c87c606SMark Murray         }
71974664626SKris Kennaway         if ((p != NULL) && (strcmp(p, "no") == 0))
72074664626SKris Kennaway             cipher = NULL;
721b077aed3SPierre Pronchery         if (noenc)
7226f9291ceSJung-uk Kim             cipher = NULL;
72374664626SKris Kennaway 
72474664626SKris Kennaway         i = 0;
72574664626SKris Kennaway  loop:
72674664626SKris Kennaway         if (!PEM_write_bio_PrivateKey(out, pkey, cipher,
7276f9291ceSJung-uk Kim                                       NULL, 0, NULL, passout)) {
72874664626SKris Kennaway             if ((ERR_GET_REASON(ERR_peek_error()) ==
7296f9291ceSJung-uk Kim                  PEM_R_PROBLEMS_GETTING_PASSWORD) && (i < 3)) {
73074664626SKris Kennaway                 ERR_clear_error();
73174664626SKris Kennaway                 i++;
73274664626SKris Kennaway                 goto loop;
73374664626SKris Kennaway             }
73474664626SKris Kennaway             goto end;
73574664626SKris Kennaway         }
736e0c4386eSCy Schubert         BIO_free_all(out);
737e71b7053SJung-uk Kim         out = NULL;
73874664626SKris Kennaway         BIO_printf(bio_err, "-----\n");
73974664626SKris Kennaway     }
74074664626SKris Kennaway 
741b077aed3SPierre Pronchery     /*
742b077aed3SPierre Pronchery      * subj is expected to be in the format /type0=value0/type1=value1/type2=...
743b077aed3SPierre Pronchery      * where characters may be escaped by \
744b077aed3SPierre Pronchery      */
745b077aed3SPierre Pronchery     if (subj != NULL
746b077aed3SPierre Pronchery             && (fsubj = parse_name(subj, chtype, multirdn, "subject")) == NULL)
747b077aed3SPierre Pronchery         goto end;
748b077aed3SPierre Pronchery 
7496f9291ceSJung-uk Kim     if (!newreq) {
750b077aed3SPierre Pronchery         req = load_csr(infile /* if NULL, reads from stdin */,
751b077aed3SPierre Pronchery                        informat, "X509 request");
752b077aed3SPierre Pronchery         if (req == NULL)
75374664626SKris Kennaway             goto end;
754b077aed3SPierre Pronchery     }
75574664626SKris Kennaway 
756b077aed3SPierre Pronchery     if (CAkeyfile == NULL)
757b077aed3SPierre Pronchery         CAkeyfile = CAfile;
758b077aed3SPierre Pronchery     if (CAkeyfile != NULL) {
759b077aed3SPierre Pronchery         if (CAfile == NULL) {
760b077aed3SPierre Pronchery             BIO_printf(bio_err,
761b077aed3SPierre Pronchery                        "Warning: Ignoring -CAkey option since no -CA option is given\n");
762b077aed3SPierre Pronchery         } else {
763b077aed3SPierre Pronchery             if ((CAkey = load_key(CAkeyfile, FORMAT_UNDEF,
764b077aed3SPierre Pronchery                                   0, passin, e,
765b077aed3SPierre Pronchery                                   CAkeyfile != CAfile
766b077aed3SPierre Pronchery                                   ? "issuer private key from -CAkey arg"
767b077aed3SPierre Pronchery                                   : "issuer private key from -CA arg")) == NULL)
76874664626SKris Kennaway                 goto end;
76974664626SKris Kennaway         }
77074664626SKris Kennaway     }
771b077aed3SPierre Pronchery     if (CAfile != NULL) {
772b077aed3SPierre Pronchery         if ((CAcert = load_cert_pass(CAfile, FORMAT_UNDEF, 1, passin,
773b077aed3SPierre Pronchery                                      "issuer cert from -CA arg")) == NULL)
774b077aed3SPierre Pronchery             goto end;
775b077aed3SPierre Pronchery         if (!X509_check_private_key(CAcert, CAkey)) {
776b077aed3SPierre Pronchery             BIO_printf(bio_err,
777b077aed3SPierre Pronchery                        "Issuer CA certificate and key do not match\n");
778b077aed3SPierre Pronchery             goto end;
779b077aed3SPierre Pronchery         }
780b077aed3SPierre Pronchery     }
781b077aed3SPierre Pronchery     if (newreq || gen_x509) {
782b077aed3SPierre Pronchery         if (CAcert == NULL && pkey == NULL) {
783b077aed3SPierre Pronchery             BIO_printf(bio_err, "Must provide a signature key using -key or"
784b077aed3SPierre Pronchery                 " provide -CA / -CAkey\n");
78574664626SKris Kennaway             goto end;
78674664626SKris Kennaway         }
7871f13597dSJung-uk Kim 
7886f9291ceSJung-uk Kim         if (req == NULL) {
789b077aed3SPierre Pronchery             req = X509_REQ_new_ex(app_get0_libctx(), app_get0_propq());
7906f9291ceSJung-uk Kim             if (req == NULL) {
79174664626SKris Kennaway                 goto end;
79274664626SKris Kennaway             }
79374664626SKris Kennaway 
794b077aed3SPierre Pronchery             if (!make_REQ(req, pkey, fsubj, multirdn, !gen_x509, chtype)){
795b077aed3SPierre Pronchery                 BIO_printf(bio_err, "Error making certificate request\n");
79674664626SKris Kennaway                 goto end;
79774664626SKris Kennaway             }
798b077aed3SPierre Pronchery             /* Note that -x509 can take over -key and -subj option values. */
79974664626SKris Kennaway         }
800b077aed3SPierre Pronchery         if (gen_x509) {
801b077aed3SPierre Pronchery             EVP_PKEY *pub_key = X509_REQ_get0_pubkey(req);
802b077aed3SPierre Pronchery             EVP_PKEY *issuer_key = CAcert != NULL ? CAkey : pkey;
80374664626SKris Kennaway             X509V3_CTX ext_ctx;
804b077aed3SPierre Pronchery             X509_NAME *issuer = CAcert != NULL ? X509_get_subject_name(CAcert) :
805b077aed3SPierre Pronchery                 X509_REQ_get_subject_name(req);
806b077aed3SPierre Pronchery             X509_NAME *n_subj = fsubj != NULL ? fsubj :
807b077aed3SPierre Pronchery                 X509_REQ_get_subject_name(req);
808b077aed3SPierre Pronchery 
809b077aed3SPierre Pronchery             if ((new_x509 = X509_new_ex(app_get0_libctx(),
810b077aed3SPierre Pronchery                                         app_get0_propq())) == NULL)
8116f9291ceSJung-uk Kim                 goto end;
81274664626SKris Kennaway 
813e71b7053SJung-uk Kim             if (serial != NULL) {
814b077aed3SPierre Pronchery                 if (!X509_set_serialNumber(new_x509, serial))
8156f9291ceSJung-uk Kim                     goto end;
8166f9291ceSJung-uk Kim             } else {
817b077aed3SPierre Pronchery                 if (!rand_serial(NULL, X509_get_serialNumber(new_x509)))
8186be8ae07SJacques Vidrine                     goto end;
8195c87c606SMark Murray             }
82074664626SKris Kennaway 
821b077aed3SPierre Pronchery             if (!X509_set_issuer_name(new_x509, issuer))
8226f9291ceSJung-uk Kim                 goto end;
823b077aed3SPierre Pronchery             if (days == UNSET_DAYS) {
824b077aed3SPierre Pronchery                 days = DEFAULT_DAYS;
825e71b7053SJung-uk Kim             }
826b077aed3SPierre Pronchery             if (!set_cert_times(new_x509, NULL, NULL, days))
8276f9291ceSJung-uk Kim                 goto end;
828b077aed3SPierre Pronchery             if (!X509_set_subject_name(new_x509, n_subj))
8296f9291ceSJung-uk Kim                 goto end;
830b077aed3SPierre Pronchery             if (!pub_key || !X509_set_pubkey(new_x509, pub_key))
8316f9291ceSJung-uk Kim                 goto end;
832b077aed3SPierre Pronchery             if (ext_copy == EXT_COPY_UNSET) {
833b077aed3SPierre Pronchery                 if (infile != NULL)
834b077aed3SPierre Pronchery                     BIO_printf(bio_err, "Warning: No -copy_extensions given; ignoring any extensions in the request\n");
835b077aed3SPierre Pronchery             } else if (!copy_extensions(new_x509, req, ext_copy)) {
836b077aed3SPierre Pronchery                 BIO_printf(bio_err, "Error copying extensions from request\n");
837b077aed3SPierre Pronchery                 goto end;
838b077aed3SPierre Pronchery             }
83974664626SKris Kennaway 
84074664626SKris Kennaway             /* Set up V3 context struct */
841b077aed3SPierre Pronchery             X509V3_set_ctx(&ext_ctx, CAcert != NULL ? CAcert : new_x509,
842b077aed3SPierre Pronchery                            new_x509, NULL, NULL, X509V3_CTX_REPLACE);
843b077aed3SPierre Pronchery             /* prepare fallback for AKID, but only if issuer cert == new_x509 */
844b077aed3SPierre Pronchery             if (CAcert == NULL) {
845b077aed3SPierre Pronchery                 if (!X509V3_set_issuer_pkey(&ext_ctx, issuer_key))
846b077aed3SPierre Pronchery                     goto end;
847b077aed3SPierre Pronchery                 ERR_set_mark();
848b077aed3SPierre Pronchery                 if (!X509_check_private_key(new_x509, issuer_key))
849b077aed3SPierre Pronchery                     BIO_printf(bio_err,
850b077aed3SPierre Pronchery                                "Warning: Signature key and public key of cert do not match\n");
851b077aed3SPierre Pronchery                 ERR_pop_to_mark();
852b077aed3SPierre Pronchery             }
8535c87c606SMark Murray             X509V3_set_nconf(&ext_ctx, req_conf);
85474664626SKris Kennaway 
85574664626SKris Kennaway             /* Add extensions */
856b077aed3SPierre Pronchery             if (extensions != NULL
857b077aed3SPierre Pronchery                     && !X509V3_EXT_add_nconf(req_conf, &ext_ctx, extensions,
858b077aed3SPierre Pronchery                                              new_x509)) {
859b077aed3SPierre Pronchery                 BIO_printf(bio_err, "Error adding x509 extensions from section %s\n",
86074664626SKris Kennaway                            extensions);
86174664626SKris Kennaway                 goto end;
86274664626SKris Kennaway             }
863e71b7053SJung-uk Kim             if (addext_conf != NULL
864e71b7053SJung-uk Kim                 && !X509V3_EXT_add_nconf(addext_conf, &ext_ctx, "default",
865b077aed3SPierre Pronchery                                          new_x509)) {
866b077aed3SPierre Pronchery                 BIO_printf(bio_err, "Error adding extensions defined via -addext\n");
867e71b7053SJung-uk Kim                 goto end;
868e71b7053SJung-uk Kim             }
86974664626SKris Kennaway 
870e71b7053SJung-uk Kim             /* If a pre-cert was requested, we need to add a poison extension */
871e71b7053SJung-uk Kim             if (precert) {
872b077aed3SPierre Pronchery                 if (X509_add1_ext_i2d(new_x509, NID_ct_precert_poison,
873b077aed3SPierre Pronchery                                       NULL, 1, 0) != 1) {
874e71b7053SJung-uk Kim                     BIO_printf(bio_err, "Error adding poison extension\n");
875e71b7053SJung-uk Kim                     goto end;
876e71b7053SJung-uk Kim                 }
877e71b7053SJung-uk Kim             }
878e71b7053SJung-uk Kim 
879b077aed3SPierre Pronchery             i = do_X509_sign(new_x509, issuer_key, digest, sigopts, &ext_ctx);
880b077aed3SPierre Pronchery             if (!i)
88174664626SKris Kennaway                 goto end;
8826f9291ceSJung-uk Kim         } else {
883f579bf8eSKris Kennaway             X509V3_CTX ext_ctx;
884f579bf8eSKris Kennaway 
885f579bf8eSKris Kennaway             /* Set up V3 context struct */
886f579bf8eSKris Kennaway             X509V3_set_ctx(&ext_ctx, NULL, NULL, req, NULL, 0);
8875c87c606SMark Murray             X509V3_set_nconf(&ext_ctx, req_conf);
888f579bf8eSKris Kennaway 
889f579bf8eSKris Kennaway             /* Add extensions */
890e71b7053SJung-uk Kim             if (req_exts != NULL
891e71b7053SJung-uk Kim                 && !X509V3_EXT_REQ_add_nconf(req_conf, &ext_ctx,
892e71b7053SJung-uk Kim                                              req_exts, req)) {
893b077aed3SPierre Pronchery                 BIO_printf(bio_err, "Error adding request extensions from section %s\n",
894f579bf8eSKris Kennaway                            req_exts);
895f579bf8eSKris Kennaway                 goto end;
896f579bf8eSKris Kennaway             }
897e71b7053SJung-uk Kim             if (addext_conf != NULL
898e71b7053SJung-uk Kim                 && !X509V3_EXT_REQ_add_nconf(addext_conf, &ext_ctx, "default",
899e71b7053SJung-uk Kim                                              req)) {
900b077aed3SPierre Pronchery                 BIO_printf(bio_err, "Error adding extensions defined via -addext\n");
901e71b7053SJung-uk Kim                 goto end;
902e71b7053SJung-uk Kim             }
903e71b7053SJung-uk Kim             i = do_X509_REQ_sign(req, pkey, digest, sigopts);
904b077aed3SPierre Pronchery             if (!i)
90574664626SKris Kennaway                 goto end;
90674664626SKris Kennaway         }
90774664626SKris Kennaway     }
90874664626SKris Kennaway 
909b077aed3SPierre Pronchery     if (subj != NULL && !newreq && !gen_x509) {
9106f9291ceSJung-uk Kim         if (verbose) {
911b077aed3SPierre Pronchery             BIO_printf(out, "Modifying subject of certificate request\n");
912b077aed3SPierre Pronchery             print_name(out, "Old subject=", X509_REQ_get_subject_name(req));
9135c87c606SMark Murray         }
9145c87c606SMark Murray 
915b077aed3SPierre Pronchery         if (!X509_REQ_set_subject_name(req, fsubj)) {
916b077aed3SPierre Pronchery             BIO_printf(bio_err, "Error modifying subject of certificate request\n");
9175c87c606SMark Murray             goto end;
9185c87c606SMark Murray         }
9195c87c606SMark Murray 
9206f9291ceSJung-uk Kim         if (verbose) {
921b077aed3SPierre Pronchery             print_name(out, "New subject=", X509_REQ_get_subject_name(req));
9225c87c606SMark Murray         }
9235c87c606SMark Murray     }
9245c87c606SMark Murray 
925b077aed3SPierre Pronchery     if (verify) {
926e71b7053SJung-uk Kim         EVP_PKEY *tpubkey = pkey;
92774664626SKris Kennaway 
928e71b7053SJung-uk Kim         if (tpubkey == NULL) {
929e71b7053SJung-uk Kim             tpubkey = X509_REQ_get0_pubkey(req);
930e71b7053SJung-uk Kim             if (tpubkey == NULL)
9316f9291ceSJung-uk Kim                 goto end;
93274664626SKris Kennaway         }
93374664626SKris Kennaway 
934b077aed3SPierre Pronchery         i = do_X509_REQ_verify(req, tpubkey, vfyopts);
93574664626SKris Kennaway 
936b077aed3SPierre Pronchery         if (i < 0)
93774664626SKris Kennaway             goto end;
938b077aed3SPierre Pronchery         if (i == 0)
939b077aed3SPierre Pronchery             BIO_printf(bio_err, "Certificate request self-signature verify failure\n");
940b077aed3SPierre Pronchery         else /* i > 0 */
941b077aed3SPierre Pronchery             BIO_printf(bio_err, "Certificate request self-signature verify OK\n");
942e71b7053SJung-uk Kim     }
94374664626SKris Kennaway 
9446f9291ceSJung-uk Kim     if (noout && !text && !modulus && !subject && !pubkey) {
945e71b7053SJung-uk Kim         ret = 0;
94674664626SKris Kennaway         goto end;
94774664626SKris Kennaway     }
94874664626SKris Kennaway 
949e71b7053SJung-uk Kim     out = bio_open_default(outfile,
950e71b7053SJung-uk Kim                            keyout != NULL && outfile != NULL &&
951e71b7053SJung-uk Kim                            strcmp(keyout, outfile) == 0 ? 'a' : 'w',
952e71b7053SJung-uk Kim                            outformat);
953e71b7053SJung-uk Kim     if (out == NULL)
95474664626SKris Kennaway         goto end;
95574664626SKris Kennaway 
9566f9291ceSJung-uk Kim     if (pubkey) {
957e71b7053SJung-uk Kim         EVP_PKEY *tpubkey = X509_REQ_get0_pubkey(req);
958e71b7053SJung-uk Kim 
9596f9291ceSJung-uk Kim         if (tpubkey == NULL) {
9605c87c606SMark Murray             BIO_printf(bio_err, "Error getting public key\n");
9615c87c606SMark Murray             goto end;
9625c87c606SMark Murray         }
9635c87c606SMark Murray         PEM_write_bio_PUBKEY(out, tpubkey);
9645c87c606SMark Murray     }
9655c87c606SMark Murray 
9666f9291ceSJung-uk Kim     if (text) {
967b077aed3SPierre Pronchery         if (gen_x509)
968b077aed3SPierre Pronchery             ret = X509_print_ex(out, new_x509, get_nameopt(), reqflag);
96974664626SKris Kennaway         else
970da327cd2SJung-uk Kim             ret = X509_REQ_print_ex(out, req, get_nameopt(), reqflag);
971da327cd2SJung-uk Kim 
972da327cd2SJung-uk Kim         if (ret == 0) {
973b077aed3SPierre Pronchery             if (gen_x509)
974da327cd2SJung-uk Kim                 BIO_printf(bio_err, "Error printing certificate\n");
975da327cd2SJung-uk Kim             else
976da327cd2SJung-uk Kim                 BIO_printf(bio_err, "Error printing certificate request\n");
977da327cd2SJung-uk Kim             goto end;
978da327cd2SJung-uk Kim         }
9795c87c606SMark Murray     }
9805c87c606SMark Murray 
9816f9291ceSJung-uk Kim     if (subject) {
982b077aed3SPierre Pronchery         print_name(out, "subject=", gen_x509
983b077aed3SPierre Pronchery                    ? X509_get_subject_name(new_x509)
984b077aed3SPierre Pronchery                    : X509_REQ_get_subject_name(req));
98574664626SKris Kennaway     }
98674664626SKris Kennaway 
9876f9291ceSJung-uk Kim     if (modulus) {
9885c87c606SMark Murray         EVP_PKEY *tpubkey;
98974664626SKris Kennaway 
990b077aed3SPierre Pronchery         if (gen_x509)
991b077aed3SPierre Pronchery             tpubkey = X509_get0_pubkey(new_x509);
99274664626SKris Kennaway         else
993e71b7053SJung-uk Kim             tpubkey = X509_REQ_get0_pubkey(req);
9946f9291ceSJung-uk Kim         if (tpubkey == NULL) {
9956f1af0d7SPierre Pronchery             BIO_puts(bio_err, "Modulus is unavailable\n");
99674664626SKris Kennaway             goto end;
99774664626SKris Kennaway         }
9986f1af0d7SPierre Pronchery         BIO_puts(out, "Modulus=");
999b077aed3SPierre Pronchery         if (EVP_PKEY_is_a(tpubkey, "RSA") || EVP_PKEY_is_a(tpubkey, "RSA-PSS")) {
1000b077aed3SPierre Pronchery             BIGNUM *n = NULL;
1001b077aed3SPierre Pronchery 
1002b077aed3SPierre Pronchery             if (!EVP_PKEY_get_bn_param(tpubkey, "n", &n))
1003b077aed3SPierre Pronchery                 goto end;
1004e71b7053SJung-uk Kim             BN_print(out, n);
1005b077aed3SPierre Pronchery             BN_free(n);
1006b077aed3SPierre Pronchery         } else {
10076f1af0d7SPierre Pronchery             BIO_puts(out, "Wrong Algorithm type");
1008b077aed3SPierre Pronchery         }
10096f1af0d7SPierre Pronchery         BIO_puts(out, "\n");
101074664626SKris Kennaway     }
101174664626SKris Kennaway 
1012b077aed3SPierre Pronchery     if (!noout && !gen_x509) {
101374664626SKris Kennaway         if (outformat == FORMAT_ASN1)
101474664626SKris Kennaway             i = i2d_X509_REQ_bio(out, req);
1015e71b7053SJung-uk Kim         else if (newhdr)
10166f9291ceSJung-uk Kim             i = PEM_write_bio_X509_REQ_NEW(out, req);
10176f9291ceSJung-uk Kim         else
10186f9291ceSJung-uk Kim             i = PEM_write_bio_X509_REQ(out, req);
10196f9291ceSJung-uk Kim         if (!i) {
1020b077aed3SPierre Pronchery             BIO_printf(bio_err, "Unable to write certificate request\n");
102174664626SKris Kennaway             goto end;
102274664626SKris Kennaway         }
102374664626SKris Kennaway     }
1024b077aed3SPierre Pronchery     if (!noout && gen_x509 && new_x509 != NULL) {
102574664626SKris Kennaway         if (outformat == FORMAT_ASN1)
1026b077aed3SPierre Pronchery             i = i2d_X509_bio(out, new_x509);
1027e71b7053SJung-uk Kim         else
1028b077aed3SPierre Pronchery             i = PEM_write_bio_X509(out, new_x509);
10296f9291ceSJung-uk Kim         if (!i) {
1030b077aed3SPierre Pronchery             BIO_printf(bio_err, "Unable to write X509 certificate\n");
103174664626SKris Kennaway             goto end;
103274664626SKris Kennaway         }
103374664626SKris Kennaway     }
1034e71b7053SJung-uk Kim     ret = 0;
103574664626SKris Kennaway  end:
1036e71b7053SJung-uk Kim     if (ret) {
103774664626SKris Kennaway         ERR_print_errors(bio_err);
103874664626SKris Kennaway     }
10396f9291ceSJung-uk Kim     NCONF_free(req_conf);
1040e71b7053SJung-uk Kim     NCONF_free(addext_conf);
1041e71b7053SJung-uk Kim     BIO_free(addext_bio);
1042ddd58736SKris Kennaway     BIO_free_all(out);
104374664626SKris Kennaway     EVP_PKEY_free(pkey);
10441f13597dSJung-uk Kim     EVP_PKEY_CTX_free(genctx);
10451f13597dSJung-uk Kim     sk_OPENSSL_STRING_free(pkeyopts);
10461f13597dSJung-uk Kim     sk_OPENSSL_STRING_free(sigopts);
1047b077aed3SPierre Pronchery     sk_OPENSSL_STRING_free(vfyopts);
1048e71b7053SJung-uk Kim     lh_OPENSSL_STRING_doall(addexts, exts_cleanup);
1049e71b7053SJung-uk Kim     lh_OPENSSL_STRING_free(addexts);
10501f13597dSJung-uk Kim #ifndef OPENSSL_NO_ENGINE
1051b077aed3SPierre Pronchery     release_engine(gen_eng);
10521f13597dSJung-uk Kim #endif
10531f13597dSJung-uk Kim     OPENSSL_free(keyalgstr);
105474664626SKris Kennaway     X509_REQ_free(req);
1055b077aed3SPierre Pronchery     X509_NAME_free(fsubj);
1056b077aed3SPierre Pronchery     X509_free(new_x509);
1057b077aed3SPierre Pronchery     X509_free(CAcert);
1058b077aed3SPierre Pronchery     EVP_PKEY_free(CAkey);
10595c87c606SMark Murray     ASN1_INTEGER_free(serial);
10606cf8931aSJung-uk Kim     release_engine(e);
1061e71b7053SJung-uk Kim     if (passin != nofree_passin)
10626f9291ceSJung-uk Kim         OPENSSL_free(passin);
1063e71b7053SJung-uk Kim     if (passout != nofree_passout)
10646f9291ceSJung-uk Kim         OPENSSL_free(passout);
1065e71b7053SJung-uk Kim     return ret;
106674664626SKris Kennaway }
106774664626SKris Kennaway 
1068b077aed3SPierre Pronchery static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, X509_NAME *fsubj,
1069b077aed3SPierre Pronchery                     int multirdn, int attribs, unsigned long chtype)
107074664626SKris Kennaway {
107174664626SKris Kennaway     int ret = 0, i;
1072f579bf8eSKris Kennaway     char no_prompt = 0;
1073b077aed3SPierre Pronchery     STACK_OF(CONF_VALUE) *dn_sk = NULL, *attr_sk = NULL;
1074f579bf8eSKris Kennaway     char *tmp, *dn_sect, *attr_sect;
107574664626SKris Kennaway 
1076b077aed3SPierre Pronchery     tmp = NCONF_get_string(req_conf, section, PROMPT);
10775c87c606SMark Murray     if (tmp == NULL)
10785c87c606SMark Murray         ERR_clear_error();
1079e71b7053SJung-uk Kim     if ((tmp != NULL) && strcmp(tmp, "no") == 0)
10806f9291ceSJung-uk Kim         no_prompt = 1;
1081f579bf8eSKris Kennaway 
1082b077aed3SPierre Pronchery     dn_sect = NCONF_get_string(req_conf, section, DISTINGUISHED_NAME);
10836f9291ceSJung-uk Kim     if (dn_sect == NULL) {
1084b077aed3SPierre Pronchery         ERR_clear_error();
1085b077aed3SPierre Pronchery     } else {
10865c87c606SMark Murray         dn_sk = NCONF_get_section(req_conf, dn_sect);
10876f9291ceSJung-uk Kim         if (dn_sk == NULL) {
1088b077aed3SPierre Pronchery             BIO_printf(bio_err, "Unable to get '%s' section\n", dn_sect);
108974664626SKris Kennaway             goto err;
109074664626SKris Kennaway         }
1091b077aed3SPierre Pronchery     }
109274664626SKris Kennaway 
1093b077aed3SPierre Pronchery     attr_sect = NCONF_get_string(req_conf, section, ATTRIBUTES);
10946f9291ceSJung-uk Kim     if (attr_sect == NULL) {
10955c87c606SMark Murray         ERR_clear_error();
10966f9291ceSJung-uk Kim     } else {
10975c87c606SMark Murray         attr_sk = NCONF_get_section(req_conf, attr_sect);
10986f9291ceSJung-uk Kim         if (attr_sk == NULL) {
1099b077aed3SPierre Pronchery             BIO_printf(bio_err, "Unable to get '%s' section\n", attr_sect);
110074664626SKris Kennaway             goto err;
110174664626SKris Kennaway         }
110274664626SKris Kennaway     }
110374664626SKris Kennaway 
1104b077aed3SPierre Pronchery     /* so far there is only version 1 */
1105b077aed3SPierre Pronchery     if (!X509_REQ_set_version(req, X509_REQ_VERSION_1))
1106b077aed3SPierre Pronchery         goto err;
110774664626SKris Kennaway 
1108b077aed3SPierre Pronchery     if (fsubj != NULL)
1109b077aed3SPierre Pronchery         i = X509_REQ_set_subject_name(req, fsubj);
1110e71b7053SJung-uk Kim     else if (no_prompt)
1111e71b7053SJung-uk Kim         i = auto_info(req, dn_sk, attr_sk, attribs, chtype);
11125c87c606SMark Murray     else
11136f9291ceSJung-uk Kim         i = prompt_info(req, dn_sk, dn_sect, attr_sk, attr_sect, attribs,
11146f9291ceSJung-uk Kim                         chtype);
11156f9291ceSJung-uk Kim     if (!i)
11166f9291ceSJung-uk Kim         goto err;
1117f579bf8eSKris Kennaway 
11186f9291ceSJung-uk Kim     if (!X509_REQ_set_pubkey(req, pkey))
11196f9291ceSJung-uk Kim         goto err;
1120f579bf8eSKris Kennaway 
1121f579bf8eSKris Kennaway     ret = 1;
1122f579bf8eSKris Kennaway  err:
1123e71b7053SJung-uk Kim     return ret;
1124f579bf8eSKris Kennaway }
1125f579bf8eSKris Kennaway 
1126f579bf8eSKris Kennaway static int prompt_info(X509_REQ *req,
1127e71b7053SJung-uk Kim                        STACK_OF(CONF_VALUE) *dn_sk, const char *dn_sect,
1128e71b7053SJung-uk Kim                        STACK_OF(CONF_VALUE) *attr_sk, const char *attr_sect,
11296f9291ceSJung-uk Kim                        int attribs, unsigned long chtype)
1130f579bf8eSKris Kennaway {
1131f579bf8eSKris Kennaway     int i;
1132f579bf8eSKris Kennaway     char *p, *q;
1133f579bf8eSKris Kennaway     char buf[100];
11343b4e3dcbSSimon L. B. Nielsen     int nid, mval;
11355c87c606SMark Murray     long n_min, n_max;
11363b4e3dcbSSimon L. B. Nielsen     char *type, *value;
11373b4e3dcbSSimon L. B. Nielsen     const char *def;
1138f579bf8eSKris Kennaway     CONF_VALUE *v;
1139b077aed3SPierre Pronchery     X509_NAME *subj = X509_REQ_get_subject_name(req);
11405c87c606SMark Murray 
11416f9291ceSJung-uk Kim     if (!batch) {
11426f9291ceSJung-uk Kim         BIO_printf(bio_err,
11436f9291ceSJung-uk Kim                    "You are about to be asked to enter information that will be incorporated\n");
114474664626SKris Kennaway         BIO_printf(bio_err, "into your certificate request.\n");
11456f9291ceSJung-uk Kim         BIO_printf(bio_err,
11466f9291ceSJung-uk Kim                    "What you are about to enter is what is called a Distinguished Name or a DN.\n");
11476f9291ceSJung-uk Kim         BIO_printf(bio_err,
11486f9291ceSJung-uk Kim                    "There are quite a few fields but you can leave some blank\n");
11496f9291ceSJung-uk Kim         BIO_printf(bio_err,
11506f9291ceSJung-uk Kim                    "For some fields there will be a default value,\n");
11516f9291ceSJung-uk Kim         BIO_printf(bio_err,
11526f9291ceSJung-uk Kim                    "If you enter '.', the field will be left blank.\n");
115374664626SKris Kennaway         BIO_printf(bio_err, "-----\n");
11545c87c606SMark Murray     }
115574664626SKris Kennaway 
11566f9291ceSJung-uk Kim     if (sk_CONF_VALUE_num(dn_sk)) {
115774664626SKris Kennaway         i = -1;
1158e71b7053SJung-uk Kim  start:
1159e71b7053SJung-uk Kim         for (;;) {
116074664626SKris Kennaway             i++;
11616f9291ceSJung-uk Kim             if (sk_CONF_VALUE_num(dn_sk) <= i)
11626f9291ceSJung-uk Kim                 break;
116374664626SKris Kennaway 
1164f579bf8eSKris Kennaway             v = sk_CONF_VALUE_value(dn_sk, i);
116574664626SKris Kennaway             p = q = NULL;
116674664626SKris Kennaway             type = v->name;
116774664626SKris Kennaway             if (!check_end(type, "_min") || !check_end(type, "_max") ||
11686f9291ceSJung-uk Kim                 !check_end(type, "_default") || !check_end(type, "_value"))
11696f9291ceSJung-uk Kim                 continue;
11706f9291ceSJung-uk Kim             /*
11716f9291ceSJung-uk Kim              * Skip past any leading X. X: X, etc to allow for multiple
11726f9291ceSJung-uk Kim              * instances
117374664626SKris Kennaway              */
117474664626SKris Kennaway             for (p = v->name; *p; p++)
11756f9291ceSJung-uk Kim                 if ((*p == ':') || (*p == ',') || (*p == '.')) {
117674664626SKris Kennaway                     p++;
11776f9291ceSJung-uk Kim                     if (*p)
11786f9291ceSJung-uk Kim                         type = p;
117974664626SKris Kennaway                     break;
118074664626SKris Kennaway                 }
11816f9291ceSJung-uk Kim             if (*type == '+') {
11823b4e3dcbSSimon L. B. Nielsen                 mval = -1;
11833b4e3dcbSSimon L. B. Nielsen                 type++;
1184e71b7053SJung-uk Kim             } else {
11853b4e3dcbSSimon L. B. Nielsen                 mval = 0;
1186e71b7053SJung-uk Kim             }
118774664626SKris Kennaway             /* If OBJ not recognised ignore it */
11886f9291ceSJung-uk Kim             if ((nid = OBJ_txt2nid(type)) == NID_undef)
11896f9291ceSJung-uk Kim                 goto start;
1190e71b7053SJung-uk Kim             if (!join(buf, sizeof(buf), v->name, "_default", "Name"))
11915c87c606SMark Murray                 return 0;
11926f9291ceSJung-uk Kim             if ((def = NCONF_get_string(req_conf, dn_sect, buf)) == NULL) {
11935c87c606SMark Murray                 ERR_clear_error();
11945c87c606SMark Murray                 def = "";
11955c87c606SMark Murray             }
1196ced566fdSJacques Vidrine 
1197e71b7053SJung-uk Kim             if (!join(buf, sizeof(buf), v->name, "_value", "Name"))
1198e71b7053SJung-uk Kim                 return 0;
11996f9291ceSJung-uk Kim             if ((value = NCONF_get_string(req_conf, dn_sect, buf)) == NULL) {
12005c87c606SMark Murray                 ERR_clear_error();
120174664626SKris Kennaway                 value = NULL;
12025c87c606SMark Murray             }
120374664626SKris Kennaway 
1204e71b7053SJung-uk Kim             if (!join(buf, sizeof(buf), v->name, "_min", "Name"))
1205e71b7053SJung-uk Kim                 return 0;
12066f9291ceSJung-uk Kim             if (!NCONF_get_number(req_conf, dn_sect, buf, &n_min)) {
1207fceca8a3SJacques Vidrine                 ERR_clear_error();
12085c87c606SMark Murray                 n_min = -1;
1209fceca8a3SJacques Vidrine             }
121074664626SKris Kennaway 
1211e71b7053SJung-uk Kim             if (!join(buf, sizeof(buf), v->name, "_max", "Name"))
1212e71b7053SJung-uk Kim                 return 0;
12136f9291ceSJung-uk Kim             if (!NCONF_get_number(req_conf, dn_sect, buf, &n_max)) {
1214fceca8a3SJacques Vidrine                 ERR_clear_error();
12155c87c606SMark Murray                 n_max = -1;
1216fceca8a3SJacques Vidrine             }
121774664626SKris Kennaway 
1218f579bf8eSKris Kennaway             if (!add_DN_object(subj, v->value, def, value, nid,
12193b4e3dcbSSimon L. B. Nielsen                                n_min, n_max, chtype, mval))
1220f579bf8eSKris Kennaway                 return 0;
122174664626SKris Kennaway         }
12226f9291ceSJung-uk Kim         if (X509_NAME_entry_count(subj) == 0) {
1223b077aed3SPierre Pronchery             BIO_printf(bio_err, "Error: No objects specified in config file\n");
1224f579bf8eSKris Kennaway             return 0;
122574664626SKris Kennaway         }
122674664626SKris Kennaway 
12276f9291ceSJung-uk Kim         if (attribs) {
12286f9291ceSJung-uk Kim             if ((attr_sk != NULL) && (sk_CONF_VALUE_num(attr_sk) > 0)
12296f9291ceSJung-uk Kim                 && (!batch)) {
12306f9291ceSJung-uk Kim                 BIO_printf(bio_err,
12316f9291ceSJung-uk Kim                            "\nPlease enter the following 'extra' attributes\n");
12326f9291ceSJung-uk Kim                 BIO_printf(bio_err,
12336f9291ceSJung-uk Kim                            "to be sent with your certificate request\n");
123474664626SKris Kennaway             }
123574664626SKris Kennaway 
123674664626SKris Kennaway             i = -1;
1237e71b7053SJung-uk Kim  start2:
1238e71b7053SJung-uk Kim             for (;;) {
123974664626SKris Kennaway                 i++;
12406f9291ceSJung-uk Kim                 if ((attr_sk == NULL) || (sk_CONF_VALUE_num(attr_sk) <= i))
124174664626SKris Kennaway                     break;
124274664626SKris Kennaway 
1243f579bf8eSKris Kennaway                 v = sk_CONF_VALUE_value(attr_sk, i);
124474664626SKris Kennaway                 type = v->name;
124574664626SKris Kennaway                 if ((nid = OBJ_txt2nid(type)) == NID_undef)
124674664626SKris Kennaway                     goto start2;
124774664626SKris Kennaway 
1248e71b7053SJung-uk Kim                 if (!join(buf, sizeof(buf), type, "_default", "Name"))
12495c87c606SMark Murray                     return 0;
12505c87c606SMark Murray                 if ((def = NCONF_get_string(req_conf, attr_sect, buf))
12516f9291ceSJung-uk Kim                     == NULL) {
12525c87c606SMark Murray                     ERR_clear_error();
125374664626SKris Kennaway                     def = "";
12545c87c606SMark Murray                 }
12555c87c606SMark Murray 
1256e71b7053SJung-uk Kim                 if (!join(buf, sizeof(buf), type, "_value", "Name"))
1257e71b7053SJung-uk Kim                     return 0;
12585c87c606SMark Murray                 if ((value = NCONF_get_string(req_conf, attr_sect, buf))
12596f9291ceSJung-uk Kim                     == NULL) {
12605c87c606SMark Murray                     ERR_clear_error();
126174664626SKris Kennaway                     value = NULL;
12625c87c606SMark Murray                 }
126374664626SKris Kennaway 
1264e71b7053SJung-uk Kim                 if (!join(buf, sizeof(buf), type, "_min", "Name"))
1265e71b7053SJung-uk Kim                     return 0;
12666f9291ceSJung-uk Kim                 if (!NCONF_get_number(req_conf, attr_sect, buf, &n_min)) {
1267ab8565e2SSimon L. B. Nielsen                     ERR_clear_error();
12685c87c606SMark Murray                     n_min = -1;
1269ab8565e2SSimon L. B. Nielsen                 }
127074664626SKris Kennaway 
1271e71b7053SJung-uk Kim                 if (!join(buf, sizeof(buf), type, "_max", "Name"))
1272e71b7053SJung-uk Kim                     return 0;
12736f9291ceSJung-uk Kim                 if (!NCONF_get_number(req_conf, attr_sect, buf, &n_max)) {
1274ab8565e2SSimon L. B. Nielsen                     ERR_clear_error();
12755c87c606SMark Murray                     n_max = -1;
1276ab8565e2SSimon L. B. Nielsen                 }
127774664626SKris Kennaway 
1278f579bf8eSKris Kennaway                 if (!add_attribute_object(req,
12796f9291ceSJung-uk Kim                                           v->value, def, value, nid, n_min,
12806f9291ceSJung-uk Kim                                           n_max, chtype))
1281f579bf8eSKris Kennaway                     return 0;
128274664626SKris Kennaway             }
128374664626SKris Kennaway         }
12846f9291ceSJung-uk Kim     } else {
128574664626SKris Kennaway         BIO_printf(bio_err, "No template, please set one up.\n");
1286f579bf8eSKris Kennaway         return 0;
128774664626SKris Kennaway     }
128874664626SKris Kennaway 
1289f579bf8eSKris Kennaway     return 1;
129074664626SKris Kennaway 
129174664626SKris Kennaway }
129274664626SKris Kennaway 
1293f579bf8eSKris Kennaway static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *dn_sk,
12946f9291ceSJung-uk Kim                      STACK_OF(CONF_VALUE) *attr_sk, int attribs,
12956f9291ceSJung-uk Kim                      unsigned long chtype)
1296f579bf8eSKris Kennaway {
1297e71b7053SJung-uk Kim     int i, spec_char, plus_char;
1298f579bf8eSKris Kennaway     char *p, *q;
1299f579bf8eSKris Kennaway     char *type;
1300f579bf8eSKris Kennaway     CONF_VALUE *v;
1301f579bf8eSKris Kennaway     X509_NAME *subj;
1302f579bf8eSKris Kennaway 
1303f579bf8eSKris Kennaway     subj = X509_REQ_get_subject_name(req);
1304f579bf8eSKris Kennaway 
13056f9291ceSJung-uk Kim     for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) {
13063b4e3dcbSSimon L. B. Nielsen         int mval;
1307f579bf8eSKris Kennaway         v = sk_CONF_VALUE_value(dn_sk, i);
1308f579bf8eSKris Kennaway         p = q = NULL;
1309f579bf8eSKris Kennaway         type = v->name;
13106f9291ceSJung-uk Kim         /*
13116f9291ceSJung-uk Kim          * Skip past any leading X. X: X, etc to allow for multiple instances
1312f579bf8eSKris Kennaway          */
1313e71b7053SJung-uk Kim         for (p = v->name; *p; p++) {
1314ddd58736SKris Kennaway #ifndef CHARSET_EBCDIC
1315b077aed3SPierre Pronchery             spec_char = (*p == ':' || *p == ',' || *p == '.');
1316ddd58736SKris Kennaway #else
1317b077aed3SPierre Pronchery             spec_char = (*p == os_toascii[':'] || *p == os_toascii[',']
1318b077aed3SPierre Pronchery                          || *p == os_toascii['.']);
1319ddd58736SKris Kennaway #endif
1320e71b7053SJung-uk Kim             if (spec_char) {
1321f579bf8eSKris Kennaway                 p++;
13226f9291ceSJung-uk Kim                 if (*p)
13236f9291ceSJung-uk Kim                     type = p;
1324f579bf8eSKris Kennaway                 break;
1325f579bf8eSKris Kennaway             }
1326e71b7053SJung-uk Kim         }
13273b4e3dcbSSimon L. B. Nielsen #ifndef CHARSET_EBCDIC
1328e71b7053SJung-uk Kim         plus_char = (*type == '+');
13293b4e3dcbSSimon L. B. Nielsen #else
1330e71b7053SJung-uk Kim         plus_char = (*type == os_toascii['+']);
13313b4e3dcbSSimon L. B. Nielsen #endif
1332e71b7053SJung-uk Kim         if (plus_char) {
1333aeb5019cSJung-uk Kim             type++;
13343b4e3dcbSSimon L. B. Nielsen             mval = -1;
1335e71b7053SJung-uk Kim         } else {
13363b4e3dcbSSimon L. B. Nielsen             mval = 0;
1337e71b7053SJung-uk Kim         }
13385c87c606SMark Murray         if (!X509_NAME_add_entry_by_txt(subj, type, chtype,
13396f9291ceSJung-uk Kim                                         (unsigned char *)v->value, -1, -1,
13406f9291ceSJung-uk Kim                                         mval))
13416f9291ceSJung-uk Kim             return 0;
1342f579bf8eSKris Kennaway 
1343f579bf8eSKris Kennaway     }
1344f579bf8eSKris Kennaway 
13456f9291ceSJung-uk Kim     if (!X509_NAME_entry_count(subj)) {
1346b077aed3SPierre Pronchery         BIO_printf(bio_err, "Error: No objects specified in config file\n");
1347f579bf8eSKris Kennaway         return 0;
1348f579bf8eSKris Kennaway     }
13496f9291ceSJung-uk Kim     if (attribs) {
13506f9291ceSJung-uk Kim         for (i = 0; i < sk_CONF_VALUE_num(attr_sk); i++) {
1351f579bf8eSKris Kennaway             v = sk_CONF_VALUE_value(attr_sk, i);
13525c87c606SMark Murray             if (!X509_REQ_add1_attr_by_txt(req, v->name, chtype,
13536f9291ceSJung-uk Kim                                            (unsigned char *)v->value, -1))
13546f9291ceSJung-uk Kim                 return 0;
1355f579bf8eSKris Kennaway         }
1356f579bf8eSKris Kennaway     }
1357f579bf8eSKris Kennaway     return 1;
1358f579bf8eSKris Kennaway }
1359f579bf8eSKris Kennaway 
13606f9291ceSJung-uk Kim static int add_DN_object(X509_NAME *n, char *text, const char *def,
13616f9291ceSJung-uk Kim                          char *value, int nid, int n_min, int n_max,
13626f9291ceSJung-uk Kim                          unsigned long chtype, int mval)
136374664626SKris Kennaway {
1364e71b7053SJung-uk Kim     int ret = 0;
1365e71b7053SJung-uk Kim     char buf[1024];
136674664626SKris Kennaway 
1367e71b7053SJung-uk Kim     ret = build_data(text, def, value, n_min, n_max, buf, sizeof(buf),
1368e71b7053SJung-uk Kim                      "DN value", "DN default");
1369e71b7053SJung-uk Kim     if ((ret == 0) || (ret == 1))
1370e71b7053SJung-uk Kim         return ret;
1371e71b7053SJung-uk Kim     ret = 1;
137294ad176cSJung-uk Kim 
13735c87c606SMark Murray     if (!X509_NAME_add_entry_by_NID(n, nid, chtype,
13746f9291ceSJung-uk Kim                                     (unsigned char *)buf, -1, -1, mval))
1375e71b7053SJung-uk Kim         ret = 0;
1376e71b7053SJung-uk Kim 
1377e71b7053SJung-uk Kim     return ret;
137874664626SKris Kennaway }
137974664626SKris Kennaway 
13803b4e3dcbSSimon L. B. Nielsen static int add_attribute_object(X509_REQ *req, char *text, const char *def,
13813b4e3dcbSSimon L. B. Nielsen                                 char *value, int nid, int n_min,
13825c87c606SMark Murray                                 int n_max, unsigned long chtype)
1383f579bf8eSKris Kennaway {
1384e71b7053SJung-uk Kim     int ret = 0;
1385e71b7053SJung-uk Kim     char buf[1024];
138674664626SKris Kennaway 
1387e71b7053SJung-uk Kim     ret = build_data(text, def, value, n_min, n_max, buf, sizeof(buf),
1388e71b7053SJung-uk Kim                      "Attribute value", "Attribute default");
1389e71b7053SJung-uk Kim     if ((ret == 0) || (ret == 1))
1390e71b7053SJung-uk Kim         return ret;
1391e71b7053SJung-uk Kim     ret = 1;
1392e71b7053SJung-uk Kim 
1393e71b7053SJung-uk Kim     if (!X509_REQ_add1_attr_by_NID(req, nid, chtype,
1394e71b7053SJung-uk Kim                                    (unsigned char *)buf, -1)) {
1395e71b7053SJung-uk Kim         BIO_printf(bio_err, "Error adding attribute\n");
1396e71b7053SJung-uk Kim         ret = 0;
1397e71b7053SJung-uk Kim     }
1398e71b7053SJung-uk Kim 
1399e71b7053SJung-uk Kim     return ret;
1400e71b7053SJung-uk Kim }
1401e71b7053SJung-uk Kim 
1402b077aed3SPierre Pronchery static int build_data(char *text, const char *def, char *value,
1403b077aed3SPierre Pronchery                       int n_min, int n_max, char *buf, const int buf_size,
1404b077aed3SPierre Pronchery                       const char *desc1, const char *desc2)
1405e71b7053SJung-uk Kim {
1406e71b7053SJung-uk Kim     int i;
1407f579bf8eSKris Kennaway  start:
14086f9291ceSJung-uk Kim     if (!batch)
14096f9291ceSJung-uk Kim         BIO_printf(bio_err, "%s [%s]:", text, def);
1410f579bf8eSKris Kennaway     (void)BIO_flush(bio_err);
14116f9291ceSJung-uk Kim     if (value != NULL) {
1412e71b7053SJung-uk Kim         if (!join(buf, buf_size, value, "\n", desc1))
1413e71b7053SJung-uk Kim             return 0;
1414f579bf8eSKris Kennaway         BIO_printf(bio_err, "%s\n", value);
14156f9291ceSJung-uk Kim     } else {
1416f579bf8eSKris Kennaway         buf[0] = '\0';
14176f9291ceSJung-uk Kim         if (!batch) {
1418e71b7053SJung-uk Kim             if (!fgets(buf, buf_size, stdin))
14196a599222SSimon L. B. Nielsen                 return 0;
14206f9291ceSJung-uk Kim         } else {
14215c87c606SMark Murray             buf[0] = '\n';
14225c87c606SMark Murray             buf[1] = '\0';
14235c87c606SMark Murray         }
1424f579bf8eSKris Kennaway     }
142574664626SKris Kennaway 
14266f9291ceSJung-uk Kim     if (buf[0] == '\0')
1427e71b7053SJung-uk Kim         return 0;
1428e71b7053SJung-uk Kim     if (buf[0] == '\n') {
1429f579bf8eSKris Kennaway         if ((def == NULL) || (def[0] == '\0'))
1430e71b7053SJung-uk Kim             return 1;
1431e71b7053SJung-uk Kim         if (!join(buf, buf_size, def, "\n", desc2))
1432e71b7053SJung-uk Kim             return 0;
1433e71b7053SJung-uk Kim     } else if ((buf[0] == '.') && (buf[1] == '\n')) {
1434e71b7053SJung-uk Kim         return 1;
1435e71b7053SJung-uk Kim     }
143674664626SKris Kennaway 
1437f579bf8eSKris Kennaway     i = strlen(buf);
14386f9291ceSJung-uk Kim     if (buf[i - 1] != '\n') {
1439b077aed3SPierre Pronchery         BIO_printf(bio_err, "Missing newline at end of input\n");
1440e71b7053SJung-uk Kim         return 0;
1441f579bf8eSKris Kennaway     }
1442f579bf8eSKris Kennaway     buf[--i] = '\0';
1443ddd58736SKris Kennaway #ifdef CHARSET_EBCDIC
1444ddd58736SKris Kennaway     ebcdic2ascii(buf, buf, i);
1445ddd58736SKris Kennaway #endif
14466f9291ceSJung-uk Kim     if (!req_check_len(i, n_min, n_max)) {
144794ad176cSJung-uk Kim         if (batch || value)
144894ad176cSJung-uk Kim             return 0;
144994ad176cSJung-uk Kim         goto start;
145094ad176cSJung-uk Kim     }
1451e71b7053SJung-uk Kim     return 2;
145274664626SKris Kennaway }
145374664626SKris Kennaway 
14545c87c606SMark Murray static int req_check_len(int len, int n_min, int n_max)
145574664626SKris Kennaway {
1456b077aed3SPierre Pronchery     if (n_min > 0 && len < n_min) {
14576f9291ceSJung-uk Kim         BIO_printf(bio_err,
1458b077aed3SPierre Pronchery                    "String too short, must be at least %d bytes long\n", n_min);
1459e71b7053SJung-uk Kim         return 0;
146074664626SKris Kennaway     }
1461b077aed3SPierre Pronchery     if (n_max >= 0 && len > n_max) {
14626f9291ceSJung-uk Kim         BIO_printf(bio_err,
1463b077aed3SPierre Pronchery                    "String too long, must be at most %d bytes long\n", n_max);
1464e71b7053SJung-uk Kim         return 0;
146574664626SKris Kennaway     }
1466e71b7053SJung-uk Kim     return 1;
146774664626SKris Kennaway }
146874664626SKris Kennaway 
146974664626SKris Kennaway /* Check if the end of a string matches 'end' */
14703b4e3dcbSSimon L. B. Nielsen static int check_end(const char *str, const char *end)
147174664626SKris Kennaway {
1472e71b7053SJung-uk Kim     size_t elen, slen;
14733b4e3dcbSSimon L. B. Nielsen     const char *tmp;
1474e71b7053SJung-uk Kim 
147574664626SKris Kennaway     elen = strlen(end);
147674664626SKris Kennaway     slen = strlen(str);
14776f9291ceSJung-uk Kim     if (elen > slen)
14786f9291ceSJung-uk Kim         return 1;
147974664626SKris Kennaway     tmp = str + slen - elen;
148074664626SKris Kennaway     return strcmp(tmp, end);
148174664626SKris Kennaway }
14821f13597dSJung-uk Kim 
1483e71b7053SJung-uk Kim /*
1484e71b7053SJung-uk Kim  * Merge the two strings together into the result buffer checking for
1485e71b7053SJung-uk Kim  * overflow and producing an error message if there is.
1486e71b7053SJung-uk Kim  */
1487e71b7053SJung-uk Kim static int join(char buf[], size_t buf_size, const char *name,
1488e71b7053SJung-uk Kim                 const char *tail, const char *desc)
1489e71b7053SJung-uk Kim {
1490e71b7053SJung-uk Kim     const size_t name_len = strlen(name), tail_len = strlen(tail);
1491e71b7053SJung-uk Kim 
1492e71b7053SJung-uk Kim     if (name_len + tail_len + 1 > buf_size) {
1493e71b7053SJung-uk Kim         BIO_printf(bio_err, "%s '%s' too long\n", desc, name);
1494e71b7053SJung-uk Kim         return 0;
1495e71b7053SJung-uk Kim     }
1496e71b7053SJung-uk Kim     memcpy(buf, name, name_len);
1497e71b7053SJung-uk Kim     memcpy(buf + name_len, tail, tail_len + 1);
1498e71b7053SJung-uk Kim     return 1;
1499e71b7053SJung-uk Kim }
1500e71b7053SJung-uk Kim 
1501e71b7053SJung-uk Kim static EVP_PKEY_CTX *set_keygen_ctx(const char *gstr,
1502b077aed3SPierre Pronchery                                     char **pkeytype, long *pkeylen,
1503b077aed3SPierre Pronchery                                     ENGINE *keygen_engine)
15041f13597dSJung-uk Kim {
15051f13597dSJung-uk Kim     EVP_PKEY_CTX *gctx = NULL;
15061f13597dSJung-uk Kim     EVP_PKEY *param = NULL;
15071f13597dSJung-uk Kim     long keylen = -1;
15081f13597dSJung-uk Kim     BIO *pbio = NULL;
1509b077aed3SPierre Pronchery     const char *keytype = NULL;
1510b077aed3SPierre Pronchery     size_t keytypelen = 0;
1511b077aed3SPierre Pronchery     int expect_paramfile = 0;
15121f13597dSJung-uk Kim     const char *paramfile = NULL;
15131f13597dSJung-uk Kim 
1514b077aed3SPierre Pronchery     /* Treat the first part of gstr, and only that */
15156f9291ceSJung-uk Kim     if (gstr == NULL) {
1516b077aed3SPierre Pronchery         /*
1517b077aed3SPierre Pronchery          * Special case: when no string given, default to RSA and the
1518b077aed3SPierre Pronchery          * key length given by |*pkeylen|.
1519b077aed3SPierre Pronchery          */
1520b077aed3SPierre Pronchery         keytype = "RSA";
15211f13597dSJung-uk Kim         keylen = *pkeylen;
15226f9291ceSJung-uk Kim     } else if (gstr[0] >= '0' && gstr[0] <= '9') {
1523b077aed3SPierre Pronchery         /* Special case: only keylength given from string, so default to RSA */
1524b077aed3SPierre Pronchery         keytype = "RSA";
1525b077aed3SPierre Pronchery         /* The second part treatment will do the rest */
1526e71b7053SJung-uk Kim     } else {
15271f13597dSJung-uk Kim         const char *p = strchr(gstr, ':');
15281f13597dSJung-uk Kim         int len;
15291f13597dSJung-uk Kim 
1530e71b7053SJung-uk Kim         if (p != NULL)
15311f13597dSJung-uk Kim             len = p - gstr;
15321f13597dSJung-uk Kim         else
15331f13597dSJung-uk Kim             len = strlen(gstr);
15341f13597dSJung-uk Kim 
1535b077aed3SPierre Pronchery         if (strncmp(gstr, "param", len) == 0) {
1536b077aed3SPierre Pronchery             expect_paramfile = 1;
1537b077aed3SPierre Pronchery             if (p == NULL) {
1538b077aed3SPierre Pronchery                 BIO_printf(bio_err,
1539b077aed3SPierre Pronchery                            "Parameter file requested but no path given: %s\n",
1540b077aed3SPierre Pronchery                            gstr);
15411f13597dSJung-uk Kim                 return NULL;
15421f13597dSJung-uk Kim             }
1543e71b7053SJung-uk Kim         } else {
1544b077aed3SPierre Pronchery             keytype = gstr;
1545b077aed3SPierre Pronchery             keytypelen = len;
1546e71b7053SJung-uk Kim         }
1547b077aed3SPierre Pronchery 
1548b077aed3SPierre Pronchery         if (p != NULL)
1549b077aed3SPierre Pronchery             gstr = gstr + len + 1;
1550b077aed3SPierre Pronchery         else
1551b077aed3SPierre Pronchery             gstr = NULL;
15521f13597dSJung-uk Kim     }
1553b077aed3SPierre Pronchery 
1554b077aed3SPierre Pronchery     /* Treat the second part of gstr, if there is one */
1555b077aed3SPierre Pronchery     if (gstr != NULL) {
1556b077aed3SPierre Pronchery         /* If the second part starts with a digit, we assume it's a size */
1557b077aed3SPierre Pronchery         if (!expect_paramfile && gstr[0] >= '0' && gstr[0] <= '9')
1558b077aed3SPierre Pronchery             keylen = atol(gstr);
1559b077aed3SPierre Pronchery         else
1560b077aed3SPierre Pronchery             paramfile = gstr;
1561e71b7053SJung-uk Kim     }
15621f13597dSJung-uk Kim 
1563e71b7053SJung-uk Kim     if (paramfile != NULL) {
15641f13597dSJung-uk Kim         pbio = BIO_new_file(paramfile, "r");
1565e71b7053SJung-uk Kim         if (pbio == NULL) {
1566b077aed3SPierre Pronchery             BIO_printf(bio_err, "Cannot open parameter file %s\n", paramfile);
15671f13597dSJung-uk Kim             return NULL;
15681f13597dSJung-uk Kim         }
15691f13597dSJung-uk Kim         param = PEM_read_bio_Parameters(pbio, NULL);
15701f13597dSJung-uk Kim 
1571e71b7053SJung-uk Kim         if (param == NULL) {
15721f13597dSJung-uk Kim             X509 *x;
1573e71b7053SJung-uk Kim 
15741f13597dSJung-uk Kim             (void)BIO_reset(pbio);
15751f13597dSJung-uk Kim             x = PEM_read_bio_X509(pbio, NULL, NULL, NULL);
1576e71b7053SJung-uk Kim             if (x != NULL) {
15771f13597dSJung-uk Kim                 param = X509_get_pubkey(x);
15781f13597dSJung-uk Kim                 X509_free(x);
15791f13597dSJung-uk Kim             }
15801f13597dSJung-uk Kim         }
15811f13597dSJung-uk Kim 
15821f13597dSJung-uk Kim         BIO_free(pbio);
15831f13597dSJung-uk Kim 
1584e71b7053SJung-uk Kim         if (param == NULL) {
1585e71b7053SJung-uk Kim             BIO_printf(bio_err, "Error reading parameter file %s\n", paramfile);
15861f13597dSJung-uk Kim             return NULL;
15871f13597dSJung-uk Kim         }
1588b077aed3SPierre Pronchery         if (keytype == NULL) {
1589b077aed3SPierre Pronchery             keytype = EVP_PKEY_get0_type_name(param);
1590b077aed3SPierre Pronchery             if (keytype == NULL) {
1591b077aed3SPierre Pronchery                 EVP_PKEY_free(param);
1592b077aed3SPierre Pronchery                 BIO_puts(bio_err, "Unable to determine key type\n");
1593b077aed3SPierre Pronchery                 return NULL;
1594b077aed3SPierre Pronchery             }
1595b077aed3SPierre Pronchery         }
1596b077aed3SPierre Pronchery     }
1597b077aed3SPierre Pronchery 
1598b077aed3SPierre Pronchery     if (keytypelen > 0)
1599b077aed3SPierre Pronchery         *pkeytype = OPENSSL_strndup(keytype, keytypelen);
1600b077aed3SPierre Pronchery     else
1601b077aed3SPierre Pronchery         *pkeytype = OPENSSL_strdup(keytype);
1602b077aed3SPierre Pronchery 
1603b077aed3SPierre Pronchery     if (*pkeytype == NULL) {
1604b077aed3SPierre Pronchery         BIO_printf(bio_err, "Out of memory\n");
16051f13597dSJung-uk Kim         EVP_PKEY_free(param);
16061f13597dSJung-uk Kim         return NULL;
16071f13597dSJung-uk Kim     }
16081f13597dSJung-uk Kim 
1609b077aed3SPierre Pronchery     if (keylen >= 0)
1610b077aed3SPierre Pronchery         *pkeylen = keylen;
16111f13597dSJung-uk Kim 
1612e71b7053SJung-uk Kim     if (param != NULL) {
1613b077aed3SPierre Pronchery         if (!EVP_PKEY_is_a(param, *pkeytype)) {
1614b077aed3SPierre Pronchery             BIO_printf(bio_err, "Key type does not match parameters\n");
1615b077aed3SPierre Pronchery             EVP_PKEY_free(param);
1616b077aed3SPierre Pronchery             return NULL;
1617b077aed3SPierre Pronchery         }
1618b077aed3SPierre Pronchery 
1619b077aed3SPierre Pronchery         if (keygen_engine != NULL)
16201f13597dSJung-uk Kim             gctx = EVP_PKEY_CTX_new(param, keygen_engine);
1621b077aed3SPierre Pronchery         else
1622b077aed3SPierre Pronchery             gctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(),
1623b077aed3SPierre Pronchery                                               param, app_get0_propq());
1624b077aed3SPierre Pronchery         *pkeylen = EVP_PKEY_get_bits(param);
16251f13597dSJung-uk Kim         EVP_PKEY_free(param);
1626e71b7053SJung-uk Kim     } else {
1627b077aed3SPierre Pronchery         if (keygen_engine != NULL) {
1628b077aed3SPierre Pronchery             int pkey_id = get_legacy_pkey_id(app_get0_libctx(), *pkeytype,
1629b077aed3SPierre Pronchery                                              keygen_engine);
1630b077aed3SPierre Pronchery 
1631b077aed3SPierre Pronchery             if (pkey_id != NID_undef)
1632b077aed3SPierre Pronchery                 gctx = EVP_PKEY_CTX_new_id(pkey_id, keygen_engine);
1633b077aed3SPierre Pronchery         } else {
1634b077aed3SPierre Pronchery             gctx = EVP_PKEY_CTX_new_from_name(app_get0_libctx(),
1635b077aed3SPierre Pronchery                                               *pkeytype, app_get0_propq());
1636b077aed3SPierre Pronchery         }
1637e71b7053SJung-uk Kim     }
16381f13597dSJung-uk Kim 
1639e71b7053SJung-uk Kim     if (gctx == NULL) {
1640e71b7053SJung-uk Kim         BIO_puts(bio_err, "Error allocating keygen context\n");
16411f13597dSJung-uk Kim         return NULL;
16421f13597dSJung-uk Kim     }
16431f13597dSJung-uk Kim 
16446f9291ceSJung-uk Kim     if (EVP_PKEY_keygen_init(gctx) <= 0) {
1645e71b7053SJung-uk Kim         BIO_puts(bio_err, "Error initializing keygen context\n");
1646e71b7053SJung-uk Kim         EVP_PKEY_CTX_free(gctx);
16471f13597dSJung-uk Kim         return NULL;
16481f13597dSJung-uk Kim     }
1649b077aed3SPierre Pronchery     if (keylen == -1 && (EVP_PKEY_CTX_is_a(gctx, "RSA")
1650b077aed3SPierre Pronchery         || EVP_PKEY_CTX_is_a(gctx, "RSA-PSS")))
1651b077aed3SPierre Pronchery         keylen = *pkeylen;
1652b077aed3SPierre Pronchery 
1653b077aed3SPierre Pronchery     if (keylen != -1) {
1654b077aed3SPierre Pronchery         OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
1655b077aed3SPierre Pronchery         size_t bits = keylen;
1656b077aed3SPierre Pronchery 
1657b077aed3SPierre Pronchery         params[0] =
1658b077aed3SPierre Pronchery             OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_BITS, &bits);
1659b077aed3SPierre Pronchery         if (EVP_PKEY_CTX_set_params(gctx, params) <= 0) {
1660b077aed3SPierre Pronchery             BIO_puts(bio_err, "Error setting keysize\n");
16611f13597dSJung-uk Kim             EVP_PKEY_CTX_free(gctx);
16621f13597dSJung-uk Kim             return NULL;
16631f13597dSJung-uk Kim         }
16641f13597dSJung-uk Kim     }
16651f13597dSJung-uk Kim 
16661f13597dSJung-uk Kim     return gctx;
16671f13597dSJung-uk Kim }
16681f13597dSJung-uk Kim 
16691f13597dSJung-uk Kim static int genpkey_cb(EVP_PKEY_CTX *ctx)
16701f13597dSJung-uk Kim {
16711f13597dSJung-uk Kim     char c = '*';
16721f13597dSJung-uk Kim     BIO *b = EVP_PKEY_CTX_get_app_data(ctx);
16731f13597dSJung-uk Kim     int p;
16741f13597dSJung-uk Kim     p = EVP_PKEY_CTX_get_keygen_info(ctx, 0);
16756f9291ceSJung-uk Kim     if (p == 0)
16766f9291ceSJung-uk Kim         c = '.';
16776f9291ceSJung-uk Kim     if (p == 1)
16786f9291ceSJung-uk Kim         c = '+';
16796f9291ceSJung-uk Kim     if (p == 2)
16806f9291ceSJung-uk Kim         c = '*';
16816f9291ceSJung-uk Kim     if (p == 3)
16826f9291ceSJung-uk Kim         c = '\n';
16831f13597dSJung-uk Kim     BIO_write(b, &c, 1);
16841f13597dSJung-uk Kim     (void)BIO_flush(b);
16851f13597dSJung-uk Kim     return 1;
16861f13597dSJung-uk Kim }
1687