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