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 */
ext_name_hash(const OPENSSL_STRING * a)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
ext_name_cmp(const OPENSSL_STRING * a,const OPENSSL_STRING * b)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
exts_cleanup(OPENSSL_STRING * x)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 */
duplicated(LHASH_OF (OPENSSL_STRING)* addexts,char * kv)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
req_main(int argc,char ** argv)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
make_REQ(X509_REQ * req,EVP_PKEY * pkey,X509_NAME * fsubj,int multirdn,int attribs,unsigned long chtype)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
prompt_info(X509_REQ * req,STACK_OF (CONF_VALUE)* dn_sk,const char * dn_sect,STACK_OF (CONF_VALUE)* attr_sk,const char * attr_sect,int attribs,unsigned long chtype)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
auto_info(X509_REQ * req,STACK_OF (CONF_VALUE)* dn_sk,STACK_OF (CONF_VALUE)* attr_sk,int attribs,unsigned long chtype)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
add_DN_object(X509_NAME * n,char * text,const char * def,char * value,int nid,int n_min,int n_max,unsigned long chtype,int mval)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
add_attribute_object(X509_REQ * req,char * text,const char * def,char * value,int nid,int n_min,int n_max,unsigned long chtype)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
build_data(char * text,const char * def,char * value,int n_min,int n_max,char * buf,const int buf_size,const char * desc1,const char * desc2)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
req_check_len(int len,int n_min,int n_max)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' */
check_end(const char * str,const char * 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 */
join(char buf[],size_t buf_size,const char * name,const char * tail,const char * desc)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
set_keygen_ctx(const char * gstr,char ** pkeytype,long * pkeylen,ENGINE * keygen_engine)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
genpkey_cb(EVP_PKEY_CTX * ctx)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