/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 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 DEF_DAYS 30
static int callb(int ok, X509_STORE_CTX *ctx);
-static int sign(X509 *x, EVP_PKEY *pkey, EVP_PKEY *fkey, int days, int clrext,
+static int sign(X509 *x, EVP_PKEY *pkey, EVP_PKEY *fkey,
+ STACK_OF(OPENSSL_STRING) *sigopts,
+ int days, int clrext,
const EVP_MD *digest, CONF *conf, const char *section,
int preserve_dates);
static int x509_certify(X509_STORE *ctx, const char *CAfile, const EVP_MD *digest,
typedef enum OPTION_choice {
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
OPT_INFORM, OPT_OUTFORM, OPT_KEYFORM, OPT_REQ, OPT_CAFORM,
- OPT_CAKEYFORM, OPT_SIGOPT, OPT_DAYS, OPT_PASSIN, OPT_EXTFILE,
+ OPT_CAKEYFORM, OPT_VFYOPT, OPT_SIGOPT, OPT_DAYS, OPT_PASSIN, OPT_EXTFILE,
OPT_EXTENSIONS, OPT_IN, OPT_OUT, OPT_SIGNKEY, OPT_CA, OPT_CAKEY,
OPT_CASERIAL, OPT_SET_SERIAL, OPT_NEW, OPT_FORCE_PUBKEY, OPT_SUBJ,
OPT_ADDTRUST, OPT_ADDREJECT, OPT_SETALIAS, OPT_CERTOPT, OPT_NAMEOPT,
OPT_SUBJECT_HASH_OLD,
OPT_ISSUER_HASH_OLD,
OPT_BADSIG, OPT_MD, OPT_ENGINE, OPT_NOCERT, OPT_PRESERVE_DATES,
- OPT_R_ENUM, OPT_EXT
+ OPT_R_ENUM, OPT_PROV_ENUM, OPT_EXT
} OPTION_CHOICE;
const OPTIONS x509_options[] = {
#endif
{"inform", OPT_INFORM, 'f',
- "Input format - default PEM (one of DER or PEM)"},
+ "CSR input format (DER or PEM) - default PEM"},
{"in", OPT_IN, '<', "Input file - default stdin"},
- {"passin", OPT_PASSIN, 's', "Private key password/pass-phrase source"},
+ {"passin", OPT_PASSIN, 's', "Private key and cert file pass-phrase source"},
{"outform", OPT_OUTFORM, 'f',
- "Output format - default PEM (one of DER or PEM)"},
+ "Output format (DER or PEM) - default PEM"},
{"out", OPT_OUT, '>', "Output file - default stdout"},
- {"keyform", OPT_KEYFORM, 'E', "Private key format - default PEM"},
+ {"keyform", OPT_KEYFORM, 'E', "Private key format (ENGINE, other values ignored)"},
{"req", OPT_REQ, '-', "Input is a certificate request, sign and output"},
+ {"vfyopt", OPT_VFYOPT, 's', "Verification parameter in n:v form"},
OPT_SECTION("Output"),
{"serial", OPT_SERIAL, '-', "Print serial number value"},
{"C", OPT_C, '-', "Print out C code forms"},
#ifndef OPENSSL_NO_MD5
{"subject_hash_old", OPT_SUBJECT_HASH_OLD, '-',
- "Print old-style (MD5) issuer hash value"},
- {"issuer_hash_old", OPT_ISSUER_HASH_OLD, '-',
"Print old-style (MD5) subject hash value"},
+ {"issuer_hash_old", OPT_ISSUER_HASH_OLD, '-',
+ "Print old-style (MD5) issuer hash value"},
#endif
- {"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"},
+ {"nameopt", OPT_NAMEOPT, 's', "Certificate subject/issuer name printing options"},
OPT_SECTION("Certificate"),
{"startdate", OPT_STARTDATE, '-', "Set notBefore field"},
{"setalias", OPT_SETALIAS, 's', "Set certificate alias"},
{"days", OPT_DAYS, 'n',
"How long till expiry of a signed certificate - def 30 days"},
- {"signkey", OPT_SIGNKEY, 's', "Self sign cert with arg"},
+ {"signkey", OPT_SIGNKEY, 's', "Self-sign cert with arg"},
{"set_serial", OPT_SET_SERIAL, 's', "Serial number to use"},
{"extensions", OPT_EXTENSIONS, 's', "Section from config file to use"},
{"certopt", OPT_CERTOPT, 's', "Various certificate text options"},
"The CA key, must be PEM format; if not in CAfile"},
{"extfile", OPT_EXTFILE, '<', "File with X509V3 extensions to add"},
OPT_R_OPTIONS,
- {"CAform", OPT_CAFORM, 'F', "CA format - default PEM"},
- {"CAkeyform", OPT_CAKEYFORM, 'f', "CA key format - default PEM"},
+ OPT_PROV_OPTIONS,
+ {"CAform", OPT_CAFORM, 'F', "CA cert format (PEM/DER/P12); has no effect"},
+ {"CAkeyform", OPT_CAKEYFORM, 'E', "CA key format (ENGINE, other values ignored)"},
{"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"},
{"CAcreateserial", OPT_CACREATESERIAL, '-',
"Create serial number file if it does not exist"},
char *subj = NULL;
X509_NAME *fsubj = NULL;
const unsigned long chtype = MBSTRING_ASC;
- const int multirdn = 0;
+ const int multirdn = 1;
STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL;
- STACK_OF(OPENSSL_STRING) *sigopts = NULL;
+ STACK_OF(OPENSSL_STRING) *sigopts = NULL, *vfyopts = NULL;
X509 *x = NULL, *xca = NULL;
X509_REQ *req = NULL, *rq = NULL;
X509_STORE *ctx = NULL;
ret = 0;
goto end;
case OPT_INFORM:
- if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat))
+ if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
goto opthelp;
break;
case OPT_IN:
goto opthelp;
break;
case OPT_KEYFORM:
- if (!opt_format(opt_arg(), OPT_FMT_PDE, &keyformat))
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyformat))
goto opthelp;
break;
case OPT_CAFORM:
- if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &CAformat))
+ if (!opt_format(opt_arg(), OPT_FMT_ANY, &CAformat))
goto opthelp;
break;
case OPT_CAKEYFORM:
if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg()))
goto opthelp;
break;
+ case OPT_VFYOPT:
+ if (!vfyopts)
+ vfyopts = sk_OPENSSL_STRING_new_null();
+ if (!vfyopts || !sk_OPENSSL_STRING_push(vfyopts, opt_arg()))
+ goto opthelp;
+ break;
case OPT_DAYS:
if (preserve_dates)
goto opthelp;
if (!opt_rand(o))
goto end;
break;
+ case OPT_PROV_CASES:
+ if (!opt_provider(o))
+ goto end;
+ break;
case OPT_EXTENSIONS:
extsect = opt_arg();
break;
goto end;
}
- if (!X509_STORE_set_default_paths(ctx)) {
+ if (!X509_STORE_set_default_paths_with_libctx(ctx, app_get0_libctx(),
+ app_get0_propq())) {
ERR_print_errors(bio_err);
goto end;
}
goto end;
}
if (fkeyfile != NULL) {
- fkey = load_pubkey(fkeyfile, keyformat, 0, NULL, e, "Forced key");
+ fkey = load_pubkey(fkeyfile, keyformat, 0, NULL, e, "forced key");
if (fkey == NULL)
goto end;
}
"The -new option requires a subject to be set using -subj\n");
goto end;
}
- if (subj != NULL && (fsubj = parse_name(subj, chtype, multirdn)) == NULL)
+ if (subj != NULL
+ && (fsubj = parse_name(subj, chtype, multirdn, "subject")) == NULL)
goto end;
if (CAkeyfile == NULL && CA_flag && CAformat == FORMAT_PEM) {
if (reqfile) {
EVP_PKEY *pkey;
- BIO *in;
- in = bio_open_default(infile, 'r', informat);
- if (in == NULL)
+ req = load_csr(infile, informat, "certificate request input");
+ if (req == NULL)
goto end;
- req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
- BIO_free(in);
-
- if (req == NULL) {
- ERR_print_errors(bio_err);
- goto end;
- }
if ((pkey = X509_REQ_get0_pubkey(req)) == NULL) {
BIO_printf(bio_err, "error unpacking public key\n");
goto end;
}
- i = X509_REQ_verify(req, pkey);
+ i = do_X509_REQ_verify(req, pkey, vfyopts);
if (i < 0) {
BIO_printf(bio_err, "Request self-signature verification error\n");
ERR_print_errors(bio_err);
"We need a private key to sign with, use -signkey or -CAkey or -CA <file> with private key\n");
goto end;
}
- if ((x = X509_new()) == NULL)
+ if ((x = X509_new_with_libctx(app_get0_libctx(), app_get0_propq())) == NULL)
goto end;
if (sno == NULL) {
if (!X509_set_pubkey(x, fkey != NULL ? fkey : X509_REQ_get0_pubkey(req)))
goto end;
} else {
- x = load_cert(infile, informat, "Certificate");
+ x = load_cert_pass(infile, FORMAT_UNDEF, passin, "certificate");
if (x == NULL)
goto end;
if (fkey != NULL && !X509_set_pubkey(x, fkey))
}
if (CA_flag) {
- xca = load_cert(CAfile, CAformat, "CA Certificate");
+ xca = load_cert_pass(CAfile, CAformat, passin, "CA certificate");
if (xca == NULL)
goto end;
}
X509_get_subject_name(x), get_nameopt());
} else if (serial == i) {
BIO_printf(out, "serial=");
- i2a_ASN1_INTEGER(out, X509_get_serialNumber(x));
+ i2a_ASN1_INTEGER(out, X509_get0_serialNumber(x));
BIO_printf(out, "\n");
} else if (next_serial == i) {
ASN1_INTEGER *ser = X509_get_serialNumber(x);
BIO_printf(bio_err, "Getting Private key\n");
if (Upkey == NULL) {
Upkey = load_key(keyfile, keyformat, 0,
- passin, e, "Private key");
+ passin, e, "private key");
if (Upkey == NULL)
goto end;
}
- if (!sign(x, Upkey, fkey, days, clrext, digest, extconf,
- extsect, preserve_dates))
+ if (!sign(x, Upkey, fkey, sigopts, days, clrext, digest,
+ extconf, extsect, preserve_dates))
goto end;
} else if (CA_flag == i) {
BIO_printf(bio_err, "Getting CA Private Key\n");
if (CAkeyfile != NULL) {
CApkey = load_key(CAkeyfile, CAkeyformat,
- 0, passin, e, "CA Private Key");
+ 0, passin, e, "CA private key");
if (CApkey == NULL)
goto end;
}
EVP_PKEY_free(CApkey);
EVP_PKEY_free(fkey);
sk_OPENSSL_STRING_free(sigopts);
+ sk_OPENSSL_STRING_free(vfyopts);
X509_REQ_free(rq);
ASN1_INTEGER_free(sno);
sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free);
sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free);
ASN1_OBJECT_free(objtmp);
release_engine(e);
- OPENSSL_free(passin);
+ clear_free(passin);
return ret;
}
goto end;
/*
- * NOTE: this certificate can/should be self signed, unless it was a
+ * NOTE: this certificate can/should be self-signed, unless it was a
* certificate request in which case it is not.
*/
X509_STORE_CTX_set_cert(xsc, x);
X509 *err_cert;
/*
- * it is ok to use a self signed certificate This case will catch both
- * the initial ok == 0 and the final ok == 1 calls to this function
+ * It is ok to use a self-signed certificate. This case will catch both
+ * the initial ok == 0 and the final ok == 1 calls to this function.
*/
err = X509_STORE_CTX_get_error(ctx);
if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)
*/
if (ok) {
BIO_printf(bio_err,
- "error with certificate to be certified - should be self signed\n");
+ "error with certificate to be certified - should be self-signed\n");
return 0;
} else {
err_cert = X509_STORE_CTX_get_current_cert(ctx);
}
/* self-issue; self-sign unless a forced public key (fkey) is given */
-static int sign(X509 *x, EVP_PKEY *pkey, EVP_PKEY *fkey, int days, int clrext,
+static int sign(X509 *x, EVP_PKEY *pkey, EVP_PKEY *fkey,
+ STACK_OF(OPENSSL_STRING) *sigopts,
+ int days, int clrext,
const EVP_MD *digest, CONF *conf, const char *section,
int preserve_dates)
{
-
if (!X509_set_issuer_name(x, X509_get_subject_name(x)))
goto err;
if (!preserve_dates && !set_cert_times(x, NULL, NULL, days))
if (!X509V3_EXT_add_nconf(conf, &ctx, section, x))
goto err;
}
- if (!X509_sign(x, pkey, digest))
+ if (!do_X509_sign(x, pkey, digest, sigopts))
goto err;
return 1;
err: