/*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
#define DEFAULT_KEY_LENGTH 2048
#define MIN_KEY_LENGTH 512
-#define DEFAULT_DAYS 30 /* default cert validity period in days */
+#define DEFAULT_DAYS 30 /* default certificate validity period in days */
#define UNSET_DAYS -2 /* -1 may be used for testing expiration checks */
#define EXT_COPY_UNSET -1
static int add_DN_object(X509_NAME *n, char *text, const char *def,
char *value, int nid, int n_min, int n_max,
unsigned long chtype, int mval);
-static int genpkey_cb(EVP_PKEY_CTX *ctx);
static int build_data(char *text, const char *def, char *value,
int n_min, int n_max, char *buf, const int buf_size,
const char *desc1, const char *desc2);
OPT_KEYOUT, OPT_PASSIN, OPT_PASSOUT, OPT_NEWKEY,
OPT_PKEYOPT, OPT_SIGOPT, OPT_VFYOPT, OPT_BATCH, OPT_NEWHDR, OPT_MODULUS,
OPT_VERIFY, OPT_NOENC, OPT_NODES, OPT_NOOUT, OPT_VERBOSE, OPT_UTF8,
- OPT_NAMEOPT, OPT_REQOPT, OPT_SUBJ, OPT_SUBJECT, OPT_TEXT, OPT_X509,
- OPT_CA, OPT_CAKEY,
- OPT_MULTIVALUE_RDN, OPT_DAYS, OPT_SET_SERIAL,
- OPT_COPY_EXTENSIONS, OPT_ADDEXT, OPT_EXTENSIONS,
- OPT_REQEXTS, OPT_PRECERT, OPT_MD,
- OPT_SECTION,
+ OPT_NAMEOPT, OPT_REQOPT, OPT_SUBJ, OPT_SUBJECT, OPT_TEXT,
+ OPT_X509, OPT_X509V1, OPT_CA, OPT_CAKEY,
+ OPT_MULTIVALUE_RDN, OPT_NOT_BEFORE, OPT_NOT_AFTER, OPT_DAYS, OPT_SET_SERIAL,
+ OPT_COPY_EXTENSIONS, OPT_EXTENSIONS, OPT_REQEXTS, OPT_ADDEXT,
+ OPT_PRECERT, OPT_MD,
+ OPT_SECTION, OPT_QUIET,
OPT_R_ENUM, OPT_PROV_ENUM
} OPTION_CHOICE;
{"keygen_engine", OPT_KEYGEN_ENGINE, 's',
"Specify engine to be used for key generation operations"},
#endif
- {"in", OPT_IN, '<', "X.509 request input file"},
- {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"},
+ {"in", OPT_IN, '<', "X.509 request input file (default stdin)"},
+ {"inform", OPT_INFORM, 'F',
+ "CSR input format to use (PEM or DER; by default try PEM first)"},
{"verify", OPT_VERIFY, '-', "Verify self-signature on the request"},
OPT_SECTION("Certificate"),
{"reqopt", OPT_REQOPT, 's', "Various request text options"},
{"text", OPT_TEXT, '-', "Text form of request"},
{"x509", OPT_X509, '-',
- "Output an x509 structure instead of a cert request"},
- {"CA", OPT_CA, '<', "Issuer certificate to use with -x509"},
+ "Output an X.509 certificate structure instead of a cert request"},
+ {"x509v1", OPT_X509V1, '-', "Request cert generation with X.509 version 1"},
+ {"CA", OPT_CA, '<', "Issuer cert to use for signing a cert, implies -x509"},
{"CAkey", OPT_CAKEY, 's',
- "Issuer private key to use with -x509; default is -CA arg"},
+ "Issuer private key to use with -CA; default is -CA arg"},
{OPT_MORE_STR, 1, 1, "(Required by some CA's)"},
{"subj", OPT_SUBJ, 's', "Set or modify subject of request or cert"},
{"subject", OPT_SUBJECT, '-',
"Print the subject of the output request or cert"},
{"multivalue-rdn", OPT_MULTIVALUE_RDN, '-',
"Deprecated; multi-valued RDNs support is always on."},
- {"days", OPT_DAYS, 'p', "Number of days cert is valid for"},
+ {"not_before", OPT_NOT_BEFORE, 's',
+ "[CC]YYMMDDHHMMSSZ value for notBefore certificate field"},
+ {"not_after", OPT_NOT_AFTER, 's',
+ "[CC]YYMMDDHHMMSSZ value for notAfter certificate field, overrides -days"},
+ {"days", OPT_DAYS, 'p', "Number of days certificate is valid for"},
{"set_serial", OPT_SET_SERIAL, 's', "Serial number to use"},
{"copy_extensions", OPT_COPY_EXTENSIONS, 's',
"copy extensions from request when using -x509"},
+ {"extensions", OPT_EXTENSIONS, 's',
+ "Cert or request extension section (override value in config file)"},
+ {"reqexts", OPT_REQEXTS, 's', "An alias for -extensions"},
{"addext", OPT_ADDEXT, 's',
"Additional cert extension key=value pair (may be given more than once)"},
- {"extensions", OPT_EXTENSIONS, 's',
- "Cert extension section (override value in config file)"},
- {"reqexts", OPT_REQEXTS, 's',
- "Request extension section (override value in config file)"},
- {"precert", OPT_PRECERT, '-', "Add a poison extension (implies -new)"},
+ {"precert", OPT_PRECERT, '-', "Add a poison extension to generated cert (implies -new)"},
OPT_SECTION("Keys and Signing"),
- {"key", OPT_KEY, 's', "Private key to use"},
+ {"key", OPT_KEY, 's', "Key for signing, and to include unless -in given"},
{"keyform", OPT_KEYFORM, 'f', "Key file format (ENGINE, other values ignored)"},
{"pubkey", OPT_PUBKEY, '-', "Output public key"},
{"keyout", OPT_KEYOUT, '>', "File to write private key to"},
{"batch", OPT_BATCH, '-',
"Do not ask anything during request generation"},
{"verbose", OPT_VERBOSE, '-', "Verbose output"},
+ {"quiet", OPT_QUIET, '-', "Terse output"},
{"noenc", OPT_NOENC, '-', "Don't encrypt private keys"},
{"nodes", OPT_NODES, '-', "Don't encrypt private keys; deprecated"},
{"noout", OPT_NOOUT, '-', "Do not output REQ"},
}
/*
- * Is the |kv| key already duplicated? This is remarkably tricky to get right.
- * Return 0 if unique, -1 on runtime error; 1 if found or a syntax error.
+ * Is the |kv| key already duplicated?
+ * Return 0 if unique, -1 on runtime error, -2 on syntax error; 1 if found.
*/
static int duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv)
{
/* Check syntax. */
/* Skip leading whitespace, make a copy. */
- while (*kv && isspace(*kv))
- if (*++kv == '\0')
- return 1;
- if ((p = strchr(kv, '=')) == NULL)
- return 1;
+ while (isspace(_UC(*kv)))
+ kv++;
+ if ((p = strchr(kv, '=')) == NULL) {
+ BIO_printf(bio_err, "Parse error on -addext: missing '='\n");
+ return -2;
+ }
off = p - kv;
if ((kv = OPENSSL_strdup(kv)) == NULL)
return -1;
/* Skip trailing space before the equal sign. */
for (p = kv + off; p > kv; --p)
- if (!isspace(p[-1]))
+ if (!isspace(_UC(p[-1])))
break;
if (p == kv) {
+ BIO_printf(bio_err, "Parse error on -addext: missing key\n");
OPENSSL_free(kv);
- return 1;
+ return -2;
}
*p = '\0';
/* Finally have a clean "key"; see if it's there [by attempt to add it]. */
p = (char *)lh_OPENSSL_STRING_insert(addexts, (OPENSSL_STRING *)kv);
if (p != NULL) {
+ BIO_printf(bio_err, "Duplicate extension name: %s\n", kv);
OPENSSL_free(p);
return 1;
} else if (lh_OPENSSL_STRING_error(addexts)) {
EVP_CIPHER *cipher = NULL;
int ext_copy = EXT_COPY_UNSET;
BIO *addext_bio = NULL;
- char *extensions = NULL;
+ char *extsect = NULL;
const char *infile = NULL, *CAfile = NULL, *CAkeyfile = NULL;
char *outfile = NULL, *keyfile = NULL, *digest = NULL;
char *keyalgstr = NULL, *p, *prog, *passargin = NULL, *passargout = NULL;
char *passin = NULL, *passout = NULL;
char *nofree_passin = NULL, *nofree_passout = NULL;
- char *req_exts = NULL, *subj = NULL;
+ char *subj = NULL;
X509_NAME *fsubj = NULL;
char *template = default_config_file, *keyout = NULL;
const char *keyalg = NULL;
OPTION_CHOICE o;
+ char *not_before = NULL, *not_after = NULL;
int days = UNSET_DAYS;
- int ret = 1, gen_x509 = 0, i = 0, newreq = 0, verbose = 0;
+ int ret = 1, gen_x509 = 0, i = 0, newreq = 0, verbose = 0, progress = 1;
int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, keyform = FORMAT_UNDEF;
int modulus = 0, multirdn = 1, verify = 0, noout = 0, text = 0;
- int noenc = 0, newhdr = 0, subject = 0, pubkey = 0, precert = 0;
+ int noenc = 0, newhdr = 0, subject = 0, pubkey = 0, precert = 0, x509v1 = 0;
long newkey_len = -1;
unsigned long chtype = MBSTRING_ASC, reqflag = 0;
cipher = (EVP_CIPHER *)EVP_des_ede3_cbc();
#endif
+ opt_set_unknown_name("digest");
prog = opt_init(argc, argv, req_options);
while ((o = opt_next()) != OPT_EOF) {
switch (o) {
break;
case OPT_VERBOSE:
verbose = 1;
+ progress = 1;
+ break;
+ case OPT_QUIET:
+ verbose = 0;
+ progress = 0;
break;
case OPT_UTF8:
chtype = MBSTRING_UTF8;
case OPT_TEXT:
text = 1;
break;
+ case OPT_X509V1:
+ x509v1 = 1;
+ /* fall thru */
case OPT_X509:
gen_x509 = 1;
break;
case OPT_CA:
CAfile = opt_arg();
+ gen_x509 = 1;
break;
case OPT_CAKEY:
CAkeyfile = opt_arg();
break;
+ case OPT_NOT_BEFORE:
+ not_before = opt_arg();
+ break;
+ case OPT_NOT_AFTER:
+ not_after = opt_arg();
+ break;
case OPT_DAYS:
days = atoi(opt_arg());
- if (days < -1) {
+ if (days <= UNSET_DAYS) {
BIO_printf(bio_err, "%s: -days parameter arg must be >= -1\n",
prog);
goto end;
goto end;
}
break;
+ case OPT_EXTENSIONS:
+ case OPT_REQEXTS:
+ extsect = opt_arg();
+ break;
case OPT_ADDEXT:
p = opt_arg();
if (addexts == NULL) {
goto end;
}
i = duplicated(addexts, p);
- if (i == 1) {
- BIO_printf(bio_err, "Duplicate extension: %s\n", p);
+ if (i == 1)
goto opthelp;
- }
+ if (i == -1)
+ BIO_printf(bio_err, "Internal error handling -addext %s\n", p);
if (i < 0 || BIO_printf(addext_bio, "%s\n", p) < 0)
goto end;
break;
- case OPT_EXTENSIONS:
- extensions = opt_arg();
- break;
- case OPT_REQEXTS:
- req_exts = opt_arg();
- break;
case OPT_PRECERT:
newreq = precert = 1;
break;
}
/* No extra arguments. */
- argc = opt_num_rest();
- if (argc != 0)
+ if (!opt_check_rest_arg(NULL))
goto opthelp;
if (!app_RAND_load())
if (!gen_x509) {
if (days != UNSET_DAYS)
- BIO_printf(bio_err, "Ignoring -days without -x509; not generating a certificate\n");
+ BIO_printf(bio_err, "Warning: Ignoring -days without -x509; not generating a certificate\n");
+ if (not_before != NULL)
+ BIO_printf(bio_err, "Warning: Ignoring -not_before without -x509; not generating a certificate\n");
+ if (not_after != NULL)
+ BIO_printf(bio_err, "Warning: Ignoring -not_after without -x509; not generating a certificate\n");
if (ext_copy == EXT_COPY_NONE)
- BIO_printf(bio_err, "Ignoring -copy_extensions 'none' when -x509 is not given\n");
+ BIO_printf(bio_err, "Warning: Ignoring -copy_extensions 'none' when -x509 is not given\n");
+ }
+ if (infile == NULL) {
+ if (gen_x509)
+ newreq = 1;
+ else if (!newreq)
+ BIO_printf(bio_err,
+ "Warning: Will read cert request from stdin since no -in option is given\n");
}
- if (gen_x509 && infile == NULL)
- newreq = 1;
if (!app_passwd(passargin, passargout, &passin, &passout)) {
BIO_printf(bio_err, "Error getting passwords\n");
goto end;
if (req_conf != NULL) {
- p = NCONF_get_string(req_conf, NULL, "oid_file");
- if (p == NULL)
- ERR_clear_error();
+ p = app_conf_try_string(req_conf, NULL, "oid_file");
if (p != NULL) {
BIO *oid_bio = BIO_new_file(p, "r");
if (!add_oid_section(req_conf))
goto end;
- if (digest == NULL) {
- p = NCONF_get_string(req_conf, section, "default_md");
- if (p == NULL)
- ERR_clear_error();
- else
+ /* Check that any specified digest is fetchable */
+ if (digest != NULL) {
+ if (!opt_check_md(digest))
+ goto opthelp;
+ } else {
+ /* No digest specified, default to configuration */
+ p = app_conf_try_string(req_conf, section, "default_md");
+ if (p != NULL)
digest = p;
}
- if (extensions == NULL) {
- extensions = NCONF_get_string(req_conf, section, V3_EXTENSIONS);
- if (extensions == NULL)
- ERR_clear_error();
- }
- if (extensions != NULL) {
- /* Check syntax of file */
+ if (extsect == NULL)
+ extsect = app_conf_try_string(req_conf, section,
+ gen_x509 ? V3_EXTENSIONS : REQ_EXTENSIONS);
+ if (extsect != NULL) {
+ /* Check syntax of extension section in config file */
X509V3_CTX ctx;
X509V3_set_ctx_test(&ctx);
X509V3_set_nconf(&ctx, req_conf);
- if (!X509V3_EXT_add_nconf(req_conf, &ctx, extensions, NULL)) {
+ if (!X509V3_EXT_add_nconf(req_conf, &ctx, extsect, NULL)) {
BIO_printf(bio_err,
- "Error checking x509 extension section %s\n",
- extensions);
+ "Error checking %s extension section %s\n",
+ gen_x509 ? "x509" : "request", extsect);
goto end;
}
}
X509V3_CTX ctx;
X509V3_set_ctx_test(&ctx);
- X509V3_set_nconf(&ctx, addext_conf);
+ X509V3_set_nconf(&ctx, req_conf);
if (!X509V3_EXT_add_nconf(addext_conf, &ctx, "default", NULL)) {
BIO_printf(bio_err, "Error checking extensions defined using -addext\n");
goto end;
}
}
- if (passin == NULL) {
+ if (passin == NULL)
passin = nofree_passin =
- NCONF_get_string(req_conf, section, "input_password");
- if (passin == NULL)
- ERR_clear_error();
- }
+ app_conf_try_string(req_conf, section, "input_password");
- if (passout == NULL) {
+ if (passout == NULL)
passout = nofree_passout =
- NCONF_get_string(req_conf, section, "output_password");
- if (passout == NULL)
- ERR_clear_error();
- }
-
- p = NCONF_get_string(req_conf, section, STRING_MASK);
- if (p == NULL)
- ERR_clear_error();
+ app_conf_try_string(req_conf, section, "output_password");
+ p = app_conf_try_string(req_conf, section, STRING_MASK);
if (p != NULL && !ASN1_STRING_set_default_mask_asc(p)) {
BIO_printf(bio_err, "Invalid global string mask setting %s\n", p);
goto end;
}
if (chtype != MBSTRING_UTF8) {
- p = NCONF_get_string(req_conf, section, UTF8_IN);
- if (p == NULL)
- ERR_clear_error();
- else if (strcmp(p, "yes") == 0)
+ p = app_conf_try_string(req_conf, section, UTF8_IN);
+ if (p != NULL && strcmp(p, "yes") == 0)
chtype = MBSTRING_UTF8;
}
- if (req_exts == NULL) {
- req_exts = NCONF_get_string(req_conf, section, REQ_EXTENSIONS);
- if (req_exts == NULL)
- ERR_clear_error();
- }
- if (req_exts != NULL) {
- /* Check syntax of file */
- X509V3_CTX ctx;
-
- X509V3_set_ctx_test(&ctx);
- X509V3_set_nconf(&ctx, req_conf);
- if (!X509V3_EXT_add_nconf(req_conf, &ctx, req_exts, NULL)) {
- BIO_printf(bio_err,
- "Error checking request extension section %s\n",
- req_exts);
- goto end;
- }
- }
-
if (keyfile != NULL) {
pkey = load_key(keyfile, keyform, 0, passin, e, "private key");
if (pkey == NULL)
goto end;
app_RAND_load_conf(req_conf, section);
}
-
+ if (keyalg != NULL && pkey != NULL) {
+ BIO_printf(bio_err,
+ "Warning: Not generating key via given -newkey option since -key is given\n");
+ /* Better throw an error in this case */
+ }
if (newreq && pkey == NULL) {
app_RAND_load_conf(req_conf, section);
- if (!NCONF_get_number(req_conf, section, BITS, &newkey_len))
+ if (!app_conf_try_number(req_conf, section, BITS, &newkey_len))
newkey_len = DEFAULT_KEY_LENGTH;
genctx = set_keygen_ctx(keyalg, &keyalgstr, &newkey_len, gen_eng);
}
}
- EVP_PKEY_CTX_set_cb(genctx, genpkey_cb);
EVP_PKEY_CTX_set_app_data(genctx, bio_err);
+ if (progress)
+ EVP_PKEY_CTX_set_cb(genctx, progress_cb);
pkey = app_keygen(genctx, keyalgstr, newkey_len, verbose);
+ if (pkey == NULL)
+ goto end;
EVP_PKEY_CTX_free(genctx);
genctx = NULL;
}
- if (keyout == NULL) {
- keyout = NCONF_get_string(req_conf, section, KEYFILE);
- if (keyout == NULL)
- ERR_clear_error();
- }
+ if (keyout == NULL && keyfile == NULL)
+ keyout = app_conf_try_string(req_conf, section, KEYFILE);
if (pkey != NULL && (keyfile == NULL || keyout != NULL)) {
if (verbose) {
if (out == NULL)
goto end;
- p = NCONF_get_string(req_conf, section, "encrypt_rsa_key");
- if (p == NULL) {
- ERR_clear_error();
- p = NCONF_get_string(req_conf, section, "encrypt_key");
- if (p == NULL)
- ERR_clear_error();
- }
- if ((p != NULL) && (strcmp(p, "no") == 0))
+ p = app_conf_try_string(req_conf, section, "encrypt_rsa_key");
+ if (p == NULL)
+ p = app_conf_try_string(req_conf, section, "encrypt_key");
+ if (p != NULL && strcmp(p, "no") == 0)
cipher = NULL;
if (noenc)
cipher = NULL;
}
goto end;
}
- BIO_free(out);
+ BIO_free_all(out);
out = NULL;
BIO_printf(bio_err, "-----\n");
}
goto end;
if (!newreq) {
- req = load_csr(infile, informat, "X509 request");
+ if (keyfile != NULL)
+ BIO_printf(bio_err,
+ "Warning: Not placing -key in cert or request since request is used\n");
+ req = load_csr_autofmt(infile /* if NULL, reads from stdin */,
+ informat, vfyopts, "X509 request");
if (req == NULL)
goto end;
+ } else if (infile != NULL) {
+ BIO_printf(bio_err,
+ "Warning: Ignoring -in option since -new or -newkey or -precert is given\n");
+ /* Better throw an error in this case, as done in the x509 app */
}
if (CAkeyfile == NULL)
if (CAkeyfile != NULL) {
if (CAfile == NULL) {
BIO_printf(bio_err,
- "Ignoring -CAkey option since no -CA option is given\n");
+ "Warning: Ignoring -CAkey option since no -CA option is given\n");
} else {
if ((CAkey = load_key(CAkeyfile, FORMAT_UNDEF,
- 0, passin, e, "issuer private key")) == NULL)
+ 0, passin, e,
+ CAkeyfile != CAfile
+ ? "issuer private key from -CAkey arg"
+ : "issuer private key from -CA arg")) == NULL)
goto end;
}
}
if (CAfile != NULL) {
- if (!gen_x509) {
+ if ((CAcert = load_cert_pass(CAfile, FORMAT_UNDEF, 1, passin,
+ "issuer cert from -CA arg")) == NULL)
+ goto end;
+ if (!X509_check_private_key(CAcert, CAkey)) {
BIO_printf(bio_err,
- "Warning: Ignoring -CA option without -x509\n");
- } else {
- if (CAkeyfile == NULL) {
- BIO_printf(bio_err,
- "Need to give the -CAkey option if using -CA\n");
- goto end;
- }
- if ((CAcert = load_cert_pass(CAfile, FORMAT_UNDEF, 1, passin,
- "issuer certificate")) == NULL)
- goto end;
- if (!X509_check_private_key(CAcert, CAkey)) {
- BIO_printf(bio_err,
- "Issuer certificate and key do not match\n");
- goto end;
- }
+ "Issuer CA certificate and key do not match\n");
+ goto end;
}
}
if (newreq || gen_x509) {
- if (pkey == NULL /* can happen only if !newreq */) {
- BIO_printf(bio_err, "Must provide a signature key using -key\n");
+ if (CAcert == NULL && pkey == NULL) {
+ BIO_printf(bio_err, "Must provide a signature key using -key or"
+ " provide -CA / -CAkey\n");
goto end;
}
goto end;
}
- if (!make_REQ(req, pkey, fsubj, multirdn, !gen_x509, chtype)){
+ if (!make_REQ(req, pkey, fsubj, multirdn, !gen_x509, chtype)) {
BIO_printf(bio_err, "Error making certificate request\n");
goto end;
}
+ /* Note that -x509 can take over -key and -subj option values. */
}
if (gen_x509) {
EVP_PKEY *pub_key = X509_REQ_get0_pubkey(req);
+ EVP_PKEY *issuer_key = CAcert != NULL ? CAkey : pkey;
X509V3_CTX ext_ctx;
X509_NAME *issuer = CAcert != NULL ? X509_get_subject_name(CAcert) :
X509_REQ_get_subject_name(req);
X509_NAME *n_subj = fsubj != NULL ? fsubj :
X509_REQ_get_subject_name(req);
+ if (CAcert != NULL && keyfile != NULL)
+ BIO_printf(bio_err,
+ "Warning: Not using -key or -newkey for signing since -CA option is given\n");
+
if ((new_x509 = X509_new_ex(app_get0_libctx(),
app_get0_propq())) == NULL)
goto end;
if (!X509_set_issuer_name(new_x509, issuer))
goto end;
- if (days == UNSET_DAYS) {
+ if (days == UNSET_DAYS)
days = DEFAULT_DAYS;
- }
- if (!set_cert_times(new_x509, NULL, NULL, days))
+ else if (not_after != NULL)
+ BIO_printf(bio_err,"Warning: -not_after option overriding -days option\n");
+ if (!set_cert_times(new_x509, not_before, not_after, days, 1))
goto end;
if (!X509_set_subject_name(new_x509, n_subj))
goto end;
if (!pub_key || !X509_set_pubkey(new_x509, pub_key))
goto end;
if (ext_copy == EXT_COPY_UNSET) {
- BIO_printf(bio_err, "Warning: No -copy_extensions given; ignoring any extensions in the request\n");
+ if (infile != NULL)
+ BIO_printf(bio_err, "Warning: No -copy_extensions given; ignoring any extensions in the request\n");
} else if (!copy_extensions(new_x509, req, ext_copy)) {
BIO_printf(bio_err, "Error copying extensions from request\n");
goto end;
/* Set up V3 context struct */
X509V3_set_ctx(&ext_ctx, CAcert != NULL ? CAcert : new_x509,
new_x509, NULL, NULL, X509V3_CTX_REPLACE);
- if (CAcert == NULL) { /* self-issued, possibly self-signed */
- if (!X509V3_set_issuer_pkey(&ext_ctx, pkey)) /* prepare right AKID */
+ /* prepare fallback for AKID, but only if issuer cert == new_x509 */
+ if (CAcert == NULL) {
+ if (!X509V3_set_issuer_pkey(&ext_ctx, issuer_key))
goto end;
- ERR_set_mark();
- if (!X509_check_private_key(new_x509, pkey))
+ if (!cert_matches_key(new_x509, issuer_key))
BIO_printf(bio_err,
"Warning: Signature key and public key of cert do not match\n");
- ERR_pop_to_mark();
}
X509V3_set_nconf(&ext_ctx, req_conf);
/* Add extensions */
- if (extensions != NULL
- && !X509V3_EXT_add_nconf(req_conf, &ext_ctx, extensions,
- new_x509)) {
+ if (extsect != NULL
+ && !X509V3_EXT_add_nconf(req_conf, &ext_ctx, extsect, new_x509)) {
BIO_printf(bio_err, "Error adding x509 extensions from section %s\n",
- extensions);
+ extsect);
goto end;
}
if (addext_conf != NULL
&& !X509V3_EXT_add_nconf(addext_conf, &ext_ctx, "default",
new_x509)) {
- BIO_printf(bio_err, "Error adding extensions defined via -addext\n");
+ BIO_printf(bio_err, "Error adding x509 extensions defined via -addext\n");
goto end;
}
}
}
- i = do_X509_sign(new_x509, CAcert != NULL ? CAkey : pkey,
- digest, sigopts, &ext_ctx);
+ i = do_X509_sign(new_x509, x509v1, issuer_key, digest, sigopts,
+ &ext_ctx);
if (!i)
goto end;
} else {
X509V3_CTX ext_ctx;
+ if (precert) {
+ BIO_printf(bio_err,
+ "Warning: Ignoring -precert flag since no cert is produced\n");
+ }
/* Set up V3 context struct */
- X509V3_set_ctx(&ext_ctx, NULL, NULL, req, NULL, 0);
+ X509V3_set_ctx(&ext_ctx, NULL, NULL, req, NULL, X509V3_CTX_REPLACE);
X509V3_set_nconf(&ext_ctx, req_conf);
/* Add extensions */
- if (req_exts != NULL
- && !X509V3_EXT_REQ_add_nconf(req_conf, &ext_ctx,
- req_exts, req)) {
+ if (extsect != NULL
+ && !X509V3_EXT_REQ_add_nconf(req_conf, &ext_ctx, extsect, req)) {
BIO_printf(bio_err, "Error adding request extensions from section %s\n",
- req_exts);
+ extsect);
goto end;
}
if (addext_conf != NULL
&& !X509V3_EXT_REQ_add_nconf(addext_conf, &ext_ctx, "default",
req)) {
- BIO_printf(bio_err, "Error adding extensions defined via -addext\n");
+ BIO_printf(bio_err, "Error adding request extensions defined via -addext\n");
goto end;
}
i = do_X509_REQ_sign(req, pkey, digest, sigopts);
if (i < 0)
goto end;
- if (i == 0)
+ if (i == 0) {
BIO_printf(bio_err, "Certificate request self-signature verify failure\n");
- else /* i > 0 */
- BIO_printf(bio_err, "Certificate request self-signature verify OK\n");
+ goto end;
+ } else /* i > 0 */
+ BIO_printf(bio_out, "Certificate request self-signature verify OK\n");
}
if (noout && !text && !modulus && !subject && !pubkey) {
else
tpubkey = X509_REQ_get0_pubkey(req);
if (tpubkey == NULL) {
- fprintf(stdout, "Modulus is unavailable\n");
+ BIO_puts(bio_err, "Modulus is unavailable\n");
goto end;
}
- fprintf(stdout, "Modulus=");
- if (EVP_PKEY_is_a(tpubkey, "RSA")) {
- BIGNUM *n;
+ BIO_puts(out, "Modulus=");
+ if (EVP_PKEY_is_a(tpubkey, "RSA") || EVP_PKEY_is_a(tpubkey, "RSA-PSS")) {
+ BIGNUM *n = NULL;
- /* Every RSA key has an 'n' */
- EVP_PKEY_get_bn_param(pkey, "n", &n);
+ if (!EVP_PKEY_get_bn_param(tpubkey, "n", &n))
+ goto end;
BN_print(out, n);
BN_free(n);
} else {
- fprintf(stdout, "Wrong Algorithm type");
+ BIO_puts(out, "Wrong Algorithm type");
}
- fprintf(stdout, "\n");
+ BIO_puts(out, "\n");
}
if (!noout && !gen_x509) {
STACK_OF(CONF_VALUE) *dn_sk = NULL, *attr_sk = NULL;
char *tmp, *dn_sect, *attr_sect;
- tmp = NCONF_get_string(req_conf, section, PROMPT);
- if (tmp == NULL)
- ERR_clear_error();
- if ((tmp != NULL) && strcmp(tmp, "no") == 0)
+ tmp = app_conf_try_string(req_conf, section, PROMPT);
+ if (tmp != NULL && strcmp(tmp, "no") == 0)
no_prompt = 1;
- dn_sect = NCONF_get_string(req_conf, section, DISTINGUISHED_NAME);
- if (dn_sect == NULL) {
- ERR_clear_error();
- } else {
+ dn_sect = app_conf_try_string(req_conf, section, DISTINGUISHED_NAME);
+ if (dn_sect != NULL) {
dn_sk = NCONF_get_section(req_conf, dn_sect);
if (dn_sk == NULL) {
BIO_printf(bio_err, "Unable to get '%s' section\n", dn_sect);
}
}
- attr_sect = NCONF_get_string(req_conf, section, ATTRIBUTES);
- if (attr_sect == NULL) {
- ERR_clear_error();
- } else {
+ attr_sect = app_conf_try_string(req_conf, section, ATTRIBUTES);
+ if (attr_sect != NULL) {
attr_sk = NCONF_get_section(req_conf, attr_sect);
if (attr_sk == NULL) {
BIO_printf(bio_err, "Unable to get '%s' section\n", attr_sect);
goto start;
if (!join(buf, sizeof(buf), v->name, "_default", "Name"))
return 0;
- if ((def = NCONF_get_string(req_conf, dn_sect, buf)) == NULL) {
- ERR_clear_error();
+ if ((def = app_conf_try_string(req_conf, dn_sect, buf)) == NULL)
def = "";
- }
if (!join(buf, sizeof(buf), v->name, "_value", "Name"))
return 0;
- if ((value = NCONF_get_string(req_conf, dn_sect, buf)) == NULL) {
- ERR_clear_error();
+ if ((value = app_conf_try_string(req_conf, dn_sect, buf)) == NULL)
value = NULL;
- }
if (!join(buf, sizeof(buf), v->name, "_min", "Name"))
return 0;
- if (!NCONF_get_number(req_conf, dn_sect, buf, &n_min)) {
- ERR_clear_error();
+ if (!app_conf_try_number(req_conf, dn_sect, buf, &n_min))
n_min = -1;
- }
if (!join(buf, sizeof(buf), v->name, "_max", "Name"))
return 0;
- if (!NCONF_get_number(req_conf, dn_sect, buf, &n_max)) {
- ERR_clear_error();
+ if (!app_conf_try_number(req_conf, dn_sect, buf, &n_max))
n_max = -1;
- }
if (!add_DN_object(subj, v->value, def, value, nid,
n_min, n_max, chtype, mval))
if (!join(buf, sizeof(buf), type, "_default", "Name"))
return 0;
- if ((def = NCONF_get_string(req_conf, attr_sect, buf))
- == NULL) {
- ERR_clear_error();
+ def = app_conf_try_string(req_conf, attr_sect, buf);
+ if (def == NULL)
def = "";
- }
if (!join(buf, sizeof(buf), type, "_value", "Name"))
return 0;
- if ((value = NCONF_get_string(req_conf, attr_sect, buf))
- == NULL) {
- ERR_clear_error();
- value = NULL;
- }
+ value = app_conf_try_string(req_conf, attr_sect, buf);
if (!join(buf, sizeof(buf), type, "_min", "Name"))
return 0;
- if (!NCONF_get_number(req_conf, attr_sect, buf, &n_min)) {
- ERR_clear_error();
+ if (!app_conf_try_number(req_conf, attr_sect, buf, &n_min))
n_min = -1;
- }
if (!join(buf, sizeof(buf), type, "_max", "Name"))
return 0;
- if (!NCONF_get_number(req_conf, attr_sect, buf, &n_max)) {
- ERR_clear_error();
+ if (!app_conf_try_number(req_conf, attr_sect, buf, &n_max))
n_max = -1;
- }
if (!add_attribute_object(req,
v->value, def, value, nid, n_min,
*pkeytype = OPENSSL_strndup(keytype, keytypelen);
else
*pkeytype = OPENSSL_strdup(keytype);
- *pkeylen = keylen;
+
+ if (*pkeytype == NULL) {
+ BIO_printf(bio_err, "Out of memory\n");
+ EVP_PKEY_free(param);
+ return NULL;
+ }
+
+ if (keylen >= 0)
+ *pkeylen = keylen;
if (param != NULL) {
if (!EVP_PKEY_is_a(param, *pkeytype)) {
else
gctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(),
param, app_get0_propq());
- *pkeylen = EVP_PKEY_bits(param);
+ *pkeylen = EVP_PKEY_get_bits(param);
EVP_PKEY_free(param);
} else {
if (keygen_engine != NULL) {
- int pkey_id = get_legacy_pkey_id(app_get0_libctx(), keytype,
+ int pkey_id = get_legacy_pkey_id(app_get0_libctx(), *pkeytype,
keygen_engine);
if (pkey_id != NID_undef)
gctx = EVP_PKEY_CTX_new_id(pkey_id, keygen_engine);
} else {
gctx = EVP_PKEY_CTX_new_from_name(app_get0_libctx(),
- keytype, app_get0_propq());
+ *pkeytype, app_get0_propq());
}
}
EVP_PKEY_CTX_free(gctx);
return NULL;
}
+ if (keylen == -1 && (EVP_PKEY_CTX_is_a(gctx, "RSA")
+ || EVP_PKEY_CTX_is_a(gctx, "RSA-PSS")))
+ keylen = *pkeylen;
+
if (keylen != -1) {
OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
size_t bits = keylen;
return gctx;
}
-static int genpkey_cb(EVP_PKEY_CTX *ctx)
-{
- char c = '*';
- BIO *b = EVP_PKEY_CTX_get_app_data(ctx);
- int p;
- p = EVP_PKEY_CTX_get_keygen_info(ctx, 0);
- if (p == 0)
- c = '.';
- if (p == 1)
- c = '+';
- if (p == 2)
- c = '*';
- if (p == 3)
- c = '\n';
- BIO_write(b, &c, 1);
- (void)BIO_flush(b);
- return 1;
-}