apps/x509 etc.: allow private key input when public key is expected

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
Reviewed-by: David von Oheimb <david.von.oheimb@siemens.com>
(Merged from https://github.com/openssl/openssl/pull/19076)
This commit is contained in:
Dr. David von Oheimb 2022-08-26 20:40:48 +02:00 committed by Dr. David von Oheimb
parent b7cc2d2f29
commit 0e89b39619
14 changed files with 123 additions and 111 deletions

View File

@ -66,8 +66,8 @@ BIO *bio_open_owner(const char *filename, int format, int private);
BIO *bio_open_default(const char *filename, char mode, int format); BIO *bio_open_default(const char *filename, char mode, int format);
BIO *bio_open_default_quiet(const char *filename, char mode, int format); BIO *bio_open_default_quiet(const char *filename, char mode, int format);
CONF *app_load_config_bio(BIO *in, const char *filename); CONF *app_load_config_bio(BIO *in, const char *filename);
#define app_load_config(filename) app_load_config_internal(filename, 0) # define app_load_config(filename) app_load_config_internal(filename, 0)
#define app_load_config_quiet(filename) app_load_config_internal(filename, 1) # define app_load_config_quiet(filename) app_load_config_internal(filename, 1)
CONF *app_load_config_internal(const char *filename, int quiet); CONF *app_load_config_internal(const char *filename, int quiet);
CONF *app_load_config_verbose(const char *filename, int verbose); CONF *app_load_config_verbose(const char *filename, int verbose);
int app_load_modules(const CONF *config); int app_load_modules(const CONF *config);
@ -100,7 +100,7 @@ int progress_cb(EVP_PKEY_CTX *ctx);
int chopup_args(ARGS *arg, char *buf); int chopup_args(ARGS *arg, char *buf);
void dump_cert_text(BIO *out, X509 *x); void dump_cert_text(BIO *out, X509 *x);
void print_name(BIO *out, const char *title, const X509_NAME *nm); void print_name(BIO *out, const char *title, const X509_NAME *nm);
void print_bignum_var(BIO *, const BIGNUM *, const char*, void print_bignum_var(BIO *, const BIGNUM *, const char *,
int, unsigned char *); int, unsigned char *);
void print_array(BIO *, const char *, int, const unsigned char *); void print_array(BIO *, const char *, int, const unsigned char *);
int set_nameopt(const char *arg); int set_nameopt(const char *arg);
@ -117,13 +117,14 @@ X509_REQ *load_csr(const char *file, int format, const char *desc);
X509_REQ *load_csr_autofmt(const char *infile, int format, const char *desc); X509_REQ *load_csr_autofmt(const char *infile, int format, const char *desc);
X509 *load_cert_pass(const char *uri, int format, int maybe_stdin, X509 *load_cert_pass(const char *uri, int format, int maybe_stdin,
const char *pass, const char *desc); const char *pass, const char *desc);
#define load_cert(uri, format, desc) load_cert_pass(uri, format, 1, NULL, desc) # define load_cert(uri, format, desc) load_cert_pass(uri, format, 1, NULL, desc)
X509_CRL *load_crl(const char *uri, int format, int maybe_stdin, X509_CRL *load_crl(const char *uri, int format, int maybe_stdin,
const char *desc); const char *desc);
void cleanse(char *str); void cleanse(char *str);
void clear_free(char *str); void clear_free(char *str);
EVP_PKEY *load_key(const char *uri, int format, int maybe_stdin, EVP_PKEY *load_key(const char *uri, int format, int maybe_stdin,
const char *pass, ENGINE *e, const char *desc); const char *pass, ENGINE *e, const char *desc);
/* first try reading public key, on failure resort to loading private key */
EVP_PKEY *load_pubkey(const char *uri, int format, int maybe_stdin, EVP_PKEY *load_pubkey(const char *uri, int format, int maybe_stdin,
const char *pass, ENGINE *e, const char *desc); const char *pass, ENGINE *e, const char *desc);
EVP_PKEY *load_keyparams(const char *uri, int format, int maybe_stdin, EVP_PKEY *load_keyparams(const char *uri, int format, int maybe_stdin,
@ -145,15 +146,11 @@ int load_certs(const char *uri, int maybe_stdin, STACK_OF(X509) **certs,
int load_crls(const char *uri, STACK_OF(X509_CRL) **crls, int load_crls(const char *uri, STACK_OF(X509_CRL) **crls,
const char *pass, const char *desc); const char *pass, const char *desc);
int load_key_certs_crls(const char *uri, int format, int maybe_stdin, int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
const char *pass, const char *desc, const char *pass, const char *desc, int quiet,
EVP_PKEY **ppkey, EVP_PKEY **ppubkey, EVP_PKEY **ppkey, EVP_PKEY **ppubkey,
EVP_PKEY **pparams, EVP_PKEY **pparams,
X509 **pcert, STACK_OF(X509) **pcerts, X509 **pcert, STACK_OF(X509) **pcerts,
X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls); X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls);
int load_key_cert_crl(const char *uri, int format, int maybe_stdin,
const char *pass, const char *desc,
EVP_PKEY **ppkey, EVP_PKEY **ppubkey,
X509 **pcert, X509_CRL **pcrl);
X509_STORE *setup_verify(const char *CAfile, int noCAfile, X509_STORE *setup_verify(const char *CAfile, int noCAfile,
const char *CApath, int noCApath, const char *CApath, int noCApath,
const char *CAstore, int noCAstore); const char *CAstore, int noCAstore);
@ -199,10 +196,9 @@ int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold,
# define DB_type 0 # define DB_type 0
# define DB_exp_date 1 # define DB_exp_date 1
# define DB_rev_date 2 # define DB_rev_date 2
# define DB_serial 3 /* index - unique */ # define DB_serial 3 /* index - unique */
# define DB_file 4 # define DB_file 4
# define DB_name 5 /* index - unique when active and not # define DB_name 5 /* index - unique when active and not disabled */
* disabled */
# define DB_NUMBER 6 # define DB_NUMBER 6
# define DB_TYPE_REV 'R' /* Revoked */ # define DB_TYPE_REV 'R' /* Revoked */
@ -243,8 +239,8 @@ int rotate_index(const char *dbfile, const char *new_suffix,
const char *old_suffix); const char *old_suffix);
void free_index(CA_DB *db); void free_index(CA_DB *db);
# define index_name_cmp_noconst(a, b) \ # define index_name_cmp_noconst(a, b) \
index_name_cmp((const OPENSSL_CSTRING *)CHECKED_PTR_OF(OPENSSL_STRING, a), \ index_name_cmp((const OPENSSL_CSTRING *)CHECKED_PTR_OF(OPENSSL_STRING, a), \
(const OPENSSL_CSTRING *)CHECKED_PTR_OF(OPENSSL_STRING, b)) (const OPENSSL_CSTRING *)CHECKED_PTR_OF(OPENSSL_STRING, b))
int index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b); int index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b);
int parse_yesno(const char *str, int def); int parse_yesno(const char *str, int def);
@ -271,12 +267,11 @@ int do_X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const char *md,
extern char *psk_key; extern char *psk_key;
unsigned char *next_protos_parse(size_t *outlen, const char *in); unsigned char *next_protos_parse(size_t *outlen, const char *in);
int check_cert_attributes(BIO *bio, X509 *x, int check_cert_attributes(BIO *bio, X509 *x,
const char *checkhost, const char *checkhost, const char *checkemail,
const char *checkemail, const char *checkip, int print); const char *checkip, int print);
void store_setup_crl_download(X509_STORE *st); void store_setup_crl_download(X509_STORE *st);
@ -310,16 +305,16 @@ ASN1_VALUE *app_http_post_asn1(const char *host, const char *port,
# define EXT_COPY_ADD 1 # define EXT_COPY_ADD 1
# define EXT_COPY_ALL 2 # define EXT_COPY_ALL 2
# define NETSCAPE_CERT_HDR "certificate" # define NETSCAPE_CERT_HDR "certificate"
# define APP_PASS_LEN 1024 # define APP_PASS_LEN 1024
/* /*
* IETF RFC 5280 says serial number must be <= 20 bytes. Use 159 bits * IETF RFC 5280 says serial number must be <= 20 bytes. Use 159 bits
* so that the first bit will never be one, so that the DER encoding * so that the first bit will never be one, so that the DER encoding
* rules won't force a leading octet. * rules won't force a leading octet.
*/ */
# define SERIAL_RAND_BITS 159 # define SERIAL_RAND_BITS 159
int app_isdir(const char *); int app_isdir(const char *);
int app_access(const char *, int flag); int app_access(const char *, int flag);

View File

@ -469,7 +469,7 @@ X509 *load_cert_pass(const char *uri, int format, int maybe_stdin,
BIO_printf(bio_err, "Unable to load %s from %s\n", desc, uri); BIO_printf(bio_err, "Unable to load %s from %s\n", desc, uri);
} }
} else { } else {
(void)load_key_certs_crls(uri, format, maybe_stdin, pass, desc, (void)load_key_certs_crls(uri, format, maybe_stdin, pass, desc, 0,
NULL, NULL, NULL, &cert, NULL, NULL, NULL); NULL, NULL, NULL, &cert, NULL, NULL, NULL);
} }
return cert; return cert;
@ -491,7 +491,7 @@ X509_CRL *load_crl(const char *uri, int format, int maybe_stdin,
BIO_printf(bio_err, "Unable to load %s from %s\n", desc, uri); BIO_printf(bio_err, "Unable to load %s from %s\n", desc, uri);
} }
} else { } else {
(void)load_key_certs_crls(uri, format, maybe_stdin, NULL, desc, (void)load_key_certs_crls(uri, format, maybe_stdin, NULL, desc, 0,
NULL, NULL, NULL, NULL, NULL, &crl, NULL); NULL, NULL, NULL, NULL, NULL, &crl, NULL);
} }
return crl; return crl;
@ -582,16 +582,16 @@ EVP_PKEY *load_key(const char *uri, int format, int may_stdin,
if (desc == NULL) if (desc == NULL)
desc = "private key"; desc = "private key";
if (format == FORMAT_ENGINE) { if (format == FORMAT_ENGINE)
uri = allocated_uri = make_engine_uri(e, uri, desc); uri = allocated_uri = make_engine_uri(e, uri, desc);
} (void)load_key_certs_crls(uri, format, may_stdin, pass, desc, 0,
(void)load_key_certs_crls(uri, format, may_stdin, pass, desc,
&pkey, NULL, NULL, NULL, NULL, NULL, NULL); &pkey, NULL, NULL, NULL, NULL, NULL, NULL);
OPENSSL_free(allocated_uri); OPENSSL_free(allocated_uri);
return pkey; return pkey;
} }
/* first try reading public key, on failure resort to loading private key */
EVP_PKEY *load_pubkey(const char *uri, int format, int maybe_stdin, EVP_PKEY *load_pubkey(const char *uri, int format, int maybe_stdin,
const char *pass, ENGINE *e, const char *desc) const char *pass, ENGINE *e, const char *desc)
{ {
@ -601,12 +601,13 @@ EVP_PKEY *load_pubkey(const char *uri, int format, int maybe_stdin,
if (desc == NULL) if (desc == NULL)
desc = "public key"; desc = "public key";
if (format == FORMAT_ENGINE) { if (format == FORMAT_ENGINE)
uri = allocated_uri = make_engine_uri(e, uri, desc); uri = allocated_uri = make_engine_uri(e, uri, desc);
} (void)load_key_certs_crls(uri, format, maybe_stdin, pass, desc, 1,
(void)load_key_certs_crls(uri, format, maybe_stdin, pass, desc,
NULL, &pkey, NULL, NULL, NULL, NULL, NULL); NULL, &pkey, NULL, NULL, NULL, NULL, NULL);
if (pkey == NULL)
(void)load_key_certs_crls(uri, format, maybe_stdin, pass, desc, 0,
&pkey, NULL, NULL, NULL, NULL, NULL, NULL);
OPENSSL_free(allocated_uri); OPENSSL_free(allocated_uri);
return pkey; return pkey;
} }
@ -616,13 +617,11 @@ EVP_PKEY *load_keyparams_suppress(const char *uri, int format, int maybe_stdin,
int suppress_decode_errors) int suppress_decode_errors)
{ {
EVP_PKEY *params = NULL; EVP_PKEY *params = NULL;
BIO *bio_bak = bio_err;
if (desc == NULL) if (desc == NULL)
desc = "key parameters"; desc = "key parameters";
if (suppress_decode_errors)
bio_err = NULL;
(void)load_key_certs_crls(uri, format, maybe_stdin, NULL, desc, (void)load_key_certs_crls(uri, format, maybe_stdin, NULL, desc,
suppress_decode_errors,
NULL, NULL, &params, NULL, NULL, NULL, NULL); NULL, NULL, &params, NULL, NULL, NULL, NULL);
if (params != NULL && keytype != NULL && !EVP_PKEY_is_a(params, keytype)) { if (params != NULL && keytype != NULL && !EVP_PKEY_is_a(params, keytype)) {
ERR_print_errors(bio_err); ERR_print_errors(bio_err);
@ -632,7 +631,6 @@ EVP_PKEY *load_keyparams_suppress(const char *uri, int format, int maybe_stdin,
EVP_PKEY_free(params); EVP_PKEY_free(params);
params = NULL; params = NULL;
} }
bio_err = bio_bak;
return params; return params;
} }
@ -725,7 +723,7 @@ int load_cert_certs(const char *uri,
return ret; return ret;
} }
pass_string = get_passwd(pass, desc); pass_string = get_passwd(pass, desc);
ret = load_key_certs_crls(uri, FORMAT_UNDEF, 0, pass_string, desc, ret = load_key_certs_crls(uri, FORMAT_UNDEF, 0, pass_string, desc, 0,
NULL, NULL, NULL, pcert, pcerts, NULL, NULL); NULL, NULL, NULL, pcert, pcerts, NULL, NULL);
clear_free(pass_string); clear_free(pass_string);
@ -833,7 +831,7 @@ int load_certs(const char *uri, int maybe_stdin, STACK_OF(X509) **certs,
if (desc == NULL) if (desc == NULL)
desc = "certificates"; desc = "certificates";
ret = load_key_certs_crls(uri, FORMAT_UNDEF, maybe_stdin, pass, desc, ret = load_key_certs_crls(uri, FORMAT_UNDEF, maybe_stdin, pass, desc, 0,
NULL, NULL, NULL, NULL, certs, NULL, NULL); NULL, NULL, NULL, NULL, certs, NULL, NULL);
if (!ret && was_NULL) { if (!ret && was_NULL) {
@ -854,7 +852,7 @@ int load_crls(const char *uri, STACK_OF(X509_CRL) **crls,
if (desc == NULL) if (desc == NULL)
desc = "CRLs"; desc = "CRLs";
ret = load_key_certs_crls(uri, FORMAT_UNDEF, 0, pass, desc, ret = load_key_certs_crls(uri, FORMAT_UNDEF, 0, pass, desc, 0,
NULL, NULL, NULL, NULL, NULL, NULL, crls); NULL, NULL, NULL, NULL, NULL, NULL, crls);
if (!ret && was_NULL) { if (!ret && was_NULL) {
@ -902,8 +900,9 @@ static const char *format2string(int format)
* of *pcerts and *pcrls (as far as they are not NULL). * of *pcerts and *pcrls (as far as they are not NULL).
*/ */
int load_key_certs_crls(const char *uri, int format, int maybe_stdin, int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
const char *pass, const char *desc, EVP_PKEY **ppkey, const char *pass, const char *desc, int quiet,
EVP_PKEY **ppubkey, EVP_PKEY **pparams, EVP_PKEY **ppkey, EVP_PKEY **ppubkey,
EVP_PKEY **pparams,
X509 **pcert, STACK_OF(X509) **pcerts, X509 **pcert, STACK_OF(X509) **pcerts,
X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls) X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls)
{ {
@ -918,8 +917,9 @@ int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
const OSSL_PARAM *params = NULL; const OSSL_PARAM *params = NULL;
if (failed == NULL) { if (failed == NULL) {
BIO_printf(bio_err, "Internal error: nothing to load from %s\n", if (!quiet)
uri != NULL ? uri : "<stdin>"); BIO_printf(bio_err, "Internal error: nothing to load from %s\n",
uri != NULL ? uri : "<stdin>");
return 0; return 0;
} }
ERR_set_mark(); ERR_set_mark();
@ -930,7 +930,8 @@ int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
SET_EXPECT1(pcert, OSSL_STORE_INFO_CERT); SET_EXPECT1(pcert, OSSL_STORE_INFO_CERT);
if (pcerts != NULL) { if (pcerts != NULL) {
if (*pcerts == NULL && (*pcerts = sk_X509_new_null()) == NULL) { if (*pcerts == NULL && (*pcerts = sk_X509_new_null()) == NULL) {
BIO_printf(bio_err, "Out of memory loading"); if (!quiet)
BIO_printf(bio_err, "Out of memory loading");
goto end; goto end;
} }
SET_EXPECT(OSSL_STORE_INFO_CERT); SET_EXPECT(OSSL_STORE_INFO_CERT);
@ -938,7 +939,8 @@ int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
SET_EXPECT1(pcrl, OSSL_STORE_INFO_CRL); SET_EXPECT1(pcrl, OSSL_STORE_INFO_CRL);
if (pcrls != NULL) { if (pcrls != NULL) {
if (*pcrls == NULL && (*pcrls = sk_X509_CRL_new_null()) == NULL) { if (*pcrls == NULL && (*pcrls = sk_X509_CRL_new_null()) == NULL) {
BIO_printf(bio_err, "Out of memory loading"); if (!quiet)
BIO_printf(bio_err, "Out of memory loading");
goto end; goto end;
} }
SET_EXPECT(OSSL_STORE_INFO_CRL); SET_EXPECT(OSSL_STORE_INFO_CRL);
@ -958,7 +960,8 @@ int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
BIO *bio; BIO *bio;
if (!maybe_stdin) { if (!maybe_stdin) {
BIO_printf(bio_err, "No filename or uri specified for loading"); if (!quiet)
BIO_printf(bio_err, "No filename or uri specified for loading");
goto end; goto end;
} }
uri = "<stdin>"; uri = "<stdin>";
@ -975,7 +978,8 @@ int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
params, NULL, NULL); params, NULL, NULL);
} }
if (ctx == NULL) { if (ctx == NULL) {
BIO_printf(bio_err, "Could not open file or uri for loading"); if (!quiet)
BIO_printf(bio_err, "Could not open file or uri for loading");
goto end; goto end;
} }
if (expect > 0 && !OSSL_STORE_expect(ctx, expect)) if (expect > 0 && !OSSL_STORE_expect(ctx, expect))
@ -1057,7 +1061,8 @@ int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
OSSL_STORE_INFO_free(info); OSSL_STORE_INFO_free(info);
if (!ok) { if (!ok) {
failed = OSSL_STORE_INFO_type_string(type); failed = OSSL_STORE_INFO_type_string(type);
BIO_printf(bio_err, "Error reading"); if (!quiet)
BIO_printf(bio_err, "Error reading");
break; break;
} }
} }
@ -1070,12 +1075,12 @@ int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
pcrls = NULL; pcrls = NULL;
if (failed == NULL) { if (failed == NULL) {
failed = FAIL_NAME; failed = FAIL_NAME;
if (failed != NULL) if (failed != NULL && !quiet)
BIO_printf(bio_err, "Could not find"); BIO_printf(bio_err, "Could not find");
} else { } else if (!quiet) {
BIO_printf(bio_err, "Could not read"); BIO_printf(bio_err, "Could not read");
} }
if (failed != NULL) { if (failed != NULL && !quiet) {
unsigned long err = ERR_peek_last_error(); unsigned long err = ERR_peek_last_error();
if (desc != NULL && strstr(desc, failed) != NULL) { if (desc != NULL && strstr(desc, failed) != NULL) {
@ -1096,7 +1101,7 @@ int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
BIO_printf(bio_err, "\n"); BIO_printf(bio_err, "\n");
ERR_print_errors(bio_err); ERR_print_errors(bio_err);
} }
if (bio_err == NULL || failed == NULL) if (quiet || failed == NULL)
/* clear any suppressed or spurious errors */ /* clear any suppressed or spurious errors */
ERR_pop_to_mark(); ERR_pop_to_mark();
else else
@ -1373,7 +1378,7 @@ X509_STORE *setup_verify(const char *CAfile, int noCAfile,
goto end; goto end;
if (CAfile != NULL) { if (CAfile != NULL) {
if (X509_LOOKUP_load_file_ex(lookup, CAfile, X509_FILETYPE_PEM, if (X509_LOOKUP_load_file_ex(lookup, CAfile, X509_FILETYPE_PEM,
libctx, propq) <= 0) { libctx, propq) <= 0) {
BIO_printf(bio_err, "Error loading file %s\n", CAfile); BIO_printf(bio_err, "Error loading file %s\n", CAfile);
goto end; goto end;
} }

View File

@ -69,8 +69,8 @@ const OPTIONS pkeyutl_options[] = {
OPT_SECTION("Input"), OPT_SECTION("Input"),
{"in", OPT_IN, '<', "Input file - default stdin"}, {"in", OPT_IN, '<', "Input file - default stdin"},
{"rawin", OPT_RAWIN, '-', "Indicate the input data is in raw form"}, {"rawin", OPT_RAWIN, '-', "Indicate the input data is in raw form"},
{"pubin", OPT_PUBIN, '-', "Input is a public key"}, {"inkey", OPT_INKEY, 's', "Input key, by default private key"},
{"inkey", OPT_INKEY, 's', "Input private key file"}, {"pubin", OPT_PUBIN, '-', "Input key is a public key"},
{"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
{"peerkey", OPT_PEERKEY, 's', "Peer key file used in key derivation"}, {"peerkey", OPT_PEERKEY, 's', "Peer key file used in key derivation"},
{"peerform", OPT_PEERFORM, 'E', "Peer key format (DER/PEM/P12/ENGINE)"}, {"peerform", OPT_PEERFORM, 'E', "Peer key format (DER/PEM/P12/ENGINE)"},

View File

@ -47,9 +47,9 @@ const OPTIONS rsautl_options[] = {
OPT_SECTION("Input"), OPT_SECTION("Input"),
{"in", OPT_IN, '<', "Input file"}, {"in", OPT_IN, '<', "Input file"},
{"inkey", OPT_INKEY, 's', "Input key"}, {"inkey", OPT_INKEY, 's', "Input key, by default an RSA private key"},
{"keyform", OPT_KEYFORM, 'E', "Private key format (ENGINE, other values ignored)"}, {"keyform", OPT_KEYFORM, 'E', "Private key format (ENGINE, other values ignored)"},
{"pubin", OPT_PUBIN, '-', "Input is an RSA public"}, {"pubin", OPT_PUBIN, '-', "Input key is an RSA public pkey"},
{"certin", OPT_CERTIN, '-', "Input is a cert carrying an RSA public key"}, {"certin", OPT_CERTIN, '-', "Input is a cert carrying an RSA public key"},
{"rev", OPT_REV, '-', "Reverse the order of the input buffer"}, {"rev", OPT_REV, '-', "Reverse the order of the input buffer"},
{"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},

View File

@ -87,7 +87,8 @@ const OPTIONS x509_options[] = {
OPT_SECTION("Certificate printing"), OPT_SECTION("Certificate printing"),
{"text", OPT_TEXT, '-', "Print the certificate in text form"}, {"text", OPT_TEXT, '-', "Print the certificate in text form"},
{"dateopt", OPT_DATEOPT, 's', "Datetime format used for printing. (rfc_822/iso_8601). Default is rfc_822."}, {"dateopt", OPT_DATEOPT, 's',
"Datetime format used for printing. (rfc_822/iso_8601). Default is rfc_822."},
{"certopt", OPT_CERTOPT, 's', "Various certificate text printing options"}, {"certopt", OPT_CERTOPT, 's', "Various certificate text printing options"},
{"fingerprint", OPT_FINGERPRINT, '-', "Print the certificate fingerprint"}, {"fingerprint", OPT_FINGERPRINT, '-', "Print the certificate fingerprint"},
{"alias", OPT_ALIAS, '-', "Print certificate alias"}, {"alias", OPT_ALIAS, '-', "Print certificate alias"},
@ -139,7 +140,7 @@ const OPTIONS x509_options[] = {
"Preserve existing validity dates"}, "Preserve existing validity dates"},
{"subj", OPT_SUBJ, 's', "Set or override certificate subject (and issuer)"}, {"subj", OPT_SUBJ, 's', "Set or override certificate subject (and issuer)"},
{"force_pubkey", OPT_FORCE_PUBKEY, '<', {"force_pubkey", OPT_FORCE_PUBKEY, '<',
"Place the given key in new certificate"}, "Key to be placed in new certificate or certificate request"},
{"clrext", OPT_CLREXT, '-', {"clrext", OPT_CLREXT, '-',
"Do not take over any extensions from the source certificate or request"}, "Do not take over any extensions from the source certificate or request"},
{"extfile", OPT_EXTFILE, '<', "Config file with X509V3 extensions to add"}, {"extfile", OPT_EXTFILE, '<', "Config file with X509V3 extensions to add"},
@ -624,8 +625,7 @@ int x509_main(int argc, char **argv)
goto err; goto err;
} }
if (newcert && reqfile) { if (newcert && reqfile) {
BIO_printf(bio_err, BIO_printf(bio_err, "The -req option cannot be used with -new\n");
"The -req option cannot be used with -new\n");
goto err; goto err;
} }
if (privkeyfile != NULL) { if (privkeyfile != NULL) {
@ -757,7 +757,7 @@ int x509_main(int argc, char **argv)
} else { } else {
if (infile == NULL) if (infile == NULL)
BIO_printf(bio_err, BIO_printf(bio_err,
"Warning: Reading certificate from stdin since no -in option is given\n"); "Warning: Reading certificate from stdin since no -in or -new option is given\n");
x = load_cert_pass(infile, informat, 1, passin, "certificate"); x = load_cert_pass(infile, informat, 1, passin, "certificate");
if (x == NULL) if (x == NULL)
goto end; goto end;
@ -893,9 +893,6 @@ int x509_main(int argc, char **argv)
} }
} }
noout = 1; noout = 1;
} else if (privkey != NULL) {
if (!do_X509_sign(x, 0, privkey, digest, sigopts, &ext_ctx))
goto end;
} else if (CAfile != NULL) { } else if (CAfile != NULL) {
if ((CAkey = load_key(CAkeyfile, CAkeyformat, if ((CAkey = load_key(CAkeyfile, CAkeyformat,
0, passin, e, "CA private key")) == NULL) 0, passin, e, "CA private key")) == NULL)
@ -908,6 +905,9 @@ int x509_main(int argc, char **argv)
if (!do_X509_sign(x, 0, CAkey, digest, sigopts, &ext_ctx)) if (!do_X509_sign(x, 0, CAkey, digest, sigopts, &ext_ctx))
goto end; goto end;
} else if (privkey != NULL) {
if (!do_X509_sign(x, 0, privkey, digest, sigopts, &ext_ctx))
goto end;
} }
if (badsig) { if (badsig) {
const ASN1_BIT_STRING *signature; const ASN1_BIT_STRING *signature;

View File

@ -115,8 +115,9 @@ This option prints out the value of the public key component of the key.
=item B<-pubin> =item B<-pubin>
By default, a private key is read from the input file. With this option a By default, a private key is read from the input.
public key is read instead. With this option a public key is read instead.
If the input contains no public key but a private key, its public part is used.
=item B<-pubout> =item B<-pubout>

View File

@ -106,8 +106,9 @@ Print the elliptic curve parameters.
=item B<-pubin> =item B<-pubin>
By default, a private key is read from the input file. With this option a By default a private key is read from the input.
public key is read instead. With this option a public key is read instead.
If the input contains no public key but a private key, its public part is used.
=item B<-pubout> =item B<-pubout>

View File

@ -89,7 +89,8 @@ see L<openssl-passphrase-options(1)>.
=item B<-pubin> =item B<-pubin>
By default a private key is read from the input. By default a private key is read from the input.
With this option only the public components are read. With this option a public key is read instead.
If the input contains no public key but a private key, its public part is used.
=back =back

View File

@ -108,7 +108,9 @@ See L<openssl-format-options(1)> for details.
=item B<-pubin> =item B<-pubin>
The input file is a public key. By default a private key is read from the key input.
With this option a public key is read instead.
If the input contains no public key but a private key, its public part is used.
=item B<-certin> =item B<-certin>

View File

@ -121,8 +121,9 @@ This option checks the consistency of an RSA private key.
=item B<-pubin> =item B<-pubin>
By default a private key is read from the input file: with this By default a private key is read from the input.
option a public key is read instead. With this option a public key is read instead.
If the input contains no public key but a private key, its public part is used.
=item B<-pubout> =item B<-pubout>

View File

@ -76,7 +76,9 @@ See L<openssl-format-options(1)> for details.
=item B<-pubin> =item B<-pubin>
The input file is an RSA public key. By default a private key is read from the key input.
With this option a public key is read instead.
If the input contains no public key but a private key, its public part is used.
=item B<-certin> =item B<-certin>

View File

@ -84,7 +84,7 @@ B<openssl> B<x509>
This command is a multi-purposes certificate handling command. This command is a multi-purposes certificate handling command.
It can be used to print certificate information, It can be used to print certificate information,
convert certificates to various forms, edit certificate trust settings, convert certificates to various forms, edit certificate trust settings,
generate certificates from scratch or from certificating requests generate certificates from scratch or from certification requests
and then self-signing them or signing them like a "micro CA". and then self-signing them or signing them like a "micro CA".
Generated certificates bear X.509 version 3. Generated certificates bear X.509 version 3.
@ -121,7 +121,8 @@ see L<openssl-passphrase-options(1)>.
=item B<-new> =item B<-new>
Generate a certificate from scratch, not using an input certificate Generate a certificate from scratch, not using an input certificate
or certificate request. So the B<-in> option must not be used in this case. or certificate request.
So this excludes the B<-in> and B<-req> options.
Instead, the B<-subj> option needs to be given. Instead, the B<-subj> option needs to be given.
The public key to include can be given with the B<-force_pubkey> option The public key to include can be given with the B<-force_pubkey> option
and defaults to the key given with the B<-key> (or B<-signkey>) option, and defaults to the key given with the B<-key> (or B<-signkey>) option,
@ -176,9 +177,7 @@ the new certificate or certificate request, resulting in a self-signature.
This option cannot be used in conjunction with the B<-CA> option. This option cannot be used in conjunction with the B<-CA> option.
It sets the issuer name to the subject name (i.e., makes it self-issued) It sets the issuer name to the subject name (i.e., makes it self-issued).
and changes the public key to the supplied value (unless overridden
by B<-force_pubkey>).
Unless the B<-preserve_dates> option is supplied, Unless the B<-preserve_dates> option is supplied,
it sets the validity start date to the current time it sets the validity start date to the current time
and the end date to a value determined by the B<-days> option. and the end date to a value determined by the B<-days> option.
@ -403,20 +402,22 @@ Example:
C</DC=org/DC=OpenSSL/DC=users/UID=123456+CN=John Doe> C</DC=org/DC=OpenSSL/DC=users/UID=123456+CN=John Doe>
This option can be used in conjunction with the B<-force_pubkey> option This option can be used with the B<-new> and B<-force_pubkey> options to create
to create a certificate even without providing an input certificate a new certificate without providing an input certificate or certificate request.
or certificate request.
=item B<-force_pubkey> I<filename> =item B<-force_pubkey> I<filename>
When a certificate is created set its public key to the key in I<filename> When a new certificate or certificate request is created
set its public key to the given key
instead of the key contained in the input instead of the key contained in the input
or given with the B<-key> (or B<-signkey>) option. or given with the B<-key> (or B<-signkey>) option.
If the input contains no public key but a private key, its public part is used.
This option is useful for creating self-issued certificates that are not This option can be used in conjunction with b<-new> and B<-subj>
to directly generate a certificate containing any desired public key.
This option is also useful for creating self-issued certificates that are not
self-signed, for instance when the key cannot be used for signing, such as DH. self-signed, for instance when the key cannot be used for signing, such as DH.
It can also be used in conjunction with B<-new> and B<-subj> to directly
generate a certificate containing any desired public key.
=item B<-clrext> =item B<-clrext>

View File

@ -16,7 +16,7 @@ use OpenSSL::Test qw/:DEFAULT srctop_file/;
setup("test_x509"); setup("test_x509");
plan tests => 32; plan tests => 33;
# Prevent MSys2 filename munging for arguments that look like file paths but # Prevent MSys2 filename munging for arguments that look like file paths but
# aren't # aren't
@ -70,18 +70,25 @@ my $extfile = srctop_file("test", "v3_ca_exts.cnf");
my $pkey = srctop_file(@certs, "ca-key.pem"); # issuer private key my $pkey = srctop_file(@certs, "ca-key.pem"); # issuer private key
my $pubkey = "ca-pubkey.pem"; # the corresponding issuer public key my $pubkey = "ca-pubkey.pem"; # the corresponding issuer public key
# use any (different) key for signing our self-issued cert: # use any (different) key for signing our self-issued cert:
my $signkey = srctop_file(@certs, "serverkey.pem"); my $key = srctop_file(@certs, "serverkey.pem");
my $selfout = "self-issued.out"; my $selfout = "self-issued.out";
my $testcert = srctop_file(@certs, "ee-cert.pem"); my $testcert = srctop_file(@certs, "ee-cert.pem");
ok(run(app(["openssl", "pkey", "-in", $pkey, "-pubout", "-out", $pubkey])) ok(run(app(["openssl", "pkey", "-in", $pkey, "-pubout", "-out", $pubkey]))
&& run(app(["openssl", "x509", "-new", "-force_pubkey", $pubkey, && run(app(["openssl", "x509", "-new", "-force_pubkey", $pubkey, "-subj", $subj,
"-subj", $subj, "-extfile", $extfile, "-extfile", $extfile, "-key", $key, "-out", $selfout]))
"-signkey", $signkey, "-out", $selfout]))
&& run(app(["openssl", "verify", "-no_check_time", && run(app(["openssl", "verify", "-no_check_time",
"-trusted", $selfout, "-partial_chain", $testcert]))); "-trusted", $selfout, "-partial_chain", $testcert])));
# not unlinking $pubkey # not unlinking $pubkey
# not unlinking $selfout # not unlinking $selfout
# simple way of directly producing a CA-signed cert with private/pubkey input
my $ca = srctop_file(@certs, "ca-cert.pem"); # issuer cert
my $caout = "ca-issued.out";
ok(run(app(["openssl", "x509", "-new", "-force_pubkey", $key, "-subj", "/CN=EE",
"-extfile", $extfile, "-CA", $ca, "-CAkey", $pkey, "-out", $caout]))
&& run(app(["openssl", "verify", "-no_check_time",
"-trusted", $ca, "-partial_chain", $caout])));
subtest 'x509 -- x.509 v1 certificate' => sub { subtest 'x509 -- x.509 v1 certificate' => sub {
tconversion( -type => 'x509', -prefix => 'x509v1', tconversion( -type => 'x509', -prefix => 'x509v1',
-in => srctop_file("test", "testx509.pem") ); -in => srctop_file("test", "testx509.pem") );

View File

@ -6,11 +6,17 @@
# in the file LICENSE in the source distribution or at # in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html # https://www.openssl.org/source/license.html
# Utility to recreate S/MIME certificates # Utility to recreate S/MIME certificates in this directory.
# Invoke when changes are need from within this directory.
OPENSSL=../../apps/openssl OPENSSL=../../apps/openssl
OPENSSL_CONF=./ca.cnf CONF=ca.cnf
export OPENSSL_CONF export OPENSSL_CONF=./$CONF
gen() {
$OPENSSL x509 -CA smroot.pem -new -days 36524 -force_pubkey $1 -subj "$2" \
-extfile $CONF -extensions $3
}
# Root CA: create certificate directly # Root CA: create certificate directly
CN="Test S/MIME RSA Root" $OPENSSL req -config ca.cnf -x509 -noenc \ CN="Test S/MIME RSA Root" $OPENSSL req -config ca.cnf -x509 -noenc \
@ -18,35 +24,27 @@ CN="Test S/MIME RSA Root" $OPENSSL req -config ca.cnf -x509 -noenc \
# EE RSA certificates with respective extensions # EE RSA certificates with respective extensions
cp ../certs/ee-key.pem smrsa1.pem cp ../certs/ee-key.pem smrsa1.pem
$OPENSSL x509 -new -key smrsa1.pem -subj "/CN=Test SMIME EE RSA #1" -days 36524 \ gen smrsa1.pem "/CN=Test SMIME EE RSA #1" usr_rsa_cert >>smrsa1.pem
-CA smroot.pem -extfile ca.cnf -extensions usr_rsa_cert >>smrsa1.pem
cp ../certs/ee-key-3072.pem smrsa2.pem cp ../certs/ee-key-3072.pem smrsa2.pem
$OPENSSL x509 -new -key smrsa2.pem -subj "/CN=Test SMIME EE RSA #2" -days 36524 \ gen smrsa2.pem "/CN=Test SMIME EE RSA #2" usr_rsa_cert >>smrsa2.pem
-CA smroot.pem -extfile ca.cnf -extensions usr_rsa_cert >>smrsa2.pem
cp ../certs/ee-key-4096.pem smrsa3.pem cp ../certs/ee-key-4096.pem smrsa3.pem
$OPENSSL x509 -new -key smrsa3.pem -subj "/CN=Test SMIME EE RSA #3" -days 36524 \ gen smrsa3.pem "/CN=Test SMIME EE RSA #3" usr_rsa_cert >>smrsa3.pem
-CA smroot.pem -extfile ca.cnf -extensions usr_rsa_cert >>smrsa3.pem
# Create DSA certificates with respective extensions # Create DSA certificates with respective extensions
cp ../certs/server-dsa-key.pem smdsa1.pem cp ../certs/server-dsa-key.pem smdsa1.pem
$OPENSSL x509 -new -key smdsa1.pem -subj "/CN=Test SMIME EE DSA #1" -days 36524 \ gen smdsa1.pem "/CN=Test SMIME EE DSA #1" signer_cert >>smdsa1.pem
-CA smroot.pem -extfile ca.cnf -extensions signer_cert >>smdsa1.pem
cp ../certs/server-dsa-key.pem smdsa2.pem cp ../certs/server-dsa-key.pem smdsa2.pem
$OPENSSL x509 -new -key smdsa2.pem -subj "/CN=Test SMIME EE DSA #1" -days 36524 \ gen smdsa2.pem "/CN=Test SMIME EE DSA #1" signer_cert >>smdsa2.pem
-CA smroot.pem -extfile ca.cnf -extensions signer_cert >>smdsa2.pem
cp ../certs/server-dsa-key.pem smdsa3.pem cp ../certs/server-dsa-key.pem smdsa3.pem
$OPENSSL x509 -new -key smdsa3.pem -subj "/CN=Test SMIME EE DSA #1" -days 36524 \ gen smdsa3.pem "/CN=Test SMIME EE DSA #1" signer_cert >>smdsa3.pem
-CA smroot.pem -extfile ca.cnf -extensions signer_cert >>smdsa3.pem
# Create EC certificates with respective extensions # Create EC certificates with respective extensions
cp ../certs/ee-ecdsa-key.pem smec1.pem cp ../certs/ee-ecdsa-key.pem smec1.pem
$OPENSSL x509 -new -key smec1.pem -subj "/CN=Test SMIME EE EC #1" -days 36524 \ gen smec1.pem "/CN=Test SMIME EE EC #1" signer_cert >>smec1.pem
-CA smroot.pem -extfile ca.cnf -extensions signer_cert >>smec1.pem
cp ../certs/server-ecdsa-key.pem smec2.pem cp ../certs/server-ecdsa-key.pem smec2.pem
$OPENSSL x509 -new -key smec2.pem -subj "/CN=Test SMIME EE EC #2" -days 36524 \ gen smec2.pem "/CN=Test SMIME EE EC #2" signer_cert >>smec2.pem
-CA smroot.pem -extfile ca.cnf -extensions signer_cert >>smec2.pem
# Do not renew this cert as it is used for legacy data decrypt test # Do not renew this cert as it is used for legacy data decrypt test
#$OPENSSL ecparam -out ecp.pem -name P-256 #$OPENSSL ecparam -out ecp.pem -name P-256
@ -61,10 +59,8 @@ $OPENSSL genpkey -genparam -algorithm DHX -out dhp.pem
$OPENSSL genpkey -paramfile dhp.pem -out smdh.pem $OPENSSL genpkey -paramfile dhp.pem -out smdh.pem
rm dhp.pem rm dhp.pem
# Create X9.42 DH certificate with respective extensions # Create X9.42 DH certificate with respective extensions
$OPENSSL x509 -new -key smdh.pem -subj "/CN=Test SMIME EE DH" -days 36524 \ gen smdh.pem "/CN=Test SMIME EE DH" dh_cert >>smdh.pem
-CA smroot.pem -extfile ca.cnf -extensions dh_cert >>smdh.pem
# EE RSA code signing end entity certificate with respective extensions # EE RSA code signing end entity certificate with respective extensions
cp ../certs/ee-key.pem csrsa1.pem cp ../certs/ee-key.pem csrsa1.pem
$OPENSSL x509 -new -key csrsa1.pem -subj "/CN=Test CodeSign EE RSA" -days 36524 \ gen csrsa1.pem "/CN=Test CodeSign EE RSA" codesign_cert >>csrsa1.pem
-CA smroot.pem -extfile ca.cnf -extensions codesign_cert >>csrsa1.pem