16f9291ceSJung-uk Kim /* 2*e71b7053SJung-uk Kim * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. 3*e71b7053SJung-uk Kim * 4*e71b7053SJung-uk Kim * Licensed under the OpenSSL license (the "License"). You may not use 5*e71b7053SJung-uk Kim * this file except in compliance with the License. You can obtain a copy 6*e71b7053SJung-uk Kim * in the file LICENSE in the source distribution or at 7*e71b7053SJung-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> 14*e71b7053SJung-uk Kim #include <ctype.h> 1574664626SKris Kennaway #include "apps.h" 16*e71b7053SJung-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> 27*e71b7053SJung-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); 52*e71b7053SJung-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, 55*e71b7053SJung-uk Kim STACK_OF(CONF_VALUE) *dn_sk, const char *dn_sect, 56*e71b7053SJung-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); 68*e71b7053SJung-uk Kim static int build_data(char *text, const char *def, 69*e71b7053SJung-uk Kim char *value, int n_min, int n_max, 70*e71b7053SJung-uk Kim char *buf, const int buf_size, 71*e71b7053SJung-uk Kim const char *desc1, const char *desc2 72*e71b7053SJung-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); 75*e71b7053SJung-uk Kim static int join(char buf[], size_t buf_size, const char *name, 76*e71b7053SJung-uk Kim const char *tail, const char *desc); 77*e71b7053SJung-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; 81*e71b7053SJung-uk Kim static CONF *addext_conf = NULL; 825c87c606SMark Murray static int batch = 0; 8374664626SKris Kennaway 84*e71b7053SJung-uk Kim typedef enum OPTION_choice { 85*e71b7053SJung-uk Kim OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, 86*e71b7053SJung-uk Kim OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_KEYGEN_ENGINE, OPT_KEY, 87*e71b7053SJung-uk Kim OPT_PUBKEY, OPT_NEW, OPT_CONFIG, OPT_KEYFORM, OPT_IN, OPT_OUT, 88*e71b7053SJung-uk Kim OPT_KEYOUT, OPT_PASSIN, OPT_PASSOUT, OPT_NEWKEY, 89*e71b7053SJung-uk Kim OPT_PKEYOPT, OPT_SIGOPT, OPT_BATCH, OPT_NEWHDR, OPT_MODULUS, 90*e71b7053SJung-uk Kim OPT_VERIFY, OPT_NODES, OPT_NOOUT, OPT_VERBOSE, OPT_UTF8, 91*e71b7053SJung-uk Kim OPT_NAMEOPT, OPT_REQOPT, OPT_SUBJ, OPT_SUBJECT, OPT_TEXT, OPT_X509, 92*e71b7053SJung-uk Kim OPT_MULTIVALUE_RDN, OPT_DAYS, OPT_SET_SERIAL, OPT_ADDEXT, OPT_EXTENSIONS, 93*e71b7053SJung-uk Kim OPT_REQEXTS, OPT_PRECERT, OPT_MD, 94*e71b7053SJung-uk Kim OPT_R_ENUM 95*e71b7053SJung-uk Kim } OPTION_CHOICE; 96f579bf8eSKris Kennaway 97*e71b7053SJung-uk Kim const OPTIONS req_options[] = { 98*e71b7053SJung-uk Kim {"help", OPT_HELP, '-', "Display this summary"}, 99*e71b7053SJung-uk Kim {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"}, 100*e71b7053SJung-uk Kim {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"}, 101*e71b7053SJung-uk Kim {"in", OPT_IN, '<', "Input file"}, 102*e71b7053SJung-uk Kim {"out", OPT_OUT, '>', "Output file"}, 103*e71b7053SJung-uk Kim {"key", OPT_KEY, 's', "Private key to use"}, 104*e71b7053SJung-uk Kim {"keyform", OPT_KEYFORM, 'f', "Key file format"}, 105*e71b7053SJung-uk Kim {"pubkey", OPT_PUBKEY, '-', "Output public key"}, 106*e71b7053SJung-uk Kim {"new", OPT_NEW, '-', "New request"}, 107*e71b7053SJung-uk Kim {"config", OPT_CONFIG, '<', "Request template file"}, 108*e71b7053SJung-uk Kim {"keyout", OPT_KEYOUT, '>', "File to send the key to"}, 109*e71b7053SJung-uk Kim {"passin", OPT_PASSIN, 's', "Private key password source"}, 110*e71b7053SJung-uk Kim {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, 111*e71b7053SJung-uk Kim OPT_R_OPTIONS, 112*e71b7053SJung-uk Kim {"newkey", OPT_NEWKEY, 's', "Specify as type:bits"}, 113*e71b7053SJung-uk Kim {"pkeyopt", OPT_PKEYOPT, 's', "Public key options as opt:value"}, 114*e71b7053SJung-uk Kim {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"}, 115*e71b7053SJung-uk Kim {"batch", OPT_BATCH, '-', 116*e71b7053SJung-uk Kim "Do not ask anything during request generation"}, 117*e71b7053SJung-uk Kim {"newhdr", OPT_NEWHDR, '-', "Output \"NEW\" in the header lines"}, 118*e71b7053SJung-uk Kim {"modulus", OPT_MODULUS, '-', "RSA modulus"}, 119*e71b7053SJung-uk Kim {"verify", OPT_VERIFY, '-', "Verify signature on REQ"}, 120*e71b7053SJung-uk Kim {"nodes", OPT_NODES, '-', "Don't encrypt the output key"}, 121*e71b7053SJung-uk Kim {"noout", OPT_NOOUT, '-', "Do not output REQ"}, 122*e71b7053SJung-uk Kim {"verbose", OPT_VERBOSE, '-', "Verbose output"}, 123*e71b7053SJung-uk Kim {"utf8", OPT_UTF8, '-', "Input characters are UTF8 (default ASCII)"}, 124*e71b7053SJung-uk Kim {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"}, 125*e71b7053SJung-uk Kim {"reqopt", OPT_REQOPT, 's', "Various request text options"}, 126*e71b7053SJung-uk Kim {"text", OPT_TEXT, '-', "Text form of request"}, 127*e71b7053SJung-uk Kim {"x509", OPT_X509, '-', 128*e71b7053SJung-uk Kim "Output a x509 structure instead of a cert request"}, 129*e71b7053SJung-uk Kim {OPT_MORE_STR, 1, 1, "(Required by some CA's)"}, 130*e71b7053SJung-uk Kim {"subj", OPT_SUBJ, 's', "Set or modify request subject"}, 131*e71b7053SJung-uk Kim {"subject", OPT_SUBJECT, '-', "Output the request's subject"}, 132*e71b7053SJung-uk Kim {"multivalue-rdn", OPT_MULTIVALUE_RDN, '-', 133*e71b7053SJung-uk Kim "Enable support for multivalued RDNs"}, 134*e71b7053SJung-uk Kim {"days", OPT_DAYS, 'p', "Number of days cert is valid for"}, 135*e71b7053SJung-uk Kim {"set_serial", OPT_SET_SERIAL, 's', "Serial number to use"}, 136*e71b7053SJung-uk Kim {"addext", OPT_ADDEXT, 's', 137*e71b7053SJung-uk Kim "Additional cert extension key=value pair (may be given more than once)"}, 138*e71b7053SJung-uk Kim {"extensions", OPT_EXTENSIONS, 's', 139*e71b7053SJung-uk Kim "Cert extension section (override value in config file)"}, 140*e71b7053SJung-uk Kim {"reqexts", OPT_REQEXTS, 's', 141*e71b7053SJung-uk Kim "Request extension section (override value in config file)"}, 142*e71b7053SJung-uk Kim {"precert", OPT_PRECERT, '-', "Add a poison extension (implies -new)"}, 143*e71b7053SJung-uk Kim {"", OPT_MD, '-', "Any supported digest"}, 144*e71b7053SJung-uk Kim #ifndef OPENSSL_NO_ENGINE 145*e71b7053SJung-uk Kim {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, 146*e71b7053SJung-uk Kim {"keygen_engine", OPT_KEYGEN_ENGINE, 's', 147*e71b7053SJung-uk Kim "Specify engine to be used for key generation operations"}, 148*e71b7053SJung-uk Kim #endif 149*e71b7053SJung-uk Kim {NULL} 150*e71b7053SJung-uk Kim }; 151*e71b7053SJung-uk Kim 152*e71b7053SJung-uk Kim 153*e71b7053SJung-uk Kim /* 154*e71b7053SJung-uk Kim * An LHASH of strings, where each string is an extension name. 155*e71b7053SJung-uk Kim */ 156*e71b7053SJung-uk Kim static unsigned long ext_name_hash(const OPENSSL_STRING *a) 15774664626SKris Kennaway { 158*e71b7053SJung-uk Kim return OPENSSL_LH_strhash((const char *)a); 159*e71b7053SJung-uk Kim } 160*e71b7053SJung-uk Kim 161*e71b7053SJung-uk Kim static int ext_name_cmp(const OPENSSL_STRING *a, const OPENSSL_STRING *b) 162*e71b7053SJung-uk Kim { 163*e71b7053SJung-uk Kim return strcmp((const char *)a, (const char *)b); 164*e71b7053SJung-uk Kim } 165*e71b7053SJung-uk Kim 166*e71b7053SJung-uk Kim static void exts_cleanup(OPENSSL_STRING *x) 167*e71b7053SJung-uk Kim { 168*e71b7053SJung-uk Kim OPENSSL_free((char *)x); 169*e71b7053SJung-uk Kim } 170*e71b7053SJung-uk Kim 171*e71b7053SJung-uk Kim /* 172*e71b7053SJung-uk Kim * Is the |kv| key already duplicated? This is remarkably tricky to get 173*e71b7053SJung-uk Kim * right. Return 0 if unique, -1 on runtime error; 1 if found or a syntax 174*e71b7053SJung-uk Kim * error. 175*e71b7053SJung-uk Kim */ 176*e71b7053SJung-uk Kim static int duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv) 177*e71b7053SJung-uk Kim { 178*e71b7053SJung-uk Kim char *p; 179*e71b7053SJung-uk Kim size_t off; 180*e71b7053SJung-uk Kim 181*e71b7053SJung-uk Kim /* Check syntax. */ 182*e71b7053SJung-uk Kim /* Skip leading whitespace, make a copy. */ 183*e71b7053SJung-uk Kim while (*kv && isspace(*kv)) 184*e71b7053SJung-uk Kim if (*++kv == '\0') 185*e71b7053SJung-uk Kim return 1; 186*e71b7053SJung-uk Kim if ((p = strchr(kv, '=')) == NULL) 187*e71b7053SJung-uk Kim return 1; 188*e71b7053SJung-uk Kim off = p - kv; 189*e71b7053SJung-uk Kim if ((kv = OPENSSL_strdup(kv)) == NULL) 190*e71b7053SJung-uk Kim return -1; 191*e71b7053SJung-uk Kim 192*e71b7053SJung-uk Kim /* Skip trailing space before the equal sign. */ 193*e71b7053SJung-uk Kim for (p = kv + off; p > kv; --p) 194*e71b7053SJung-uk Kim if (!isspace(p[-1])) 195*e71b7053SJung-uk Kim break; 196*e71b7053SJung-uk Kim if (p == kv) { 197*e71b7053SJung-uk Kim OPENSSL_free(kv); 198*e71b7053SJung-uk Kim return 1; 199*e71b7053SJung-uk Kim } 200*e71b7053SJung-uk Kim *p = '\0'; 201*e71b7053SJung-uk Kim 202*e71b7053SJung-uk Kim /* Finally have a clean "key"; see if it's there [by attempt to add it]. */ 203*e71b7053SJung-uk Kim if ((p = (char *)lh_OPENSSL_STRING_insert(addexts, (OPENSSL_STRING*)kv)) 204*e71b7053SJung-uk Kim != NULL || lh_OPENSSL_STRING_error(addexts)) { 205*e71b7053SJung-uk Kim OPENSSL_free(p != NULL ? p : kv); 206*e71b7053SJung-uk Kim return -1; 207*e71b7053SJung-uk Kim } 208*e71b7053SJung-uk Kim 209*e71b7053SJung-uk Kim return 0; 210*e71b7053SJung-uk Kim } 211*e71b7053SJung-uk Kim 212*e71b7053SJung-uk Kim int req_main(int argc, char **argv) 213*e71b7053SJung-uk Kim { 214*e71b7053SJung-uk Kim ASN1_INTEGER *serial = NULL; 215*e71b7053SJung-uk Kim BIO *in = NULL, *out = NULL; 2161f13597dSJung-uk Kim ENGINE *e = NULL, *gen_eng = NULL; 217*e71b7053SJung-uk Kim EVP_PKEY *pkey = NULL; 218*e71b7053SJung-uk Kim EVP_PKEY_CTX *genctx = NULL; 219*e71b7053SJung-uk Kim STACK_OF(OPENSSL_STRING) *pkeyopts = NULL, *sigopts = NULL; 220*e71b7053SJung-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; 225*e71b7053SJung-uk Kim BIO *addext_bio = NULL; 226*e71b7053SJung-uk Kim char *extensions = NULL, *infile = NULL; 227*e71b7053SJung-uk Kim char *outfile = NULL, *keyfile = NULL; 228*e71b7053SJung-uk Kim char *keyalgstr = NULL, *p, *prog, *passargin = NULL, *passargout = NULL; 229*e71b7053SJung-uk Kim char *passin = NULL, *passout = NULL; 230*e71b7053SJung-uk Kim char *nofree_passin = NULL, *nofree_passout = NULL; 231*e71b7053SJung-uk Kim char *req_exts = NULL, *subj = NULL; 232*e71b7053SJung-uk Kim char *template = default_config_file, *keyout = NULL; 233*e71b7053SJung-uk Kim const char *keyalg = NULL; 234*e71b7053SJung-uk Kim OPTION_CHOICE o; 235*e71b7053SJung-uk Kim int ret = 1, x509 = 0, days = 0, i = 0, newreq = 0, verbose = 0; 236*e71b7053SJung-uk Kim int pkey_type = -1, private = 0; 237*e71b7053SJung-uk Kim int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyform = FORMAT_PEM; 238*e71b7053SJung-uk Kim int modulus = 0, multirdn = 0, verify = 0, noout = 0, text = 0; 239*e71b7053SJung-uk Kim int nodes = 0, newhdr = 0, subject = 0, pubkey = 0, precert = 0; 240*e71b7053SJung-uk Kim long newkey = -1; 241*e71b7053SJung-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 247*e71b7053SJung-uk Kim prog = opt_init(argc, argv, req_options); 248*e71b7053SJung-uk Kim while ((o = opt_next()) != OPT_EOF) { 249*e71b7053SJung-uk Kim switch (o) { 250*e71b7053SJung-uk Kim case OPT_EOF: 251*e71b7053SJung-uk Kim case OPT_ERR: 252*e71b7053SJung-uk Kim opthelp: 253*e71b7053SJung-uk Kim BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); 254*e71b7053SJung-uk Kim goto end; 255*e71b7053SJung-uk Kim case OPT_HELP: 256*e71b7053SJung-uk Kim opt_help(req_options); 257*e71b7053SJung-uk Kim ret = 0; 258*e71b7053SJung-uk Kim goto end; 259*e71b7053SJung-uk Kim case OPT_INFORM: 260*e71b7053SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) 261*e71b7053SJung-uk Kim goto opthelp; 262*e71b7053SJung-uk Kim break; 263*e71b7053SJung-uk Kim case OPT_OUTFORM: 264*e71b7053SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) 265*e71b7053SJung-uk Kim goto opthelp; 266*e71b7053SJung-uk Kim break; 267*e71b7053SJung-uk Kim case OPT_ENGINE: 268*e71b7053SJung-uk Kim e = setup_engine(opt_arg(), 0); 269*e71b7053SJung-uk Kim break; 270*e71b7053SJung-uk Kim case OPT_KEYGEN_ENGINE: 271fceca8a3SJacques Vidrine #ifndef OPENSSL_NO_ENGINE 272*e71b7053SJung-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); 275*e71b7053SJung-uk Kim goto opthelp; 2761f13597dSJung-uk Kim } 277fceca8a3SJacques Vidrine #endif 278*e71b7053SJung-uk Kim break; 279*e71b7053SJung-uk Kim case OPT_KEY: 280*e71b7053SJung-uk Kim keyfile = opt_arg(); 281*e71b7053SJung-uk Kim break; 282*e71b7053SJung-uk Kim case OPT_PUBKEY: 2835c87c606SMark Murray pubkey = 1; 284*e71b7053SJung-uk Kim break; 285*e71b7053SJung-uk Kim case OPT_NEW: 28674664626SKris Kennaway newreq = 1; 287*e71b7053SJung-uk Kim break; 288*e71b7053SJung-uk Kim case OPT_CONFIG: 289*e71b7053SJung-uk Kim template = opt_arg(); 290*e71b7053SJung-uk Kim break; 291*e71b7053SJung-uk Kim case OPT_KEYFORM: 292*e71b7053SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform)) 293*e71b7053SJung-uk Kim goto opthelp; 294*e71b7053SJung-uk Kim break; 295*e71b7053SJung-uk Kim case OPT_IN: 296*e71b7053SJung-uk Kim infile = opt_arg(); 297*e71b7053SJung-uk Kim break; 298*e71b7053SJung-uk Kim case OPT_OUT: 299*e71b7053SJung-uk Kim outfile = opt_arg(); 300*e71b7053SJung-uk Kim break; 301*e71b7053SJung-uk Kim case OPT_KEYOUT: 302*e71b7053SJung-uk Kim keyout = opt_arg(); 303*e71b7053SJung-uk Kim break; 304*e71b7053SJung-uk Kim case OPT_PASSIN: 305*e71b7053SJung-uk Kim passargin = opt_arg(); 306*e71b7053SJung-uk Kim break; 307*e71b7053SJung-uk Kim case OPT_PASSOUT: 308*e71b7053SJung-uk Kim passargout = opt_arg(); 309*e71b7053SJung-uk Kim break; 310*e71b7053SJung-uk Kim case OPT_R_CASES: 311*e71b7053SJung-uk Kim if (!opt_rand(o)) 312*e71b7053SJung-uk Kim goto end; 313*e71b7053SJung-uk Kim break; 314*e71b7053SJung-uk Kim case OPT_NEWKEY: 315*e71b7053SJung-uk Kim keyalg = opt_arg(); 3161f13597dSJung-uk Kim newreq = 1; 317*e71b7053SJung-uk Kim break; 318*e71b7053SJung-uk Kim case OPT_PKEYOPT: 3191f13597dSJung-uk Kim if (!pkeyopts) 3201f13597dSJung-uk Kim pkeyopts = sk_OPENSSL_STRING_new_null(); 321*e71b7053SJung-uk Kim if (!pkeyopts || !sk_OPENSSL_STRING_push(pkeyopts, opt_arg())) 322*e71b7053SJung-uk Kim goto opthelp; 323*e71b7053SJung-uk Kim break; 324*e71b7053SJung-uk Kim case OPT_SIGOPT: 3251f13597dSJung-uk Kim if (!sigopts) 3261f13597dSJung-uk Kim sigopts = sk_OPENSSL_STRING_new_null(); 327*e71b7053SJung-uk Kim if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg())) 328*e71b7053SJung-uk Kim goto opthelp; 32974664626SKris Kennaway break; 330*e71b7053SJung-uk Kim case OPT_BATCH: 331*e71b7053SJung-uk Kim batch = 1; 332*e71b7053SJung-uk Kim break; 333*e71b7053SJung-uk Kim case OPT_NEWHDR: 334*e71b7053SJung-uk Kim newhdr = 1; 335*e71b7053SJung-uk Kim break; 336*e71b7053SJung-uk Kim case OPT_MODULUS: 337*e71b7053SJung-uk Kim modulus = 1; 338*e71b7053SJung-uk Kim break; 339*e71b7053SJung-uk Kim case OPT_VERIFY: 340*e71b7053SJung-uk Kim verify = 1; 341*e71b7053SJung-uk Kim break; 342*e71b7053SJung-uk Kim case OPT_NODES: 343*e71b7053SJung-uk Kim nodes = 1; 344*e71b7053SJung-uk Kim break; 345*e71b7053SJung-uk Kim case OPT_NOOUT: 346*e71b7053SJung-uk Kim noout = 1; 347*e71b7053SJung-uk Kim break; 348*e71b7053SJung-uk Kim case OPT_VERBOSE: 349*e71b7053SJung-uk Kim verbose = 1; 350*e71b7053SJung-uk Kim break; 351*e71b7053SJung-uk Kim case OPT_UTF8: 352*e71b7053SJung-uk Kim chtype = MBSTRING_UTF8; 353*e71b7053SJung-uk Kim break; 354*e71b7053SJung-uk Kim case OPT_NAMEOPT: 355*e71b7053SJung-uk Kim if (!set_nameopt(opt_arg())) 356*e71b7053SJung-uk Kim goto opthelp; 357*e71b7053SJung-uk Kim break; 358*e71b7053SJung-uk Kim case OPT_REQOPT: 359*e71b7053SJung-uk Kim if (!set_cert_ex(&reqflag, opt_arg())) 360*e71b7053SJung-uk Kim goto opthelp; 361*e71b7053SJung-uk Kim break; 362*e71b7053SJung-uk Kim case OPT_TEXT: 363*e71b7053SJung-uk Kim text = 1; 364*e71b7053SJung-uk Kim break; 365*e71b7053SJung-uk Kim case OPT_X509: 366*e71b7053SJung-uk Kim x509 = 1; 367*e71b7053SJung-uk Kim break; 368*e71b7053SJung-uk Kim case OPT_DAYS: 369*e71b7053SJung-uk Kim days = atoi(opt_arg()); 370*e71b7053SJung-uk Kim break; 371*e71b7053SJung-uk Kim case OPT_SET_SERIAL: 372*e71b7053SJung-uk Kim if (serial != NULL) { 373*e71b7053SJung-uk Kim BIO_printf(bio_err, "Serial number supplied twice\n"); 374*e71b7053SJung-uk Kim goto opthelp; 37574664626SKris Kennaway } 376*e71b7053SJung-uk Kim serial = s2i_ASN1_INTEGER(NULL, opt_arg()); 377*e71b7053SJung-uk Kim if (serial == NULL) 378*e71b7053SJung-uk Kim goto opthelp; 379*e71b7053SJung-uk Kim break; 380*e71b7053SJung-uk Kim case OPT_SUBJECT: 381*e71b7053SJung-uk Kim subject = 1; 382*e71b7053SJung-uk Kim break; 383*e71b7053SJung-uk Kim case OPT_SUBJ: 384*e71b7053SJung-uk Kim subj = opt_arg(); 385*e71b7053SJung-uk Kim break; 386*e71b7053SJung-uk Kim case OPT_MULTIVALUE_RDN: 387*e71b7053SJung-uk Kim multirdn = 1; 388*e71b7053SJung-uk Kim break; 389*e71b7053SJung-uk Kim case OPT_ADDEXT: 390*e71b7053SJung-uk Kim p = opt_arg(); 391*e71b7053SJung-uk Kim if (addexts == NULL) { 392*e71b7053SJung-uk Kim addexts = lh_OPENSSL_STRING_new(ext_name_hash, ext_name_cmp); 393*e71b7053SJung-uk Kim addext_bio = BIO_new(BIO_s_mem()); 394*e71b7053SJung-uk Kim if (addexts == NULL || addext_bio == NULL) 39574664626SKris Kennaway goto end; 39674664626SKris Kennaway } 397*e71b7053SJung-uk Kim i = duplicated(addexts, p); 398*e71b7053SJung-uk Kim if (i == 1) 399*e71b7053SJung-uk Kim goto opthelp; 400*e71b7053SJung-uk Kim if (i < 0 || BIO_printf(addext_bio, "%s\n", opt_arg()) < 0) 401*e71b7053SJung-uk Kim goto end; 402*e71b7053SJung-uk Kim break; 403*e71b7053SJung-uk Kim case OPT_EXTENSIONS: 404*e71b7053SJung-uk Kim extensions = opt_arg(); 405*e71b7053SJung-uk Kim break; 406*e71b7053SJung-uk Kim case OPT_REQEXTS: 407*e71b7053SJung-uk Kim req_exts = opt_arg(); 408*e71b7053SJung-uk Kim break; 409*e71b7053SJung-uk Kim case OPT_PRECERT: 410*e71b7053SJung-uk Kim newreq = precert = 1; 411*e71b7053SJung-uk Kim break; 412*e71b7053SJung-uk Kim case OPT_MD: 413*e71b7053SJung-uk Kim if (!opt_md(opt_unknown(), &md_alg)) 414*e71b7053SJung-uk Kim goto opthelp; 415*e71b7053SJung-uk Kim digest = md_alg; 416*e71b7053SJung-uk Kim break; 417*e71b7053SJung-uk Kim } 418*e71b7053SJung-uk Kim } 419*e71b7053SJung-uk Kim argc = opt_num_rest(); 420*e71b7053SJung-uk Kim if (argc != 0) 421*e71b7053SJung-uk Kim goto opthelp; 42274664626SKris Kennaway 423*e71b7053SJung-uk Kim if (days && !x509) 424*e71b7053SJung-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 428*e71b7053SJung-uk Kim /* TODO: simplify this as pkey is still always NULL here */ 429*e71b7053SJung-uk Kim private = newreq && (pkey == NULL) ? 1 : 0; 430*e71b7053SJung-uk Kim 431*e71b7053SJung-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); 438*e71b7053SJung-uk Kim req_conf = app_load_config(template); 439*e71b7053SJung-uk Kim if (addext_bio) { 440*e71b7053SJung-uk Kim if (verbose) 441*e71b7053SJung-uk Kim BIO_printf(bio_err, 442*e71b7053SJung-uk Kim "Using additional configuration from command line\n"); 443*e71b7053SJung-uk Kim addext_conf = app_load_config_bio(addext_bio, NULL); 44474664626SKris Kennaway } 445*e71b7053SJung-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 } 467*e71b7053SJung-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"); 472*e71b7053SJung-uk Kim if (p == NULL) { 4735c87c606SMark Murray ERR_clear_error(); 474*e71b7053SJung-uk Kim } else { 475*e71b7053SJung-uk Kim if (!opt_md(p, &md_alg)) 476*e71b7053SJung-uk Kim goto opthelp; 47774664626SKris Kennaway digest = md_alg; 47874664626SKris Kennaway } 4795c87c606SMark Murray } 48074664626SKris Kennaway 481*e71b7053SJung-uk Kim if (extensions == NULL) { 4825c87c606SMark Murray extensions = NCONF_get_string(req_conf, SECTION, V3_EXTENSIONS); 483*e71b7053SJung-uk Kim if (extensions == NULL) 4845c87c606SMark Murray ERR_clear_error(); 4855c87c606SMark Murray } 486*e71b7053SJung-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 } 497*e71b7053SJung-uk Kim if (addext_conf != NULL) { 498*e71b7053SJung-uk Kim /* Check syntax of command line extensions */ 499*e71b7053SJung-uk Kim X509V3_CTX ctx; 500*e71b7053SJung-uk Kim X509V3_set_ctx_test(&ctx); 501*e71b7053SJung-uk Kim X509V3_set_nconf(&ctx, addext_conf); 502*e71b7053SJung-uk Kim if (!X509V3_EXT_add_nconf(addext_conf, &ctx, "default", NULL)) { 503*e71b7053SJung-uk Kim BIO_printf(bio_err, "Error Loading command line extensions\n"); 504*e71b7053SJung-uk Kim goto end; 505*e71b7053SJung-uk Kim } 506*e71b7053SJung-uk Kim } 50774664626SKris Kennaway 508*e71b7053SJung-uk Kim if (passin == NULL) { 509*e71b7053SJung-uk Kim passin = nofree_passin = 510*e71b7053SJung-uk Kim NCONF_get_string(req_conf, SECTION, "input_password"); 511*e71b7053SJung-uk Kim if (passin == NULL) 5125c87c606SMark Murray ERR_clear_error(); 5135c87c606SMark Murray } 514f579bf8eSKris Kennaway 515*e71b7053SJung-uk Kim if (passout == NULL) { 516*e71b7053SJung-uk Kim passout = nofree_passout = 517*e71b7053SJung-uk Kim NCONF_get_string(req_conf, SECTION, "output_password"); 518*e71b7053SJung-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); 523*e71b7053SJung-uk Kim if (p == NULL) 5245c87c606SMark Murray ERR_clear_error(); 525f579bf8eSKris Kennaway 526*e71b7053SJung-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); 533*e71b7053SJung-uk Kim if (p == NULL) 5345c87c606SMark Murray ERR_clear_error(); 535*e71b7053SJung-uk Kim else if (strcmp(p, "yes") == 0) 5365c87c606SMark Murray chtype = MBSTRING_UTF8; 5375c87c606SMark Murray } 5385c87c606SMark Murray 539*e71b7053SJung-uk Kim if (req_exts == NULL) { 5405c87c606SMark Murray req_exts = NCONF_get_string(req_conf, SECTION, REQ_EXTENSIONS); 541*e71b7053SJung-uk Kim if (req_exts == NULL) 5425c87c606SMark Murray ERR_clear_error(); 5435c87c606SMark Murray } 544*e71b7053SJung-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) { 558*e71b7053SJung-uk Kim pkey = load_key(keyfile, keyform, 0, passin, e, "Private Key"); 559*e71b7053SJung-uk Kim if (pkey == NULL) { 560*e71b7053SJung-uk Kim /* load_key() has already printed an appropriate message */ 56174664626SKris Kennaway goto end; 5626f9291ceSJung-uk Kim } else { 563*e71b7053SJung-uk Kim app_RAND_load_conf(req_conf, SECTION); 564ddd58736SKris Kennaway } 56574664626SKris Kennaway } 56674664626SKris Kennaway 5676f9291ceSJung-uk Kim if (newreq && (pkey == NULL)) { 568*e71b7053SJung-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 574*e71b7053SJung-uk Kim if (keyalg != NULL) { 575*e71b7053SJung-uk Kim genctx = set_keygen_ctx(keyalg, &pkey_type, &newkey, 5761f13597dSJung-uk Kim &keyalgstr, gen_eng); 577*e71b7053SJung-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 589*e71b7053SJung-uk Kim if (pkey_type == EVP_PKEY_RSA && newkey > OPENSSL_RSA_MAX_MODULUS_BITS) 590*e71b7053SJung-uk Kim BIO_printf(bio_err, 591*e71b7053SJung-uk Kim "Warning: It is not recommended to use more than %d bit for RSA keys.\n" 592*e71b7053SJung-uk Kim " Your key size is %ld! Larger key size may behave not as expected.\n", 593*e71b7053SJung-uk Kim OPENSSL_RSA_MAX_MODULUS_BITS, newkey); 594*e71b7053SJung-uk Kim 595*e71b7053SJung-uk Kim #ifndef OPENSSL_NO_DSA 596*e71b7053SJung-uk Kim if (pkey_type == EVP_PKEY_DSA && newkey > OPENSSL_DSA_MAX_MODULUS_BITS) 597*e71b7053SJung-uk Kim BIO_printf(bio_err, 598*e71b7053SJung-uk Kim "Warning: It is not recommended to use more than %d bit for DSA keys.\n" 599*e71b7053SJung-uk Kim " Your key size is %ld! Larger key size may behave not as expected.\n", 600*e71b7053SJung-uk Kim OPENSSL_DSA_MAX_MODULUS_BITS, newkey); 601*e71b7053SJung-uk Kim #endif 602*e71b7053SJung-uk Kim 603*e71b7053SJung-uk Kim if (genctx == NULL) { 604*e71b7053SJung-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 610*e71b7053SJung-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 622*e71b7053SJung-uk Kim if (pkey_type == EVP_PKEY_EC) { 623*e71b7053SJung-uk Kim BIO_printf(bio_err, "Generating an EC private key\n"); 624*e71b7053SJung-uk Kim } else { 625*e71b7053SJung-uk Kim BIO_printf(bio_err, "Generating a %s private key\n", keyalgstr); 626*e71b7053SJung-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 645*e71b7053SJung-uk Kim if (keyout == NULL) 64674664626SKris Kennaway BIO_printf(bio_err, "writing new private key to stdout\n"); 647*e71b7053SJung-uk Kim else 64874664626SKris Kennaway BIO_printf(bio_err, "writing new private key to '%s'\n", keyout); 649*e71b7053SJung-uk Kim out = bio_open_owner(keyout, outformat, private); 650*e71b7053SJung-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: 667*e71b7053SJung-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 } 678*e71b7053SJung-uk Kim BIO_free(out); 679*e71b7053SJung-uk Kim out = NULL; 68074664626SKris Kennaway BIO_printf(bio_err, "-----\n"); 68174664626SKris Kennaway } 68274664626SKris Kennaway 6836f9291ceSJung-uk Kim if (!newreq) { 684*e71b7053SJung-uk Kim in = bio_open_default(infile, 'r', informat); 685*e71b7053SJung-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); 690*e71b7053SJung-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 */ 724*e71b7053SJung-uk Kim if ((extensions != NULL || addext_conf != NULL) 725*e71b7053SJung-uk Kim && !X509_set_version(x509ss, 2)) 7266f9291ceSJung-uk Kim goto end; 727*e71b7053SJung-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; 737*e71b7053SJung-uk Kim if (days == 0) { 738*e71b7053SJung-uk Kim /* set default days if it's not specified */ 739*e71b7053SJung-uk Kim days = 30; 740*e71b7053SJung-uk Kim } 741*e71b7053SJung-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; 746*e71b7053SJung-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 */ 756*e71b7053SJung-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 } 763*e71b7053SJung-uk Kim if (addext_conf != NULL 764*e71b7053SJung-uk Kim && !X509V3_EXT_add_nconf(addext_conf, &ext_ctx, "default", 765*e71b7053SJung-uk Kim x509ss)) { 766*e71b7053SJung-uk Kim BIO_printf(bio_err, "Error Loading command line extensions\n"); 767*e71b7053SJung-uk Kim goto end; 768*e71b7053SJung-uk Kim } 76974664626SKris Kennaway 770*e71b7053SJung-uk Kim /* If a pre-cert was requested, we need to add a poison extension */ 771*e71b7053SJung-uk Kim if (precert) { 772*e71b7053SJung-uk Kim if (X509_add1_ext_i2d(x509ss, NID_ct_precert_poison, NULL, 1, 0) 773*e71b7053SJung-uk Kim != 1) { 774*e71b7053SJung-uk Kim BIO_printf(bio_err, "Error adding poison extension\n"); 775*e71b7053SJung-uk Kim goto end; 776*e71b7053SJung-uk Kim } 777*e71b7053SJung-uk Kim } 778*e71b7053SJung-uk Kim 779*e71b7053SJung-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 */ 793*e71b7053SJung-uk Kim if (req_exts != NULL 794*e71b7053SJung-uk Kim && !X509V3_EXT_REQ_add_nconf(req_conf, &ext_ctx, 795*e71b7053SJung-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 } 800*e71b7053SJung-uk Kim if (addext_conf != NULL 801*e71b7053SJung-uk Kim && !X509V3_EXT_REQ_add_nconf(addext_conf, &ext_ctx, "default", 802*e71b7053SJung-uk Kim req)) { 803*e71b7053SJung-uk Kim BIO_printf(bio_err, "Error Loading command line extensions\n"); 804*e71b7053SJung-uk Kim goto end; 805*e71b7053SJung-uk Kim } 806*e71b7053SJung-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) { 815*e71b7053SJung-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=", 823*e71b7053SJung-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"); 828*e71b7053SJung-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=", 834*e71b7053SJung-uk Kim X509_REQ_get_subject_name(req), get_nameopt()); 8355c87c606SMark Murray } 8365c87c606SMark Murray } 8375c87c606SMark Murray 8386f9291ceSJung-uk Kim if (verify && !x509) { 839*e71b7053SJung-uk Kim EVP_PKEY *tpubkey = pkey; 84074664626SKris Kennaway 841*e71b7053SJung-uk Kim if (tpubkey == NULL) { 842*e71b7053SJung-uk Kim tpubkey = X509_REQ_get0_pubkey(req); 843*e71b7053SJung-uk Kim if (tpubkey == NULL) 8446f9291ceSJung-uk Kim goto end; 84574664626SKris Kennaway } 84674664626SKris Kennaway 847*e71b7053SJung-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); 854*e71b7053SJung-uk Kim } else { /* if (i > 0) */ 85574664626SKris Kennaway BIO_printf(bio_err, "verify OK\n"); 85674664626SKris Kennaway } 857*e71b7053SJung-uk Kim } 85874664626SKris Kennaway 8596f9291ceSJung-uk Kim if (noout && !text && !modulus && !subject && !pubkey) { 860*e71b7053SJung-uk Kim ret = 0; 86174664626SKris Kennaway goto end; 86274664626SKris Kennaway } 86374664626SKris Kennaway 864*e71b7053SJung-uk Kim out = bio_open_default(outfile, 865*e71b7053SJung-uk Kim keyout != NULL && outfile != NULL && 866*e71b7053SJung-uk Kim strcmp(keyout, outfile) == 0 ? 'a' : 'w', 867*e71b7053SJung-uk Kim outformat); 868*e71b7053SJung-uk Kim if (out == NULL) 86974664626SKris Kennaway goto end; 87074664626SKris Kennaway 8716f9291ceSJung-uk Kim if (pubkey) { 872*e71b7053SJung-uk Kim EVP_PKEY *tpubkey = X509_REQ_get0_pubkey(req); 873*e71b7053SJung-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*e71b7053SJung-uk Kim X509_print_ex(out, x509ss, get_nameopt(), reqflag); 88574664626SKris Kennaway else 886*e71b7053SJung-uk Kim X509_REQ_print_ex(out, req, get_nameopt(), reqflag); 8875c87c606SMark Murray } 8885c87c606SMark Murray 8896f9291ceSJung-uk Kim if (subject) { 8905c87c606SMark Murray if (x509) 8916f9291ceSJung-uk Kim print_name(out, "subject=", X509_get_subject_name(x509ss), 892*e71b7053SJung-uk Kim get_nameopt()); 8935c87c606SMark Murray else 8946f9291ceSJung-uk Kim print_name(out, "subject=", X509_REQ_get_subject_name(req), 895*e71b7053SJung-uk Kim get_nameopt()); 89674664626SKris Kennaway } 89774664626SKris Kennaway 8986f9291ceSJung-uk Kim if (modulus) { 8995c87c606SMark Murray EVP_PKEY *tpubkey; 90074664626SKris Kennaway 90174664626SKris Kennaway if (x509) 902*e71b7053SJung-uk Kim tpubkey = X509_get0_pubkey(x509ss); 90374664626SKris Kennaway else 904*e71b7053SJung-uk Kim tpubkey = X509_REQ_get0_pubkey(req); 9056f9291ceSJung-uk Kim if (tpubkey == NULL) { 90674664626SKris Kennaway fprintf(stdout, "Modulus=unavailable\n"); 90774664626SKris Kennaway goto end; 90874664626SKris Kennaway } 90974664626SKris Kennaway fprintf(stdout, "Modulus="); 9105c87c606SMark Murray #ifndef OPENSSL_NO_RSA 911*e71b7053SJung-uk Kim if (EVP_PKEY_base_id(tpubkey) == EVP_PKEY_RSA) { 912*e71b7053SJung-uk Kim const BIGNUM *n; 913*e71b7053SJung-uk Kim RSA_get0_key(EVP_PKEY_get0_RSA(tpubkey), &n, NULL, NULL); 914*e71b7053SJung-uk Kim BN_print(out, n); 915*e71b7053SJung-uk Kim } else 91674664626SKris Kennaway #endif 91774664626SKris Kennaway fprintf(stdout, "Wrong Algorithm type"); 91874664626SKris Kennaway fprintf(stdout, "\n"); 91974664626SKris Kennaway } 92074664626SKris Kennaway 9216f9291ceSJung-uk Kim if (!noout && !x509) { 92274664626SKris Kennaway if (outformat == FORMAT_ASN1) 92374664626SKris Kennaway i = i2d_X509_REQ_bio(out, req); 924*e71b7053SJung-uk Kim else if (newhdr) 9256f9291ceSJung-uk Kim i = PEM_write_bio_X509_REQ_NEW(out, req); 9266f9291ceSJung-uk Kim else 9276f9291ceSJung-uk Kim i = PEM_write_bio_X509_REQ(out, req); 9286f9291ceSJung-uk Kim if (!i) { 92974664626SKris Kennaway BIO_printf(bio_err, "unable to write X509 request\n"); 93074664626SKris Kennaway goto end; 93174664626SKris Kennaway } 93274664626SKris Kennaway } 9336f9291ceSJung-uk Kim if (!noout && x509 && (x509ss != NULL)) { 93474664626SKris Kennaway if (outformat == FORMAT_ASN1) 93574664626SKris Kennaway i = i2d_X509_bio(out, x509ss); 936*e71b7053SJung-uk Kim else 93774664626SKris Kennaway i = PEM_write_bio_X509(out, x509ss); 9386f9291ceSJung-uk Kim if (!i) { 93974664626SKris Kennaway BIO_printf(bio_err, "unable to write X509 certificate\n"); 94074664626SKris Kennaway goto end; 94174664626SKris Kennaway } 94274664626SKris Kennaway } 943*e71b7053SJung-uk Kim ret = 0; 94474664626SKris Kennaway end: 945*e71b7053SJung-uk Kim if (ret) { 94674664626SKris Kennaway ERR_print_errors(bio_err); 94774664626SKris Kennaway } 9486f9291ceSJung-uk Kim NCONF_free(req_conf); 949*e71b7053SJung-uk Kim NCONF_free(addext_conf); 950*e71b7053SJung-uk Kim BIO_free(addext_bio); 95174664626SKris Kennaway BIO_free(in); 952ddd58736SKris Kennaway BIO_free_all(out); 95374664626SKris Kennaway EVP_PKEY_free(pkey); 9541f13597dSJung-uk Kim EVP_PKEY_CTX_free(genctx); 9551f13597dSJung-uk Kim sk_OPENSSL_STRING_free(pkeyopts); 9561f13597dSJung-uk Kim sk_OPENSSL_STRING_free(sigopts); 957*e71b7053SJung-uk Kim lh_OPENSSL_STRING_doall(addexts, exts_cleanup); 958*e71b7053SJung-uk Kim lh_OPENSSL_STRING_free(addexts); 9591f13597dSJung-uk Kim #ifndef OPENSSL_NO_ENGINE 9601f13597dSJung-uk Kim ENGINE_free(gen_eng); 9611f13597dSJung-uk Kim #endif 9621f13597dSJung-uk Kim OPENSSL_free(keyalgstr); 96374664626SKris Kennaway X509_REQ_free(req); 96474664626SKris Kennaway X509_free(x509ss); 9655c87c606SMark Murray ASN1_INTEGER_free(serial); 9666cf8931aSJung-uk Kim release_engine(e); 967*e71b7053SJung-uk Kim if (passin != nofree_passin) 9686f9291ceSJung-uk Kim OPENSSL_free(passin); 969*e71b7053SJung-uk Kim if (passout != nofree_passout) 9706f9291ceSJung-uk Kim OPENSSL_free(passout); 971*e71b7053SJung-uk Kim return ret; 97274664626SKris Kennaway } 97374664626SKris Kennaway 9743b4e3dcbSSimon L. B. Nielsen static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *subj, int multirdn, 9753b4e3dcbSSimon L. B. Nielsen int attribs, unsigned long chtype) 97674664626SKris Kennaway { 97774664626SKris Kennaway int ret = 0, i; 978f579bf8eSKris Kennaway char no_prompt = 0; 979f579bf8eSKris Kennaway STACK_OF(CONF_VALUE) *dn_sk, *attr_sk = NULL; 980f579bf8eSKris Kennaway char *tmp, *dn_sect, *attr_sect; 98174664626SKris Kennaway 9825c87c606SMark Murray tmp = NCONF_get_string(req_conf, SECTION, PROMPT); 9835c87c606SMark Murray if (tmp == NULL) 9845c87c606SMark Murray ERR_clear_error(); 985*e71b7053SJung-uk Kim if ((tmp != NULL) && strcmp(tmp, "no") == 0) 9866f9291ceSJung-uk Kim no_prompt = 1; 987f579bf8eSKris Kennaway 9885c87c606SMark Murray dn_sect = NCONF_get_string(req_conf, SECTION, DISTINGUISHED_NAME); 9896f9291ceSJung-uk Kim if (dn_sect == NULL) { 99074664626SKris Kennaway BIO_printf(bio_err, "unable to find '%s' in config\n", 99174664626SKris Kennaway DISTINGUISHED_NAME); 99274664626SKris Kennaway goto err; 99374664626SKris Kennaway } 9945c87c606SMark Murray dn_sk = NCONF_get_section(req_conf, dn_sect); 9956f9291ceSJung-uk Kim if (dn_sk == NULL) { 996f579bf8eSKris Kennaway BIO_printf(bio_err, "unable to get '%s' section\n", dn_sect); 99774664626SKris Kennaway goto err; 99874664626SKris Kennaway } 99974664626SKris Kennaway 10005c87c606SMark Murray attr_sect = NCONF_get_string(req_conf, SECTION, ATTRIBUTES); 10016f9291ceSJung-uk Kim if (attr_sect == NULL) { 10025c87c606SMark Murray ERR_clear_error(); 1003f579bf8eSKris Kennaway attr_sk = NULL; 10046f9291ceSJung-uk Kim } else { 10055c87c606SMark Murray attr_sk = NCONF_get_section(req_conf, attr_sect); 10066f9291ceSJung-uk Kim if (attr_sk == NULL) { 1007f579bf8eSKris Kennaway BIO_printf(bio_err, "unable to get '%s' section\n", attr_sect); 100874664626SKris Kennaway goto err; 100974664626SKris Kennaway } 101074664626SKris Kennaway } 101174664626SKris Kennaway 1012f579bf8eSKris Kennaway /* setup version number */ 10136f9291ceSJung-uk Kim if (!X509_REQ_set_version(req, 0L)) 10146f9291ceSJung-uk Kim goto err; /* version 1 */ 101574664626SKris Kennaway 10165c87c606SMark Murray if (subj) 10173b4e3dcbSSimon L. B. Nielsen i = build_subject(req, subj, chtype, multirdn); 1018*e71b7053SJung-uk Kim else if (no_prompt) 1019*e71b7053SJung-uk Kim i = auto_info(req, dn_sk, attr_sk, attribs, chtype); 10205c87c606SMark Murray else 10216f9291ceSJung-uk Kim i = prompt_info(req, dn_sk, dn_sect, attr_sk, attr_sect, attribs, 10226f9291ceSJung-uk Kim chtype); 10236f9291ceSJung-uk Kim if (!i) 10246f9291ceSJung-uk Kim goto err; 1025f579bf8eSKris Kennaway 10266f9291ceSJung-uk Kim if (!X509_REQ_set_pubkey(req, pkey)) 10276f9291ceSJung-uk Kim goto err; 1028f579bf8eSKris Kennaway 1029f579bf8eSKris Kennaway ret = 1; 1030f579bf8eSKris Kennaway err: 1031*e71b7053SJung-uk Kim return ret; 1032f579bf8eSKris Kennaway } 1033f579bf8eSKris Kennaway 10345c87c606SMark Murray /* 10355c87c606SMark Murray * subject is expected to be in the format /type0=value0/type1=value1/type2=... 10365c87c606SMark Murray * where characters may be escaped by \ 10375c87c606SMark Murray */ 1038*e71b7053SJung-uk Kim static int build_subject(X509_REQ *req, const char *subject, unsigned long chtype, 10396f9291ceSJung-uk Kim int multirdn) 10405c87c606SMark Murray { 10415c87c606SMark Murray X509_NAME *n; 10425c87c606SMark Murray 1043*e71b7053SJung-uk Kim if ((n = parse_name(subject, chtype, multirdn)) == NULL) 10445c87c606SMark Murray return 0; 10455c87c606SMark Murray 10466f9291ceSJung-uk Kim if (!X509_REQ_set_subject_name(req, n)) { 10475c87c606SMark Murray X509_NAME_free(n); 10485c87c606SMark Murray return 0; 10495c87c606SMark Murray } 10505c87c606SMark Murray X509_NAME_free(n); 10515c87c606SMark Murray return 1; 10525c87c606SMark Murray } 10535c87c606SMark Murray 1054f579bf8eSKris Kennaway static int prompt_info(X509_REQ *req, 1055*e71b7053SJung-uk Kim STACK_OF(CONF_VALUE) *dn_sk, const char *dn_sect, 1056*e71b7053SJung-uk Kim STACK_OF(CONF_VALUE) *attr_sk, const char *attr_sect, 10576f9291ceSJung-uk Kim int attribs, unsigned long chtype) 1058f579bf8eSKris Kennaway { 1059f579bf8eSKris Kennaway int i; 1060f579bf8eSKris Kennaway char *p, *q; 1061f579bf8eSKris Kennaway char buf[100]; 10623b4e3dcbSSimon L. B. Nielsen int nid, mval; 10635c87c606SMark Murray long n_min, n_max; 10643b4e3dcbSSimon L. B. Nielsen char *type, *value; 10653b4e3dcbSSimon L. B. Nielsen const char *def; 1066f579bf8eSKris Kennaway CONF_VALUE *v; 1067f579bf8eSKris Kennaway X509_NAME *subj; 1068f579bf8eSKris Kennaway subj = X509_REQ_get_subject_name(req); 10695c87c606SMark Murray 10706f9291ceSJung-uk Kim if (!batch) { 10716f9291ceSJung-uk Kim BIO_printf(bio_err, 10726f9291ceSJung-uk Kim "You are about to be asked to enter information that will be incorporated\n"); 107374664626SKris Kennaway BIO_printf(bio_err, "into your certificate request.\n"); 10746f9291ceSJung-uk Kim BIO_printf(bio_err, 10756f9291ceSJung-uk Kim "What you are about to enter is what is called a Distinguished Name or a DN.\n"); 10766f9291ceSJung-uk Kim BIO_printf(bio_err, 10776f9291ceSJung-uk Kim "There are quite a few fields but you can leave some blank\n"); 10786f9291ceSJung-uk Kim BIO_printf(bio_err, 10796f9291ceSJung-uk Kim "For some fields there will be a default value,\n"); 10806f9291ceSJung-uk Kim BIO_printf(bio_err, 10816f9291ceSJung-uk Kim "If you enter '.', the field will be left blank.\n"); 108274664626SKris Kennaway BIO_printf(bio_err, "-----\n"); 10835c87c606SMark Murray } 108474664626SKris Kennaway 10856f9291ceSJung-uk Kim if (sk_CONF_VALUE_num(dn_sk)) { 108674664626SKris Kennaway i = -1; 1087*e71b7053SJung-uk Kim start: 1088*e71b7053SJung-uk Kim for ( ; ; ) { 108974664626SKris Kennaway i++; 10906f9291ceSJung-uk Kim if (sk_CONF_VALUE_num(dn_sk) <= i) 10916f9291ceSJung-uk Kim break; 109274664626SKris Kennaway 1093f579bf8eSKris Kennaway v = sk_CONF_VALUE_value(dn_sk, i); 109474664626SKris Kennaway p = q = NULL; 109574664626SKris Kennaway type = v->name; 109674664626SKris Kennaway if (!check_end(type, "_min") || !check_end(type, "_max") || 10976f9291ceSJung-uk Kim !check_end(type, "_default") || !check_end(type, "_value")) 10986f9291ceSJung-uk Kim continue; 10996f9291ceSJung-uk Kim /* 11006f9291ceSJung-uk Kim * Skip past any leading X. X: X, etc to allow for multiple 11016f9291ceSJung-uk Kim * instances 110274664626SKris Kennaway */ 110374664626SKris Kennaway for (p = v->name; *p; p++) 11046f9291ceSJung-uk Kim if ((*p == ':') || (*p == ',') || (*p == '.')) { 110574664626SKris Kennaway p++; 11066f9291ceSJung-uk Kim if (*p) 11076f9291ceSJung-uk Kim type = p; 110874664626SKris Kennaway break; 110974664626SKris Kennaway } 11106f9291ceSJung-uk Kim if (*type == '+') { 11113b4e3dcbSSimon L. B. Nielsen mval = -1; 11123b4e3dcbSSimon L. B. Nielsen type++; 1113*e71b7053SJung-uk Kim } else { 11143b4e3dcbSSimon L. B. Nielsen mval = 0; 1115*e71b7053SJung-uk Kim } 111674664626SKris Kennaway /* If OBJ not recognised ignore it */ 11176f9291ceSJung-uk Kim if ((nid = OBJ_txt2nid(type)) == NID_undef) 11186f9291ceSJung-uk Kim goto start; 1119*e71b7053SJung-uk Kim if (!join(buf, sizeof(buf), v->name, "_default", "Name")) 11205c87c606SMark Murray return 0; 11216f9291ceSJung-uk Kim if ((def = NCONF_get_string(req_conf, dn_sect, buf)) == NULL) { 11225c87c606SMark Murray ERR_clear_error(); 11235c87c606SMark Murray def = ""; 11245c87c606SMark Murray } 1125ced566fdSJacques Vidrine 1126*e71b7053SJung-uk Kim if (!join(buf, sizeof(buf), v->name, "_value", "Name")) 1127*e71b7053SJung-uk Kim return 0; 11286f9291ceSJung-uk Kim if ((value = NCONF_get_string(req_conf, dn_sect, buf)) == NULL) { 11295c87c606SMark Murray ERR_clear_error(); 113074664626SKris Kennaway value = NULL; 11315c87c606SMark Murray } 113274664626SKris Kennaway 1133*e71b7053SJung-uk Kim if (!join(buf, sizeof(buf), v->name, "_min", "Name")) 1134*e71b7053SJung-uk Kim return 0; 11356f9291ceSJung-uk Kim if (!NCONF_get_number(req_conf, dn_sect, buf, &n_min)) { 1136fceca8a3SJacques Vidrine ERR_clear_error(); 11375c87c606SMark Murray n_min = -1; 1138fceca8a3SJacques Vidrine } 113974664626SKris Kennaway 1140*e71b7053SJung-uk Kim 1141*e71b7053SJung-uk Kim if (!join(buf, sizeof(buf), v->name, "_max", "Name")) 1142*e71b7053SJung-uk Kim return 0; 11436f9291ceSJung-uk Kim if (!NCONF_get_number(req_conf, dn_sect, buf, &n_max)) { 1144fceca8a3SJacques Vidrine ERR_clear_error(); 11455c87c606SMark Murray n_max = -1; 1146fceca8a3SJacques Vidrine } 114774664626SKris Kennaway 1148f579bf8eSKris Kennaway if (!add_DN_object(subj, v->value, def, value, nid, 11493b4e3dcbSSimon L. B. Nielsen n_min, n_max, chtype, mval)) 1150f579bf8eSKris Kennaway return 0; 115174664626SKris Kennaway } 11526f9291ceSJung-uk Kim if (X509_NAME_entry_count(subj) == 0) { 11536f9291ceSJung-uk Kim BIO_printf(bio_err, 11546f9291ceSJung-uk Kim "error, no objects specified in config file\n"); 1155f579bf8eSKris Kennaway return 0; 115674664626SKris Kennaway } 115774664626SKris Kennaway 11586f9291ceSJung-uk Kim if (attribs) { 11596f9291ceSJung-uk Kim if ((attr_sk != NULL) && (sk_CONF_VALUE_num(attr_sk) > 0) 11606f9291ceSJung-uk Kim && (!batch)) { 11616f9291ceSJung-uk Kim BIO_printf(bio_err, 11626f9291ceSJung-uk Kim "\nPlease enter the following 'extra' attributes\n"); 11636f9291ceSJung-uk Kim BIO_printf(bio_err, 11646f9291ceSJung-uk Kim "to be sent with your certificate request\n"); 116574664626SKris Kennaway } 116674664626SKris Kennaway 116774664626SKris Kennaway i = -1; 1168*e71b7053SJung-uk Kim start2: 1169*e71b7053SJung-uk Kim for ( ; ; ) { 117074664626SKris Kennaway i++; 11716f9291ceSJung-uk Kim if ((attr_sk == NULL) || (sk_CONF_VALUE_num(attr_sk) <= i)) 117274664626SKris Kennaway break; 117374664626SKris Kennaway 1174f579bf8eSKris Kennaway v = sk_CONF_VALUE_value(attr_sk, i); 117574664626SKris Kennaway type = v->name; 117674664626SKris Kennaway if ((nid = OBJ_txt2nid(type)) == NID_undef) 117774664626SKris Kennaway goto start2; 117874664626SKris Kennaway 1179*e71b7053SJung-uk Kim if (!join(buf, sizeof(buf), type, "_default", "Name")) 11805c87c606SMark Murray return 0; 11815c87c606SMark Murray if ((def = NCONF_get_string(req_conf, attr_sect, buf)) 11826f9291ceSJung-uk Kim == NULL) { 11835c87c606SMark Murray ERR_clear_error(); 118474664626SKris Kennaway def = ""; 11855c87c606SMark Murray } 11865c87c606SMark Murray 1187*e71b7053SJung-uk Kim if (!join(buf, sizeof(buf), type, "_value", "Name")) 1188*e71b7053SJung-uk Kim return 0; 11895c87c606SMark Murray if ((value = NCONF_get_string(req_conf, attr_sect, buf)) 11906f9291ceSJung-uk Kim == NULL) { 11915c87c606SMark Murray ERR_clear_error(); 119274664626SKris Kennaway value = NULL; 11935c87c606SMark Murray } 119474664626SKris Kennaway 1195*e71b7053SJung-uk Kim if (!join(buf, sizeof(buf), type,"_min", "Name")) 1196*e71b7053SJung-uk Kim return 0; 11976f9291ceSJung-uk Kim if (!NCONF_get_number(req_conf, attr_sect, buf, &n_min)) { 1198ab8565e2SSimon L. B. Nielsen ERR_clear_error(); 11995c87c606SMark Murray n_min = -1; 1200ab8565e2SSimon L. B. Nielsen } 120174664626SKris Kennaway 1202*e71b7053SJung-uk Kim if (!join(buf, sizeof(buf), type, "_max", "Name")) 1203*e71b7053SJung-uk Kim return 0; 12046f9291ceSJung-uk Kim if (!NCONF_get_number(req_conf, attr_sect, buf, &n_max)) { 1205ab8565e2SSimon L. B. Nielsen ERR_clear_error(); 12065c87c606SMark Murray n_max = -1; 1207ab8565e2SSimon L. B. Nielsen } 120874664626SKris Kennaway 1209f579bf8eSKris Kennaway if (!add_attribute_object(req, 12106f9291ceSJung-uk Kim v->value, def, value, nid, n_min, 12116f9291ceSJung-uk Kim n_max, chtype)) 1212f579bf8eSKris Kennaway return 0; 121374664626SKris Kennaway } 121474664626SKris Kennaway } 12156f9291ceSJung-uk Kim } else { 121674664626SKris Kennaway BIO_printf(bio_err, "No template, please set one up.\n"); 1217f579bf8eSKris Kennaway return 0; 121874664626SKris Kennaway } 121974664626SKris Kennaway 1220f579bf8eSKris Kennaway return 1; 122174664626SKris Kennaway 122274664626SKris Kennaway } 122374664626SKris Kennaway 1224f579bf8eSKris Kennaway static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *dn_sk, 12256f9291ceSJung-uk Kim STACK_OF(CONF_VALUE) *attr_sk, int attribs, 12266f9291ceSJung-uk Kim unsigned long chtype) 1227f579bf8eSKris Kennaway { 1228*e71b7053SJung-uk Kim int i, spec_char, plus_char; 1229f579bf8eSKris Kennaway char *p, *q; 1230f579bf8eSKris Kennaway char *type; 1231f579bf8eSKris Kennaway CONF_VALUE *v; 1232f579bf8eSKris Kennaway X509_NAME *subj; 1233f579bf8eSKris Kennaway 1234f579bf8eSKris Kennaway subj = X509_REQ_get_subject_name(req); 1235f579bf8eSKris Kennaway 12366f9291ceSJung-uk Kim for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) { 12373b4e3dcbSSimon L. B. Nielsen int mval; 1238f579bf8eSKris Kennaway v = sk_CONF_VALUE_value(dn_sk, i); 1239f579bf8eSKris Kennaway p = q = NULL; 1240f579bf8eSKris Kennaway type = v->name; 12416f9291ceSJung-uk Kim /* 12426f9291ceSJung-uk Kim * Skip past any leading X. X: X, etc to allow for multiple instances 1243f579bf8eSKris Kennaway */ 1244*e71b7053SJung-uk Kim for (p = v->name; *p; p++) { 1245ddd58736SKris Kennaway #ifndef CHARSET_EBCDIC 1246*e71b7053SJung-uk Kim spec_char = ((*p == ':') || (*p == ',') || (*p == '.')); 1247ddd58736SKris Kennaway #else 1248*e71b7053SJung-uk Kim spec_char = ((*p == os_toascii[':']) || (*p == os_toascii[',']) 1249*e71b7053SJung-uk Kim || (*p == os_toascii['.'])); 1250ddd58736SKris Kennaway #endif 1251*e71b7053SJung-uk Kim if (spec_char) { 1252f579bf8eSKris Kennaway p++; 12536f9291ceSJung-uk Kim if (*p) 12546f9291ceSJung-uk Kim type = p; 1255f579bf8eSKris Kennaway break; 1256f579bf8eSKris Kennaway } 1257*e71b7053SJung-uk Kim } 12583b4e3dcbSSimon L. B. Nielsen #ifndef CHARSET_EBCDIC 1259*e71b7053SJung-uk Kim plus_char = (*type == '+'); 12603b4e3dcbSSimon L. B. Nielsen #else 1261*e71b7053SJung-uk Kim plus_char = (*type == os_toascii['+']); 12623b4e3dcbSSimon L. B. Nielsen #endif 1263*e71b7053SJung-uk Kim if (plus_char) { 1264aeb5019cSJung-uk Kim type++; 12653b4e3dcbSSimon L. B. Nielsen mval = -1; 1266*e71b7053SJung-uk Kim } else { 12673b4e3dcbSSimon L. B. Nielsen mval = 0; 1268*e71b7053SJung-uk Kim } 12695c87c606SMark Murray if (!X509_NAME_add_entry_by_txt(subj, type, chtype, 12706f9291ceSJung-uk Kim (unsigned char *)v->value, -1, -1, 12716f9291ceSJung-uk Kim mval)) 12726f9291ceSJung-uk Kim return 0; 1273f579bf8eSKris Kennaway 1274f579bf8eSKris Kennaway } 1275f579bf8eSKris Kennaway 12766f9291ceSJung-uk Kim if (!X509_NAME_entry_count(subj)) { 1277f579bf8eSKris Kennaway BIO_printf(bio_err, "error, no objects specified in config file\n"); 1278f579bf8eSKris Kennaway return 0; 1279f579bf8eSKris Kennaway } 12806f9291ceSJung-uk Kim if (attribs) { 12816f9291ceSJung-uk Kim for (i = 0; i < sk_CONF_VALUE_num(attr_sk); i++) { 1282f579bf8eSKris Kennaway v = sk_CONF_VALUE_value(attr_sk, i); 12835c87c606SMark Murray if (!X509_REQ_add1_attr_by_txt(req, v->name, chtype, 12846f9291ceSJung-uk Kim (unsigned char *)v->value, -1)) 12856f9291ceSJung-uk Kim return 0; 1286f579bf8eSKris Kennaway } 1287f579bf8eSKris Kennaway } 1288f579bf8eSKris Kennaway return 1; 1289f579bf8eSKris Kennaway } 1290f579bf8eSKris Kennaway 12916f9291ceSJung-uk Kim static int add_DN_object(X509_NAME *n, char *text, const char *def, 12926f9291ceSJung-uk Kim char *value, int nid, int n_min, int n_max, 12936f9291ceSJung-uk Kim unsigned long chtype, int mval) 129474664626SKris Kennaway { 1295*e71b7053SJung-uk Kim int ret = 0; 1296*e71b7053SJung-uk Kim char buf[1024]; 129774664626SKris Kennaway 1298*e71b7053SJung-uk Kim ret = build_data(text, def, value, n_min, n_max, buf, sizeof(buf), 1299*e71b7053SJung-uk Kim "DN value", "DN default"); 1300*e71b7053SJung-uk Kim if ((ret == 0) || (ret == 1)) 1301*e71b7053SJung-uk Kim return ret; 1302*e71b7053SJung-uk Kim ret = 1; 130394ad176cSJung-uk Kim 13045c87c606SMark Murray if (!X509_NAME_add_entry_by_NID(n, nid, chtype, 13056f9291ceSJung-uk Kim (unsigned char *)buf, -1, -1, mval)) 1306*e71b7053SJung-uk Kim ret = 0; 1307*e71b7053SJung-uk Kim 1308*e71b7053SJung-uk Kim return ret; 130974664626SKris Kennaway } 131074664626SKris Kennaway 13113b4e3dcbSSimon L. B. Nielsen static int add_attribute_object(X509_REQ *req, char *text, const char *def, 13123b4e3dcbSSimon L. B. Nielsen char *value, int nid, int n_min, 13135c87c606SMark Murray int n_max, unsigned long chtype) 1314f579bf8eSKris Kennaway { 1315*e71b7053SJung-uk Kim int ret = 0; 1316*e71b7053SJung-uk Kim char buf[1024]; 131774664626SKris Kennaway 1318*e71b7053SJung-uk Kim ret = build_data(text, def, value, n_min, n_max, buf, sizeof(buf), 1319*e71b7053SJung-uk Kim "Attribute value", "Attribute default"); 1320*e71b7053SJung-uk Kim if ((ret == 0) || (ret == 1)) 1321*e71b7053SJung-uk Kim return ret; 1322*e71b7053SJung-uk Kim ret = 1; 1323*e71b7053SJung-uk Kim 1324*e71b7053SJung-uk Kim if (!X509_REQ_add1_attr_by_NID(req, nid, chtype, 1325*e71b7053SJung-uk Kim (unsigned char *)buf, -1)) { 1326*e71b7053SJung-uk Kim BIO_printf(bio_err, "Error adding attribute\n"); 1327*e71b7053SJung-uk Kim ERR_print_errors(bio_err); 1328*e71b7053SJung-uk Kim ret = 0; 1329*e71b7053SJung-uk Kim } 1330*e71b7053SJung-uk Kim 1331*e71b7053SJung-uk Kim return ret; 1332*e71b7053SJung-uk Kim } 1333*e71b7053SJung-uk Kim 1334*e71b7053SJung-uk Kim 1335*e71b7053SJung-uk Kim static int build_data(char *text, const char *def, 1336*e71b7053SJung-uk Kim char *value, int n_min, int n_max, 1337*e71b7053SJung-uk Kim char *buf, const int buf_size, 1338*e71b7053SJung-uk Kim const char *desc1, const char *desc2 1339*e71b7053SJung-uk Kim ) 1340*e71b7053SJung-uk Kim { 1341*e71b7053SJung-uk Kim int i; 1342f579bf8eSKris Kennaway start: 13436f9291ceSJung-uk Kim if (!batch) 13446f9291ceSJung-uk Kim BIO_printf(bio_err, "%s [%s]:", text, def); 1345f579bf8eSKris Kennaway (void)BIO_flush(bio_err); 13466f9291ceSJung-uk Kim if (value != NULL) { 1347*e71b7053SJung-uk Kim if (!join(buf, buf_size, value, "\n", desc1)) 1348*e71b7053SJung-uk Kim return 0; 1349f579bf8eSKris Kennaway BIO_printf(bio_err, "%s\n", value); 13506f9291ceSJung-uk Kim } else { 1351f579bf8eSKris Kennaway buf[0] = '\0'; 13526f9291ceSJung-uk Kim if (!batch) { 1353*e71b7053SJung-uk Kim if (!fgets(buf, buf_size, stdin)) 13546a599222SSimon L. B. Nielsen return 0; 13556f9291ceSJung-uk Kim } else { 13565c87c606SMark Murray buf[0] = '\n'; 13575c87c606SMark Murray buf[1] = '\0'; 13585c87c606SMark Murray } 1359f579bf8eSKris Kennaway } 136074664626SKris Kennaway 13616f9291ceSJung-uk Kim if (buf[0] == '\0') 1362*e71b7053SJung-uk Kim return 0; 1363*e71b7053SJung-uk Kim if (buf[0] == '\n') { 1364f579bf8eSKris Kennaway if ((def == NULL) || (def[0] == '\0')) 1365*e71b7053SJung-uk Kim return 1; 1366*e71b7053SJung-uk Kim if (!join(buf, buf_size, def, "\n", desc2)) 1367*e71b7053SJung-uk Kim return 0; 1368*e71b7053SJung-uk Kim } else if ((buf[0] == '.') && (buf[1] == '\n')) { 1369*e71b7053SJung-uk Kim return 1; 1370*e71b7053SJung-uk Kim } 137174664626SKris Kennaway 1372f579bf8eSKris Kennaway i = strlen(buf); 13736f9291ceSJung-uk Kim if (buf[i - 1] != '\n') { 1374f579bf8eSKris Kennaway BIO_printf(bio_err, "weird input :-(\n"); 1375*e71b7053SJung-uk Kim return 0; 1376f579bf8eSKris Kennaway } 1377f579bf8eSKris Kennaway buf[--i] = '\0'; 1378ddd58736SKris Kennaway #ifdef CHARSET_EBCDIC 1379ddd58736SKris Kennaway ebcdic2ascii(buf, buf, i); 1380ddd58736SKris Kennaway #endif 13816f9291ceSJung-uk Kim if (!req_check_len(i, n_min, n_max)) { 138294ad176cSJung-uk Kim if (batch || value) 138394ad176cSJung-uk Kim return 0; 138494ad176cSJung-uk Kim goto start; 138594ad176cSJung-uk Kim } 1386*e71b7053SJung-uk Kim return 2; 138774664626SKris Kennaway } 138874664626SKris Kennaway 13895c87c606SMark Murray static int req_check_len(int len, int n_min, int n_max) 139074664626SKris Kennaway { 13916f9291ceSJung-uk Kim if ((n_min > 0) && (len < n_min)) { 13926f9291ceSJung-uk Kim BIO_printf(bio_err, 13936f9291ceSJung-uk Kim "string is too short, it needs to be at least %d bytes long\n", 13946f9291ceSJung-uk Kim n_min); 1395*e71b7053SJung-uk Kim return 0; 139674664626SKris Kennaway } 13976f9291ceSJung-uk Kim if ((n_max >= 0) && (len > n_max)) { 13986f9291ceSJung-uk Kim BIO_printf(bio_err, 1399*e71b7053SJung-uk Kim "string is too long, it needs to be no more than %d bytes long\n", 14006f9291ceSJung-uk Kim n_max); 1401*e71b7053SJung-uk Kim return 0; 140274664626SKris Kennaway } 1403*e71b7053SJung-uk Kim return 1; 140474664626SKris Kennaway } 140574664626SKris Kennaway 140674664626SKris Kennaway /* Check if the end of a string matches 'end' */ 14073b4e3dcbSSimon L. B. Nielsen static int check_end(const char *str, const char *end) 140874664626SKris Kennaway { 1409*e71b7053SJung-uk Kim size_t elen, slen; 14103b4e3dcbSSimon L. B. Nielsen const char *tmp; 1411*e71b7053SJung-uk Kim 141274664626SKris Kennaway elen = strlen(end); 141374664626SKris Kennaway slen = strlen(str); 14146f9291ceSJung-uk Kim if (elen > slen) 14156f9291ceSJung-uk Kim return 1; 141674664626SKris Kennaway tmp = str + slen - elen; 141774664626SKris Kennaway return strcmp(tmp, end); 141874664626SKris Kennaway } 14191f13597dSJung-uk Kim 1420*e71b7053SJung-uk Kim /* 1421*e71b7053SJung-uk Kim * Merge the two strings together into the result buffer checking for 1422*e71b7053SJung-uk Kim * overflow and producing an error message if there is. 1423*e71b7053SJung-uk Kim */ 1424*e71b7053SJung-uk Kim static int join(char buf[], size_t buf_size, const char *name, 1425*e71b7053SJung-uk Kim const char *tail, const char *desc) 1426*e71b7053SJung-uk Kim { 1427*e71b7053SJung-uk Kim const size_t name_len = strlen(name), tail_len = strlen(tail); 1428*e71b7053SJung-uk Kim 1429*e71b7053SJung-uk Kim if (name_len + tail_len + 1 > buf_size) { 1430*e71b7053SJung-uk Kim BIO_printf(bio_err, "%s '%s' too long\n", desc, name); 1431*e71b7053SJung-uk Kim return 0; 1432*e71b7053SJung-uk Kim } 1433*e71b7053SJung-uk Kim memcpy(buf, name, name_len); 1434*e71b7053SJung-uk Kim memcpy(buf + name_len, tail, tail_len + 1); 1435*e71b7053SJung-uk Kim return 1; 1436*e71b7053SJung-uk Kim } 1437*e71b7053SJung-uk Kim 1438*e71b7053SJung-uk Kim static EVP_PKEY_CTX *set_keygen_ctx(const char *gstr, 14396f9291ceSJung-uk Kim int *pkey_type, long *pkeylen, 14406f9291ceSJung-uk Kim char **palgnam, ENGINE *keygen_engine) 14411f13597dSJung-uk Kim { 14421f13597dSJung-uk Kim EVP_PKEY_CTX *gctx = NULL; 14431f13597dSJung-uk Kim EVP_PKEY *param = NULL; 14441f13597dSJung-uk Kim long keylen = -1; 14451f13597dSJung-uk Kim BIO *pbio = NULL; 14461f13597dSJung-uk Kim const char *paramfile = NULL; 14471f13597dSJung-uk Kim 14486f9291ceSJung-uk Kim if (gstr == NULL) { 14491f13597dSJung-uk Kim *pkey_type = EVP_PKEY_RSA; 14501f13597dSJung-uk Kim keylen = *pkeylen; 14516f9291ceSJung-uk Kim } else if (gstr[0] >= '0' && gstr[0] <= '9') { 14521f13597dSJung-uk Kim *pkey_type = EVP_PKEY_RSA; 14531f13597dSJung-uk Kim keylen = atol(gstr); 14541f13597dSJung-uk Kim *pkeylen = keylen; 1455*e71b7053SJung-uk Kim } else if (strncmp(gstr, "param:", 6) == 0) { 14561f13597dSJung-uk Kim paramfile = gstr + 6; 1457*e71b7053SJung-uk Kim } else { 14581f13597dSJung-uk Kim const char *p = strchr(gstr, ':'); 14591f13597dSJung-uk Kim int len; 14601f13597dSJung-uk Kim ENGINE *tmpeng; 14611f13597dSJung-uk Kim const EVP_PKEY_ASN1_METHOD *ameth; 14621f13597dSJung-uk Kim 1463*e71b7053SJung-uk Kim if (p != NULL) 14641f13597dSJung-uk Kim len = p - gstr; 14651f13597dSJung-uk Kim else 14661f13597dSJung-uk Kim len = strlen(gstr); 14676f9291ceSJung-uk Kim /* 14686f9291ceSJung-uk Kim * The lookup of a the string will cover all engines so keep a note 14696f9291ceSJung-uk Kim * of the implementation. 14701f13597dSJung-uk Kim */ 14711f13597dSJung-uk Kim 14721f13597dSJung-uk Kim ameth = EVP_PKEY_asn1_find_str(&tmpeng, gstr, len); 14731f13597dSJung-uk Kim 1474*e71b7053SJung-uk Kim if (ameth == NULL) { 1475*e71b7053SJung-uk Kim BIO_printf(bio_err, "Unknown algorithm %.*s\n", len, gstr); 14761f13597dSJung-uk Kim return NULL; 14771f13597dSJung-uk Kim } 14781f13597dSJung-uk Kim 14796f9291ceSJung-uk Kim EVP_PKEY_asn1_get0_info(NULL, pkey_type, NULL, NULL, NULL, ameth); 14801f13597dSJung-uk Kim #ifndef OPENSSL_NO_ENGINE 14811f13597dSJung-uk Kim ENGINE_finish(tmpeng); 14821f13597dSJung-uk Kim #endif 14836f9291ceSJung-uk Kim if (*pkey_type == EVP_PKEY_RSA) { 1484*e71b7053SJung-uk Kim if (p != NULL) { 14851f13597dSJung-uk Kim keylen = atol(p + 1); 14861f13597dSJung-uk Kim *pkeylen = keylen; 1487*e71b7053SJung-uk Kim } else { 1488560ede85SJung-uk Kim keylen = *pkeylen; 1489*e71b7053SJung-uk Kim } 1490*e71b7053SJung-uk Kim } else if (p != NULL) { 14911f13597dSJung-uk Kim paramfile = p + 1; 14921f13597dSJung-uk Kim } 1493*e71b7053SJung-uk Kim } 14941f13597dSJung-uk Kim 1495*e71b7053SJung-uk Kim if (paramfile != NULL) { 14961f13597dSJung-uk Kim pbio = BIO_new_file(paramfile, "r"); 1497*e71b7053SJung-uk Kim if (pbio == NULL) { 1498*e71b7053SJung-uk Kim BIO_printf(bio_err, "Can't open parameter file %s\n", paramfile); 14991f13597dSJung-uk Kim return NULL; 15001f13597dSJung-uk Kim } 15011f13597dSJung-uk Kim param = PEM_read_bio_Parameters(pbio, NULL); 15021f13597dSJung-uk Kim 1503*e71b7053SJung-uk Kim if (param == NULL) { 15041f13597dSJung-uk Kim X509 *x; 1505*e71b7053SJung-uk Kim 15061f13597dSJung-uk Kim (void)BIO_reset(pbio); 15071f13597dSJung-uk Kim x = PEM_read_bio_X509(pbio, NULL, NULL, NULL); 1508*e71b7053SJung-uk Kim if (x != NULL) { 15091f13597dSJung-uk Kim param = X509_get_pubkey(x); 15101f13597dSJung-uk Kim X509_free(x); 15111f13597dSJung-uk Kim } 15121f13597dSJung-uk Kim } 15131f13597dSJung-uk Kim 15141f13597dSJung-uk Kim BIO_free(pbio); 15151f13597dSJung-uk Kim 1516*e71b7053SJung-uk Kim if (param == NULL) { 1517*e71b7053SJung-uk Kim BIO_printf(bio_err, "Error reading parameter file %s\n", paramfile); 15181f13597dSJung-uk Kim return NULL; 15191f13597dSJung-uk Kim } 1520*e71b7053SJung-uk Kim if (*pkey_type == -1) { 15211f13597dSJung-uk Kim *pkey_type = EVP_PKEY_id(param); 1522*e71b7053SJung-uk Kim } else if (*pkey_type != EVP_PKEY_base_id(param)) { 1523*e71b7053SJung-uk Kim BIO_printf(bio_err, "Key Type does not match parameters\n"); 15241f13597dSJung-uk Kim EVP_PKEY_free(param); 15251f13597dSJung-uk Kim return NULL; 15261f13597dSJung-uk Kim } 15271f13597dSJung-uk Kim } 15281f13597dSJung-uk Kim 1529*e71b7053SJung-uk Kim if (palgnam != NULL) { 15301f13597dSJung-uk Kim const EVP_PKEY_ASN1_METHOD *ameth; 15311f13597dSJung-uk Kim ENGINE *tmpeng; 15321f13597dSJung-uk Kim const char *anam; 1533*e71b7053SJung-uk Kim 15341f13597dSJung-uk Kim ameth = EVP_PKEY_asn1_find(&tmpeng, *pkey_type); 1535*e71b7053SJung-uk Kim if (ameth == NULL) { 1536*e71b7053SJung-uk Kim BIO_puts(bio_err, "Internal error: can't find key algorithm\n"); 15371f13597dSJung-uk Kim return NULL; 15381f13597dSJung-uk Kim } 15391f13597dSJung-uk Kim EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL, &anam, ameth); 1540*e71b7053SJung-uk Kim *palgnam = OPENSSL_strdup(anam); 15411f13597dSJung-uk Kim #ifndef OPENSSL_NO_ENGINE 15421f13597dSJung-uk Kim ENGINE_finish(tmpeng); 15431f13597dSJung-uk Kim #endif 15441f13597dSJung-uk Kim } 15451f13597dSJung-uk Kim 1546*e71b7053SJung-uk Kim if (param != NULL) { 15471f13597dSJung-uk Kim gctx = EVP_PKEY_CTX_new(param, keygen_engine); 15481f13597dSJung-uk Kim *pkeylen = EVP_PKEY_bits(param); 15491f13597dSJung-uk Kim EVP_PKEY_free(param); 1550*e71b7053SJung-uk Kim } else { 15511f13597dSJung-uk Kim gctx = EVP_PKEY_CTX_new_id(*pkey_type, keygen_engine); 1552*e71b7053SJung-uk Kim } 15531f13597dSJung-uk Kim 1554*e71b7053SJung-uk Kim if (gctx == NULL) { 1555*e71b7053SJung-uk Kim BIO_puts(bio_err, "Error allocating keygen context\n"); 1556*e71b7053SJung-uk Kim ERR_print_errors(bio_err); 15571f13597dSJung-uk Kim return NULL; 15581f13597dSJung-uk Kim } 15591f13597dSJung-uk Kim 15606f9291ceSJung-uk Kim if (EVP_PKEY_keygen_init(gctx) <= 0) { 1561*e71b7053SJung-uk Kim BIO_puts(bio_err, "Error initializing keygen context\n"); 1562*e71b7053SJung-uk Kim ERR_print_errors(bio_err); 1563*e71b7053SJung-uk Kim EVP_PKEY_CTX_free(gctx); 15641f13597dSJung-uk Kim return NULL; 15651f13597dSJung-uk Kim } 15661f13597dSJung-uk Kim #ifndef OPENSSL_NO_RSA 15676f9291ceSJung-uk Kim if ((*pkey_type == EVP_PKEY_RSA) && (keylen != -1)) { 15686f9291ceSJung-uk Kim if (EVP_PKEY_CTX_set_rsa_keygen_bits(gctx, keylen) <= 0) { 1569*e71b7053SJung-uk Kim BIO_puts(bio_err, "Error setting RSA keysize\n"); 1570*e71b7053SJung-uk Kim ERR_print_errors(bio_err); 15711f13597dSJung-uk Kim EVP_PKEY_CTX_free(gctx); 15721f13597dSJung-uk Kim return NULL; 15731f13597dSJung-uk Kim } 15741f13597dSJung-uk Kim } 15751f13597dSJung-uk Kim #endif 15761f13597dSJung-uk Kim 15771f13597dSJung-uk Kim return gctx; 15781f13597dSJung-uk Kim } 15791f13597dSJung-uk Kim 15801f13597dSJung-uk Kim static int genpkey_cb(EVP_PKEY_CTX *ctx) 15811f13597dSJung-uk Kim { 15821f13597dSJung-uk Kim char c = '*'; 15831f13597dSJung-uk Kim BIO *b = EVP_PKEY_CTX_get_app_data(ctx); 15841f13597dSJung-uk Kim int p; 15851f13597dSJung-uk Kim p = EVP_PKEY_CTX_get_keygen_info(ctx, 0); 15866f9291ceSJung-uk Kim if (p == 0) 15876f9291ceSJung-uk Kim c = '.'; 15886f9291ceSJung-uk Kim if (p == 1) 15896f9291ceSJung-uk Kim c = '+'; 15906f9291ceSJung-uk Kim if (p == 2) 15916f9291ceSJung-uk Kim c = '*'; 15926f9291ceSJung-uk Kim if (p == 3) 15936f9291ceSJung-uk Kim c = '\n'; 15941f13597dSJung-uk Kim BIO_write(b, &c, 1); 15951f13597dSJung-uk Kim (void)BIO_flush(b); 15961f13597dSJung-uk Kim return 1; 15971f13597dSJung-uk Kim } 15981f13597dSJung-uk Kim 1599*e71b7053SJung-uk Kim static int do_sign_init(EVP_MD_CTX *ctx, EVP_PKEY *pkey, 16001f13597dSJung-uk Kim const EVP_MD *md, STACK_OF(OPENSSL_STRING) *sigopts) 16011f13597dSJung-uk Kim { 16021f13597dSJung-uk Kim EVP_PKEY_CTX *pkctx = NULL; 1603*e71b7053SJung-uk Kim int i, def_nid; 1604*e71b7053SJung-uk Kim 1605*e71b7053SJung-uk Kim if (ctx == NULL) 1606*e71b7053SJung-uk Kim return 0; 1607*e71b7053SJung-uk Kim /* 1608*e71b7053SJung-uk Kim * EVP_PKEY_get_default_digest_nid() returns 2 if the digest is mandatory 1609*e71b7053SJung-uk Kim * for this algorithm. 1610*e71b7053SJung-uk Kim */ 1611*e71b7053SJung-uk Kim if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) == 2 1612*e71b7053SJung-uk Kim && def_nid == NID_undef) { 1613*e71b7053SJung-uk Kim /* The signing algorithm requires there to be no digest */ 1614*e71b7053SJung-uk Kim md = NULL; 1615*e71b7053SJung-uk Kim } 16161f13597dSJung-uk Kim if (!EVP_DigestSignInit(ctx, &pkctx, md, NULL, pkey)) 16171f13597dSJung-uk Kim return 0; 16186f9291ceSJung-uk Kim for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) { 16191f13597dSJung-uk Kim char *sigopt = sk_OPENSSL_STRING_value(sigopts, i); 16206f9291ceSJung-uk Kim if (pkey_ctrl_string(pkctx, sigopt) <= 0) { 1621*e71b7053SJung-uk Kim BIO_printf(bio_err, "parameter error \"%s\"\n", sigopt); 16221f13597dSJung-uk Kim ERR_print_errors(bio_err); 16231f13597dSJung-uk Kim return 0; 16241f13597dSJung-uk Kim } 16251f13597dSJung-uk Kim } 16261f13597dSJung-uk Kim return 1; 16271f13597dSJung-uk Kim } 16281f13597dSJung-uk Kim 1629*e71b7053SJung-uk Kim int do_X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md, 16301f13597dSJung-uk Kim STACK_OF(OPENSSL_STRING) *sigopts) 16311f13597dSJung-uk Kim { 16321f13597dSJung-uk Kim int rv; 1633*e71b7053SJung-uk Kim EVP_MD_CTX *mctx = EVP_MD_CTX_new(); 1634*e71b7053SJung-uk Kim 1635*e71b7053SJung-uk Kim rv = do_sign_init(mctx, pkey, md, sigopts); 16361f13597dSJung-uk Kim if (rv > 0) 1637*e71b7053SJung-uk Kim rv = X509_sign_ctx(x, mctx); 1638*e71b7053SJung-uk Kim EVP_MD_CTX_free(mctx); 16391f13597dSJung-uk Kim return rv > 0 ? 1 : 0; 16401f13597dSJung-uk Kim } 16411f13597dSJung-uk Kim 1642*e71b7053SJung-uk Kim int do_X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md, 16431f13597dSJung-uk Kim STACK_OF(OPENSSL_STRING) *sigopts) 16441f13597dSJung-uk Kim { 16451f13597dSJung-uk Kim int rv; 1646*e71b7053SJung-uk Kim EVP_MD_CTX *mctx = EVP_MD_CTX_new(); 1647*e71b7053SJung-uk Kim rv = do_sign_init(mctx, pkey, md, sigopts); 16481f13597dSJung-uk Kim if (rv > 0) 1649*e71b7053SJung-uk Kim rv = X509_REQ_sign_ctx(x, mctx); 1650*e71b7053SJung-uk Kim EVP_MD_CTX_free(mctx); 16511f13597dSJung-uk Kim return rv > 0 ? 1 : 0; 16521f13597dSJung-uk Kim } 16531f13597dSJung-uk Kim 1654*e71b7053SJung-uk Kim int do_X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md, 16551f13597dSJung-uk Kim STACK_OF(OPENSSL_STRING) *sigopts) 16561f13597dSJung-uk Kim { 16571f13597dSJung-uk Kim int rv; 1658*e71b7053SJung-uk Kim EVP_MD_CTX *mctx = EVP_MD_CTX_new(); 1659*e71b7053SJung-uk Kim rv = do_sign_init(mctx, pkey, md, sigopts); 16601f13597dSJung-uk Kim if (rv > 0) 1661*e71b7053SJung-uk Kim rv = X509_CRL_sign_ctx(x, mctx); 1662*e71b7053SJung-uk Kim EVP_MD_CTX_free(mctx); 16631f13597dSJung-uk Kim return rv > 0 ? 1 : 0; 16641f13597dSJung-uk Kim } 1665