16f9291ceSJung-uk Kim /* 2aa795734SPierre Pronchery * Copyright 1995-2023 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); 572e71b7053SJung-uk Kim X509V3_set_nconf(&ctx, addext_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); 6881f13597dSJung-uk Kim 6891f13597dSJung-uk Kim EVP_PKEY_CTX_free(genctx); 6901f13597dSJung-uk Kim genctx = NULL; 691b077aed3SPierre Pronchery } 692b077aed3SPierre Pronchery if (keyout == NULL && keyfile == NULL) { 693b077aed3SPierre Pronchery keyout = NCONF_get_string(req_conf, section, KEYFILE); 6945c87c606SMark Murray if (keyout == NULL) 6955c87c606SMark Murray ERR_clear_error(); 6965c87c606SMark Murray } 69774664626SKris Kennaway 698b077aed3SPierre Pronchery if (pkey != NULL && (keyfile == NULL || keyout != NULL)) { 699b077aed3SPierre Pronchery if (verbose) { 700b077aed3SPierre Pronchery BIO_printf(bio_err, "Writing private key to "); 701e71b7053SJung-uk Kim if (keyout == NULL) 702b077aed3SPierre Pronchery BIO_printf(bio_err, "stdout\n"); 703e71b7053SJung-uk Kim else 704b077aed3SPierre Pronchery BIO_printf(bio_err, "'%s'\n", keyout); 705b077aed3SPierre Pronchery } 706b077aed3SPierre Pronchery out = bio_open_owner(keyout, outformat, newreq); 707e71b7053SJung-uk Kim if (out == NULL) 70874664626SKris Kennaway goto end; 70974664626SKris Kennaway 710b077aed3SPierre Pronchery p = NCONF_get_string(req_conf, section, "encrypt_rsa_key"); 7116f9291ceSJung-uk Kim if (p == NULL) { 7125c87c606SMark Murray ERR_clear_error(); 713b077aed3SPierre Pronchery p = NCONF_get_string(req_conf, section, "encrypt_key"); 7145c87c606SMark Murray if (p == NULL) 7155c87c606SMark Murray ERR_clear_error(); 7165c87c606SMark Murray } 71774664626SKris Kennaway if ((p != NULL) && (strcmp(p, "no") == 0)) 71874664626SKris Kennaway cipher = NULL; 719b077aed3SPierre Pronchery if (noenc) 7206f9291ceSJung-uk Kim cipher = NULL; 72174664626SKris Kennaway 72274664626SKris Kennaway i = 0; 72374664626SKris Kennaway loop: 72474664626SKris Kennaway if (!PEM_write_bio_PrivateKey(out, pkey, cipher, 7256f9291ceSJung-uk Kim NULL, 0, NULL, passout)) { 72674664626SKris Kennaway if ((ERR_GET_REASON(ERR_peek_error()) == 7276f9291ceSJung-uk Kim PEM_R_PROBLEMS_GETTING_PASSWORD) && (i < 3)) { 72874664626SKris Kennaway ERR_clear_error(); 72974664626SKris Kennaway i++; 73074664626SKris Kennaway goto loop; 73174664626SKris Kennaway } 73274664626SKris Kennaway goto end; 73374664626SKris Kennaway } 734e71b7053SJung-uk Kim BIO_free(out); 735e71b7053SJung-uk Kim out = NULL; 73674664626SKris Kennaway BIO_printf(bio_err, "-----\n"); 73774664626SKris Kennaway } 73874664626SKris Kennaway 739b077aed3SPierre Pronchery /* 740b077aed3SPierre Pronchery * subj is expected to be in the format /type0=value0/type1=value1/type2=... 741b077aed3SPierre Pronchery * where characters may be escaped by \ 742b077aed3SPierre Pronchery */ 743b077aed3SPierre Pronchery if (subj != NULL 744b077aed3SPierre Pronchery && (fsubj = parse_name(subj, chtype, multirdn, "subject")) == NULL) 745b077aed3SPierre Pronchery goto end; 746b077aed3SPierre Pronchery 7476f9291ceSJung-uk Kim if (!newreq) { 748b077aed3SPierre Pronchery req = load_csr(infile /* if NULL, reads from stdin */, 749b077aed3SPierre Pronchery informat, "X509 request"); 750b077aed3SPierre Pronchery if (req == NULL) 75174664626SKris Kennaway goto end; 752b077aed3SPierre Pronchery } 75374664626SKris Kennaway 754b077aed3SPierre Pronchery if (CAkeyfile == NULL) 755b077aed3SPierre Pronchery CAkeyfile = CAfile; 756b077aed3SPierre Pronchery if (CAkeyfile != NULL) { 757b077aed3SPierre Pronchery if (CAfile == NULL) { 758b077aed3SPierre Pronchery BIO_printf(bio_err, 759b077aed3SPierre Pronchery "Warning: Ignoring -CAkey option since no -CA option is given\n"); 760b077aed3SPierre Pronchery } else { 761b077aed3SPierre Pronchery if ((CAkey = load_key(CAkeyfile, FORMAT_UNDEF, 762b077aed3SPierre Pronchery 0, passin, e, 763b077aed3SPierre Pronchery CAkeyfile != CAfile 764b077aed3SPierre Pronchery ? "issuer private key from -CAkey arg" 765b077aed3SPierre Pronchery : "issuer private key from -CA arg")) == NULL) 76674664626SKris Kennaway goto end; 76774664626SKris Kennaway } 76874664626SKris Kennaway } 769b077aed3SPierre Pronchery if (CAfile != NULL) { 770b077aed3SPierre Pronchery if ((CAcert = load_cert_pass(CAfile, FORMAT_UNDEF, 1, passin, 771b077aed3SPierre Pronchery "issuer cert from -CA arg")) == NULL) 772b077aed3SPierre Pronchery goto end; 773b077aed3SPierre Pronchery if (!X509_check_private_key(CAcert, CAkey)) { 774b077aed3SPierre Pronchery BIO_printf(bio_err, 775b077aed3SPierre Pronchery "Issuer CA certificate and key do not match\n"); 776b077aed3SPierre Pronchery goto end; 777b077aed3SPierre Pronchery } 778b077aed3SPierre Pronchery } 779b077aed3SPierre Pronchery if (newreq || gen_x509) { 780b077aed3SPierre Pronchery if (CAcert == NULL && pkey == NULL) { 781b077aed3SPierre Pronchery BIO_printf(bio_err, "Must provide a signature key using -key or" 782b077aed3SPierre Pronchery " provide -CA / -CAkey\n"); 78374664626SKris Kennaway goto end; 78474664626SKris Kennaway } 7851f13597dSJung-uk Kim 7866f9291ceSJung-uk Kim if (req == NULL) { 787b077aed3SPierre Pronchery req = X509_REQ_new_ex(app_get0_libctx(), app_get0_propq()); 7886f9291ceSJung-uk Kim if (req == NULL) { 78974664626SKris Kennaway goto end; 79074664626SKris Kennaway } 79174664626SKris Kennaway 792b077aed3SPierre Pronchery if (!make_REQ(req, pkey, fsubj, multirdn, !gen_x509, chtype)){ 793b077aed3SPierre Pronchery BIO_printf(bio_err, "Error making certificate request\n"); 79474664626SKris Kennaway goto end; 79574664626SKris Kennaway } 796b077aed3SPierre Pronchery /* Note that -x509 can take over -key and -subj option values. */ 79774664626SKris Kennaway } 798b077aed3SPierre Pronchery if (gen_x509) { 799b077aed3SPierre Pronchery EVP_PKEY *pub_key = X509_REQ_get0_pubkey(req); 800b077aed3SPierre Pronchery EVP_PKEY *issuer_key = CAcert != NULL ? CAkey : pkey; 80174664626SKris Kennaway X509V3_CTX ext_ctx; 802b077aed3SPierre Pronchery X509_NAME *issuer = CAcert != NULL ? X509_get_subject_name(CAcert) : 803b077aed3SPierre Pronchery X509_REQ_get_subject_name(req); 804b077aed3SPierre Pronchery X509_NAME *n_subj = fsubj != NULL ? fsubj : 805b077aed3SPierre Pronchery X509_REQ_get_subject_name(req); 806b077aed3SPierre Pronchery 807b077aed3SPierre Pronchery if ((new_x509 = X509_new_ex(app_get0_libctx(), 808b077aed3SPierre Pronchery app_get0_propq())) == NULL) 8096f9291ceSJung-uk Kim goto end; 81074664626SKris Kennaway 811e71b7053SJung-uk Kim if (serial != NULL) { 812b077aed3SPierre Pronchery if (!X509_set_serialNumber(new_x509, serial)) 8136f9291ceSJung-uk Kim goto end; 8146f9291ceSJung-uk Kim } else { 815b077aed3SPierre Pronchery if (!rand_serial(NULL, X509_get_serialNumber(new_x509))) 8166be8ae07SJacques Vidrine goto end; 8175c87c606SMark Murray } 81874664626SKris Kennaway 819b077aed3SPierre Pronchery if (!X509_set_issuer_name(new_x509, issuer)) 8206f9291ceSJung-uk Kim goto end; 821b077aed3SPierre Pronchery if (days == UNSET_DAYS) { 822b077aed3SPierre Pronchery days = DEFAULT_DAYS; 823e71b7053SJung-uk Kim } 824b077aed3SPierre Pronchery if (!set_cert_times(new_x509, NULL, NULL, days)) 8256f9291ceSJung-uk Kim goto end; 826b077aed3SPierre Pronchery if (!X509_set_subject_name(new_x509, n_subj)) 8276f9291ceSJung-uk Kim goto end; 828b077aed3SPierre Pronchery if (!pub_key || !X509_set_pubkey(new_x509, pub_key)) 8296f9291ceSJung-uk Kim goto end; 830b077aed3SPierre Pronchery if (ext_copy == EXT_COPY_UNSET) { 831b077aed3SPierre Pronchery if (infile != NULL) 832b077aed3SPierre Pronchery BIO_printf(bio_err, "Warning: No -copy_extensions given; ignoring any extensions in the request\n"); 833b077aed3SPierre Pronchery } else if (!copy_extensions(new_x509, req, ext_copy)) { 834b077aed3SPierre Pronchery BIO_printf(bio_err, "Error copying extensions from request\n"); 835b077aed3SPierre Pronchery goto end; 836b077aed3SPierre Pronchery } 83774664626SKris Kennaway 83874664626SKris Kennaway /* Set up V3 context struct */ 839b077aed3SPierre Pronchery X509V3_set_ctx(&ext_ctx, CAcert != NULL ? CAcert : new_x509, 840b077aed3SPierre Pronchery new_x509, NULL, NULL, X509V3_CTX_REPLACE); 841b077aed3SPierre Pronchery /* prepare fallback for AKID, but only if issuer cert == new_x509 */ 842b077aed3SPierre Pronchery if (CAcert == NULL) { 843b077aed3SPierre Pronchery if (!X509V3_set_issuer_pkey(&ext_ctx, issuer_key)) 844b077aed3SPierre Pronchery goto end; 845b077aed3SPierre Pronchery ERR_set_mark(); 846b077aed3SPierre Pronchery if (!X509_check_private_key(new_x509, issuer_key)) 847b077aed3SPierre Pronchery BIO_printf(bio_err, 848b077aed3SPierre Pronchery "Warning: Signature key and public key of cert do not match\n"); 849b077aed3SPierre Pronchery ERR_pop_to_mark(); 850b077aed3SPierre Pronchery } 8515c87c606SMark Murray X509V3_set_nconf(&ext_ctx, req_conf); 85274664626SKris Kennaway 85374664626SKris Kennaway /* Add extensions */ 854b077aed3SPierre Pronchery if (extensions != NULL 855b077aed3SPierre Pronchery && !X509V3_EXT_add_nconf(req_conf, &ext_ctx, extensions, 856b077aed3SPierre Pronchery new_x509)) { 857b077aed3SPierre Pronchery BIO_printf(bio_err, "Error adding x509 extensions from section %s\n", 85874664626SKris Kennaway extensions); 85974664626SKris Kennaway goto end; 86074664626SKris Kennaway } 861e71b7053SJung-uk Kim if (addext_conf != NULL 862e71b7053SJung-uk Kim && !X509V3_EXT_add_nconf(addext_conf, &ext_ctx, "default", 863b077aed3SPierre Pronchery new_x509)) { 864b077aed3SPierre Pronchery BIO_printf(bio_err, "Error adding extensions defined via -addext\n"); 865e71b7053SJung-uk Kim goto end; 866e71b7053SJung-uk Kim } 86774664626SKris Kennaway 868e71b7053SJung-uk Kim /* If a pre-cert was requested, we need to add a poison extension */ 869e71b7053SJung-uk Kim if (precert) { 870b077aed3SPierre Pronchery if (X509_add1_ext_i2d(new_x509, NID_ct_precert_poison, 871b077aed3SPierre Pronchery NULL, 1, 0) != 1) { 872e71b7053SJung-uk Kim BIO_printf(bio_err, "Error adding poison extension\n"); 873e71b7053SJung-uk Kim goto end; 874e71b7053SJung-uk Kim } 875e71b7053SJung-uk Kim } 876e71b7053SJung-uk Kim 877b077aed3SPierre Pronchery i = do_X509_sign(new_x509, issuer_key, digest, sigopts, &ext_ctx); 878b077aed3SPierre Pronchery if (!i) 87974664626SKris Kennaway goto end; 8806f9291ceSJung-uk Kim } else { 881f579bf8eSKris Kennaway X509V3_CTX ext_ctx; 882f579bf8eSKris Kennaway 883f579bf8eSKris Kennaway /* Set up V3 context struct */ 884f579bf8eSKris Kennaway X509V3_set_ctx(&ext_ctx, NULL, NULL, req, NULL, 0); 8855c87c606SMark Murray X509V3_set_nconf(&ext_ctx, req_conf); 886f579bf8eSKris Kennaway 887f579bf8eSKris Kennaway /* Add extensions */ 888e71b7053SJung-uk Kim if (req_exts != NULL 889e71b7053SJung-uk Kim && !X509V3_EXT_REQ_add_nconf(req_conf, &ext_ctx, 890e71b7053SJung-uk Kim req_exts, req)) { 891b077aed3SPierre Pronchery BIO_printf(bio_err, "Error adding request extensions from section %s\n", 892f579bf8eSKris Kennaway req_exts); 893f579bf8eSKris Kennaway goto end; 894f579bf8eSKris Kennaway } 895e71b7053SJung-uk Kim if (addext_conf != NULL 896e71b7053SJung-uk Kim && !X509V3_EXT_REQ_add_nconf(addext_conf, &ext_ctx, "default", 897e71b7053SJung-uk Kim req)) { 898b077aed3SPierre Pronchery BIO_printf(bio_err, "Error adding extensions defined via -addext\n"); 899e71b7053SJung-uk Kim goto end; 900e71b7053SJung-uk Kim } 901e71b7053SJung-uk Kim i = do_X509_REQ_sign(req, pkey, digest, sigopts); 902b077aed3SPierre Pronchery if (!i) 90374664626SKris Kennaway goto end; 90474664626SKris Kennaway } 90574664626SKris Kennaway } 90674664626SKris Kennaway 907b077aed3SPierre Pronchery if (subj != NULL && !newreq && !gen_x509) { 9086f9291ceSJung-uk Kim if (verbose) { 909b077aed3SPierre Pronchery BIO_printf(out, "Modifying subject of certificate request\n"); 910b077aed3SPierre Pronchery print_name(out, "Old subject=", X509_REQ_get_subject_name(req)); 9115c87c606SMark Murray } 9125c87c606SMark Murray 913b077aed3SPierre Pronchery if (!X509_REQ_set_subject_name(req, fsubj)) { 914b077aed3SPierre Pronchery BIO_printf(bio_err, "Error modifying subject of certificate request\n"); 9155c87c606SMark Murray goto end; 9165c87c606SMark Murray } 9175c87c606SMark Murray 9186f9291ceSJung-uk Kim if (verbose) { 919b077aed3SPierre Pronchery print_name(out, "New subject=", X509_REQ_get_subject_name(req)); 9205c87c606SMark Murray } 9215c87c606SMark Murray } 9225c87c606SMark Murray 923b077aed3SPierre Pronchery if (verify) { 924e71b7053SJung-uk Kim EVP_PKEY *tpubkey = pkey; 92574664626SKris Kennaway 926e71b7053SJung-uk Kim if (tpubkey == NULL) { 927e71b7053SJung-uk Kim tpubkey = X509_REQ_get0_pubkey(req); 928e71b7053SJung-uk Kim if (tpubkey == NULL) 9296f9291ceSJung-uk Kim goto end; 93074664626SKris Kennaway } 93174664626SKris Kennaway 932b077aed3SPierre Pronchery i = do_X509_REQ_verify(req, tpubkey, vfyopts); 93374664626SKris Kennaway 934b077aed3SPierre Pronchery if (i < 0) 93574664626SKris Kennaway goto end; 936b077aed3SPierre Pronchery if (i == 0) 937b077aed3SPierre Pronchery BIO_printf(bio_err, "Certificate request self-signature verify failure\n"); 938b077aed3SPierre Pronchery else /* i > 0 */ 939b077aed3SPierre Pronchery BIO_printf(bio_err, "Certificate request self-signature verify OK\n"); 940e71b7053SJung-uk Kim } 94174664626SKris Kennaway 9426f9291ceSJung-uk Kim if (noout && !text && !modulus && !subject && !pubkey) { 943e71b7053SJung-uk Kim ret = 0; 94474664626SKris Kennaway goto end; 94574664626SKris Kennaway } 94674664626SKris Kennaway 947e71b7053SJung-uk Kim out = bio_open_default(outfile, 948e71b7053SJung-uk Kim keyout != NULL && outfile != NULL && 949e71b7053SJung-uk Kim strcmp(keyout, outfile) == 0 ? 'a' : 'w', 950e71b7053SJung-uk Kim outformat); 951e71b7053SJung-uk Kim if (out == NULL) 95274664626SKris Kennaway goto end; 95374664626SKris Kennaway 9546f9291ceSJung-uk Kim if (pubkey) { 955e71b7053SJung-uk Kim EVP_PKEY *tpubkey = X509_REQ_get0_pubkey(req); 956e71b7053SJung-uk Kim 9576f9291ceSJung-uk Kim if (tpubkey == NULL) { 9585c87c606SMark Murray BIO_printf(bio_err, "Error getting public key\n"); 9595c87c606SMark Murray goto end; 9605c87c606SMark Murray } 9615c87c606SMark Murray PEM_write_bio_PUBKEY(out, tpubkey); 9625c87c606SMark Murray } 9635c87c606SMark Murray 9646f9291ceSJung-uk Kim if (text) { 965b077aed3SPierre Pronchery if (gen_x509) 966b077aed3SPierre Pronchery ret = X509_print_ex(out, new_x509, get_nameopt(), reqflag); 96774664626SKris Kennaway else 968da327cd2SJung-uk Kim ret = X509_REQ_print_ex(out, req, get_nameopt(), reqflag); 969da327cd2SJung-uk Kim 970da327cd2SJung-uk Kim if (ret == 0) { 971b077aed3SPierre Pronchery if (gen_x509) 972da327cd2SJung-uk Kim BIO_printf(bio_err, "Error printing certificate\n"); 973da327cd2SJung-uk Kim else 974da327cd2SJung-uk Kim BIO_printf(bio_err, "Error printing certificate request\n"); 975da327cd2SJung-uk Kim goto end; 976da327cd2SJung-uk Kim } 9775c87c606SMark Murray } 9785c87c606SMark Murray 9796f9291ceSJung-uk Kim if (subject) { 980b077aed3SPierre Pronchery print_name(out, "subject=", gen_x509 981b077aed3SPierre Pronchery ? X509_get_subject_name(new_x509) 982b077aed3SPierre Pronchery : X509_REQ_get_subject_name(req)); 98374664626SKris Kennaway } 98474664626SKris Kennaway 9856f9291ceSJung-uk Kim if (modulus) { 9865c87c606SMark Murray EVP_PKEY *tpubkey; 98774664626SKris Kennaway 988b077aed3SPierre Pronchery if (gen_x509) 989b077aed3SPierre Pronchery tpubkey = X509_get0_pubkey(new_x509); 99074664626SKris Kennaway else 991e71b7053SJung-uk Kim tpubkey = X509_REQ_get0_pubkey(req); 9926f9291ceSJung-uk Kim if (tpubkey == NULL) { 993*6f1af0d7SPierre Pronchery BIO_puts(bio_err, "Modulus is unavailable\n"); 99474664626SKris Kennaway goto end; 99574664626SKris Kennaway } 996*6f1af0d7SPierre Pronchery BIO_puts(out, "Modulus="); 997b077aed3SPierre Pronchery if (EVP_PKEY_is_a(tpubkey, "RSA") || EVP_PKEY_is_a(tpubkey, "RSA-PSS")) { 998b077aed3SPierre Pronchery BIGNUM *n = NULL; 999b077aed3SPierre Pronchery 1000b077aed3SPierre Pronchery if (!EVP_PKEY_get_bn_param(tpubkey, "n", &n)) 1001b077aed3SPierre Pronchery goto end; 1002e71b7053SJung-uk Kim BN_print(out, n); 1003b077aed3SPierre Pronchery BN_free(n); 1004b077aed3SPierre Pronchery } else { 1005*6f1af0d7SPierre Pronchery BIO_puts(out, "Wrong Algorithm type"); 1006b077aed3SPierre Pronchery } 1007*6f1af0d7SPierre Pronchery BIO_puts(out, "\n"); 100874664626SKris Kennaway } 100974664626SKris Kennaway 1010b077aed3SPierre Pronchery if (!noout && !gen_x509) { 101174664626SKris Kennaway if (outformat == FORMAT_ASN1) 101274664626SKris Kennaway i = i2d_X509_REQ_bio(out, req); 1013e71b7053SJung-uk Kim else if (newhdr) 10146f9291ceSJung-uk Kim i = PEM_write_bio_X509_REQ_NEW(out, req); 10156f9291ceSJung-uk Kim else 10166f9291ceSJung-uk Kim i = PEM_write_bio_X509_REQ(out, req); 10176f9291ceSJung-uk Kim if (!i) { 1018b077aed3SPierre Pronchery BIO_printf(bio_err, "Unable to write certificate request\n"); 101974664626SKris Kennaway goto end; 102074664626SKris Kennaway } 102174664626SKris Kennaway } 1022b077aed3SPierre Pronchery if (!noout && gen_x509 && new_x509 != NULL) { 102374664626SKris Kennaway if (outformat == FORMAT_ASN1) 1024b077aed3SPierre Pronchery i = i2d_X509_bio(out, new_x509); 1025e71b7053SJung-uk Kim else 1026b077aed3SPierre Pronchery i = PEM_write_bio_X509(out, new_x509); 10276f9291ceSJung-uk Kim if (!i) { 1028b077aed3SPierre Pronchery BIO_printf(bio_err, "Unable to write X509 certificate\n"); 102974664626SKris Kennaway goto end; 103074664626SKris Kennaway } 103174664626SKris Kennaway } 1032e71b7053SJung-uk Kim ret = 0; 103374664626SKris Kennaway end: 1034e71b7053SJung-uk Kim if (ret) { 103574664626SKris Kennaway ERR_print_errors(bio_err); 103674664626SKris Kennaway } 10376f9291ceSJung-uk Kim NCONF_free(req_conf); 1038e71b7053SJung-uk Kim NCONF_free(addext_conf); 1039e71b7053SJung-uk Kim BIO_free(addext_bio); 1040ddd58736SKris Kennaway BIO_free_all(out); 104174664626SKris Kennaway EVP_PKEY_free(pkey); 10421f13597dSJung-uk Kim EVP_PKEY_CTX_free(genctx); 10431f13597dSJung-uk Kim sk_OPENSSL_STRING_free(pkeyopts); 10441f13597dSJung-uk Kim sk_OPENSSL_STRING_free(sigopts); 1045b077aed3SPierre Pronchery sk_OPENSSL_STRING_free(vfyopts); 1046e71b7053SJung-uk Kim lh_OPENSSL_STRING_doall(addexts, exts_cleanup); 1047e71b7053SJung-uk Kim lh_OPENSSL_STRING_free(addexts); 10481f13597dSJung-uk Kim #ifndef OPENSSL_NO_ENGINE 1049b077aed3SPierre Pronchery release_engine(gen_eng); 10501f13597dSJung-uk Kim #endif 10511f13597dSJung-uk Kim OPENSSL_free(keyalgstr); 105274664626SKris Kennaway X509_REQ_free(req); 1053b077aed3SPierre Pronchery X509_NAME_free(fsubj); 1054b077aed3SPierre Pronchery X509_free(new_x509); 1055b077aed3SPierre Pronchery X509_free(CAcert); 1056b077aed3SPierre Pronchery EVP_PKEY_free(CAkey); 10575c87c606SMark Murray ASN1_INTEGER_free(serial); 10586cf8931aSJung-uk Kim release_engine(e); 1059e71b7053SJung-uk Kim if (passin != nofree_passin) 10606f9291ceSJung-uk Kim OPENSSL_free(passin); 1061e71b7053SJung-uk Kim if (passout != nofree_passout) 10626f9291ceSJung-uk Kim OPENSSL_free(passout); 1063e71b7053SJung-uk Kim return ret; 106474664626SKris Kennaway } 106574664626SKris Kennaway 1066b077aed3SPierre Pronchery static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, X509_NAME *fsubj, 1067b077aed3SPierre Pronchery int multirdn, int attribs, unsigned long chtype) 106874664626SKris Kennaway { 106974664626SKris Kennaway int ret = 0, i; 1070f579bf8eSKris Kennaway char no_prompt = 0; 1071b077aed3SPierre Pronchery STACK_OF(CONF_VALUE) *dn_sk = NULL, *attr_sk = NULL; 1072f579bf8eSKris Kennaway char *tmp, *dn_sect, *attr_sect; 107374664626SKris Kennaway 1074b077aed3SPierre Pronchery tmp = NCONF_get_string(req_conf, section, PROMPT); 10755c87c606SMark Murray if (tmp == NULL) 10765c87c606SMark Murray ERR_clear_error(); 1077e71b7053SJung-uk Kim if ((tmp != NULL) && strcmp(tmp, "no") == 0) 10786f9291ceSJung-uk Kim no_prompt = 1; 1079f579bf8eSKris Kennaway 1080b077aed3SPierre Pronchery dn_sect = NCONF_get_string(req_conf, section, DISTINGUISHED_NAME); 10816f9291ceSJung-uk Kim if (dn_sect == NULL) { 1082b077aed3SPierre Pronchery ERR_clear_error(); 1083b077aed3SPierre Pronchery } else { 10845c87c606SMark Murray dn_sk = NCONF_get_section(req_conf, dn_sect); 10856f9291ceSJung-uk Kim if (dn_sk == NULL) { 1086b077aed3SPierre Pronchery BIO_printf(bio_err, "Unable to get '%s' section\n", dn_sect); 108774664626SKris Kennaway goto err; 108874664626SKris Kennaway } 1089b077aed3SPierre Pronchery } 109074664626SKris Kennaway 1091b077aed3SPierre Pronchery attr_sect = NCONF_get_string(req_conf, section, ATTRIBUTES); 10926f9291ceSJung-uk Kim if (attr_sect == NULL) { 10935c87c606SMark Murray ERR_clear_error(); 10946f9291ceSJung-uk Kim } else { 10955c87c606SMark Murray attr_sk = NCONF_get_section(req_conf, attr_sect); 10966f9291ceSJung-uk Kim if (attr_sk == NULL) { 1097b077aed3SPierre Pronchery BIO_printf(bio_err, "Unable to get '%s' section\n", attr_sect); 109874664626SKris Kennaway goto err; 109974664626SKris Kennaway } 110074664626SKris Kennaway } 110174664626SKris Kennaway 1102b077aed3SPierre Pronchery /* so far there is only version 1 */ 1103b077aed3SPierre Pronchery if (!X509_REQ_set_version(req, X509_REQ_VERSION_1)) 1104b077aed3SPierre Pronchery goto err; 110574664626SKris Kennaway 1106b077aed3SPierre Pronchery if (fsubj != NULL) 1107b077aed3SPierre Pronchery i = X509_REQ_set_subject_name(req, fsubj); 1108e71b7053SJung-uk Kim else if (no_prompt) 1109e71b7053SJung-uk Kim i = auto_info(req, dn_sk, attr_sk, attribs, chtype); 11105c87c606SMark Murray else 11116f9291ceSJung-uk Kim i = prompt_info(req, dn_sk, dn_sect, attr_sk, attr_sect, attribs, 11126f9291ceSJung-uk Kim chtype); 11136f9291ceSJung-uk Kim if (!i) 11146f9291ceSJung-uk Kim goto err; 1115f579bf8eSKris Kennaway 11166f9291ceSJung-uk Kim if (!X509_REQ_set_pubkey(req, pkey)) 11176f9291ceSJung-uk Kim goto err; 1118f579bf8eSKris Kennaway 1119f579bf8eSKris Kennaway ret = 1; 1120f579bf8eSKris Kennaway err: 1121e71b7053SJung-uk Kim return ret; 1122f579bf8eSKris Kennaway } 1123f579bf8eSKris Kennaway 1124f579bf8eSKris Kennaway static int prompt_info(X509_REQ *req, 1125e71b7053SJung-uk Kim STACK_OF(CONF_VALUE) *dn_sk, const char *dn_sect, 1126e71b7053SJung-uk Kim STACK_OF(CONF_VALUE) *attr_sk, const char *attr_sect, 11276f9291ceSJung-uk Kim int attribs, unsigned long chtype) 1128f579bf8eSKris Kennaway { 1129f579bf8eSKris Kennaway int i; 1130f579bf8eSKris Kennaway char *p, *q; 1131f579bf8eSKris Kennaway char buf[100]; 11323b4e3dcbSSimon L. B. Nielsen int nid, mval; 11335c87c606SMark Murray long n_min, n_max; 11343b4e3dcbSSimon L. B. Nielsen char *type, *value; 11353b4e3dcbSSimon L. B. Nielsen const char *def; 1136f579bf8eSKris Kennaway CONF_VALUE *v; 1137b077aed3SPierre Pronchery X509_NAME *subj = X509_REQ_get_subject_name(req); 11385c87c606SMark Murray 11396f9291ceSJung-uk Kim if (!batch) { 11406f9291ceSJung-uk Kim BIO_printf(bio_err, 11416f9291ceSJung-uk Kim "You are about to be asked to enter information that will be incorporated\n"); 114274664626SKris Kennaway BIO_printf(bio_err, "into your certificate request.\n"); 11436f9291ceSJung-uk Kim BIO_printf(bio_err, 11446f9291ceSJung-uk Kim "What you are about to enter is what is called a Distinguished Name or a DN.\n"); 11456f9291ceSJung-uk Kim BIO_printf(bio_err, 11466f9291ceSJung-uk Kim "There are quite a few fields but you can leave some blank\n"); 11476f9291ceSJung-uk Kim BIO_printf(bio_err, 11486f9291ceSJung-uk Kim "For some fields there will be a default value,\n"); 11496f9291ceSJung-uk Kim BIO_printf(bio_err, 11506f9291ceSJung-uk Kim "If you enter '.', the field will be left blank.\n"); 115174664626SKris Kennaway BIO_printf(bio_err, "-----\n"); 11525c87c606SMark Murray } 115374664626SKris Kennaway 11546f9291ceSJung-uk Kim if (sk_CONF_VALUE_num(dn_sk)) { 115574664626SKris Kennaway i = -1; 1156e71b7053SJung-uk Kim start: 1157e71b7053SJung-uk Kim for (;;) { 115874664626SKris Kennaway i++; 11596f9291ceSJung-uk Kim if (sk_CONF_VALUE_num(dn_sk) <= i) 11606f9291ceSJung-uk Kim break; 116174664626SKris Kennaway 1162f579bf8eSKris Kennaway v = sk_CONF_VALUE_value(dn_sk, i); 116374664626SKris Kennaway p = q = NULL; 116474664626SKris Kennaway type = v->name; 116574664626SKris Kennaway if (!check_end(type, "_min") || !check_end(type, "_max") || 11666f9291ceSJung-uk Kim !check_end(type, "_default") || !check_end(type, "_value")) 11676f9291ceSJung-uk Kim continue; 11686f9291ceSJung-uk Kim /* 11696f9291ceSJung-uk Kim * Skip past any leading X. X: X, etc to allow for multiple 11706f9291ceSJung-uk Kim * instances 117174664626SKris Kennaway */ 117274664626SKris Kennaway for (p = v->name; *p; p++) 11736f9291ceSJung-uk Kim if ((*p == ':') || (*p == ',') || (*p == '.')) { 117474664626SKris Kennaway p++; 11756f9291ceSJung-uk Kim if (*p) 11766f9291ceSJung-uk Kim type = p; 117774664626SKris Kennaway break; 117874664626SKris Kennaway } 11796f9291ceSJung-uk Kim if (*type == '+') { 11803b4e3dcbSSimon L. B. Nielsen mval = -1; 11813b4e3dcbSSimon L. B. Nielsen type++; 1182e71b7053SJung-uk Kim } else { 11833b4e3dcbSSimon L. B. Nielsen mval = 0; 1184e71b7053SJung-uk Kim } 118574664626SKris Kennaway /* If OBJ not recognised ignore it */ 11866f9291ceSJung-uk Kim if ((nid = OBJ_txt2nid(type)) == NID_undef) 11876f9291ceSJung-uk Kim goto start; 1188e71b7053SJung-uk Kim if (!join(buf, sizeof(buf), v->name, "_default", "Name")) 11895c87c606SMark Murray return 0; 11906f9291ceSJung-uk Kim if ((def = NCONF_get_string(req_conf, dn_sect, buf)) == NULL) { 11915c87c606SMark Murray ERR_clear_error(); 11925c87c606SMark Murray def = ""; 11935c87c606SMark Murray } 1194ced566fdSJacques Vidrine 1195e71b7053SJung-uk Kim if (!join(buf, sizeof(buf), v->name, "_value", "Name")) 1196e71b7053SJung-uk Kim return 0; 11976f9291ceSJung-uk Kim if ((value = NCONF_get_string(req_conf, dn_sect, buf)) == NULL) { 11985c87c606SMark Murray ERR_clear_error(); 119974664626SKris Kennaway value = NULL; 12005c87c606SMark Murray } 120174664626SKris Kennaway 1202e71b7053SJung-uk Kim if (!join(buf, sizeof(buf), v->name, "_min", "Name")) 1203e71b7053SJung-uk Kim return 0; 12046f9291ceSJung-uk Kim if (!NCONF_get_number(req_conf, dn_sect, buf, &n_min)) { 1205fceca8a3SJacques Vidrine ERR_clear_error(); 12065c87c606SMark Murray n_min = -1; 1207fceca8a3SJacques Vidrine } 120874664626SKris Kennaway 1209e71b7053SJung-uk Kim if (!join(buf, sizeof(buf), v->name, "_max", "Name")) 1210e71b7053SJung-uk Kim return 0; 12116f9291ceSJung-uk Kim if (!NCONF_get_number(req_conf, dn_sect, buf, &n_max)) { 1212fceca8a3SJacques Vidrine ERR_clear_error(); 12135c87c606SMark Murray n_max = -1; 1214fceca8a3SJacques Vidrine } 121574664626SKris Kennaway 1216f579bf8eSKris Kennaway if (!add_DN_object(subj, v->value, def, value, nid, 12173b4e3dcbSSimon L. B. Nielsen n_min, n_max, chtype, mval)) 1218f579bf8eSKris Kennaway return 0; 121974664626SKris Kennaway } 12206f9291ceSJung-uk Kim if (X509_NAME_entry_count(subj) == 0) { 1221b077aed3SPierre Pronchery BIO_printf(bio_err, "Error: No objects specified in config file\n"); 1222f579bf8eSKris Kennaway return 0; 122374664626SKris Kennaway } 122474664626SKris Kennaway 12256f9291ceSJung-uk Kim if (attribs) { 12266f9291ceSJung-uk Kim if ((attr_sk != NULL) && (sk_CONF_VALUE_num(attr_sk) > 0) 12276f9291ceSJung-uk Kim && (!batch)) { 12286f9291ceSJung-uk Kim BIO_printf(bio_err, 12296f9291ceSJung-uk Kim "\nPlease enter the following 'extra' attributes\n"); 12306f9291ceSJung-uk Kim BIO_printf(bio_err, 12316f9291ceSJung-uk Kim "to be sent with your certificate request\n"); 123274664626SKris Kennaway } 123374664626SKris Kennaway 123474664626SKris Kennaway i = -1; 1235e71b7053SJung-uk Kim start2: 1236e71b7053SJung-uk Kim for (;;) { 123774664626SKris Kennaway i++; 12386f9291ceSJung-uk Kim if ((attr_sk == NULL) || (sk_CONF_VALUE_num(attr_sk) <= i)) 123974664626SKris Kennaway break; 124074664626SKris Kennaway 1241f579bf8eSKris Kennaway v = sk_CONF_VALUE_value(attr_sk, i); 124274664626SKris Kennaway type = v->name; 124374664626SKris Kennaway if ((nid = OBJ_txt2nid(type)) == NID_undef) 124474664626SKris Kennaway goto start2; 124574664626SKris Kennaway 1246e71b7053SJung-uk Kim if (!join(buf, sizeof(buf), type, "_default", "Name")) 12475c87c606SMark Murray return 0; 12485c87c606SMark Murray if ((def = NCONF_get_string(req_conf, attr_sect, buf)) 12496f9291ceSJung-uk Kim == NULL) { 12505c87c606SMark Murray ERR_clear_error(); 125174664626SKris Kennaway def = ""; 12525c87c606SMark Murray } 12535c87c606SMark Murray 1254e71b7053SJung-uk Kim if (!join(buf, sizeof(buf), type, "_value", "Name")) 1255e71b7053SJung-uk Kim return 0; 12565c87c606SMark Murray if ((value = NCONF_get_string(req_conf, attr_sect, buf)) 12576f9291ceSJung-uk Kim == NULL) { 12585c87c606SMark Murray ERR_clear_error(); 125974664626SKris Kennaway value = NULL; 12605c87c606SMark Murray } 126174664626SKris Kennaway 1262e71b7053SJung-uk Kim if (!join(buf, sizeof(buf), type, "_min", "Name")) 1263e71b7053SJung-uk Kim return 0; 12646f9291ceSJung-uk Kim if (!NCONF_get_number(req_conf, attr_sect, buf, &n_min)) { 1265ab8565e2SSimon L. B. Nielsen ERR_clear_error(); 12665c87c606SMark Murray n_min = -1; 1267ab8565e2SSimon L. B. Nielsen } 126874664626SKris Kennaway 1269e71b7053SJung-uk Kim if (!join(buf, sizeof(buf), type, "_max", "Name")) 1270e71b7053SJung-uk Kim return 0; 12716f9291ceSJung-uk Kim if (!NCONF_get_number(req_conf, attr_sect, buf, &n_max)) { 1272ab8565e2SSimon L. B. Nielsen ERR_clear_error(); 12735c87c606SMark Murray n_max = -1; 1274ab8565e2SSimon L. B. Nielsen } 127574664626SKris Kennaway 1276f579bf8eSKris Kennaway if (!add_attribute_object(req, 12776f9291ceSJung-uk Kim v->value, def, value, nid, n_min, 12786f9291ceSJung-uk Kim n_max, chtype)) 1279f579bf8eSKris Kennaway return 0; 128074664626SKris Kennaway } 128174664626SKris Kennaway } 12826f9291ceSJung-uk Kim } else { 128374664626SKris Kennaway BIO_printf(bio_err, "No template, please set one up.\n"); 1284f579bf8eSKris Kennaway return 0; 128574664626SKris Kennaway } 128674664626SKris Kennaway 1287f579bf8eSKris Kennaway return 1; 128874664626SKris Kennaway 128974664626SKris Kennaway } 129074664626SKris Kennaway 1291f579bf8eSKris Kennaway static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *dn_sk, 12926f9291ceSJung-uk Kim STACK_OF(CONF_VALUE) *attr_sk, int attribs, 12936f9291ceSJung-uk Kim unsigned long chtype) 1294f579bf8eSKris Kennaway { 1295e71b7053SJung-uk Kim int i, spec_char, plus_char; 1296f579bf8eSKris Kennaway char *p, *q; 1297f579bf8eSKris Kennaway char *type; 1298f579bf8eSKris Kennaway CONF_VALUE *v; 1299f579bf8eSKris Kennaway X509_NAME *subj; 1300f579bf8eSKris Kennaway 1301f579bf8eSKris Kennaway subj = X509_REQ_get_subject_name(req); 1302f579bf8eSKris Kennaway 13036f9291ceSJung-uk Kim for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) { 13043b4e3dcbSSimon L. B. Nielsen int mval; 1305f579bf8eSKris Kennaway v = sk_CONF_VALUE_value(dn_sk, i); 1306f579bf8eSKris Kennaway p = q = NULL; 1307f579bf8eSKris Kennaway type = v->name; 13086f9291ceSJung-uk Kim /* 13096f9291ceSJung-uk Kim * Skip past any leading X. X: X, etc to allow for multiple instances 1310f579bf8eSKris Kennaway */ 1311e71b7053SJung-uk Kim for (p = v->name; *p; p++) { 1312ddd58736SKris Kennaway #ifndef CHARSET_EBCDIC 1313b077aed3SPierre Pronchery spec_char = (*p == ':' || *p == ',' || *p == '.'); 1314ddd58736SKris Kennaway #else 1315b077aed3SPierre Pronchery spec_char = (*p == os_toascii[':'] || *p == os_toascii[','] 1316b077aed3SPierre Pronchery || *p == os_toascii['.']); 1317ddd58736SKris Kennaway #endif 1318e71b7053SJung-uk Kim if (spec_char) { 1319f579bf8eSKris Kennaway p++; 13206f9291ceSJung-uk Kim if (*p) 13216f9291ceSJung-uk Kim type = p; 1322f579bf8eSKris Kennaway break; 1323f579bf8eSKris Kennaway } 1324e71b7053SJung-uk Kim } 13253b4e3dcbSSimon L. B. Nielsen #ifndef CHARSET_EBCDIC 1326e71b7053SJung-uk Kim plus_char = (*type == '+'); 13273b4e3dcbSSimon L. B. Nielsen #else 1328e71b7053SJung-uk Kim plus_char = (*type == os_toascii['+']); 13293b4e3dcbSSimon L. B. Nielsen #endif 1330e71b7053SJung-uk Kim if (plus_char) { 1331aeb5019cSJung-uk Kim type++; 13323b4e3dcbSSimon L. B. Nielsen mval = -1; 1333e71b7053SJung-uk Kim } else { 13343b4e3dcbSSimon L. B. Nielsen mval = 0; 1335e71b7053SJung-uk Kim } 13365c87c606SMark Murray if (!X509_NAME_add_entry_by_txt(subj, type, chtype, 13376f9291ceSJung-uk Kim (unsigned char *)v->value, -1, -1, 13386f9291ceSJung-uk Kim mval)) 13396f9291ceSJung-uk Kim return 0; 1340f579bf8eSKris Kennaway 1341f579bf8eSKris Kennaway } 1342f579bf8eSKris Kennaway 13436f9291ceSJung-uk Kim if (!X509_NAME_entry_count(subj)) { 1344b077aed3SPierre Pronchery BIO_printf(bio_err, "Error: No objects specified in config file\n"); 1345f579bf8eSKris Kennaway return 0; 1346f579bf8eSKris Kennaway } 13476f9291ceSJung-uk Kim if (attribs) { 13486f9291ceSJung-uk Kim for (i = 0; i < sk_CONF_VALUE_num(attr_sk); i++) { 1349f579bf8eSKris Kennaway v = sk_CONF_VALUE_value(attr_sk, i); 13505c87c606SMark Murray if (!X509_REQ_add1_attr_by_txt(req, v->name, chtype, 13516f9291ceSJung-uk Kim (unsigned char *)v->value, -1)) 13526f9291ceSJung-uk Kim return 0; 1353f579bf8eSKris Kennaway } 1354f579bf8eSKris Kennaway } 1355f579bf8eSKris Kennaway return 1; 1356f579bf8eSKris Kennaway } 1357f579bf8eSKris Kennaway 13586f9291ceSJung-uk Kim static int add_DN_object(X509_NAME *n, char *text, const char *def, 13596f9291ceSJung-uk Kim char *value, int nid, int n_min, int n_max, 13606f9291ceSJung-uk Kim unsigned long chtype, int mval) 136174664626SKris Kennaway { 1362e71b7053SJung-uk Kim int ret = 0; 1363e71b7053SJung-uk Kim char buf[1024]; 136474664626SKris Kennaway 1365e71b7053SJung-uk Kim ret = build_data(text, def, value, n_min, n_max, buf, sizeof(buf), 1366e71b7053SJung-uk Kim "DN value", "DN default"); 1367e71b7053SJung-uk Kim if ((ret == 0) || (ret == 1)) 1368e71b7053SJung-uk Kim return ret; 1369e71b7053SJung-uk Kim ret = 1; 137094ad176cSJung-uk Kim 13715c87c606SMark Murray if (!X509_NAME_add_entry_by_NID(n, nid, chtype, 13726f9291ceSJung-uk Kim (unsigned char *)buf, -1, -1, mval)) 1373e71b7053SJung-uk Kim ret = 0; 1374e71b7053SJung-uk Kim 1375e71b7053SJung-uk Kim return ret; 137674664626SKris Kennaway } 137774664626SKris Kennaway 13783b4e3dcbSSimon L. B. Nielsen static int add_attribute_object(X509_REQ *req, char *text, const char *def, 13793b4e3dcbSSimon L. B. Nielsen char *value, int nid, int n_min, 13805c87c606SMark Murray int n_max, unsigned long chtype) 1381f579bf8eSKris Kennaway { 1382e71b7053SJung-uk Kim int ret = 0; 1383e71b7053SJung-uk Kim char buf[1024]; 138474664626SKris Kennaway 1385e71b7053SJung-uk Kim ret = build_data(text, def, value, n_min, n_max, buf, sizeof(buf), 1386e71b7053SJung-uk Kim "Attribute value", "Attribute default"); 1387e71b7053SJung-uk Kim if ((ret == 0) || (ret == 1)) 1388e71b7053SJung-uk Kim return ret; 1389e71b7053SJung-uk Kim ret = 1; 1390e71b7053SJung-uk Kim 1391e71b7053SJung-uk Kim if (!X509_REQ_add1_attr_by_NID(req, nid, chtype, 1392e71b7053SJung-uk Kim (unsigned char *)buf, -1)) { 1393e71b7053SJung-uk Kim BIO_printf(bio_err, "Error adding attribute\n"); 1394e71b7053SJung-uk Kim ret = 0; 1395e71b7053SJung-uk Kim } 1396e71b7053SJung-uk Kim 1397e71b7053SJung-uk Kim return ret; 1398e71b7053SJung-uk Kim } 1399e71b7053SJung-uk Kim 1400b077aed3SPierre Pronchery static int build_data(char *text, const char *def, char *value, 1401b077aed3SPierre Pronchery int n_min, int n_max, char *buf, const int buf_size, 1402b077aed3SPierre Pronchery const char *desc1, const char *desc2) 1403e71b7053SJung-uk Kim { 1404e71b7053SJung-uk Kim int i; 1405f579bf8eSKris Kennaway start: 14066f9291ceSJung-uk Kim if (!batch) 14076f9291ceSJung-uk Kim BIO_printf(bio_err, "%s [%s]:", text, def); 1408f579bf8eSKris Kennaway (void)BIO_flush(bio_err); 14096f9291ceSJung-uk Kim if (value != NULL) { 1410e71b7053SJung-uk Kim if (!join(buf, buf_size, value, "\n", desc1)) 1411e71b7053SJung-uk Kim return 0; 1412f579bf8eSKris Kennaway BIO_printf(bio_err, "%s\n", value); 14136f9291ceSJung-uk Kim } else { 1414f579bf8eSKris Kennaway buf[0] = '\0'; 14156f9291ceSJung-uk Kim if (!batch) { 1416e71b7053SJung-uk Kim if (!fgets(buf, buf_size, stdin)) 14176a599222SSimon L. B. Nielsen return 0; 14186f9291ceSJung-uk Kim } else { 14195c87c606SMark Murray buf[0] = '\n'; 14205c87c606SMark Murray buf[1] = '\0'; 14215c87c606SMark Murray } 1422f579bf8eSKris Kennaway } 142374664626SKris Kennaway 14246f9291ceSJung-uk Kim if (buf[0] == '\0') 1425e71b7053SJung-uk Kim return 0; 1426e71b7053SJung-uk Kim if (buf[0] == '\n') { 1427f579bf8eSKris Kennaway if ((def == NULL) || (def[0] == '\0')) 1428e71b7053SJung-uk Kim return 1; 1429e71b7053SJung-uk Kim if (!join(buf, buf_size, def, "\n", desc2)) 1430e71b7053SJung-uk Kim return 0; 1431e71b7053SJung-uk Kim } else if ((buf[0] == '.') && (buf[1] == '\n')) { 1432e71b7053SJung-uk Kim return 1; 1433e71b7053SJung-uk Kim } 143474664626SKris Kennaway 1435f579bf8eSKris Kennaway i = strlen(buf); 14366f9291ceSJung-uk Kim if (buf[i - 1] != '\n') { 1437b077aed3SPierre Pronchery BIO_printf(bio_err, "Missing newline at end of input\n"); 1438e71b7053SJung-uk Kim return 0; 1439f579bf8eSKris Kennaway } 1440f579bf8eSKris Kennaway buf[--i] = '\0'; 1441ddd58736SKris Kennaway #ifdef CHARSET_EBCDIC 1442ddd58736SKris Kennaway ebcdic2ascii(buf, buf, i); 1443ddd58736SKris Kennaway #endif 14446f9291ceSJung-uk Kim if (!req_check_len(i, n_min, n_max)) { 144594ad176cSJung-uk Kim if (batch || value) 144694ad176cSJung-uk Kim return 0; 144794ad176cSJung-uk Kim goto start; 144894ad176cSJung-uk Kim } 1449e71b7053SJung-uk Kim return 2; 145074664626SKris Kennaway } 145174664626SKris Kennaway 14525c87c606SMark Murray static int req_check_len(int len, int n_min, int n_max) 145374664626SKris Kennaway { 1454b077aed3SPierre Pronchery if (n_min > 0 && len < n_min) { 14556f9291ceSJung-uk Kim BIO_printf(bio_err, 1456b077aed3SPierre Pronchery "String too short, must be at least %d bytes long\n", n_min); 1457e71b7053SJung-uk Kim return 0; 145874664626SKris Kennaway } 1459b077aed3SPierre Pronchery if (n_max >= 0 && len > n_max) { 14606f9291ceSJung-uk Kim BIO_printf(bio_err, 1461b077aed3SPierre Pronchery "String too long, must be at most %d bytes long\n", n_max); 1462e71b7053SJung-uk Kim return 0; 146374664626SKris Kennaway } 1464e71b7053SJung-uk Kim return 1; 146574664626SKris Kennaway } 146674664626SKris Kennaway 146774664626SKris Kennaway /* Check if the end of a string matches 'end' */ 14683b4e3dcbSSimon L. B. Nielsen static int check_end(const char *str, const char *end) 146974664626SKris Kennaway { 1470e71b7053SJung-uk Kim size_t elen, slen; 14713b4e3dcbSSimon L. B. Nielsen const char *tmp; 1472e71b7053SJung-uk Kim 147374664626SKris Kennaway elen = strlen(end); 147474664626SKris Kennaway slen = strlen(str); 14756f9291ceSJung-uk Kim if (elen > slen) 14766f9291ceSJung-uk Kim return 1; 147774664626SKris Kennaway tmp = str + slen - elen; 147874664626SKris Kennaway return strcmp(tmp, end); 147974664626SKris Kennaway } 14801f13597dSJung-uk Kim 1481e71b7053SJung-uk Kim /* 1482e71b7053SJung-uk Kim * Merge the two strings together into the result buffer checking for 1483e71b7053SJung-uk Kim * overflow and producing an error message if there is. 1484e71b7053SJung-uk Kim */ 1485e71b7053SJung-uk Kim static int join(char buf[], size_t buf_size, const char *name, 1486e71b7053SJung-uk Kim const char *tail, const char *desc) 1487e71b7053SJung-uk Kim { 1488e71b7053SJung-uk Kim const size_t name_len = strlen(name), tail_len = strlen(tail); 1489e71b7053SJung-uk Kim 1490e71b7053SJung-uk Kim if (name_len + tail_len + 1 > buf_size) { 1491e71b7053SJung-uk Kim BIO_printf(bio_err, "%s '%s' too long\n", desc, name); 1492e71b7053SJung-uk Kim return 0; 1493e71b7053SJung-uk Kim } 1494e71b7053SJung-uk Kim memcpy(buf, name, name_len); 1495e71b7053SJung-uk Kim memcpy(buf + name_len, tail, tail_len + 1); 1496e71b7053SJung-uk Kim return 1; 1497e71b7053SJung-uk Kim } 1498e71b7053SJung-uk Kim 1499e71b7053SJung-uk Kim static EVP_PKEY_CTX *set_keygen_ctx(const char *gstr, 1500b077aed3SPierre Pronchery char **pkeytype, long *pkeylen, 1501b077aed3SPierre Pronchery ENGINE *keygen_engine) 15021f13597dSJung-uk Kim { 15031f13597dSJung-uk Kim EVP_PKEY_CTX *gctx = NULL; 15041f13597dSJung-uk Kim EVP_PKEY *param = NULL; 15051f13597dSJung-uk Kim long keylen = -1; 15061f13597dSJung-uk Kim BIO *pbio = NULL; 1507b077aed3SPierre Pronchery const char *keytype = NULL; 1508b077aed3SPierre Pronchery size_t keytypelen = 0; 1509b077aed3SPierre Pronchery int expect_paramfile = 0; 15101f13597dSJung-uk Kim const char *paramfile = NULL; 15111f13597dSJung-uk Kim 1512b077aed3SPierre Pronchery /* Treat the first part of gstr, and only that */ 15136f9291ceSJung-uk Kim if (gstr == NULL) { 1514b077aed3SPierre Pronchery /* 1515b077aed3SPierre Pronchery * Special case: when no string given, default to RSA and the 1516b077aed3SPierre Pronchery * key length given by |*pkeylen|. 1517b077aed3SPierre Pronchery */ 1518b077aed3SPierre Pronchery keytype = "RSA"; 15191f13597dSJung-uk Kim keylen = *pkeylen; 15206f9291ceSJung-uk Kim } else if (gstr[0] >= '0' && gstr[0] <= '9') { 1521b077aed3SPierre Pronchery /* Special case: only keylength given from string, so default to RSA */ 1522b077aed3SPierre Pronchery keytype = "RSA"; 1523b077aed3SPierre Pronchery /* The second part treatment will do the rest */ 1524e71b7053SJung-uk Kim } else { 15251f13597dSJung-uk Kim const char *p = strchr(gstr, ':'); 15261f13597dSJung-uk Kim int len; 15271f13597dSJung-uk Kim 1528e71b7053SJung-uk Kim if (p != NULL) 15291f13597dSJung-uk Kim len = p - gstr; 15301f13597dSJung-uk Kim else 15311f13597dSJung-uk Kim len = strlen(gstr); 15321f13597dSJung-uk Kim 1533b077aed3SPierre Pronchery if (strncmp(gstr, "param", len) == 0) { 1534b077aed3SPierre Pronchery expect_paramfile = 1; 1535b077aed3SPierre Pronchery if (p == NULL) { 1536b077aed3SPierre Pronchery BIO_printf(bio_err, 1537b077aed3SPierre Pronchery "Parameter file requested but no path given: %s\n", 1538b077aed3SPierre Pronchery gstr); 15391f13597dSJung-uk Kim return NULL; 15401f13597dSJung-uk Kim } 1541e71b7053SJung-uk Kim } else { 1542b077aed3SPierre Pronchery keytype = gstr; 1543b077aed3SPierre Pronchery keytypelen = len; 1544e71b7053SJung-uk Kim } 1545b077aed3SPierre Pronchery 1546b077aed3SPierre Pronchery if (p != NULL) 1547b077aed3SPierre Pronchery gstr = gstr + len + 1; 1548b077aed3SPierre Pronchery else 1549b077aed3SPierre Pronchery gstr = NULL; 15501f13597dSJung-uk Kim } 1551b077aed3SPierre Pronchery 1552b077aed3SPierre Pronchery /* Treat the second part of gstr, if there is one */ 1553b077aed3SPierre Pronchery if (gstr != NULL) { 1554b077aed3SPierre Pronchery /* If the second part starts with a digit, we assume it's a size */ 1555b077aed3SPierre Pronchery if (!expect_paramfile && gstr[0] >= '0' && gstr[0] <= '9') 1556b077aed3SPierre Pronchery keylen = atol(gstr); 1557b077aed3SPierre Pronchery else 1558b077aed3SPierre Pronchery paramfile = gstr; 1559e71b7053SJung-uk Kim } 15601f13597dSJung-uk Kim 1561e71b7053SJung-uk Kim if (paramfile != NULL) { 15621f13597dSJung-uk Kim pbio = BIO_new_file(paramfile, "r"); 1563e71b7053SJung-uk Kim if (pbio == NULL) { 1564b077aed3SPierre Pronchery BIO_printf(bio_err, "Cannot open parameter file %s\n", paramfile); 15651f13597dSJung-uk Kim return NULL; 15661f13597dSJung-uk Kim } 15671f13597dSJung-uk Kim param = PEM_read_bio_Parameters(pbio, NULL); 15681f13597dSJung-uk Kim 1569e71b7053SJung-uk Kim if (param == NULL) { 15701f13597dSJung-uk Kim X509 *x; 1571e71b7053SJung-uk Kim 15721f13597dSJung-uk Kim (void)BIO_reset(pbio); 15731f13597dSJung-uk Kim x = PEM_read_bio_X509(pbio, NULL, NULL, NULL); 1574e71b7053SJung-uk Kim if (x != NULL) { 15751f13597dSJung-uk Kim param = X509_get_pubkey(x); 15761f13597dSJung-uk Kim X509_free(x); 15771f13597dSJung-uk Kim } 15781f13597dSJung-uk Kim } 15791f13597dSJung-uk Kim 15801f13597dSJung-uk Kim BIO_free(pbio); 15811f13597dSJung-uk Kim 1582e71b7053SJung-uk Kim if (param == NULL) { 1583e71b7053SJung-uk Kim BIO_printf(bio_err, "Error reading parameter file %s\n", paramfile); 15841f13597dSJung-uk Kim return NULL; 15851f13597dSJung-uk Kim } 1586b077aed3SPierre Pronchery if (keytype == NULL) { 1587b077aed3SPierre Pronchery keytype = EVP_PKEY_get0_type_name(param); 1588b077aed3SPierre Pronchery if (keytype == NULL) { 1589b077aed3SPierre Pronchery EVP_PKEY_free(param); 1590b077aed3SPierre Pronchery BIO_puts(bio_err, "Unable to determine key type\n"); 1591b077aed3SPierre Pronchery return NULL; 1592b077aed3SPierre Pronchery } 1593b077aed3SPierre Pronchery } 1594b077aed3SPierre Pronchery } 1595b077aed3SPierre Pronchery 1596b077aed3SPierre Pronchery if (keytypelen > 0) 1597b077aed3SPierre Pronchery *pkeytype = OPENSSL_strndup(keytype, keytypelen); 1598b077aed3SPierre Pronchery else 1599b077aed3SPierre Pronchery *pkeytype = OPENSSL_strdup(keytype); 1600b077aed3SPierre Pronchery 1601b077aed3SPierre Pronchery if (*pkeytype == NULL) { 1602b077aed3SPierre Pronchery BIO_printf(bio_err, "Out of memory\n"); 16031f13597dSJung-uk Kim EVP_PKEY_free(param); 16041f13597dSJung-uk Kim return NULL; 16051f13597dSJung-uk Kim } 16061f13597dSJung-uk Kim 1607b077aed3SPierre Pronchery if (keylen >= 0) 1608b077aed3SPierre Pronchery *pkeylen = keylen; 16091f13597dSJung-uk Kim 1610e71b7053SJung-uk Kim if (param != NULL) { 1611b077aed3SPierre Pronchery if (!EVP_PKEY_is_a(param, *pkeytype)) { 1612b077aed3SPierre Pronchery BIO_printf(bio_err, "Key type does not match parameters\n"); 1613b077aed3SPierre Pronchery EVP_PKEY_free(param); 1614b077aed3SPierre Pronchery return NULL; 1615b077aed3SPierre Pronchery } 1616b077aed3SPierre Pronchery 1617b077aed3SPierre Pronchery if (keygen_engine != NULL) 16181f13597dSJung-uk Kim gctx = EVP_PKEY_CTX_new(param, keygen_engine); 1619b077aed3SPierre Pronchery else 1620b077aed3SPierre Pronchery gctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(), 1621b077aed3SPierre Pronchery param, app_get0_propq()); 1622b077aed3SPierre Pronchery *pkeylen = EVP_PKEY_get_bits(param); 16231f13597dSJung-uk Kim EVP_PKEY_free(param); 1624e71b7053SJung-uk Kim } else { 1625b077aed3SPierre Pronchery if (keygen_engine != NULL) { 1626b077aed3SPierre Pronchery int pkey_id = get_legacy_pkey_id(app_get0_libctx(), *pkeytype, 1627b077aed3SPierre Pronchery keygen_engine); 1628b077aed3SPierre Pronchery 1629b077aed3SPierre Pronchery if (pkey_id != NID_undef) 1630b077aed3SPierre Pronchery gctx = EVP_PKEY_CTX_new_id(pkey_id, keygen_engine); 1631b077aed3SPierre Pronchery } else { 1632b077aed3SPierre Pronchery gctx = EVP_PKEY_CTX_new_from_name(app_get0_libctx(), 1633b077aed3SPierre Pronchery *pkeytype, app_get0_propq()); 1634b077aed3SPierre Pronchery } 1635e71b7053SJung-uk Kim } 16361f13597dSJung-uk Kim 1637e71b7053SJung-uk Kim if (gctx == NULL) { 1638e71b7053SJung-uk Kim BIO_puts(bio_err, "Error allocating keygen context\n"); 16391f13597dSJung-uk Kim return NULL; 16401f13597dSJung-uk Kim } 16411f13597dSJung-uk Kim 16426f9291ceSJung-uk Kim if (EVP_PKEY_keygen_init(gctx) <= 0) { 1643e71b7053SJung-uk Kim BIO_puts(bio_err, "Error initializing keygen context\n"); 1644e71b7053SJung-uk Kim EVP_PKEY_CTX_free(gctx); 16451f13597dSJung-uk Kim return NULL; 16461f13597dSJung-uk Kim } 1647b077aed3SPierre Pronchery if (keylen == -1 && (EVP_PKEY_CTX_is_a(gctx, "RSA") 1648b077aed3SPierre Pronchery || EVP_PKEY_CTX_is_a(gctx, "RSA-PSS"))) 1649b077aed3SPierre Pronchery keylen = *pkeylen; 1650b077aed3SPierre Pronchery 1651b077aed3SPierre Pronchery if (keylen != -1) { 1652b077aed3SPierre Pronchery OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END }; 1653b077aed3SPierre Pronchery size_t bits = keylen; 1654b077aed3SPierre Pronchery 1655b077aed3SPierre Pronchery params[0] = 1656b077aed3SPierre Pronchery OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_BITS, &bits); 1657b077aed3SPierre Pronchery if (EVP_PKEY_CTX_set_params(gctx, params) <= 0) { 1658b077aed3SPierre Pronchery BIO_puts(bio_err, "Error setting keysize\n"); 16591f13597dSJung-uk Kim EVP_PKEY_CTX_free(gctx); 16601f13597dSJung-uk Kim return NULL; 16611f13597dSJung-uk Kim } 16621f13597dSJung-uk Kim } 16631f13597dSJung-uk Kim 16641f13597dSJung-uk Kim return gctx; 16651f13597dSJung-uk Kim } 16661f13597dSJung-uk Kim 16671f13597dSJung-uk Kim static int genpkey_cb(EVP_PKEY_CTX *ctx) 16681f13597dSJung-uk Kim { 16691f13597dSJung-uk Kim char c = '*'; 16701f13597dSJung-uk Kim BIO *b = EVP_PKEY_CTX_get_app_data(ctx); 16711f13597dSJung-uk Kim int p; 16721f13597dSJung-uk Kim p = EVP_PKEY_CTX_get_keygen_info(ctx, 0); 16736f9291ceSJung-uk Kim if (p == 0) 16746f9291ceSJung-uk Kim c = '.'; 16756f9291ceSJung-uk Kim if (p == 1) 16766f9291ceSJung-uk Kim c = '+'; 16776f9291ceSJung-uk Kim if (p == 2) 16786f9291ceSJung-uk Kim c = '*'; 16796f9291ceSJung-uk Kim if (p == 3) 16806f9291ceSJung-uk Kim c = '\n'; 16811f13597dSJung-uk Kim BIO_write(b, &c, 1); 16821f13597dSJung-uk Kim (void)BIO_flush(b); 16831f13597dSJung-uk Kim return 1; 16841f13597dSJung-uk Kim } 1685