16f9291ceSJung-uk Kim /* 2*da327cd2SJung-uk Kim * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. 3e71b7053SJung-uk Kim * 4e71b7053SJung-uk Kim * Licensed under the OpenSSL license (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" 1774664626SKris Kennaway #include <openssl/bio.h> 1874664626SKris Kennaway #include <openssl/evp.h> 1974664626SKris Kennaway #include <openssl/conf.h> 2074664626SKris Kennaway #include <openssl/err.h> 2174664626SKris Kennaway #include <openssl/asn1.h> 2274664626SKris Kennaway #include <openssl/x509.h> 2374664626SKris Kennaway #include <openssl/x509v3.h> 2474664626SKris Kennaway #include <openssl/objects.h> 2574664626SKris Kennaway #include <openssl/pem.h> 263b4e3dcbSSimon L. B. Nielsen #include <openssl/bn.h> 27e71b7053SJung-uk Kim #include <openssl/lhash.h> 283b4e3dcbSSimon L. B. Nielsen #ifndef OPENSSL_NO_RSA 293b4e3dcbSSimon L. B. Nielsen # include <openssl/rsa.h> 303b4e3dcbSSimon L. B. Nielsen #endif 313b4e3dcbSSimon L. B. Nielsen #ifndef OPENSSL_NO_DSA 323b4e3dcbSSimon L. B. Nielsen # include <openssl/dsa.h> 333b4e3dcbSSimon L. B. Nielsen #endif 3474664626SKris Kennaway 3574664626SKris Kennaway #define SECTION "req" 3674664626SKris Kennaway 3774664626SKris Kennaway #define BITS "default_bits" 3874664626SKris Kennaway #define KEYFILE "default_keyfile" 39f579bf8eSKris Kennaway #define PROMPT "prompt" 4074664626SKris Kennaway #define DISTINGUISHED_NAME "distinguished_name" 4174664626SKris Kennaway #define ATTRIBUTES "attributes" 4274664626SKris Kennaway #define V3_EXTENSIONS "x509_extensions" 43f579bf8eSKris Kennaway #define REQ_EXTENSIONS "req_extensions" 44f579bf8eSKris Kennaway #define STRING_MASK "string_mask" 455c87c606SMark Murray #define UTF8_IN "utf8" 4674664626SKris Kennaway 474c6a0400SJung-uk Kim #define DEFAULT_KEY_LENGTH 2048 484c6a0400SJung-uk Kim #define MIN_KEY_LENGTH 512 4974664626SKris Kennaway 503b4e3dcbSSimon L. B. Nielsen static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *dn, int mutlirdn, 513b4e3dcbSSimon L. B. Nielsen int attribs, unsigned long chtype); 52e71b7053SJung-uk Kim static int build_subject(X509_REQ *req, const char *subj, unsigned long chtype, 533b4e3dcbSSimon L. B. Nielsen int multirdn); 54f579bf8eSKris Kennaway static int prompt_info(X509_REQ *req, 55e71b7053SJung-uk Kim STACK_OF(CONF_VALUE) *dn_sk, const char *dn_sect, 56e71b7053SJung-uk Kim STACK_OF(CONF_VALUE) *attr_sk, const char *attr_sect, 576f9291ceSJung-uk Kim int attribs, unsigned long chtype); 58f579bf8eSKris Kennaway static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *sk, 595c87c606SMark Murray STACK_OF(CONF_VALUE) *attr, int attribs, 605c87c606SMark Murray unsigned long chtype); 613b4e3dcbSSimon L. B. Nielsen static int add_attribute_object(X509_REQ *req, char *text, const char *def, 626f9291ceSJung-uk Kim char *value, int nid, int n_min, int n_max, 636f9291ceSJung-uk Kim unsigned long chtype); 646f9291ceSJung-uk Kim static int add_DN_object(X509_NAME *n, char *text, const char *def, 656f9291ceSJung-uk Kim char *value, int nid, int n_min, int n_max, 666f9291ceSJung-uk Kim unsigned long chtype, int mval); 671f13597dSJung-uk Kim static int genpkey_cb(EVP_PKEY_CTX *ctx); 68e71b7053SJung-uk Kim static int build_data(char *text, const char *def, 69e71b7053SJung-uk Kim char *value, int n_min, int n_max, 70e71b7053SJung-uk Kim char *buf, const int buf_size, 71e71b7053SJung-uk Kim const char *desc1, const char *desc2 72e71b7053SJung-uk Kim ); 735c87c606SMark Murray static int req_check_len(int len, int n_min, int n_max); 743b4e3dcbSSimon L. B. Nielsen static int check_end(const char *str, const char *end); 75e71b7053SJung-uk Kim static int join(char buf[], size_t buf_size, const char *name, 76e71b7053SJung-uk Kim const char *tail, const char *desc); 77e71b7053SJung-uk Kim static EVP_PKEY_CTX *set_keygen_ctx(const char *gstr, 786f9291ceSJung-uk Kim int *pkey_type, long *pkeylen, 796f9291ceSJung-uk Kim char **palgnam, ENGINE *keygen_engine); 805c87c606SMark Murray static CONF *req_conf = NULL; 81e71b7053SJung-uk Kim static CONF *addext_conf = NULL; 825c87c606SMark Murray static int batch = 0; 8374664626SKris Kennaway 84e71b7053SJung-uk Kim typedef enum OPTION_choice { 85e71b7053SJung-uk Kim OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, 86e71b7053SJung-uk Kim OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_KEYGEN_ENGINE, OPT_KEY, 87e71b7053SJung-uk Kim OPT_PUBKEY, OPT_NEW, OPT_CONFIG, OPT_KEYFORM, OPT_IN, OPT_OUT, 88e71b7053SJung-uk Kim OPT_KEYOUT, OPT_PASSIN, OPT_PASSOUT, OPT_NEWKEY, 89e71b7053SJung-uk Kim OPT_PKEYOPT, OPT_SIGOPT, OPT_BATCH, OPT_NEWHDR, OPT_MODULUS, 90e71b7053SJung-uk Kim OPT_VERIFY, OPT_NODES, OPT_NOOUT, OPT_VERBOSE, OPT_UTF8, 91e71b7053SJung-uk Kim OPT_NAMEOPT, OPT_REQOPT, OPT_SUBJ, OPT_SUBJECT, OPT_TEXT, OPT_X509, 92e71b7053SJung-uk Kim OPT_MULTIVALUE_RDN, OPT_DAYS, OPT_SET_SERIAL, OPT_ADDEXT, OPT_EXTENSIONS, 93e71b7053SJung-uk Kim OPT_REQEXTS, OPT_PRECERT, OPT_MD, 94e71b7053SJung-uk Kim OPT_R_ENUM 95e71b7053SJung-uk Kim } OPTION_CHOICE; 96f579bf8eSKris Kennaway 97e71b7053SJung-uk Kim const OPTIONS req_options[] = { 98e71b7053SJung-uk Kim {"help", OPT_HELP, '-', "Display this summary"}, 99e71b7053SJung-uk Kim {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"}, 100e71b7053SJung-uk Kim {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"}, 101e71b7053SJung-uk Kim {"in", OPT_IN, '<', "Input file"}, 102e71b7053SJung-uk Kim {"out", OPT_OUT, '>', "Output file"}, 103e71b7053SJung-uk Kim {"key", OPT_KEY, 's', "Private key to use"}, 104e71b7053SJung-uk Kim {"keyform", OPT_KEYFORM, 'f', "Key file format"}, 105e71b7053SJung-uk Kim {"pubkey", OPT_PUBKEY, '-', "Output public key"}, 106e71b7053SJung-uk Kim {"new", OPT_NEW, '-', "New request"}, 107e71b7053SJung-uk Kim {"config", OPT_CONFIG, '<', "Request template file"}, 108e71b7053SJung-uk Kim {"keyout", OPT_KEYOUT, '>', "File to send the key to"}, 109e71b7053SJung-uk Kim {"passin", OPT_PASSIN, 's', "Private key password source"}, 110e71b7053SJung-uk Kim {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, 111e71b7053SJung-uk Kim OPT_R_OPTIONS, 112e71b7053SJung-uk Kim {"newkey", OPT_NEWKEY, 's', "Specify as type:bits"}, 113e71b7053SJung-uk Kim {"pkeyopt", OPT_PKEYOPT, 's', "Public key options as opt:value"}, 114e71b7053SJung-uk Kim {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"}, 115e71b7053SJung-uk Kim {"batch", OPT_BATCH, '-', 116e71b7053SJung-uk Kim "Do not ask anything during request generation"}, 117e71b7053SJung-uk Kim {"newhdr", OPT_NEWHDR, '-', "Output \"NEW\" in the header lines"}, 118e71b7053SJung-uk Kim {"modulus", OPT_MODULUS, '-', "RSA modulus"}, 119e71b7053SJung-uk Kim {"verify", OPT_VERIFY, '-', "Verify signature on REQ"}, 120e71b7053SJung-uk Kim {"nodes", OPT_NODES, '-', "Don't encrypt the output key"}, 121e71b7053SJung-uk Kim {"noout", OPT_NOOUT, '-', "Do not output REQ"}, 122e71b7053SJung-uk Kim {"verbose", OPT_VERBOSE, '-', "Verbose output"}, 123e71b7053SJung-uk Kim {"utf8", OPT_UTF8, '-', "Input characters are UTF8 (default ASCII)"}, 124e71b7053SJung-uk Kim {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"}, 125e71b7053SJung-uk Kim {"reqopt", OPT_REQOPT, 's', "Various request text options"}, 126e71b7053SJung-uk Kim {"text", OPT_TEXT, '-', "Text form of request"}, 127e71b7053SJung-uk Kim {"x509", OPT_X509, '-', 128e71b7053SJung-uk Kim "Output a x509 structure instead of a cert request"}, 129e71b7053SJung-uk Kim {OPT_MORE_STR, 1, 1, "(Required by some CA's)"}, 130e71b7053SJung-uk Kim {"subj", OPT_SUBJ, 's', "Set or modify request subject"}, 131e71b7053SJung-uk Kim {"subject", OPT_SUBJECT, '-', "Output the request's subject"}, 132e71b7053SJung-uk Kim {"multivalue-rdn", OPT_MULTIVALUE_RDN, '-', 133e71b7053SJung-uk Kim "Enable support for multivalued RDNs"}, 134e71b7053SJung-uk Kim {"days", OPT_DAYS, 'p', "Number of days cert is valid for"}, 135e71b7053SJung-uk Kim {"set_serial", OPT_SET_SERIAL, 's', "Serial number to use"}, 136e71b7053SJung-uk Kim {"addext", OPT_ADDEXT, 's', 137e71b7053SJung-uk Kim "Additional cert extension key=value pair (may be given more than once)"}, 138e71b7053SJung-uk Kim {"extensions", OPT_EXTENSIONS, 's', 139e71b7053SJung-uk Kim "Cert extension section (override value in config file)"}, 140e71b7053SJung-uk Kim {"reqexts", OPT_REQEXTS, 's', 141e71b7053SJung-uk Kim "Request extension section (override value in config file)"}, 142e71b7053SJung-uk Kim {"precert", OPT_PRECERT, '-', "Add a poison extension (implies -new)"}, 143e71b7053SJung-uk Kim {"", OPT_MD, '-', "Any supported digest"}, 144e71b7053SJung-uk Kim #ifndef OPENSSL_NO_ENGINE 145e71b7053SJung-uk Kim {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, 146e71b7053SJung-uk Kim {"keygen_engine", OPT_KEYGEN_ENGINE, 's', 147e71b7053SJung-uk Kim "Specify engine to be used for key generation operations"}, 148e71b7053SJung-uk Kim #endif 149e71b7053SJung-uk Kim {NULL} 150e71b7053SJung-uk Kim }; 151e71b7053SJung-uk Kim 152e71b7053SJung-uk Kim 153e71b7053SJung-uk Kim /* 154e71b7053SJung-uk Kim * An LHASH of strings, where each string is an extension name. 155e71b7053SJung-uk Kim */ 156e71b7053SJung-uk Kim static unsigned long ext_name_hash(const OPENSSL_STRING *a) 15774664626SKris Kennaway { 158e71b7053SJung-uk Kim return OPENSSL_LH_strhash((const char *)a); 159e71b7053SJung-uk Kim } 160e71b7053SJung-uk Kim 161e71b7053SJung-uk Kim static int ext_name_cmp(const OPENSSL_STRING *a, const OPENSSL_STRING *b) 162e71b7053SJung-uk Kim { 163e71b7053SJung-uk Kim return strcmp((const char *)a, (const char *)b); 164e71b7053SJung-uk Kim } 165e71b7053SJung-uk Kim 166e71b7053SJung-uk Kim static void exts_cleanup(OPENSSL_STRING *x) 167e71b7053SJung-uk Kim { 168e71b7053SJung-uk Kim OPENSSL_free((char *)x); 169e71b7053SJung-uk Kim } 170e71b7053SJung-uk Kim 171e71b7053SJung-uk Kim /* 172e71b7053SJung-uk Kim * Is the |kv| key already duplicated? This is remarkably tricky to get 173e71b7053SJung-uk Kim * right. Return 0 if unique, -1 on runtime error; 1 if found or a syntax 174e71b7053SJung-uk Kim * error. 175e71b7053SJung-uk Kim */ 176e71b7053SJung-uk Kim static int duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv) 177e71b7053SJung-uk Kim { 178e71b7053SJung-uk Kim char *p; 179e71b7053SJung-uk Kim size_t off; 180e71b7053SJung-uk Kim 181e71b7053SJung-uk Kim /* Check syntax. */ 182e71b7053SJung-uk Kim /* Skip leading whitespace, make a copy. */ 183e71b7053SJung-uk Kim while (*kv && isspace(*kv)) 184e71b7053SJung-uk Kim if (*++kv == '\0') 185e71b7053SJung-uk Kim return 1; 186e71b7053SJung-uk Kim if ((p = strchr(kv, '=')) == NULL) 187e71b7053SJung-uk Kim return 1; 188e71b7053SJung-uk Kim off = p - kv; 189e71b7053SJung-uk Kim if ((kv = OPENSSL_strdup(kv)) == NULL) 190e71b7053SJung-uk Kim return -1; 191e71b7053SJung-uk Kim 192e71b7053SJung-uk Kim /* Skip trailing space before the equal sign. */ 193e71b7053SJung-uk Kim for (p = kv + off; p > kv; --p) 194e71b7053SJung-uk Kim if (!isspace(p[-1])) 195e71b7053SJung-uk Kim break; 196e71b7053SJung-uk Kim if (p == kv) { 197e71b7053SJung-uk Kim OPENSSL_free(kv); 198e71b7053SJung-uk Kim return 1; 199e71b7053SJung-uk Kim } 200e71b7053SJung-uk Kim *p = '\0'; 201e71b7053SJung-uk Kim 202e71b7053SJung-uk Kim /* Finally have a clean "key"; see if it's there [by attempt to add it]. */ 203e71b7053SJung-uk Kim if ((p = (char *)lh_OPENSSL_STRING_insert(addexts, (OPENSSL_STRING*)kv)) 204e71b7053SJung-uk Kim != NULL || lh_OPENSSL_STRING_error(addexts)) { 205e71b7053SJung-uk Kim OPENSSL_free(p != NULL ? p : kv); 206e71b7053SJung-uk Kim return -1; 207e71b7053SJung-uk Kim } 208e71b7053SJung-uk Kim 209e71b7053SJung-uk Kim return 0; 210e71b7053SJung-uk Kim } 211e71b7053SJung-uk Kim 212e71b7053SJung-uk Kim int req_main(int argc, char **argv) 213e71b7053SJung-uk Kim { 214e71b7053SJung-uk Kim ASN1_INTEGER *serial = NULL; 215e71b7053SJung-uk Kim BIO *in = NULL, *out = NULL; 2161f13597dSJung-uk Kim ENGINE *e = NULL, *gen_eng = NULL; 217e71b7053SJung-uk Kim EVP_PKEY *pkey = NULL; 218e71b7053SJung-uk Kim EVP_PKEY_CTX *genctx = NULL; 219e71b7053SJung-uk Kim STACK_OF(OPENSSL_STRING) *pkeyopts = NULL, *sigopts = NULL; 220e71b7053SJung-uk Kim LHASH_OF(OPENSSL_STRING) *addexts = NULL; 22174664626SKris Kennaway X509 *x509ss = NULL; 22274664626SKris Kennaway X509_REQ *req = NULL; 2235c87c606SMark Murray const EVP_CIPHER *cipher = NULL; 2241f13597dSJung-uk Kim const EVP_MD *md_alg = NULL, *digest = NULL; 225e71b7053SJung-uk Kim BIO *addext_bio = NULL; 226e71b7053SJung-uk Kim char *extensions = NULL, *infile = NULL; 227e71b7053SJung-uk Kim char *outfile = NULL, *keyfile = NULL; 228e71b7053SJung-uk Kim char *keyalgstr = NULL, *p, *prog, *passargin = NULL, *passargout = NULL; 229e71b7053SJung-uk Kim char *passin = NULL, *passout = NULL; 230e71b7053SJung-uk Kim char *nofree_passin = NULL, *nofree_passout = NULL; 231e71b7053SJung-uk Kim char *req_exts = NULL, *subj = NULL; 232e71b7053SJung-uk Kim char *template = default_config_file, *keyout = NULL; 233e71b7053SJung-uk Kim const char *keyalg = NULL; 234e71b7053SJung-uk Kim OPTION_CHOICE o; 235e71b7053SJung-uk Kim int ret = 1, x509 = 0, days = 0, i = 0, newreq = 0, verbose = 0; 236e71b7053SJung-uk Kim int pkey_type = -1, private = 0; 237e71b7053SJung-uk Kim int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyform = FORMAT_PEM; 238e71b7053SJung-uk Kim int modulus = 0, multirdn = 0, verify = 0, noout = 0, text = 0; 239e71b7053SJung-uk Kim int nodes = 0, newhdr = 0, subject = 0, pubkey = 0, precert = 0; 240e71b7053SJung-uk Kim long newkey = -1; 241e71b7053SJung-uk Kim unsigned long chtype = MBSTRING_ASC, reqflag = 0; 24274664626SKris Kennaway 2435c87c606SMark Murray #ifndef OPENSSL_NO_DES 24474664626SKris Kennaway cipher = EVP_des_ede3_cbc(); 24574664626SKris Kennaway #endif 24674664626SKris Kennaway 247e71b7053SJung-uk Kim prog = opt_init(argc, argv, req_options); 248e71b7053SJung-uk Kim while ((o = opt_next()) != OPT_EOF) { 249e71b7053SJung-uk Kim switch (o) { 250e71b7053SJung-uk Kim case OPT_EOF: 251e71b7053SJung-uk Kim case OPT_ERR: 252e71b7053SJung-uk Kim opthelp: 253e71b7053SJung-uk Kim BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 254e71b7053SJung-uk Kim goto end; 255e71b7053SJung-uk Kim case OPT_HELP: 256e71b7053SJung-uk Kim opt_help(req_options); 257e71b7053SJung-uk Kim ret = 0; 258e71b7053SJung-uk Kim goto end; 259e71b7053SJung-uk Kim case OPT_INFORM: 260e71b7053SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) 261e71b7053SJung-uk Kim goto opthelp; 262e71b7053SJung-uk Kim break; 263e71b7053SJung-uk Kim case OPT_OUTFORM: 264e71b7053SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) 265e71b7053SJung-uk Kim goto opthelp; 266e71b7053SJung-uk Kim break; 267e71b7053SJung-uk Kim case OPT_ENGINE: 268e71b7053SJung-uk Kim e = setup_engine(opt_arg(), 0); 269e71b7053SJung-uk Kim break; 270e71b7053SJung-uk Kim case OPT_KEYGEN_ENGINE: 271fceca8a3SJacques Vidrine #ifndef OPENSSL_NO_ENGINE 272e71b7053SJung-uk Kim gen_eng = ENGINE_by_id(opt_arg()); 2736f9291ceSJung-uk Kim if (gen_eng == NULL) { 2741f13597dSJung-uk Kim BIO_printf(bio_err, "Can't find keygen engine %s\n", *argv); 275e71b7053SJung-uk Kim goto opthelp; 2761f13597dSJung-uk Kim } 277fceca8a3SJacques Vidrine #endif 278e71b7053SJung-uk Kim break; 279e71b7053SJung-uk Kim case OPT_KEY: 280e71b7053SJung-uk Kim keyfile = opt_arg(); 281e71b7053SJung-uk Kim break; 282e71b7053SJung-uk Kim case OPT_PUBKEY: 2835c87c606SMark Murray pubkey = 1; 284e71b7053SJung-uk Kim break; 285e71b7053SJung-uk Kim case OPT_NEW: 28674664626SKris Kennaway newreq = 1; 287e71b7053SJung-uk Kim break; 288e71b7053SJung-uk Kim case OPT_CONFIG: 289e71b7053SJung-uk Kim template = opt_arg(); 290e71b7053SJung-uk Kim break; 291e71b7053SJung-uk Kim case OPT_KEYFORM: 292e71b7053SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform)) 293e71b7053SJung-uk Kim goto opthelp; 294e71b7053SJung-uk Kim break; 295e71b7053SJung-uk Kim case OPT_IN: 296e71b7053SJung-uk Kim infile = opt_arg(); 297e71b7053SJung-uk Kim break; 298e71b7053SJung-uk Kim case OPT_OUT: 299e71b7053SJung-uk Kim outfile = opt_arg(); 300e71b7053SJung-uk Kim break; 301e71b7053SJung-uk Kim case OPT_KEYOUT: 302e71b7053SJung-uk Kim keyout = opt_arg(); 303e71b7053SJung-uk Kim break; 304e71b7053SJung-uk Kim case OPT_PASSIN: 305e71b7053SJung-uk Kim passargin = opt_arg(); 306e71b7053SJung-uk Kim break; 307e71b7053SJung-uk Kim case OPT_PASSOUT: 308e71b7053SJung-uk Kim passargout = opt_arg(); 309e71b7053SJung-uk Kim break; 310e71b7053SJung-uk Kim case OPT_R_CASES: 311e71b7053SJung-uk Kim if (!opt_rand(o)) 312e71b7053SJung-uk Kim goto end; 313e71b7053SJung-uk Kim break; 314e71b7053SJung-uk Kim case OPT_NEWKEY: 315e71b7053SJung-uk Kim keyalg = opt_arg(); 3161f13597dSJung-uk Kim newreq = 1; 317e71b7053SJung-uk Kim break; 318e71b7053SJung-uk Kim case OPT_PKEYOPT: 3191f13597dSJung-uk Kim if (!pkeyopts) 3201f13597dSJung-uk Kim pkeyopts = sk_OPENSSL_STRING_new_null(); 321e71b7053SJung-uk Kim if (!pkeyopts || !sk_OPENSSL_STRING_push(pkeyopts, opt_arg())) 322e71b7053SJung-uk Kim goto opthelp; 323e71b7053SJung-uk Kim break; 324e71b7053SJung-uk Kim case OPT_SIGOPT: 3251f13597dSJung-uk Kim if (!sigopts) 3261f13597dSJung-uk Kim sigopts = sk_OPENSSL_STRING_new_null(); 327e71b7053SJung-uk Kim if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg())) 328e71b7053SJung-uk Kim goto opthelp; 32974664626SKris Kennaway break; 330e71b7053SJung-uk Kim case OPT_BATCH: 331e71b7053SJung-uk Kim batch = 1; 332e71b7053SJung-uk Kim break; 333e71b7053SJung-uk Kim case OPT_NEWHDR: 334e71b7053SJung-uk Kim newhdr = 1; 335e71b7053SJung-uk Kim break; 336e71b7053SJung-uk Kim case OPT_MODULUS: 337e71b7053SJung-uk Kim modulus = 1; 338e71b7053SJung-uk Kim break; 339e71b7053SJung-uk Kim case OPT_VERIFY: 340e71b7053SJung-uk Kim verify = 1; 341e71b7053SJung-uk Kim break; 342e71b7053SJung-uk Kim case OPT_NODES: 343e71b7053SJung-uk Kim nodes = 1; 344e71b7053SJung-uk Kim break; 345e71b7053SJung-uk Kim case OPT_NOOUT: 346e71b7053SJung-uk Kim noout = 1; 347e71b7053SJung-uk Kim break; 348e71b7053SJung-uk Kim case OPT_VERBOSE: 349e71b7053SJung-uk Kim verbose = 1; 350e71b7053SJung-uk Kim break; 351e71b7053SJung-uk Kim case OPT_UTF8: 352e71b7053SJung-uk Kim chtype = MBSTRING_UTF8; 353e71b7053SJung-uk Kim break; 354e71b7053SJung-uk Kim case OPT_NAMEOPT: 355e71b7053SJung-uk Kim if (!set_nameopt(opt_arg())) 356e71b7053SJung-uk Kim goto opthelp; 357e71b7053SJung-uk Kim break; 358e71b7053SJung-uk Kim case OPT_REQOPT: 359e71b7053SJung-uk Kim if (!set_cert_ex(&reqflag, opt_arg())) 360e71b7053SJung-uk Kim goto opthelp; 361e71b7053SJung-uk Kim break; 362e71b7053SJung-uk Kim case OPT_TEXT: 363e71b7053SJung-uk Kim text = 1; 364e71b7053SJung-uk Kim break; 365e71b7053SJung-uk Kim case OPT_X509: 366e71b7053SJung-uk Kim x509 = 1; 367e71b7053SJung-uk Kim break; 368e71b7053SJung-uk Kim case OPT_DAYS: 369e71b7053SJung-uk Kim days = atoi(opt_arg()); 370e71b7053SJung-uk Kim break; 371e71b7053SJung-uk Kim case OPT_SET_SERIAL: 372e71b7053SJung-uk Kim if (serial != NULL) { 373e71b7053SJung-uk Kim BIO_printf(bio_err, "Serial number supplied twice\n"); 374e71b7053SJung-uk Kim goto opthelp; 37574664626SKris Kennaway } 376e71b7053SJung-uk Kim serial = s2i_ASN1_INTEGER(NULL, opt_arg()); 377e71b7053SJung-uk Kim if (serial == NULL) 378e71b7053SJung-uk Kim goto opthelp; 379e71b7053SJung-uk Kim break; 380e71b7053SJung-uk Kim case OPT_SUBJECT: 381e71b7053SJung-uk Kim subject = 1; 382e71b7053SJung-uk Kim break; 383e71b7053SJung-uk Kim case OPT_SUBJ: 384e71b7053SJung-uk Kim subj = opt_arg(); 385e71b7053SJung-uk Kim break; 386e71b7053SJung-uk Kim case OPT_MULTIVALUE_RDN: 387e71b7053SJung-uk Kim multirdn = 1; 388e71b7053SJung-uk Kim break; 389e71b7053SJung-uk Kim case OPT_ADDEXT: 390e71b7053SJung-uk Kim p = opt_arg(); 391e71b7053SJung-uk Kim if (addexts == NULL) { 392e71b7053SJung-uk Kim addexts = lh_OPENSSL_STRING_new(ext_name_hash, ext_name_cmp); 393e71b7053SJung-uk Kim addext_bio = BIO_new(BIO_s_mem()); 394e71b7053SJung-uk Kim if (addexts == NULL || addext_bio == NULL) 39574664626SKris Kennaway goto end; 39674664626SKris Kennaway } 397e71b7053SJung-uk Kim i = duplicated(addexts, p); 398e71b7053SJung-uk Kim if (i == 1) 399e71b7053SJung-uk Kim goto opthelp; 400e71b7053SJung-uk Kim if (i < 0 || BIO_printf(addext_bio, "%s\n", opt_arg()) < 0) 401e71b7053SJung-uk Kim goto end; 402e71b7053SJung-uk Kim break; 403e71b7053SJung-uk Kim case OPT_EXTENSIONS: 404e71b7053SJung-uk Kim extensions = opt_arg(); 405e71b7053SJung-uk Kim break; 406e71b7053SJung-uk Kim case OPT_REQEXTS: 407e71b7053SJung-uk Kim req_exts = opt_arg(); 408e71b7053SJung-uk Kim break; 409e71b7053SJung-uk Kim case OPT_PRECERT: 410e71b7053SJung-uk Kim newreq = precert = 1; 411e71b7053SJung-uk Kim break; 412e71b7053SJung-uk Kim case OPT_MD: 413e71b7053SJung-uk Kim if (!opt_md(opt_unknown(), &md_alg)) 414e71b7053SJung-uk Kim goto opthelp; 415e71b7053SJung-uk Kim digest = md_alg; 416e71b7053SJung-uk Kim break; 417e71b7053SJung-uk Kim } 418e71b7053SJung-uk Kim } 419e71b7053SJung-uk Kim argc = opt_num_rest(); 420e71b7053SJung-uk Kim if (argc != 0) 421e71b7053SJung-uk Kim goto opthelp; 42274664626SKris Kennaway 423e71b7053SJung-uk Kim if (days && !x509) 424e71b7053SJung-uk Kim BIO_printf(bio_err, "Ignoring -days; not generating a certificate\n"); 425ed7112f0SJung-uk Kim if (x509 && infile == NULL) 426ed7112f0SJung-uk Kim newreq = 1; 427ed7112f0SJung-uk Kim 428e71b7053SJung-uk Kim /* TODO: simplify this as pkey is still always NULL here */ 429e71b7053SJung-uk Kim private = newreq && (pkey == NULL) ? 1 : 0; 430e71b7053SJung-uk Kim 431e71b7053SJung-uk Kim if (!app_passwd(passargin, passargout, &passin, &passout)) { 432f579bf8eSKris Kennaway BIO_printf(bio_err, "Error getting passwords\n"); 433f579bf8eSKris Kennaway goto end; 434f579bf8eSKris Kennaway } 43574664626SKris Kennaway 4365c87c606SMark Murray if (verbose) 43774664626SKris Kennaway BIO_printf(bio_err, "Using configuration from %s\n", template); 438e71b7053SJung-uk Kim req_conf = app_load_config(template); 439e71b7053SJung-uk Kim if (addext_bio) { 440e71b7053SJung-uk Kim if (verbose) 441e71b7053SJung-uk Kim BIO_printf(bio_err, 442e71b7053SJung-uk Kim "Using additional configuration from command line\n"); 443e71b7053SJung-uk Kim addext_conf = app_load_config_bio(addext_bio, NULL); 44474664626SKris Kennaway } 445e71b7053SJung-uk Kim if (template != default_config_file && !app_load_modules(req_conf)) 4463b4e3dcbSSimon L. B. Nielsen goto end; 44774664626SKris Kennaway 4486f9291ceSJung-uk Kim if (req_conf != NULL) { 4495c87c606SMark Murray p = NCONF_get_string(req_conf, NULL, "oid_file"); 4505c87c606SMark Murray if (p == NULL) 4515c87c606SMark Murray ERR_clear_error(); 4526f9291ceSJung-uk Kim if (p != NULL) { 45374664626SKris Kennaway BIO *oid_bio; 45474664626SKris Kennaway 45574664626SKris Kennaway oid_bio = BIO_new_file(p, "r"); 4566f9291ceSJung-uk Kim if (oid_bio == NULL) { 4576f9291ceSJung-uk Kim /*- 45874664626SKris Kennaway BIO_printf(bio_err,"problems opening %s for extra oid's\n",p); 45974664626SKris Kennaway ERR_print_errors(bio_err); 46074664626SKris Kennaway */ 4616f9291ceSJung-uk Kim } else { 46274664626SKris Kennaway OBJ_create_objects(oid_bio); 46374664626SKris Kennaway BIO_free(oid_bio); 46474664626SKris Kennaway } 46574664626SKris Kennaway } 46674664626SKris Kennaway } 467e71b7053SJung-uk Kim if (!add_oid_section(req_conf)) 4686f9291ceSJung-uk Kim goto end; 46974664626SKris Kennaway 4706f9291ceSJung-uk Kim if (md_alg == NULL) { 4715c87c606SMark Murray p = NCONF_get_string(req_conf, SECTION, "default_md"); 472e71b7053SJung-uk Kim if (p == NULL) { 4735c87c606SMark Murray ERR_clear_error(); 474e71b7053SJung-uk Kim } else { 475e71b7053SJung-uk Kim if (!opt_md(p, &md_alg)) 476e71b7053SJung-uk Kim goto opthelp; 47774664626SKris Kennaway digest = md_alg; 47874664626SKris Kennaway } 4795c87c606SMark Murray } 48074664626SKris Kennaway 481e71b7053SJung-uk Kim if (extensions == NULL) { 4825c87c606SMark Murray extensions = NCONF_get_string(req_conf, SECTION, V3_EXTENSIONS); 483e71b7053SJung-uk Kim if (extensions == NULL) 4845c87c606SMark Murray ERR_clear_error(); 4855c87c606SMark Murray } 486e71b7053SJung-uk Kim if (extensions != NULL) { 48774664626SKris Kennaway /* Check syntax of file */ 48874664626SKris Kennaway X509V3_CTX ctx; 48974664626SKris Kennaway X509V3_set_ctx_test(&ctx); 4905c87c606SMark Murray X509V3_set_nconf(&ctx, req_conf); 4915c87c606SMark Murray if (!X509V3_EXT_add_nconf(req_conf, &ctx, extensions, NULL)) { 49274664626SKris Kennaway BIO_printf(bio_err, 49374664626SKris Kennaway "Error Loading extension section %s\n", extensions); 49474664626SKris Kennaway goto end; 49574664626SKris Kennaway } 49674664626SKris Kennaway } 497e71b7053SJung-uk Kim if (addext_conf != NULL) { 498e71b7053SJung-uk Kim /* Check syntax of command line extensions */ 499e71b7053SJung-uk Kim X509V3_CTX ctx; 500e71b7053SJung-uk Kim X509V3_set_ctx_test(&ctx); 501e71b7053SJung-uk Kim X509V3_set_nconf(&ctx, addext_conf); 502e71b7053SJung-uk Kim if (!X509V3_EXT_add_nconf(addext_conf, &ctx, "default", NULL)) { 503e71b7053SJung-uk Kim BIO_printf(bio_err, "Error Loading command line extensions\n"); 504e71b7053SJung-uk Kim goto end; 505e71b7053SJung-uk Kim } 506e71b7053SJung-uk Kim } 50774664626SKris Kennaway 508e71b7053SJung-uk Kim if (passin == NULL) { 509e71b7053SJung-uk Kim passin = nofree_passin = 510e71b7053SJung-uk Kim NCONF_get_string(req_conf, SECTION, "input_password"); 511e71b7053SJung-uk Kim if (passin == NULL) 5125c87c606SMark Murray ERR_clear_error(); 5135c87c606SMark Murray } 514f579bf8eSKris Kennaway 515e71b7053SJung-uk Kim if (passout == NULL) { 516e71b7053SJung-uk Kim passout = nofree_passout = 517e71b7053SJung-uk Kim NCONF_get_string(req_conf, SECTION, "output_password"); 518e71b7053SJung-uk Kim if (passout == NULL) 5195c87c606SMark Murray ERR_clear_error(); 5205c87c606SMark Murray } 521f579bf8eSKris Kennaway 5225c87c606SMark Murray p = NCONF_get_string(req_conf, SECTION, STRING_MASK); 523e71b7053SJung-uk Kim if (p == NULL) 5245c87c606SMark Murray ERR_clear_error(); 525f579bf8eSKris Kennaway 526e71b7053SJung-uk Kim if (p != NULL && !ASN1_STRING_set_default_mask_asc(p)) { 527f579bf8eSKris Kennaway BIO_printf(bio_err, "Invalid global string mask setting %s\n", p); 528f579bf8eSKris Kennaway goto end; 529f579bf8eSKris Kennaway } 530f579bf8eSKris Kennaway 5316f9291ceSJung-uk Kim if (chtype != MBSTRING_UTF8) { 5325c87c606SMark Murray p = NCONF_get_string(req_conf, SECTION, UTF8_IN); 533e71b7053SJung-uk Kim if (p == NULL) 5345c87c606SMark Murray ERR_clear_error(); 535e71b7053SJung-uk Kim else if (strcmp(p, "yes") == 0) 5365c87c606SMark Murray chtype = MBSTRING_UTF8; 5375c87c606SMark Murray } 5385c87c606SMark Murray 539e71b7053SJung-uk Kim if (req_exts == NULL) { 5405c87c606SMark Murray req_exts = NCONF_get_string(req_conf, SECTION, REQ_EXTENSIONS); 541e71b7053SJung-uk Kim if (req_exts == NULL) 5425c87c606SMark Murray ERR_clear_error(); 5435c87c606SMark Murray } 544e71b7053SJung-uk Kim if (req_exts != NULL) { 545f579bf8eSKris Kennaway /* Check syntax of file */ 546f579bf8eSKris Kennaway X509V3_CTX ctx; 547f579bf8eSKris Kennaway X509V3_set_ctx_test(&ctx); 5485c87c606SMark Murray X509V3_set_nconf(&ctx, req_conf); 5495c87c606SMark Murray if (!X509V3_EXT_add_nconf(req_conf, &ctx, req_exts, NULL)) { 550f579bf8eSKris Kennaway BIO_printf(bio_err, 551f579bf8eSKris Kennaway "Error Loading request extension section %s\n", 552f579bf8eSKris Kennaway req_exts); 553f579bf8eSKris Kennaway goto end; 554f579bf8eSKris Kennaway } 555f579bf8eSKris Kennaway } 556f579bf8eSKris Kennaway 5576f9291ceSJung-uk Kim if (keyfile != NULL) { 558e71b7053SJung-uk Kim pkey = load_key(keyfile, keyform, 0, passin, e, "Private Key"); 559e71b7053SJung-uk Kim if (pkey == NULL) { 560e71b7053SJung-uk Kim /* load_key() has already printed an appropriate message */ 56174664626SKris Kennaway goto end; 5626f9291ceSJung-uk Kim } else { 563e71b7053SJung-uk Kim app_RAND_load_conf(req_conf, SECTION); 564ddd58736SKris Kennaway } 56574664626SKris Kennaway } 56674664626SKris Kennaway 5676f9291ceSJung-uk Kim if (newreq && (pkey == NULL)) { 568e71b7053SJung-uk Kim app_RAND_load_conf(req_conf, SECTION); 56974664626SKris Kennaway 5706f9291ceSJung-uk Kim if (!NCONF_get_number(req_conf, SECTION, BITS, &newkey)) { 571560ede85SJung-uk Kim newkey = DEFAULT_KEY_LENGTH; 572560ede85SJung-uk Kim } 573560ede85SJung-uk Kim 574e71b7053SJung-uk Kim if (keyalg != NULL) { 575e71b7053SJung-uk Kim genctx = set_keygen_ctx(keyalg, &pkey_type, &newkey, 5761f13597dSJung-uk Kim &keyalgstr, gen_eng); 577e71b7053SJung-uk Kim if (genctx == NULL) 5781f13597dSJung-uk Kim goto end; 5791f13597dSJung-uk Kim } 5801f13597dSJung-uk Kim 5816f9291ceSJung-uk Kim if (newkey < MIN_KEY_LENGTH 5826f9291ceSJung-uk Kim && (pkey_type == EVP_PKEY_RSA || pkey_type == EVP_PKEY_DSA)) { 58374664626SKris Kennaway BIO_printf(bio_err, "private key length is too short,\n"); 5846f9291ceSJung-uk Kim BIO_printf(bio_err, "it needs to be at least %d bits, not %ld\n", 5856f9291ceSJung-uk Kim MIN_KEY_LENGTH, newkey); 58674664626SKris Kennaway goto end; 58774664626SKris Kennaway } 5881f13597dSJung-uk Kim 589e71b7053SJung-uk Kim if (pkey_type == EVP_PKEY_RSA && newkey > OPENSSL_RSA_MAX_MODULUS_BITS) 590e71b7053SJung-uk Kim BIO_printf(bio_err, 591e71b7053SJung-uk Kim "Warning: It is not recommended to use more than %d bit for RSA keys.\n" 592e71b7053SJung-uk Kim " Your key size is %ld! Larger key size may behave not as expected.\n", 593e71b7053SJung-uk Kim OPENSSL_RSA_MAX_MODULUS_BITS, newkey); 594e71b7053SJung-uk Kim 595e71b7053SJung-uk Kim #ifndef OPENSSL_NO_DSA 596e71b7053SJung-uk Kim if (pkey_type == EVP_PKEY_DSA && newkey > OPENSSL_DSA_MAX_MODULUS_BITS) 597e71b7053SJung-uk Kim BIO_printf(bio_err, 598e71b7053SJung-uk Kim "Warning: It is not recommended to use more than %d bit for DSA keys.\n" 599e71b7053SJung-uk Kim " Your key size is %ld! Larger key size may behave not as expected.\n", 600e71b7053SJung-uk Kim OPENSSL_DSA_MAX_MODULUS_BITS, newkey); 601e71b7053SJung-uk Kim #endif 602e71b7053SJung-uk Kim 603e71b7053SJung-uk Kim if (genctx == NULL) { 604e71b7053SJung-uk Kim genctx = set_keygen_ctx(NULL, &pkey_type, &newkey, 6051f13597dSJung-uk Kim &keyalgstr, gen_eng); 6061f13597dSJung-uk Kim if (!genctx) 6071f13597dSJung-uk Kim goto end; 6081f13597dSJung-uk Kim } 6091f13597dSJung-uk Kim 610e71b7053SJung-uk Kim if (pkeyopts != NULL) { 6111f13597dSJung-uk Kim char *genopt; 6126f9291ceSJung-uk Kim for (i = 0; i < sk_OPENSSL_STRING_num(pkeyopts); i++) { 6131f13597dSJung-uk Kim genopt = sk_OPENSSL_STRING_value(pkeyopts, i); 6146f9291ceSJung-uk Kim if (pkey_ctrl_string(genctx, genopt) <= 0) { 6156f9291ceSJung-uk Kim BIO_printf(bio_err, "parameter error \"%s\"\n", genopt); 6161f13597dSJung-uk Kim ERR_print_errors(bio_err); 6171f13597dSJung-uk Kim goto end; 6181f13597dSJung-uk Kim } 6191f13597dSJung-uk Kim } 6201f13597dSJung-uk Kim } 6211f13597dSJung-uk Kim 622e71b7053SJung-uk Kim if (pkey_type == EVP_PKEY_EC) { 623e71b7053SJung-uk Kim BIO_printf(bio_err, "Generating an EC private key\n"); 624e71b7053SJung-uk Kim } else { 625e71b7053SJung-uk Kim BIO_printf(bio_err, "Generating a %s private key\n", keyalgstr); 626e71b7053SJung-uk Kim } 62774664626SKris Kennaway 6281f13597dSJung-uk Kim EVP_PKEY_CTX_set_cb(genctx, genpkey_cb); 6291f13597dSJung-uk Kim EVP_PKEY_CTX_set_app_data(genctx, bio_err); 63074664626SKris Kennaway 6316f9291ceSJung-uk Kim if (EVP_PKEY_keygen(genctx, &pkey) <= 0) { 6321f13597dSJung-uk Kim BIO_puts(bio_err, "Error Generating Key\n"); 63374664626SKris Kennaway goto end; 63474664626SKris Kennaway } 6351f13597dSJung-uk Kim 6361f13597dSJung-uk Kim EVP_PKEY_CTX_free(genctx); 6371f13597dSJung-uk Kim genctx = NULL; 63874664626SKris Kennaway 6396f9291ceSJung-uk Kim if (keyout == NULL) { 6405c87c606SMark Murray keyout = NCONF_get_string(req_conf, SECTION, KEYFILE); 6415c87c606SMark Murray if (keyout == NULL) 6425c87c606SMark Murray ERR_clear_error(); 6435c87c606SMark Murray } 64474664626SKris Kennaway 645e71b7053SJung-uk Kim if (keyout == NULL) 64674664626SKris Kennaway BIO_printf(bio_err, "writing new private key to stdout\n"); 647e71b7053SJung-uk Kim else 64874664626SKris Kennaway BIO_printf(bio_err, "writing new private key to '%s'\n", keyout); 649e71b7053SJung-uk Kim out = bio_open_owner(keyout, outformat, private); 650e71b7053SJung-uk Kim if (out == NULL) 65174664626SKris Kennaway goto end; 65274664626SKris Kennaway 6535c87c606SMark Murray p = NCONF_get_string(req_conf, SECTION, "encrypt_rsa_key"); 6546f9291ceSJung-uk Kim if (p == NULL) { 6555c87c606SMark Murray ERR_clear_error(); 6565c87c606SMark Murray p = NCONF_get_string(req_conf, SECTION, "encrypt_key"); 6575c87c606SMark Murray if (p == NULL) 6585c87c606SMark Murray ERR_clear_error(); 6595c87c606SMark Murray } 66074664626SKris Kennaway if ((p != NULL) && (strcmp(p, "no") == 0)) 66174664626SKris Kennaway cipher = NULL; 6626f9291ceSJung-uk Kim if (nodes) 6636f9291ceSJung-uk Kim cipher = NULL; 66474664626SKris Kennaway 66574664626SKris Kennaway i = 0; 66674664626SKris Kennaway loop: 667e71b7053SJung-uk Kim assert(private); 66874664626SKris Kennaway if (!PEM_write_bio_PrivateKey(out, pkey, cipher, 6696f9291ceSJung-uk Kim NULL, 0, NULL, passout)) { 67074664626SKris Kennaway if ((ERR_GET_REASON(ERR_peek_error()) == 6716f9291ceSJung-uk Kim PEM_R_PROBLEMS_GETTING_PASSWORD) && (i < 3)) { 67274664626SKris Kennaway ERR_clear_error(); 67374664626SKris Kennaway i++; 67474664626SKris Kennaway goto loop; 67574664626SKris Kennaway } 67674664626SKris Kennaway goto end; 67774664626SKris Kennaway } 678e71b7053SJung-uk Kim BIO_free(out); 679e71b7053SJung-uk Kim out = NULL; 68074664626SKris Kennaway BIO_printf(bio_err, "-----\n"); 68174664626SKris Kennaway } 68274664626SKris Kennaway 6836f9291ceSJung-uk Kim if (!newreq) { 684e71b7053SJung-uk Kim in = bio_open_default(infile, 'r', informat); 685e71b7053SJung-uk Kim if (in == NULL) 68674664626SKris Kennaway goto end; 68774664626SKris Kennaway 68874664626SKris Kennaway if (informat == FORMAT_ASN1) 68974664626SKris Kennaway req = d2i_X509_REQ_bio(in, NULL); 690e71b7053SJung-uk Kim else 69174664626SKris Kennaway req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL); 6926f9291ceSJung-uk Kim if (req == NULL) { 69374664626SKris Kennaway BIO_printf(bio_err, "unable to load X509 request\n"); 69474664626SKris Kennaway goto end; 69574664626SKris Kennaway } 69674664626SKris Kennaway } 69774664626SKris Kennaway 698ed7112f0SJung-uk Kim if (newreq || x509) { 6996f9291ceSJung-uk Kim if (pkey == NULL) { 70074664626SKris Kennaway BIO_printf(bio_err, "you need to specify a private key\n"); 70174664626SKris Kennaway goto end; 70274664626SKris Kennaway } 7031f13597dSJung-uk Kim 7046f9291ceSJung-uk Kim if (req == NULL) { 70574664626SKris Kennaway req = X509_REQ_new(); 7066f9291ceSJung-uk Kim if (req == NULL) { 70774664626SKris Kennaway goto end; 70874664626SKris Kennaway } 70974664626SKris Kennaway 7103b4e3dcbSSimon L. B. Nielsen i = make_REQ(req, pkey, subj, multirdn, !x509, chtype); 7115c87c606SMark Murray subj = NULL; /* done processing '-subj' option */ 7126f9291ceSJung-uk Kim if (!i) { 71374664626SKris Kennaway BIO_printf(bio_err, "problems making Certificate Request\n"); 71474664626SKris Kennaway goto end; 71574664626SKris Kennaway } 71674664626SKris Kennaway } 7176f9291ceSJung-uk Kim if (x509) { 71874664626SKris Kennaway EVP_PKEY *tmppkey; 71974664626SKris Kennaway X509V3_CTX ext_ctx; 7206f9291ceSJung-uk Kim if ((x509ss = X509_new()) == NULL) 7216f9291ceSJung-uk Kim goto end; 72274664626SKris Kennaway 72374664626SKris Kennaway /* Set version to V3 */ 724e71b7053SJung-uk Kim if ((extensions != NULL || addext_conf != NULL) 725e71b7053SJung-uk Kim && !X509_set_version(x509ss, 2)) 7266f9291ceSJung-uk Kim goto end; 727e71b7053SJung-uk Kim if (serial != NULL) { 7286f9291ceSJung-uk Kim if (!X509_set_serialNumber(x509ss, serial)) 7296f9291ceSJung-uk Kim goto end; 7306f9291ceSJung-uk Kim } else { 7316f9291ceSJung-uk Kim if (!rand_serial(NULL, X509_get_serialNumber(x509ss))) 7326be8ae07SJacques Vidrine goto end; 7335c87c606SMark Murray } 73474664626SKris Kennaway 7356f9291ceSJung-uk Kim if (!X509_set_issuer_name(x509ss, X509_REQ_get_subject_name(req))) 7366f9291ceSJung-uk Kim goto end; 737e71b7053SJung-uk Kim if (days == 0) { 738e71b7053SJung-uk Kim /* set default days if it's not specified */ 739e71b7053SJung-uk Kim days = 30; 740e71b7053SJung-uk Kim } 741e71b7053SJung-uk Kim if (!set_cert_times(x509ss, NULL, NULL, days)) 7426f9291ceSJung-uk Kim goto end; 7436f9291ceSJung-uk Kim if (!X509_set_subject_name 7446f9291ceSJung-uk Kim (x509ss, X509_REQ_get_subject_name(req))) 7456f9291ceSJung-uk Kim goto end; 746e71b7053SJung-uk Kim tmppkey = X509_REQ_get0_pubkey(req); 7476f9291ceSJung-uk Kim if (!tmppkey || !X509_set_pubkey(x509ss, tmppkey)) 7486f9291ceSJung-uk Kim goto end; 74974664626SKris Kennaway 75074664626SKris Kennaway /* Set up V3 context struct */ 75174664626SKris Kennaway 75274664626SKris Kennaway X509V3_set_ctx(&ext_ctx, x509ss, x509ss, NULL, NULL, 0); 7535c87c606SMark Murray X509V3_set_nconf(&ext_ctx, req_conf); 75474664626SKris Kennaway 75574664626SKris Kennaway /* Add extensions */ 756e71b7053SJung-uk Kim if (extensions != NULL && !X509V3_EXT_add_nconf(req_conf, 7576f9291ceSJung-uk Kim &ext_ctx, extensions, 7586f9291ceSJung-uk Kim x509ss)) { 7596f9291ceSJung-uk Kim BIO_printf(bio_err, "Error Loading extension section %s\n", 76074664626SKris Kennaway extensions); 76174664626SKris Kennaway goto end; 76274664626SKris Kennaway } 763e71b7053SJung-uk Kim if (addext_conf != NULL 764e71b7053SJung-uk Kim && !X509V3_EXT_add_nconf(addext_conf, &ext_ctx, "default", 765e71b7053SJung-uk Kim x509ss)) { 766e71b7053SJung-uk Kim BIO_printf(bio_err, "Error Loading command line extensions\n"); 767e71b7053SJung-uk Kim goto end; 768e71b7053SJung-uk Kim } 76974664626SKris Kennaway 770e71b7053SJung-uk Kim /* If a pre-cert was requested, we need to add a poison extension */ 771e71b7053SJung-uk Kim if (precert) { 772e71b7053SJung-uk Kim if (X509_add1_ext_i2d(x509ss, NID_ct_precert_poison, NULL, 1, 0) 773e71b7053SJung-uk Kim != 1) { 774e71b7053SJung-uk Kim BIO_printf(bio_err, "Error adding poison extension\n"); 775e71b7053SJung-uk Kim goto end; 776e71b7053SJung-uk Kim } 777e71b7053SJung-uk Kim } 778e71b7053SJung-uk Kim 779e71b7053SJung-uk Kim i = do_X509_sign(x509ss, pkey, digest, sigopts); 7806f9291ceSJung-uk Kim if (!i) { 7811f13597dSJung-uk Kim ERR_print_errors(bio_err); 78274664626SKris Kennaway goto end; 78374664626SKris Kennaway } 7846f9291ceSJung-uk Kim } else { 785f579bf8eSKris Kennaway X509V3_CTX ext_ctx; 786f579bf8eSKris Kennaway 787f579bf8eSKris Kennaway /* Set up V3 context struct */ 788f579bf8eSKris Kennaway 789f579bf8eSKris Kennaway X509V3_set_ctx(&ext_ctx, NULL, NULL, req, NULL, 0); 7905c87c606SMark Murray X509V3_set_nconf(&ext_ctx, req_conf); 791f579bf8eSKris Kennaway 792f579bf8eSKris Kennaway /* Add extensions */ 793e71b7053SJung-uk Kim if (req_exts != NULL 794e71b7053SJung-uk Kim && !X509V3_EXT_REQ_add_nconf(req_conf, &ext_ctx, 795e71b7053SJung-uk Kim req_exts, req)) { 7966f9291ceSJung-uk Kim BIO_printf(bio_err, "Error Loading extension section %s\n", 797f579bf8eSKris Kennaway req_exts); 798f579bf8eSKris Kennaway goto end; 799f579bf8eSKris Kennaway } 800e71b7053SJung-uk Kim if (addext_conf != NULL 801e71b7053SJung-uk Kim && !X509V3_EXT_REQ_add_nconf(addext_conf, &ext_ctx, "default", 802e71b7053SJung-uk Kim req)) { 803e71b7053SJung-uk Kim BIO_printf(bio_err, "Error Loading command line extensions\n"); 804e71b7053SJung-uk Kim goto end; 805e71b7053SJung-uk Kim } 806e71b7053SJung-uk Kim i = do_X509_REQ_sign(req, pkey, digest, sigopts); 8076f9291ceSJung-uk Kim if (!i) { 8081f13597dSJung-uk Kim ERR_print_errors(bio_err); 80974664626SKris Kennaway goto end; 81074664626SKris Kennaway } 81174664626SKris Kennaway } 8121f13597dSJung-uk Kim } 81374664626SKris Kennaway 8146f9291ceSJung-uk Kim if (subj && x509) { 815e71b7053SJung-uk Kim BIO_printf(bio_err, "Cannot modify certificate subject\n"); 8165c87c606SMark Murray goto end; 8175c87c606SMark Murray } 8185c87c606SMark Murray 8196f9291ceSJung-uk Kim if (subj && !x509) { 8206f9291ceSJung-uk Kim if (verbose) { 8215c87c606SMark Murray BIO_printf(bio_err, "Modifying Request's Subject\n"); 8226f9291ceSJung-uk Kim print_name(bio_err, "old subject=", 823e71b7053SJung-uk Kim X509_REQ_get_subject_name(req), get_nameopt()); 8245c87c606SMark Murray } 8255c87c606SMark Murray 8266f9291ceSJung-uk Kim if (build_subject(req, subj, chtype, multirdn) == 0) { 8275c87c606SMark Murray BIO_printf(bio_err, "ERROR: cannot modify subject\n"); 828e71b7053SJung-uk Kim ret = 1; 8295c87c606SMark Murray goto end; 8305c87c606SMark Murray } 8315c87c606SMark Murray 8326f9291ceSJung-uk Kim if (verbose) { 8336f9291ceSJung-uk Kim print_name(bio_err, "new subject=", 834e71b7053SJung-uk Kim X509_REQ_get_subject_name(req), get_nameopt()); 8355c87c606SMark Murray } 8365c87c606SMark Murray } 8375c87c606SMark Murray 8386f9291ceSJung-uk Kim if (verify && !x509) { 839e71b7053SJung-uk Kim EVP_PKEY *tpubkey = pkey; 84074664626SKris Kennaway 841e71b7053SJung-uk Kim if (tpubkey == NULL) { 842e71b7053SJung-uk Kim tpubkey = X509_REQ_get0_pubkey(req); 843e71b7053SJung-uk Kim if (tpubkey == NULL) 8446f9291ceSJung-uk Kim goto end; 84574664626SKris Kennaway } 84674664626SKris Kennaway 847e71b7053SJung-uk Kim i = X509_REQ_verify(req, tpubkey); 84874664626SKris Kennaway 8496f9291ceSJung-uk Kim if (i < 0) { 85074664626SKris Kennaway goto end; 8516f9291ceSJung-uk Kim } else if (i == 0) { 85274664626SKris Kennaway BIO_printf(bio_err, "verify failure\n"); 8535c87c606SMark Murray ERR_print_errors(bio_err); 854e71b7053SJung-uk Kim } else { /* if (i > 0) */ 85574664626SKris Kennaway BIO_printf(bio_err, "verify OK\n"); 85674664626SKris Kennaway } 857e71b7053SJung-uk Kim } 85874664626SKris Kennaway 8596f9291ceSJung-uk Kim if (noout && !text && !modulus && !subject && !pubkey) { 860e71b7053SJung-uk Kim ret = 0; 86174664626SKris Kennaway goto end; 86274664626SKris Kennaway } 86374664626SKris Kennaway 864e71b7053SJung-uk Kim out = bio_open_default(outfile, 865e71b7053SJung-uk Kim keyout != NULL && outfile != NULL && 866e71b7053SJung-uk Kim strcmp(keyout, outfile) == 0 ? 'a' : 'w', 867e71b7053SJung-uk Kim outformat); 868e71b7053SJung-uk Kim if (out == NULL) 86974664626SKris Kennaway goto end; 87074664626SKris Kennaway 8716f9291ceSJung-uk Kim if (pubkey) { 872e71b7053SJung-uk Kim EVP_PKEY *tpubkey = X509_REQ_get0_pubkey(req); 873e71b7053SJung-uk Kim 8746f9291ceSJung-uk Kim if (tpubkey == NULL) { 8755c87c606SMark Murray BIO_printf(bio_err, "Error getting public key\n"); 8765c87c606SMark Murray ERR_print_errors(bio_err); 8775c87c606SMark Murray goto end; 8785c87c606SMark Murray } 8795c87c606SMark Murray PEM_write_bio_PUBKEY(out, tpubkey); 8805c87c606SMark Murray } 8815c87c606SMark Murray 8826f9291ceSJung-uk Kim if (text) { 88374664626SKris Kennaway if (x509) 884*da327cd2SJung-uk Kim ret = X509_print_ex(out, x509ss, get_nameopt(), reqflag); 88574664626SKris Kennaway else 886*da327cd2SJung-uk Kim ret = X509_REQ_print_ex(out, req, get_nameopt(), reqflag); 887*da327cd2SJung-uk Kim 888*da327cd2SJung-uk Kim if (ret == 0) { 889*da327cd2SJung-uk Kim if (x509) 890*da327cd2SJung-uk Kim BIO_printf(bio_err, "Error printing certificate\n"); 891*da327cd2SJung-uk Kim else 892*da327cd2SJung-uk Kim BIO_printf(bio_err, "Error printing certificate request\n"); 893*da327cd2SJung-uk Kim 894*da327cd2SJung-uk Kim ERR_print_errors(bio_err); 895*da327cd2SJung-uk Kim goto end; 896*da327cd2SJung-uk Kim } 8975c87c606SMark Murray } 8985c87c606SMark Murray 8996f9291ceSJung-uk Kim if (subject) { 9005c87c606SMark Murray if (x509) 9016f9291ceSJung-uk Kim print_name(out, "subject=", X509_get_subject_name(x509ss), 902e71b7053SJung-uk Kim get_nameopt()); 9035c87c606SMark Murray else 9046f9291ceSJung-uk Kim print_name(out, "subject=", X509_REQ_get_subject_name(req), 905e71b7053SJung-uk Kim get_nameopt()); 90674664626SKris Kennaway } 90774664626SKris Kennaway 9086f9291ceSJung-uk Kim if (modulus) { 9095c87c606SMark Murray EVP_PKEY *tpubkey; 91074664626SKris Kennaway 91174664626SKris Kennaway if (x509) 912e71b7053SJung-uk Kim tpubkey = X509_get0_pubkey(x509ss); 91374664626SKris Kennaway else 914e71b7053SJung-uk Kim tpubkey = X509_REQ_get0_pubkey(req); 9156f9291ceSJung-uk Kim if (tpubkey == NULL) { 91674664626SKris Kennaway fprintf(stdout, "Modulus=unavailable\n"); 91774664626SKris Kennaway goto end; 91874664626SKris Kennaway } 91974664626SKris Kennaway fprintf(stdout, "Modulus="); 9205c87c606SMark Murray #ifndef OPENSSL_NO_RSA 921e71b7053SJung-uk Kim if (EVP_PKEY_base_id(tpubkey) == EVP_PKEY_RSA) { 922e71b7053SJung-uk Kim const BIGNUM *n; 923e71b7053SJung-uk Kim RSA_get0_key(EVP_PKEY_get0_RSA(tpubkey), &n, NULL, NULL); 924e71b7053SJung-uk Kim BN_print(out, n); 925e71b7053SJung-uk Kim } else 92674664626SKris Kennaway #endif 92774664626SKris Kennaway fprintf(stdout, "Wrong Algorithm type"); 92874664626SKris Kennaway fprintf(stdout, "\n"); 92974664626SKris Kennaway } 93074664626SKris Kennaway 9316f9291ceSJung-uk Kim if (!noout && !x509) { 93274664626SKris Kennaway if (outformat == FORMAT_ASN1) 93374664626SKris Kennaway i = i2d_X509_REQ_bio(out, req); 934e71b7053SJung-uk Kim else if (newhdr) 9356f9291ceSJung-uk Kim i = PEM_write_bio_X509_REQ_NEW(out, req); 9366f9291ceSJung-uk Kim else 9376f9291ceSJung-uk Kim i = PEM_write_bio_X509_REQ(out, req); 9386f9291ceSJung-uk Kim if (!i) { 93974664626SKris Kennaway BIO_printf(bio_err, "unable to write X509 request\n"); 94074664626SKris Kennaway goto end; 94174664626SKris Kennaway } 94274664626SKris Kennaway } 9436f9291ceSJung-uk Kim if (!noout && x509 && (x509ss != NULL)) { 94474664626SKris Kennaway if (outformat == FORMAT_ASN1) 94574664626SKris Kennaway i = i2d_X509_bio(out, x509ss); 946e71b7053SJung-uk Kim else 94774664626SKris Kennaway i = PEM_write_bio_X509(out, x509ss); 9486f9291ceSJung-uk Kim if (!i) { 94974664626SKris Kennaway BIO_printf(bio_err, "unable to write X509 certificate\n"); 95074664626SKris Kennaway goto end; 95174664626SKris Kennaway } 95274664626SKris Kennaway } 953e71b7053SJung-uk Kim ret = 0; 95474664626SKris Kennaway end: 955e71b7053SJung-uk Kim if (ret) { 95674664626SKris Kennaway ERR_print_errors(bio_err); 95774664626SKris Kennaway } 9586f9291ceSJung-uk Kim NCONF_free(req_conf); 959e71b7053SJung-uk Kim NCONF_free(addext_conf); 960e71b7053SJung-uk Kim BIO_free(addext_bio); 96174664626SKris Kennaway BIO_free(in); 962ddd58736SKris Kennaway BIO_free_all(out); 96374664626SKris Kennaway EVP_PKEY_free(pkey); 9641f13597dSJung-uk Kim EVP_PKEY_CTX_free(genctx); 9651f13597dSJung-uk Kim sk_OPENSSL_STRING_free(pkeyopts); 9661f13597dSJung-uk Kim sk_OPENSSL_STRING_free(sigopts); 967e71b7053SJung-uk Kim lh_OPENSSL_STRING_doall(addexts, exts_cleanup); 968e71b7053SJung-uk Kim lh_OPENSSL_STRING_free(addexts); 9691f13597dSJung-uk Kim #ifndef OPENSSL_NO_ENGINE 9701f13597dSJung-uk Kim ENGINE_free(gen_eng); 9711f13597dSJung-uk Kim #endif 9721f13597dSJung-uk Kim OPENSSL_free(keyalgstr); 97374664626SKris Kennaway X509_REQ_free(req); 97474664626SKris Kennaway X509_free(x509ss); 9755c87c606SMark Murray ASN1_INTEGER_free(serial); 9766cf8931aSJung-uk Kim release_engine(e); 977e71b7053SJung-uk Kim if (passin != nofree_passin) 9786f9291ceSJung-uk Kim OPENSSL_free(passin); 979e71b7053SJung-uk Kim if (passout != nofree_passout) 9806f9291ceSJung-uk Kim OPENSSL_free(passout); 981e71b7053SJung-uk Kim return ret; 98274664626SKris Kennaway } 98374664626SKris Kennaway 9843b4e3dcbSSimon L. B. Nielsen static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *subj, int multirdn, 9853b4e3dcbSSimon L. B. Nielsen int attribs, unsigned long chtype) 98674664626SKris Kennaway { 98774664626SKris Kennaway int ret = 0, i; 988f579bf8eSKris Kennaway char no_prompt = 0; 989f579bf8eSKris Kennaway STACK_OF(CONF_VALUE) *dn_sk, *attr_sk = NULL; 990f579bf8eSKris Kennaway char *tmp, *dn_sect, *attr_sect; 99174664626SKris Kennaway 9925c87c606SMark Murray tmp = NCONF_get_string(req_conf, SECTION, PROMPT); 9935c87c606SMark Murray if (tmp == NULL) 9945c87c606SMark Murray ERR_clear_error(); 995e71b7053SJung-uk Kim if ((tmp != NULL) && strcmp(tmp, "no") == 0) 9966f9291ceSJung-uk Kim no_prompt = 1; 997f579bf8eSKris Kennaway 9985c87c606SMark Murray dn_sect = NCONF_get_string(req_conf, SECTION, DISTINGUISHED_NAME); 9996f9291ceSJung-uk Kim if (dn_sect == NULL) { 100074664626SKris Kennaway BIO_printf(bio_err, "unable to find '%s' in config\n", 100174664626SKris Kennaway DISTINGUISHED_NAME); 100274664626SKris Kennaway goto err; 100374664626SKris Kennaway } 10045c87c606SMark Murray dn_sk = NCONF_get_section(req_conf, dn_sect); 10056f9291ceSJung-uk Kim if (dn_sk == NULL) { 1006f579bf8eSKris Kennaway BIO_printf(bio_err, "unable to get '%s' section\n", dn_sect); 100774664626SKris Kennaway goto err; 100874664626SKris Kennaway } 100974664626SKris Kennaway 10105c87c606SMark Murray attr_sect = NCONF_get_string(req_conf, SECTION, ATTRIBUTES); 10116f9291ceSJung-uk Kim if (attr_sect == NULL) { 10125c87c606SMark Murray ERR_clear_error(); 1013f579bf8eSKris Kennaway attr_sk = NULL; 10146f9291ceSJung-uk Kim } else { 10155c87c606SMark Murray attr_sk = NCONF_get_section(req_conf, attr_sect); 10166f9291ceSJung-uk Kim if (attr_sk == NULL) { 1017f579bf8eSKris Kennaway BIO_printf(bio_err, "unable to get '%s' section\n", attr_sect); 101874664626SKris Kennaway goto err; 101974664626SKris Kennaway } 102074664626SKris Kennaway } 102174664626SKris Kennaway 1022f579bf8eSKris Kennaway /* setup version number */ 10236f9291ceSJung-uk Kim if (!X509_REQ_set_version(req, 0L)) 10246f9291ceSJung-uk Kim goto err; /* version 1 */ 102574664626SKris Kennaway 10265c87c606SMark Murray if (subj) 10273b4e3dcbSSimon L. B. Nielsen i = build_subject(req, subj, chtype, multirdn); 1028e71b7053SJung-uk Kim else if (no_prompt) 1029e71b7053SJung-uk Kim i = auto_info(req, dn_sk, attr_sk, attribs, chtype); 10305c87c606SMark Murray else 10316f9291ceSJung-uk Kim i = prompt_info(req, dn_sk, dn_sect, attr_sk, attr_sect, attribs, 10326f9291ceSJung-uk Kim chtype); 10336f9291ceSJung-uk Kim if (!i) 10346f9291ceSJung-uk Kim goto err; 1035f579bf8eSKris Kennaway 10366f9291ceSJung-uk Kim if (!X509_REQ_set_pubkey(req, pkey)) 10376f9291ceSJung-uk Kim goto err; 1038f579bf8eSKris Kennaway 1039f579bf8eSKris Kennaway ret = 1; 1040f579bf8eSKris Kennaway err: 1041e71b7053SJung-uk Kim return ret; 1042f579bf8eSKris Kennaway } 1043f579bf8eSKris Kennaway 10445c87c606SMark Murray /* 10455c87c606SMark Murray * subject is expected to be in the format /type0=value0/type1=value1/type2=... 10465c87c606SMark Murray * where characters may be escaped by \ 10475c87c606SMark Murray */ 1048e71b7053SJung-uk Kim static int build_subject(X509_REQ *req, const char *subject, unsigned long chtype, 10496f9291ceSJung-uk Kim int multirdn) 10505c87c606SMark Murray { 10515c87c606SMark Murray X509_NAME *n; 10525c87c606SMark Murray 1053e71b7053SJung-uk Kim if ((n = parse_name(subject, chtype, multirdn)) == NULL) 10545c87c606SMark Murray return 0; 10555c87c606SMark Murray 10566f9291ceSJung-uk Kim if (!X509_REQ_set_subject_name(req, n)) { 10575c87c606SMark Murray X509_NAME_free(n); 10585c87c606SMark Murray return 0; 10595c87c606SMark Murray } 10605c87c606SMark Murray X509_NAME_free(n); 10615c87c606SMark Murray return 1; 10625c87c606SMark Murray } 10635c87c606SMark Murray 1064f579bf8eSKris Kennaway static int prompt_info(X509_REQ *req, 1065e71b7053SJung-uk Kim STACK_OF(CONF_VALUE) *dn_sk, const char *dn_sect, 1066e71b7053SJung-uk Kim STACK_OF(CONF_VALUE) *attr_sk, const char *attr_sect, 10676f9291ceSJung-uk Kim int attribs, unsigned long chtype) 1068f579bf8eSKris Kennaway { 1069f579bf8eSKris Kennaway int i; 1070f579bf8eSKris Kennaway char *p, *q; 1071f579bf8eSKris Kennaway char buf[100]; 10723b4e3dcbSSimon L. B. Nielsen int nid, mval; 10735c87c606SMark Murray long n_min, n_max; 10743b4e3dcbSSimon L. B. Nielsen char *type, *value; 10753b4e3dcbSSimon L. B. Nielsen const char *def; 1076f579bf8eSKris Kennaway CONF_VALUE *v; 1077f579bf8eSKris Kennaway X509_NAME *subj; 1078f579bf8eSKris Kennaway subj = X509_REQ_get_subject_name(req); 10795c87c606SMark Murray 10806f9291ceSJung-uk Kim if (!batch) { 10816f9291ceSJung-uk Kim BIO_printf(bio_err, 10826f9291ceSJung-uk Kim "You are about to be asked to enter information that will be incorporated\n"); 108374664626SKris Kennaway BIO_printf(bio_err, "into your certificate request.\n"); 10846f9291ceSJung-uk Kim BIO_printf(bio_err, 10856f9291ceSJung-uk Kim "What you are about to enter is what is called a Distinguished Name or a DN.\n"); 10866f9291ceSJung-uk Kim BIO_printf(bio_err, 10876f9291ceSJung-uk Kim "There are quite a few fields but you can leave some blank\n"); 10886f9291ceSJung-uk Kim BIO_printf(bio_err, 10896f9291ceSJung-uk Kim "For some fields there will be a default value,\n"); 10906f9291ceSJung-uk Kim BIO_printf(bio_err, 10916f9291ceSJung-uk Kim "If you enter '.', the field will be left blank.\n"); 109274664626SKris Kennaway BIO_printf(bio_err, "-----\n"); 10935c87c606SMark Murray } 109474664626SKris Kennaway 10956f9291ceSJung-uk Kim if (sk_CONF_VALUE_num(dn_sk)) { 109674664626SKris Kennaway i = -1; 1097e71b7053SJung-uk Kim start: 1098e71b7053SJung-uk Kim for ( ; ; ) { 109974664626SKris Kennaway i++; 11006f9291ceSJung-uk Kim if (sk_CONF_VALUE_num(dn_sk) <= i) 11016f9291ceSJung-uk Kim break; 110274664626SKris Kennaway 1103f579bf8eSKris Kennaway v = sk_CONF_VALUE_value(dn_sk, i); 110474664626SKris Kennaway p = q = NULL; 110574664626SKris Kennaway type = v->name; 110674664626SKris Kennaway if (!check_end(type, "_min") || !check_end(type, "_max") || 11076f9291ceSJung-uk Kim !check_end(type, "_default") || !check_end(type, "_value")) 11086f9291ceSJung-uk Kim continue; 11096f9291ceSJung-uk Kim /* 11106f9291ceSJung-uk Kim * Skip past any leading X. X: X, etc to allow for multiple 11116f9291ceSJung-uk Kim * instances 111274664626SKris Kennaway */ 111374664626SKris Kennaway for (p = v->name; *p; p++) 11146f9291ceSJung-uk Kim if ((*p == ':') || (*p == ',') || (*p == '.')) { 111574664626SKris Kennaway p++; 11166f9291ceSJung-uk Kim if (*p) 11176f9291ceSJung-uk Kim type = p; 111874664626SKris Kennaway break; 111974664626SKris Kennaway } 11206f9291ceSJung-uk Kim if (*type == '+') { 11213b4e3dcbSSimon L. B. Nielsen mval = -1; 11223b4e3dcbSSimon L. B. Nielsen type++; 1123e71b7053SJung-uk Kim } else { 11243b4e3dcbSSimon L. B. Nielsen mval = 0; 1125e71b7053SJung-uk Kim } 112674664626SKris Kennaway /* If OBJ not recognised ignore it */ 11276f9291ceSJung-uk Kim if ((nid = OBJ_txt2nid(type)) == NID_undef) 11286f9291ceSJung-uk Kim goto start; 1129e71b7053SJung-uk Kim if (!join(buf, sizeof(buf), v->name, "_default", "Name")) 11305c87c606SMark Murray return 0; 11316f9291ceSJung-uk Kim if ((def = NCONF_get_string(req_conf, dn_sect, buf)) == NULL) { 11325c87c606SMark Murray ERR_clear_error(); 11335c87c606SMark Murray def = ""; 11345c87c606SMark Murray } 1135ced566fdSJacques Vidrine 1136e71b7053SJung-uk Kim if (!join(buf, sizeof(buf), v->name, "_value", "Name")) 1137e71b7053SJung-uk Kim return 0; 11386f9291ceSJung-uk Kim if ((value = NCONF_get_string(req_conf, dn_sect, buf)) == NULL) { 11395c87c606SMark Murray ERR_clear_error(); 114074664626SKris Kennaway value = NULL; 11415c87c606SMark Murray } 114274664626SKris Kennaway 1143e71b7053SJung-uk Kim if (!join(buf, sizeof(buf), v->name, "_min", "Name")) 1144e71b7053SJung-uk Kim return 0; 11456f9291ceSJung-uk Kim if (!NCONF_get_number(req_conf, dn_sect, buf, &n_min)) { 1146fceca8a3SJacques Vidrine ERR_clear_error(); 11475c87c606SMark Murray n_min = -1; 1148fceca8a3SJacques Vidrine } 114974664626SKris Kennaway 1150e71b7053SJung-uk Kim 1151e71b7053SJung-uk Kim if (!join(buf, sizeof(buf), v->name, "_max", "Name")) 1152e71b7053SJung-uk Kim return 0; 11536f9291ceSJung-uk Kim if (!NCONF_get_number(req_conf, dn_sect, buf, &n_max)) { 1154fceca8a3SJacques Vidrine ERR_clear_error(); 11555c87c606SMark Murray n_max = -1; 1156fceca8a3SJacques Vidrine } 115774664626SKris Kennaway 1158f579bf8eSKris Kennaway if (!add_DN_object(subj, v->value, def, value, nid, 11593b4e3dcbSSimon L. B. Nielsen n_min, n_max, chtype, mval)) 1160f579bf8eSKris Kennaway return 0; 116174664626SKris Kennaway } 11626f9291ceSJung-uk Kim if (X509_NAME_entry_count(subj) == 0) { 11636f9291ceSJung-uk Kim BIO_printf(bio_err, 11646f9291ceSJung-uk Kim "error, no objects specified in config file\n"); 1165f579bf8eSKris Kennaway return 0; 116674664626SKris Kennaway } 116774664626SKris Kennaway 11686f9291ceSJung-uk Kim if (attribs) { 11696f9291ceSJung-uk Kim if ((attr_sk != NULL) && (sk_CONF_VALUE_num(attr_sk) > 0) 11706f9291ceSJung-uk Kim && (!batch)) { 11716f9291ceSJung-uk Kim BIO_printf(bio_err, 11726f9291ceSJung-uk Kim "\nPlease enter the following 'extra' attributes\n"); 11736f9291ceSJung-uk Kim BIO_printf(bio_err, 11746f9291ceSJung-uk Kim "to be sent with your certificate request\n"); 117574664626SKris Kennaway } 117674664626SKris Kennaway 117774664626SKris Kennaway i = -1; 1178e71b7053SJung-uk Kim start2: 1179e71b7053SJung-uk Kim for ( ; ; ) { 118074664626SKris Kennaway i++; 11816f9291ceSJung-uk Kim if ((attr_sk == NULL) || (sk_CONF_VALUE_num(attr_sk) <= i)) 118274664626SKris Kennaway break; 118374664626SKris Kennaway 1184f579bf8eSKris Kennaway v = sk_CONF_VALUE_value(attr_sk, i); 118574664626SKris Kennaway type = v->name; 118674664626SKris Kennaway if ((nid = OBJ_txt2nid(type)) == NID_undef) 118774664626SKris Kennaway goto start2; 118874664626SKris Kennaway 1189e71b7053SJung-uk Kim if (!join(buf, sizeof(buf), type, "_default", "Name")) 11905c87c606SMark Murray return 0; 11915c87c606SMark Murray if ((def = NCONF_get_string(req_conf, attr_sect, buf)) 11926f9291ceSJung-uk Kim == NULL) { 11935c87c606SMark Murray ERR_clear_error(); 119474664626SKris Kennaway def = ""; 11955c87c606SMark Murray } 11965c87c606SMark Murray 1197e71b7053SJung-uk Kim if (!join(buf, sizeof(buf), type, "_value", "Name")) 1198e71b7053SJung-uk Kim return 0; 11995c87c606SMark Murray if ((value = NCONF_get_string(req_conf, attr_sect, buf)) 12006f9291ceSJung-uk Kim == NULL) { 12015c87c606SMark Murray ERR_clear_error(); 120274664626SKris Kennaway value = NULL; 12035c87c606SMark Murray } 120474664626SKris Kennaway 1205e71b7053SJung-uk Kim if (!join(buf, sizeof(buf), type,"_min", "Name")) 1206e71b7053SJung-uk Kim return 0; 12076f9291ceSJung-uk Kim if (!NCONF_get_number(req_conf, attr_sect, buf, &n_min)) { 1208ab8565e2SSimon L. B. Nielsen ERR_clear_error(); 12095c87c606SMark Murray n_min = -1; 1210ab8565e2SSimon L. B. Nielsen } 121174664626SKris Kennaway 1212e71b7053SJung-uk Kim if (!join(buf, sizeof(buf), type, "_max", "Name")) 1213e71b7053SJung-uk Kim return 0; 12146f9291ceSJung-uk Kim if (!NCONF_get_number(req_conf, attr_sect, buf, &n_max)) { 1215ab8565e2SSimon L. B. Nielsen ERR_clear_error(); 12165c87c606SMark Murray n_max = -1; 1217ab8565e2SSimon L. B. Nielsen } 121874664626SKris Kennaway 1219f579bf8eSKris Kennaway if (!add_attribute_object(req, 12206f9291ceSJung-uk Kim v->value, def, value, nid, n_min, 12216f9291ceSJung-uk Kim n_max, chtype)) 1222f579bf8eSKris Kennaway return 0; 122374664626SKris Kennaway } 122474664626SKris Kennaway } 12256f9291ceSJung-uk Kim } else { 122674664626SKris Kennaway BIO_printf(bio_err, "No template, please set one up.\n"); 1227f579bf8eSKris Kennaway return 0; 122874664626SKris Kennaway } 122974664626SKris Kennaway 1230f579bf8eSKris Kennaway return 1; 123174664626SKris Kennaway 123274664626SKris Kennaway } 123374664626SKris Kennaway 1234f579bf8eSKris Kennaway static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *dn_sk, 12356f9291ceSJung-uk Kim STACK_OF(CONF_VALUE) *attr_sk, int attribs, 12366f9291ceSJung-uk Kim unsigned long chtype) 1237f579bf8eSKris Kennaway { 1238e71b7053SJung-uk Kim int i, spec_char, plus_char; 1239f579bf8eSKris Kennaway char *p, *q; 1240f579bf8eSKris Kennaway char *type; 1241f579bf8eSKris Kennaway CONF_VALUE *v; 1242f579bf8eSKris Kennaway X509_NAME *subj; 1243f579bf8eSKris Kennaway 1244f579bf8eSKris Kennaway subj = X509_REQ_get_subject_name(req); 1245f579bf8eSKris Kennaway 12466f9291ceSJung-uk Kim for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) { 12473b4e3dcbSSimon L. B. Nielsen int mval; 1248f579bf8eSKris Kennaway v = sk_CONF_VALUE_value(dn_sk, i); 1249f579bf8eSKris Kennaway p = q = NULL; 1250f579bf8eSKris Kennaway type = v->name; 12516f9291ceSJung-uk Kim /* 12526f9291ceSJung-uk Kim * Skip past any leading X. X: X, etc to allow for multiple instances 1253f579bf8eSKris Kennaway */ 1254e71b7053SJung-uk Kim for (p = v->name; *p; p++) { 1255ddd58736SKris Kennaway #ifndef CHARSET_EBCDIC 1256e71b7053SJung-uk Kim spec_char = ((*p == ':') || (*p == ',') || (*p == '.')); 1257ddd58736SKris Kennaway #else 1258e71b7053SJung-uk Kim spec_char = ((*p == os_toascii[':']) || (*p == os_toascii[',']) 1259e71b7053SJung-uk Kim || (*p == os_toascii['.'])); 1260ddd58736SKris Kennaway #endif 1261e71b7053SJung-uk Kim if (spec_char) { 1262f579bf8eSKris Kennaway p++; 12636f9291ceSJung-uk Kim if (*p) 12646f9291ceSJung-uk Kim type = p; 1265f579bf8eSKris Kennaway break; 1266f579bf8eSKris Kennaway } 1267e71b7053SJung-uk Kim } 12683b4e3dcbSSimon L. B. Nielsen #ifndef CHARSET_EBCDIC 1269e71b7053SJung-uk Kim plus_char = (*type == '+'); 12703b4e3dcbSSimon L. B. Nielsen #else 1271e71b7053SJung-uk Kim plus_char = (*type == os_toascii['+']); 12723b4e3dcbSSimon L. B. Nielsen #endif 1273e71b7053SJung-uk Kim if (plus_char) { 1274aeb5019cSJung-uk Kim type++; 12753b4e3dcbSSimon L. B. Nielsen mval = -1; 1276e71b7053SJung-uk Kim } else { 12773b4e3dcbSSimon L. B. Nielsen mval = 0; 1278e71b7053SJung-uk Kim } 12795c87c606SMark Murray if (!X509_NAME_add_entry_by_txt(subj, type, chtype, 12806f9291ceSJung-uk Kim (unsigned char *)v->value, -1, -1, 12816f9291ceSJung-uk Kim mval)) 12826f9291ceSJung-uk Kim return 0; 1283f579bf8eSKris Kennaway 1284f579bf8eSKris Kennaway } 1285f579bf8eSKris Kennaway 12866f9291ceSJung-uk Kim if (!X509_NAME_entry_count(subj)) { 1287f579bf8eSKris Kennaway BIO_printf(bio_err, "error, no objects specified in config file\n"); 1288f579bf8eSKris Kennaway return 0; 1289f579bf8eSKris Kennaway } 12906f9291ceSJung-uk Kim if (attribs) { 12916f9291ceSJung-uk Kim for (i = 0; i < sk_CONF_VALUE_num(attr_sk); i++) { 1292f579bf8eSKris Kennaway v = sk_CONF_VALUE_value(attr_sk, i); 12935c87c606SMark Murray if (!X509_REQ_add1_attr_by_txt(req, v->name, chtype, 12946f9291ceSJung-uk Kim (unsigned char *)v->value, -1)) 12956f9291ceSJung-uk Kim return 0; 1296f579bf8eSKris Kennaway } 1297f579bf8eSKris Kennaway } 1298f579bf8eSKris Kennaway return 1; 1299f579bf8eSKris Kennaway } 1300f579bf8eSKris Kennaway 13016f9291ceSJung-uk Kim static int add_DN_object(X509_NAME *n, char *text, const char *def, 13026f9291ceSJung-uk Kim char *value, int nid, int n_min, int n_max, 13036f9291ceSJung-uk Kim unsigned long chtype, int mval) 130474664626SKris Kennaway { 1305e71b7053SJung-uk Kim int ret = 0; 1306e71b7053SJung-uk Kim char buf[1024]; 130774664626SKris Kennaway 1308e71b7053SJung-uk Kim ret = build_data(text, def, value, n_min, n_max, buf, sizeof(buf), 1309e71b7053SJung-uk Kim "DN value", "DN default"); 1310e71b7053SJung-uk Kim if ((ret == 0) || (ret == 1)) 1311e71b7053SJung-uk Kim return ret; 1312e71b7053SJung-uk Kim ret = 1; 131394ad176cSJung-uk Kim 13145c87c606SMark Murray if (!X509_NAME_add_entry_by_NID(n, nid, chtype, 13156f9291ceSJung-uk Kim (unsigned char *)buf, -1, -1, mval)) 1316e71b7053SJung-uk Kim ret = 0; 1317e71b7053SJung-uk Kim 1318e71b7053SJung-uk Kim return ret; 131974664626SKris Kennaway } 132074664626SKris Kennaway 13213b4e3dcbSSimon L. B. Nielsen static int add_attribute_object(X509_REQ *req, char *text, const char *def, 13223b4e3dcbSSimon L. B. Nielsen char *value, int nid, int n_min, 13235c87c606SMark Murray int n_max, unsigned long chtype) 1324f579bf8eSKris Kennaway { 1325e71b7053SJung-uk Kim int ret = 0; 1326e71b7053SJung-uk Kim char buf[1024]; 132774664626SKris Kennaway 1328e71b7053SJung-uk Kim ret = build_data(text, def, value, n_min, n_max, buf, sizeof(buf), 1329e71b7053SJung-uk Kim "Attribute value", "Attribute default"); 1330e71b7053SJung-uk Kim if ((ret == 0) || (ret == 1)) 1331e71b7053SJung-uk Kim return ret; 1332e71b7053SJung-uk Kim ret = 1; 1333e71b7053SJung-uk Kim 1334e71b7053SJung-uk Kim if (!X509_REQ_add1_attr_by_NID(req, nid, chtype, 1335e71b7053SJung-uk Kim (unsigned char *)buf, -1)) { 1336e71b7053SJung-uk Kim BIO_printf(bio_err, "Error adding attribute\n"); 1337e71b7053SJung-uk Kim ERR_print_errors(bio_err); 1338e71b7053SJung-uk Kim ret = 0; 1339e71b7053SJung-uk Kim } 1340e71b7053SJung-uk Kim 1341e71b7053SJung-uk Kim return ret; 1342e71b7053SJung-uk Kim } 1343e71b7053SJung-uk Kim 1344e71b7053SJung-uk Kim 1345e71b7053SJung-uk Kim static int build_data(char *text, const char *def, 1346e71b7053SJung-uk Kim char *value, int n_min, int n_max, 1347e71b7053SJung-uk Kim char *buf, const int buf_size, 1348e71b7053SJung-uk Kim const char *desc1, const char *desc2 1349e71b7053SJung-uk Kim ) 1350e71b7053SJung-uk Kim { 1351e71b7053SJung-uk Kim int i; 1352f579bf8eSKris Kennaway start: 13536f9291ceSJung-uk Kim if (!batch) 13546f9291ceSJung-uk Kim BIO_printf(bio_err, "%s [%s]:", text, def); 1355f579bf8eSKris Kennaway (void)BIO_flush(bio_err); 13566f9291ceSJung-uk Kim if (value != NULL) { 1357e71b7053SJung-uk Kim if (!join(buf, buf_size, value, "\n", desc1)) 1358e71b7053SJung-uk Kim return 0; 1359f579bf8eSKris Kennaway BIO_printf(bio_err, "%s\n", value); 13606f9291ceSJung-uk Kim } else { 1361f579bf8eSKris Kennaway buf[0] = '\0'; 13626f9291ceSJung-uk Kim if (!batch) { 1363e71b7053SJung-uk Kim if (!fgets(buf, buf_size, stdin)) 13646a599222SSimon L. B. Nielsen return 0; 13656f9291ceSJung-uk Kim } else { 13665c87c606SMark Murray buf[0] = '\n'; 13675c87c606SMark Murray buf[1] = '\0'; 13685c87c606SMark Murray } 1369f579bf8eSKris Kennaway } 137074664626SKris Kennaway 13716f9291ceSJung-uk Kim if (buf[0] == '\0') 1372e71b7053SJung-uk Kim return 0; 1373e71b7053SJung-uk Kim if (buf[0] == '\n') { 1374f579bf8eSKris Kennaway if ((def == NULL) || (def[0] == '\0')) 1375e71b7053SJung-uk Kim return 1; 1376e71b7053SJung-uk Kim if (!join(buf, buf_size, def, "\n", desc2)) 1377e71b7053SJung-uk Kim return 0; 1378e71b7053SJung-uk Kim } else if ((buf[0] == '.') && (buf[1] == '\n')) { 1379e71b7053SJung-uk Kim return 1; 1380e71b7053SJung-uk Kim } 138174664626SKris Kennaway 1382f579bf8eSKris Kennaway i = strlen(buf); 13836f9291ceSJung-uk Kim if (buf[i - 1] != '\n') { 1384f579bf8eSKris Kennaway BIO_printf(bio_err, "weird input :-(\n"); 1385e71b7053SJung-uk Kim return 0; 1386f579bf8eSKris Kennaway } 1387f579bf8eSKris Kennaway buf[--i] = '\0'; 1388ddd58736SKris Kennaway #ifdef CHARSET_EBCDIC 1389ddd58736SKris Kennaway ebcdic2ascii(buf, buf, i); 1390ddd58736SKris Kennaway #endif 13916f9291ceSJung-uk Kim if (!req_check_len(i, n_min, n_max)) { 139294ad176cSJung-uk Kim if (batch || value) 139394ad176cSJung-uk Kim return 0; 139494ad176cSJung-uk Kim goto start; 139594ad176cSJung-uk Kim } 1396e71b7053SJung-uk Kim return 2; 139774664626SKris Kennaway } 139874664626SKris Kennaway 13995c87c606SMark Murray static int req_check_len(int len, int n_min, int n_max) 140074664626SKris Kennaway { 14016f9291ceSJung-uk Kim if ((n_min > 0) && (len < n_min)) { 14026f9291ceSJung-uk Kim BIO_printf(bio_err, 14036f9291ceSJung-uk Kim "string is too short, it needs to be at least %d bytes long\n", 14046f9291ceSJung-uk Kim n_min); 1405e71b7053SJung-uk Kim return 0; 140674664626SKris Kennaway } 14076f9291ceSJung-uk Kim if ((n_max >= 0) && (len > n_max)) { 14086f9291ceSJung-uk Kim BIO_printf(bio_err, 1409e71b7053SJung-uk Kim "string is too long, it needs to be no more than %d bytes long\n", 14106f9291ceSJung-uk Kim n_max); 1411e71b7053SJung-uk Kim return 0; 141274664626SKris Kennaway } 1413e71b7053SJung-uk Kim return 1; 141474664626SKris Kennaway } 141574664626SKris Kennaway 141674664626SKris Kennaway /* Check if the end of a string matches 'end' */ 14173b4e3dcbSSimon L. B. Nielsen static int check_end(const char *str, const char *end) 141874664626SKris Kennaway { 1419e71b7053SJung-uk Kim size_t elen, slen; 14203b4e3dcbSSimon L. B. Nielsen const char *tmp; 1421e71b7053SJung-uk Kim 142274664626SKris Kennaway elen = strlen(end); 142374664626SKris Kennaway slen = strlen(str); 14246f9291ceSJung-uk Kim if (elen > slen) 14256f9291ceSJung-uk Kim return 1; 142674664626SKris Kennaway tmp = str + slen - elen; 142774664626SKris Kennaway return strcmp(tmp, end); 142874664626SKris Kennaway } 14291f13597dSJung-uk Kim 1430e71b7053SJung-uk Kim /* 1431e71b7053SJung-uk Kim * Merge the two strings together into the result buffer checking for 1432e71b7053SJung-uk Kim * overflow and producing an error message if there is. 1433e71b7053SJung-uk Kim */ 1434e71b7053SJung-uk Kim static int join(char buf[], size_t buf_size, const char *name, 1435e71b7053SJung-uk Kim const char *tail, const char *desc) 1436e71b7053SJung-uk Kim { 1437e71b7053SJung-uk Kim const size_t name_len = strlen(name), tail_len = strlen(tail); 1438e71b7053SJung-uk Kim 1439e71b7053SJung-uk Kim if (name_len + tail_len + 1 > buf_size) { 1440e71b7053SJung-uk Kim BIO_printf(bio_err, "%s '%s' too long\n", desc, name); 1441e71b7053SJung-uk Kim return 0; 1442e71b7053SJung-uk Kim } 1443e71b7053SJung-uk Kim memcpy(buf, name, name_len); 1444e71b7053SJung-uk Kim memcpy(buf + name_len, tail, tail_len + 1); 1445e71b7053SJung-uk Kim return 1; 1446e71b7053SJung-uk Kim } 1447e71b7053SJung-uk Kim 1448e71b7053SJung-uk Kim static EVP_PKEY_CTX *set_keygen_ctx(const char *gstr, 14496f9291ceSJung-uk Kim int *pkey_type, long *pkeylen, 14506f9291ceSJung-uk Kim char **palgnam, ENGINE *keygen_engine) 14511f13597dSJung-uk Kim { 14521f13597dSJung-uk Kim EVP_PKEY_CTX *gctx = NULL; 14531f13597dSJung-uk Kim EVP_PKEY *param = NULL; 14541f13597dSJung-uk Kim long keylen = -1; 14551f13597dSJung-uk Kim BIO *pbio = NULL; 14561f13597dSJung-uk Kim const char *paramfile = NULL; 14571f13597dSJung-uk Kim 14586f9291ceSJung-uk Kim if (gstr == NULL) { 14591f13597dSJung-uk Kim *pkey_type = EVP_PKEY_RSA; 14601f13597dSJung-uk Kim keylen = *pkeylen; 14616f9291ceSJung-uk Kim } else if (gstr[0] >= '0' && gstr[0] <= '9') { 14621f13597dSJung-uk Kim *pkey_type = EVP_PKEY_RSA; 14631f13597dSJung-uk Kim keylen = atol(gstr); 14641f13597dSJung-uk Kim *pkeylen = keylen; 1465e71b7053SJung-uk Kim } else if (strncmp(gstr, "param:", 6) == 0) { 14661f13597dSJung-uk Kim paramfile = gstr + 6; 1467e71b7053SJung-uk Kim } else { 14681f13597dSJung-uk Kim const char *p = strchr(gstr, ':'); 14691f13597dSJung-uk Kim int len; 14701f13597dSJung-uk Kim ENGINE *tmpeng; 14711f13597dSJung-uk Kim const EVP_PKEY_ASN1_METHOD *ameth; 14721f13597dSJung-uk Kim 1473e71b7053SJung-uk Kim if (p != NULL) 14741f13597dSJung-uk Kim len = p - gstr; 14751f13597dSJung-uk Kim else 14761f13597dSJung-uk Kim len = strlen(gstr); 14776f9291ceSJung-uk Kim /* 14786f9291ceSJung-uk Kim * The lookup of a the string will cover all engines so keep a note 14796f9291ceSJung-uk Kim * of the implementation. 14801f13597dSJung-uk Kim */ 14811f13597dSJung-uk Kim 14821f13597dSJung-uk Kim ameth = EVP_PKEY_asn1_find_str(&tmpeng, gstr, len); 14831f13597dSJung-uk Kim 1484e71b7053SJung-uk Kim if (ameth == NULL) { 1485e71b7053SJung-uk Kim BIO_printf(bio_err, "Unknown algorithm %.*s\n", len, gstr); 14861f13597dSJung-uk Kim return NULL; 14871f13597dSJung-uk Kim } 14881f13597dSJung-uk Kim 14896f9291ceSJung-uk Kim EVP_PKEY_asn1_get0_info(NULL, pkey_type, NULL, NULL, NULL, ameth); 14901f13597dSJung-uk Kim #ifndef OPENSSL_NO_ENGINE 14911f13597dSJung-uk Kim ENGINE_finish(tmpeng); 14921f13597dSJung-uk Kim #endif 14936f9291ceSJung-uk Kim if (*pkey_type == EVP_PKEY_RSA) { 1494e71b7053SJung-uk Kim if (p != NULL) { 14951f13597dSJung-uk Kim keylen = atol(p + 1); 14961f13597dSJung-uk Kim *pkeylen = keylen; 1497e71b7053SJung-uk Kim } else { 1498560ede85SJung-uk Kim keylen = *pkeylen; 1499e71b7053SJung-uk Kim } 1500e71b7053SJung-uk Kim } else if (p != NULL) { 15011f13597dSJung-uk Kim paramfile = p + 1; 15021f13597dSJung-uk Kim } 1503e71b7053SJung-uk Kim } 15041f13597dSJung-uk Kim 1505e71b7053SJung-uk Kim if (paramfile != NULL) { 15061f13597dSJung-uk Kim pbio = BIO_new_file(paramfile, "r"); 1507e71b7053SJung-uk Kim if (pbio == NULL) { 1508e71b7053SJung-uk Kim BIO_printf(bio_err, "Can't open parameter file %s\n", paramfile); 15091f13597dSJung-uk Kim return NULL; 15101f13597dSJung-uk Kim } 15111f13597dSJung-uk Kim param = PEM_read_bio_Parameters(pbio, NULL); 15121f13597dSJung-uk Kim 1513e71b7053SJung-uk Kim if (param == NULL) { 15141f13597dSJung-uk Kim X509 *x; 1515e71b7053SJung-uk Kim 15161f13597dSJung-uk Kim (void)BIO_reset(pbio); 15171f13597dSJung-uk Kim x = PEM_read_bio_X509(pbio, NULL, NULL, NULL); 1518e71b7053SJung-uk Kim if (x != NULL) { 15191f13597dSJung-uk Kim param = X509_get_pubkey(x); 15201f13597dSJung-uk Kim X509_free(x); 15211f13597dSJung-uk Kim } 15221f13597dSJung-uk Kim } 15231f13597dSJung-uk Kim 15241f13597dSJung-uk Kim BIO_free(pbio); 15251f13597dSJung-uk Kim 1526e71b7053SJung-uk Kim if (param == NULL) { 1527e71b7053SJung-uk Kim BIO_printf(bio_err, "Error reading parameter file %s\n", paramfile); 15281f13597dSJung-uk Kim return NULL; 15291f13597dSJung-uk Kim } 1530e71b7053SJung-uk Kim if (*pkey_type == -1) { 15311f13597dSJung-uk Kim *pkey_type = EVP_PKEY_id(param); 1532e71b7053SJung-uk Kim } else if (*pkey_type != EVP_PKEY_base_id(param)) { 1533e71b7053SJung-uk Kim BIO_printf(bio_err, "Key Type does not match parameters\n"); 15341f13597dSJung-uk Kim EVP_PKEY_free(param); 15351f13597dSJung-uk Kim return NULL; 15361f13597dSJung-uk Kim } 15371f13597dSJung-uk Kim } 15381f13597dSJung-uk Kim 1539e71b7053SJung-uk Kim if (palgnam != NULL) { 15401f13597dSJung-uk Kim const EVP_PKEY_ASN1_METHOD *ameth; 15411f13597dSJung-uk Kim ENGINE *tmpeng; 15421f13597dSJung-uk Kim const char *anam; 1543e71b7053SJung-uk Kim 15441f13597dSJung-uk Kim ameth = EVP_PKEY_asn1_find(&tmpeng, *pkey_type); 1545e71b7053SJung-uk Kim if (ameth == NULL) { 1546e71b7053SJung-uk Kim BIO_puts(bio_err, "Internal error: can't find key algorithm\n"); 15471f13597dSJung-uk Kim return NULL; 15481f13597dSJung-uk Kim } 15491f13597dSJung-uk Kim EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL, &anam, ameth); 1550e71b7053SJung-uk Kim *palgnam = OPENSSL_strdup(anam); 15511f13597dSJung-uk Kim #ifndef OPENSSL_NO_ENGINE 15521f13597dSJung-uk Kim ENGINE_finish(tmpeng); 15531f13597dSJung-uk Kim #endif 15541f13597dSJung-uk Kim } 15551f13597dSJung-uk Kim 1556e71b7053SJung-uk Kim if (param != NULL) { 15571f13597dSJung-uk Kim gctx = EVP_PKEY_CTX_new(param, keygen_engine); 15581f13597dSJung-uk Kim *pkeylen = EVP_PKEY_bits(param); 15591f13597dSJung-uk Kim EVP_PKEY_free(param); 1560e71b7053SJung-uk Kim } else { 15611f13597dSJung-uk Kim gctx = EVP_PKEY_CTX_new_id(*pkey_type, keygen_engine); 1562e71b7053SJung-uk Kim } 15631f13597dSJung-uk Kim 1564e71b7053SJung-uk Kim if (gctx == NULL) { 1565e71b7053SJung-uk Kim BIO_puts(bio_err, "Error allocating keygen context\n"); 1566e71b7053SJung-uk Kim ERR_print_errors(bio_err); 15671f13597dSJung-uk Kim return NULL; 15681f13597dSJung-uk Kim } 15691f13597dSJung-uk Kim 15706f9291ceSJung-uk Kim if (EVP_PKEY_keygen_init(gctx) <= 0) { 1571e71b7053SJung-uk Kim BIO_puts(bio_err, "Error initializing keygen context\n"); 1572e71b7053SJung-uk Kim ERR_print_errors(bio_err); 1573e71b7053SJung-uk Kim EVP_PKEY_CTX_free(gctx); 15741f13597dSJung-uk Kim return NULL; 15751f13597dSJung-uk Kim } 15761f13597dSJung-uk Kim #ifndef OPENSSL_NO_RSA 15776f9291ceSJung-uk Kim if ((*pkey_type == EVP_PKEY_RSA) && (keylen != -1)) { 15786f9291ceSJung-uk Kim if (EVP_PKEY_CTX_set_rsa_keygen_bits(gctx, keylen) <= 0) { 1579e71b7053SJung-uk Kim BIO_puts(bio_err, "Error setting RSA keysize\n"); 1580e71b7053SJung-uk Kim ERR_print_errors(bio_err); 15811f13597dSJung-uk Kim EVP_PKEY_CTX_free(gctx); 15821f13597dSJung-uk Kim return NULL; 15831f13597dSJung-uk Kim } 15841f13597dSJung-uk Kim } 15851f13597dSJung-uk Kim #endif 15861f13597dSJung-uk Kim 15871f13597dSJung-uk Kim return gctx; 15881f13597dSJung-uk Kim } 15891f13597dSJung-uk Kim 15901f13597dSJung-uk Kim static int genpkey_cb(EVP_PKEY_CTX *ctx) 15911f13597dSJung-uk Kim { 15921f13597dSJung-uk Kim char c = '*'; 15931f13597dSJung-uk Kim BIO *b = EVP_PKEY_CTX_get_app_data(ctx); 15941f13597dSJung-uk Kim int p; 15951f13597dSJung-uk Kim p = EVP_PKEY_CTX_get_keygen_info(ctx, 0); 15966f9291ceSJung-uk Kim if (p == 0) 15976f9291ceSJung-uk Kim c = '.'; 15986f9291ceSJung-uk Kim if (p == 1) 15996f9291ceSJung-uk Kim c = '+'; 16006f9291ceSJung-uk Kim if (p == 2) 16016f9291ceSJung-uk Kim c = '*'; 16026f9291ceSJung-uk Kim if (p == 3) 16036f9291ceSJung-uk Kim c = '\n'; 16041f13597dSJung-uk Kim BIO_write(b, &c, 1); 16051f13597dSJung-uk Kim (void)BIO_flush(b); 16061f13597dSJung-uk Kim return 1; 16071f13597dSJung-uk Kim } 16081f13597dSJung-uk Kim 1609e71b7053SJung-uk Kim static int do_sign_init(EVP_MD_CTX *ctx, EVP_PKEY *pkey, 16101f13597dSJung-uk Kim const EVP_MD *md, STACK_OF(OPENSSL_STRING) *sigopts) 16111f13597dSJung-uk Kim { 16121f13597dSJung-uk Kim EVP_PKEY_CTX *pkctx = NULL; 1613e71b7053SJung-uk Kim int i, def_nid; 1614e71b7053SJung-uk Kim 1615e71b7053SJung-uk Kim if (ctx == NULL) 1616e71b7053SJung-uk Kim return 0; 1617e71b7053SJung-uk Kim /* 1618e71b7053SJung-uk Kim * EVP_PKEY_get_default_digest_nid() returns 2 if the digest is mandatory 1619e71b7053SJung-uk Kim * for this algorithm. 1620e71b7053SJung-uk Kim */ 1621e71b7053SJung-uk Kim if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) == 2 1622e71b7053SJung-uk Kim && def_nid == NID_undef) { 1623e71b7053SJung-uk Kim /* The signing algorithm requires there to be no digest */ 1624e71b7053SJung-uk Kim md = NULL; 1625e71b7053SJung-uk Kim } 16261f13597dSJung-uk Kim if (!EVP_DigestSignInit(ctx, &pkctx, md, NULL, pkey)) 16271f13597dSJung-uk Kim return 0; 16286f9291ceSJung-uk Kim for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) { 16291f13597dSJung-uk Kim char *sigopt = sk_OPENSSL_STRING_value(sigopts, i); 16306f9291ceSJung-uk Kim if (pkey_ctrl_string(pkctx, sigopt) <= 0) { 1631e71b7053SJung-uk Kim BIO_printf(bio_err, "parameter error \"%s\"\n", sigopt); 16321f13597dSJung-uk Kim ERR_print_errors(bio_err); 16331f13597dSJung-uk Kim return 0; 16341f13597dSJung-uk Kim } 16351f13597dSJung-uk Kim } 16361f13597dSJung-uk Kim return 1; 16371f13597dSJung-uk Kim } 16381f13597dSJung-uk Kim 1639e71b7053SJung-uk Kim int do_X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md, 16401f13597dSJung-uk Kim STACK_OF(OPENSSL_STRING) *sigopts) 16411f13597dSJung-uk Kim { 16421f13597dSJung-uk Kim int rv; 1643e71b7053SJung-uk Kim EVP_MD_CTX *mctx = EVP_MD_CTX_new(); 1644e71b7053SJung-uk Kim 1645e71b7053SJung-uk Kim rv = do_sign_init(mctx, pkey, md, sigopts); 16461f13597dSJung-uk Kim if (rv > 0) 1647e71b7053SJung-uk Kim rv = X509_sign_ctx(x, mctx); 1648e71b7053SJung-uk Kim EVP_MD_CTX_free(mctx); 16491f13597dSJung-uk Kim return rv > 0 ? 1 : 0; 16501f13597dSJung-uk Kim } 16511f13597dSJung-uk Kim 1652e71b7053SJung-uk Kim int do_X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md, 16531f13597dSJung-uk Kim STACK_OF(OPENSSL_STRING) *sigopts) 16541f13597dSJung-uk Kim { 16551f13597dSJung-uk Kim int rv; 1656e71b7053SJung-uk Kim EVP_MD_CTX *mctx = EVP_MD_CTX_new(); 1657e71b7053SJung-uk Kim rv = do_sign_init(mctx, pkey, md, sigopts); 16581f13597dSJung-uk Kim if (rv > 0) 1659e71b7053SJung-uk Kim rv = X509_REQ_sign_ctx(x, mctx); 1660e71b7053SJung-uk Kim EVP_MD_CTX_free(mctx); 16611f13597dSJung-uk Kim return rv > 0 ? 1 : 0; 16621f13597dSJung-uk Kim } 16631f13597dSJung-uk Kim 1664e71b7053SJung-uk Kim int do_X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md, 16651f13597dSJung-uk Kim STACK_OF(OPENSSL_STRING) *sigopts) 16661f13597dSJung-uk Kim { 16671f13597dSJung-uk Kim int rv; 1668e71b7053SJung-uk Kim EVP_MD_CTX *mctx = EVP_MD_CTX_new(); 1669e71b7053SJung-uk Kim rv = do_sign_init(mctx, pkey, md, sigopts); 16701f13597dSJung-uk Kim if (rv > 0) 1671e71b7053SJung-uk Kim rv = X509_CRL_sign_ctx(x, mctx); 1672e71b7053SJung-uk Kim EVP_MD_CTX_free(mctx); 16731f13597dSJung-uk Kim return rv > 0 ? 1 : 0; 16741f13597dSJung-uk Kim } 1675