Use OSSL_STORE for load_{,pub}key() and load_cert() in apps/lib/apps.c

This also adds the more flexible and general load_key_cert_crl()
as well as helper functions get_passwd(), cleanse(), and clear_free()
to be used also in apps/cmp.c etc.

Reviewed-by: Richard Levitte <levitte@openssl.org>
Reviewed-by: David von Oheimb <david.von.oheimb@siemens.com>
(Merged from https://github.com/openssl/openssl/pull/11755)
master
Dr. David von Oheimb 3 years ago
parent 60d5331350
commit 6d382c74b3

@ -215,12 +215,12 @@ const OPTIONS ca_options[] = {
OPT_SECTION("Signing"),
{"md", OPT_MD, 's', "md to use; one of md2, md5, sha or sha1"},
{"keyfile", OPT_KEYFILE, 's', "Private key"},
{"keyform", OPT_KEYFORM, 'f', "Private key file format (PEM or ENGINE)"},
{"keyform", OPT_KEYFORM, 'f', "Private key file format (ENGINE, other values ignored)"},
{"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
{"key", OPT_KEY, 's', "Key to decode the private key if it is encrypted"},
{"cert", OPT_CERT, '<', "The CA cert"},
{"certform", OPT_CERTFORM, 'F',
"certificate input format (DER or PEM); default PEM"},
"certificate input format (DER/PEM/P12); has no effect"},
{"selfsign", OPT_SELFSIGN, '-',
"Sign a cert with the key associated with it"},
{"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"},
@ -385,7 +385,7 @@ opthelp:
certfile = opt_arg();
break;
case OPT_CERTFORM:
if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &certformat))
if (!opt_format(opt_arg(), OPT_FMT_ANY, &certformat))
goto opthelp;
break;
case OPT_SELFSIGN:
@ -573,8 +573,7 @@ end_of_options:
}
}
pkey = load_key(keyfile, keyformat, 0, key, e, "CA private key");
if (key != NULL)
OPENSSL_cleanse(key, strlen(key));
cleanse(key);
if (pkey == NULL)
/* load_key() has already printed an appropriate message */
goto end;

@ -46,157 +46,6 @@ DEFINE_STACK_OF(X509)
DEFINE_STACK_OF(X509_EXTENSION)
DEFINE_STACK_OF(OSSL_CMP_ITAV)
/* start TODO remove when PR #11755 is merged */
static char *get_passwd(const char *pass, const char *desc)
{
char *result = NULL;
app_passwd(pass, NULL, &result, NULL);
return result;
}
static void cleanse(char *str)
{
if (str != NULL)
OPENSSL_cleanse(str, strlen(str));
}
static void clear_free(char *str)
{
if (str != NULL)
OPENSSL_clear_free(str, strlen(str));
}
static int load_key_cert_crl(const char *uri, int maybe_stdin,
const char *pass, const char *desc,
EVP_PKEY **ppkey, X509 **pcert, X509_CRL **pcrl)
{
PW_CB_DATA uidata;
OSSL_STORE_CTX *ctx = NULL;
int ret = 0;
if (ppkey != NULL)
*ppkey = NULL;
if (pcert != NULL)
*pcert = NULL;
if (pcrl != NULL)
*pcrl = NULL;
uidata.password = pass;
uidata.prompt_info = uri;
ctx = OSSL_STORE_open(uri, get_ui_method(), &uidata, NULL, NULL);
if (ctx == NULL) {
BIO_printf(bio_err, "Could not open file or uri %s for loading %s\n",
uri, desc);
goto end;
}
for (;;) {
OSSL_STORE_INFO *info = OSSL_STORE_load(ctx);
int type = info == NULL ? 0 : OSSL_STORE_INFO_get_type(info);
const char *infostr =
info == NULL ? NULL : OSSL_STORE_INFO_type_string(type);
int err = 0;
if (info == NULL) {
if (OSSL_STORE_eof(ctx))
ret = 1;
break;
}
switch (type) {
case OSSL_STORE_INFO_PKEY:
if (ppkey != NULL && *ppkey == NULL)
err = ((*ppkey = OSSL_STORE_INFO_get1_PKEY(info)) == NULL);
break;
case OSSL_STORE_INFO_CERT:
if (pcert != NULL && *pcert == NULL)
err = ((*pcert = OSSL_STORE_INFO_get1_CERT(info)) == NULL);
break;
case OSSL_STORE_INFO_CRL:
if (pcrl != NULL && *pcrl == NULL)
err = ((*pcrl = OSSL_STORE_INFO_get1_CRL(info)) == NULL);
break;
default:
/* skip any other type */
break;
}
OSSL_STORE_INFO_free(info);
if (err) {
BIO_printf(bio_err, "Could not read %s of %s from %s\n",
infostr, desc, uri);
break;
}
}
end:
if (ctx != NULL)
OSSL_STORE_close(ctx);
if (!ret)
ERR_print_errors(bio_err);
return ret;
}
static
EVP_PKEY *load_key_preliminary(const char *uri, int format, int may_stdin,
const char *pass, ENGINE *e, const char *desc)
{
EVP_PKEY *pkey = NULL;
if (desc == NULL)
desc = "private key";
if (format == FORMAT_ENGINE) {
if (e == NULL) {
BIO_printf(bio_err, "No engine specified for loading %s\n", desc);
} else {
#ifndef OPENSSL_NO_ENGINE
PW_CB_DATA cb_data;
cb_data.password = pass;
cb_data.prompt_info = uri;
if (ENGINE_init(e)) {
pkey = ENGINE_load_private_key(e, uri,
(UI_METHOD *)get_ui_method(),
&cb_data);
ENGINE_finish(e);
}
if (pkey == NULL) {
BIO_printf(bio_err, "Cannot load %s from engine\n", desc);
ERR_print_errors(bio_err);
}
#else
BIO_printf(bio_err, "Engines not supported for loading %s\n", desc);
#endif
}
} else {
(void)load_key_cert_crl(uri, may_stdin, pass, desc, &pkey, NULL, NULL);
}
if (pkey == NULL) {
BIO_printf(bio_err, "Unable to load %s\n", desc);
ERR_print_errors(bio_err);
}
return pkey;
}
static X509 *load_cert_pass(const char *uri, int maybe_stdin,
const char *pass, const char *desc)
{
X509 *cert = NULL;
if (desc == NULL)
desc = "certificate";
(void)load_key_cert_crl(uri, maybe_stdin, pass, desc, NULL, &cert, NULL);
if (cert == NULL) {
BIO_printf(bio_err, "Unable to load %s\n", desc);
ERR_print_errors(bio_err);
}
return cert;
}
/* end TODO remove when PR #11755 is merged */
static char *opt_config = NULL;
#define CMP_SECTION "cmp"
#define SECTION_NAME_MAX 40 /* max length of section name */
@ -832,7 +681,7 @@ static EVP_PKEY *load_key_pwd(const char *uri, int format,
const char *pass, ENGINE *e, const char *desc)
{
char *pass_string = get_passwd(pass, desc);
EVP_PKEY *pkey = load_key_preliminary(uri, format, 0, pass_string, e, desc);
EVP_PKEY *pkey = load_key(uri, format, 0, pass_string, e, desc);
clear_free(pass_string);
return pkey;

@ -196,7 +196,7 @@ const OPTIONS cms_options[] = {
{"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
{"inkey", OPT_INKEY, 's',
"Input private key (if not signer or recipient)"},
{"keyform", OPT_KEYFORM, 'f', "Input private key format (PEM or ENGINE)"},
{"keyform", OPT_KEYFORM, 'f', "Input private key format (ENGINE, other values ignored)"},
{"keyopt", OPT_KEYOPT, 's', "Set public key parameters as n:v pairs"},
OPT_SECTION("Mail header"),
@ -576,7 +576,7 @@ int cms_main(int argc, char **argv)
if (operation == SMIME_ENCRYPT) {
if (encerts == NULL && (encerts = sk_X509_new_null()) == NULL)
goto end;
cert = load_cert(opt_arg(), FORMAT_PEM,
cert = load_cert(opt_arg(), FORMAT_UNDEF,
"recipient certificate file");
if (cert == NULL)
goto end;
@ -756,7 +756,7 @@ int cms_main(int argc, char **argv)
if ((encerts = sk_X509_new_null()) == NULL)
goto end;
while (*argv) {
if ((cert = load_cert(*argv, FORMAT_PEM,
if ((cert = load_cert(*argv, FORMAT_UNDEF,
"recipient certificate file")) == NULL)
goto end;
sk_X509_push(encerts, cert);
@ -774,7 +774,7 @@ int cms_main(int argc, char **argv)
}
if (recipfile != NULL && (operation == SMIME_DECRYPT)) {
if ((recip = load_cert(recipfile, FORMAT_PEM,
if ((recip = load_cert(recipfile, FORMAT_UNDEF,
"recipient certificate file")) == NULL) {
ERR_print_errors(bio_err);
goto end;
@ -782,7 +782,7 @@ int cms_main(int argc, char **argv)
}
if (originatorfile != NULL) {
if ((originator = load_cert(originatorfile, FORMAT_PEM,
if ((originator = load_cert(originatorfile, FORMAT_UNDEF,
"originator certificate file")) == NULL) {
ERR_print_errors(bio_err);
goto end;
@ -790,7 +790,7 @@ int cms_main(int argc, char **argv)
}
if (operation == SMIME_SIGN_RECEIPT) {
if ((signer = load_cert(signerfile, FORMAT_PEM,
if ((signer = load_cert(signerfile, FORMAT_UNDEF,
"receipt signer certificate file")) == NULL) {
ERR_print_errors(bio_err);
goto end;
@ -1019,7 +1019,8 @@ int cms_main(int argc, char **argv)
signerfile = sk_OPENSSL_STRING_value(sksigners, i);
keyfile = sk_OPENSSL_STRING_value(skkeys, i);
signer = load_cert(signerfile, FORMAT_PEM, "signer certificate");
signer = load_cert(signerfile, FORMAT_UNDEF,
"signer certificate");
if (signer == NULL) {
ret = 2;
goto end;

@ -34,9 +34,9 @@ const OPTIONS crl_options[] = {
OPT_SECTION("Input"),
{"in", OPT_IN, '<', "Input file - default stdin"},
{"inform", OPT_INFORM, 'F', "Input format; default PEM"},
{"inform", OPT_INFORM, 'F', "CRL input format (DER or PEM); has no effect"},
{"key", OPT_KEY, '<', "CRL signing Private key to use"},
{"keyform", OPT_KEYFORM, 'F', "Private key file format (PEM or ENGINE)"},
{"keyform", OPT_KEYFORM, 'F', "Private key file format (DER/PEM/P12); has no effect"},
OPT_SECTION("Output"),
{"out", OPT_OUT, '>', "output file - default stdout"},
@ -122,7 +122,7 @@ int crl_main(int argc, char **argv)
outfile = opt_arg();
break;
case OPT_KEYFORM:
if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &keyformat))
if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyformat))
goto opthelp;
break;
case OPT_KEY:

@ -64,7 +64,7 @@ const OPTIONS dgst_options[] = {
{"c", OPT_C, '-', "Print the digest with separating colons"},
{"r", OPT_R, '-', "Print the digest in coreutils format"},
{"out", OPT_OUT, '>', "Output to filename rather than stdout"},
{"keyform", OPT_KEYFORM, 'f', "Key file format (PEM or ENGINE)"},
{"keyform", OPT_KEYFORM, 'f', "Key file format (ENGINE, other values ignored)"},
{"hex", OPT_HEX, '-', "Print as hex dump"},
{"binary", OPT_BINARY, '-', "Print in binary form"},
{"d", OPT_DEBUG, '-', "Print debug info"},

@ -48,7 +48,7 @@ const OPTIONS dsa_options[] = {
OPT_SECTION("Input"),
{"in", OPT_IN, 's', "Input key"},
{"inform", OPT_INFORM, 'f', "Input format, DER PEM PVK"},
{"inform", OPT_INFORM, 'f', "Input format (DER/PEM/PVK); has no effect"},
{"pubin", OPT_PUBIN, '-', "Expect a public key in input file"},
{"passin", OPT_PASSIN, 's', "Input file pass phrase source"},

@ -49,7 +49,7 @@ const OPTIONS ec_options[] = {
OPT_SECTION("Input"),
{"in", OPT_IN, 's', "Input file"},
{"inform", OPT_INFORM, 'f', "Input format - DER or PEM"},
{"inform", OPT_INFORM, 'f', "Input format (DER/PEM/P12/ENGINE)"},
{"pubin", OPT_PUBIN, '-', "Expect a public key in input file"},
{"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
{"check", OPT_CHECK, '-', "check key consistency"},

@ -538,7 +538,7 @@ int enc_main(int argc, char **argv)
goto end;
}
/* wiping secret data as we no longer need it */
OPENSSL_cleanse(hkey, strlen(hkey));
cleanse(hkey);
}
if ((benc = BIO_new(BIO_f_cipher())) == NULL)

@ -102,19 +102,28 @@ int set_cert_ex(unsigned long *flags, const char *arg);
int set_name_ex(unsigned long *flags, const char *arg);
int set_ext_copy(int *copy_type, const char *arg);
int copy_extensions(X509 *x, X509_REQ *req, int copy_type);
char *get_passwd(const char *pass, const char *desc);
int app_passwd(const char *arg1, const char *arg2, char **pass1, char **pass2);
int add_oid_section(CONF *conf);
X509_REQ *load_csr(const char *file, int format, const char *desc);
X509 *load_cert(const char *file, int format, const char *desc);
X509_CRL *load_crl(const char *infile, int format, const char *desc);
EVP_PKEY *load_key(const char *file, int format, int maybe_stdin,
X509 *load_cert_pass(const char *uri, int maybe_stdin,
const char *pass, const char *desc);
/* the format parameter is meanwhile not needed anymore and thus ignored */
X509 *load_cert(const char *uri, int format, const char *desc);
X509_CRL *load_crl(const char *uri, int format, const char *desc);
void cleanse(char *str);
void clear_free(char *str);
EVP_PKEY *load_key(const char *uri, int format, int maybe_stdin,
const char *pass, ENGINE *e, const char *desc);
EVP_PKEY *load_pubkey(const char *file, 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);
int load_certs(const char *file, STACK_OF(X509) **certs, int format,
const char *pass, const char *desc);
int load_crls(const char *file, STACK_OF(X509_CRL) **crls, int format,
const char *pass, const char *desc);
int load_key_cert_crl(const char *uri, int maybe_stdin,
const char *pass, const char *desc,
EVP_PKEY **ppkey, X509 **pcert, X509_CRL **pcrl);
X509_STORE *setup_verify(const char *CAfile, int noCAfile,
const char *CApath, int noCApath,
const char *CAstore, int noCAstore);

@ -132,9 +132,9 @@
{ "xchain_build", OPT_X_CHAIN_BUILD, '-', \
"build certificate chain for the extended certificates"}, \
{ "xcertform", OPT_X_CERTFORM, 'F', \
"format of Extended certificate (PEM or DER) PEM default " }, \
"format of Extended certificate (PEM/DER/P12); has no effect" }, \
{ "xkeyform", OPT_X_KEYFORM, 'F', \
"format of Extended certificate's key (PEM or DER) PEM default"}
"format of Extended certificate's key (DER/PEM/P12); has no effect"}
# define OPT_X_CASES \
OPT_X__FIRST: case OPT_X__LAST: break; \

@ -29,6 +29,7 @@
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/pem.h>
#include <openssl/store.h>
#include <openssl/pkcs12.h>
#include <openssl/ui.h>
#include <openssl/safestack.h>
@ -209,6 +210,24 @@ int wrap_password_callback(char *buf, int bufsiz, int verify, void *userdata)
static char *app_get_pass(const char *arg, int keepbio);
char *get_passwd(const char *pass, const char *desc)
{
char *result = NULL;
if (desc == NULL)
desc = "<unknown>";
if (!app_passwd(pass, NULL, &result, NULL))
BIO_printf(bio_err, "Error getting password for %s\n", desc);
if (pass != NULL && result == NULL) {
BIO_printf(bio_err,
"Trying plain input string (better precede with 'pass:')\n");
result = OPENSSL_strdup(pass);
if (result == NULL)
BIO_printf(bio_err, "Out of memory getting password for %s\n", desc);
}
return result;
}
int app_passwd(const char *arg1, const char *arg2, char **pass1, char **pass2)
{
int same = arg1 != NULL && arg2 != NULL && strcmp(arg1, arg2) == 0;
@ -412,126 +431,44 @@ int add_oid_section(CONF *conf)
return 1;
}
static int load_pkcs12(BIO *in, const char *desc,
pem_password_cb *pem_cb, PW_CB_DATA *cb_data,
EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca)
X509 *load_cert_pass(const char *uri, int maybe_stdin,
const char *pass, const char *desc)
{
const char *pass;
char tpass[PEM_BUFSIZE];
int len, ret = 0;
PKCS12 *p12;
X509 *cert = NULL;
p12 = d2i_PKCS12_bio(in, NULL);
if (p12 == NULL) {
if (desc != NULL)
BIO_printf(bio_err, "Error loading PKCS12 file for %s\n", desc);
else
BIO_printf(bio_err, "Error loading PKCS12 file\n");
goto die;
}
/* See if an empty password will do */
if (PKCS12_verify_mac(p12, "", 0) || PKCS12_verify_mac(p12, NULL, 0)) {
pass = "";
} else {
if (pem_cb == NULL)
pem_cb = (pem_password_cb *)password_callback;
len = pem_cb(tpass, PEM_BUFSIZE, 0, cb_data);
if (len < 0) {
BIO_printf(bio_err, "Passphrase callback error for %s\n",
desc != NULL ? desc : "PKCS12 input");
goto die;
}
if (len < PEM_BUFSIZE)
tpass[len] = 0;
if (!PKCS12_verify_mac(p12, tpass, len)) {
BIO_printf(bio_err,
"Mac verify error (wrong password?) in PKCS12 file for %s\n",
desc != NULL ? desc : "PKCS12 input");
goto die;
}
pass = tpass;
}
ret = PKCS12_parse(p12, pass, pkey, cert, ca);
die:
PKCS12_free(p12);
return ret;
}
X509 *load_cert(const char *file, int format, const char *desc)
{
X509 *x = NULL;
BIO *cert;
if (format == FORMAT_HTTP) {
#if !defined(OPENSSL_NO_SOCK)
x = X509_load_http(file, NULL, NULL, 0 /* timeout */);
#endif
return x;
}
if (file == NULL) {
if (desc == NULL)
desc = "certificate";
if (uri == NULL) {
unbuffer(stdin);
cert = dup_bio_in(format);
} else {
cert = bio_open_default(file, 'r', format);
uri = "";
}
if (cert == NULL)
goto end;
if (format == FORMAT_ASN1) {
x = d2i_X509_bio(cert, NULL);
} else if (format == FORMAT_PEM) {
x = PEM_read_bio_X509_AUX(cert, NULL,
(pem_password_cb *)password_callback, NULL);
} else if (format == FORMAT_PKCS12) {
if (!load_pkcs12(cert, desc, NULL, NULL, NULL, &x, NULL))
goto end;
} else {
print_format_error(format,
#if !defined(OPENSSL_NO_OCSP) && !defined(OPENSSL_NO_SOCK)
OPT_FMT_HTTP |
#endif
OPT_FMT_PEMDER | OPT_FMT_PKCS12);
}
end:
if (x == NULL && desc != NULL) {
(void)load_key_cert_crl(uri, maybe_stdin, pass, desc, NULL, &cert, NULL);
if (cert == NULL) {
BIO_printf(bio_err, "Unable to load %s\n", desc);
ERR_print_errors(bio_err);
}
BIO_free(cert);
return x;
return cert;
}
X509_CRL *load_crl(const char *infile, int format, const char *desc)
/* the format parameter is meanwhile not needed anymore and thus ignored */
X509 *load_cert(const char *uri, int format, const char *desc)
{
X509_CRL *x = NULL;
BIO *in = NULL;
if (format == FORMAT_HTTP) {
#if !defined(OPENSSL_NO_SOCK)
x = X509_CRL_load_http(infile, NULL, NULL, 0 /* timeout */);
#endif
return x;
}
return load_cert_pass(uri, 0, NULL, desc);
}
in = bio_open_default(infile, 'r', format);
if (in == NULL)
goto end;
if (format == FORMAT_ASN1) {
x = d2i_X509_CRL_bio(in, NULL);
} else if (format == FORMAT_PEM) {
x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
} else
print_format_error(format, OPT_FMT_PEMDER);
/* the format parameter is meanwhile not needed anymore and thus ignored */
X509_CRL *load_crl(const char *uri, int format, const char *desc)
{
X509_CRL *crl = NULL;
end:
if (x == NULL && desc != NULL) {
if (desc == NULL)
desc = "CRL";
(void)load_key_cert_crl(uri, 0, NULL, desc, NULL, NULL, &crl);
if (crl == NULL) {
BIO_printf(bio_err, "Unable to load %s\n", desc);
ERR_print_errors(bio_err);
}
BIO_free(in);
return x;
return crl;
}
X509_REQ *load_csr(const char *file, int format, const char *desc)
@ -539,6 +476,8 @@ X509_REQ *load_csr(const char *file, int format, const char *desc)
X509_REQ *req = NULL;
BIO *in;
if (desc == NULL)
desc = "CSR";
in = bio_open_default(file, 'r', format);
if (in == NULL)
goto end;
@ -551,7 +490,7 @@ X509_REQ *load_csr(const char *file, int format, const char *desc)
print_format_error(format, OPT_FMT_PEMDER);
end:
if (req == NULL && desc != NULL) {
if (req == NULL) {
BIO_printf(bio_err, "Unable to load %s\n", desc);
ERR_print_errors(bio_err);
}
@ -559,173 +498,92 @@ X509_REQ *load_csr(const char *file, int format, const char *desc)
return req;
}
EVP_PKEY *load_key(const char *file, int format, int maybe_stdin,
void cleanse(char *str)
{
if (str != NULL)
OPENSSL_cleanse(str, strlen(str));
}
void clear_free(char *str)
{
if (str != NULL)
OPENSSL_clear_free(str, strlen(str));
}
EVP_PKEY *load_key(const char *uri, int format, int may_stdin,
const char *pass, ENGINE *e, const char *desc)
{
BIO *key = NULL;
EVP_PKEY *pkey = NULL;
PW_CB_DATA cb_data;
cb_data.password = pass;
cb_data.prompt_info = file;
if (desc == NULL)
desc = "private key";
if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE)) {
BIO_printf(bio_err, "No keyfile specified\n");
goto end;
}
if (format == FORMAT_ENGINE) {
if (e == NULL) {
BIO_printf(bio_err, "No engine specified\n");
BIO_printf(bio_err, "No engine specified for loading %s\n", desc);
} else {
#ifndef OPENSSL_NO_ENGINE
PW_CB_DATA cb_data;
cb_data.password = pass;
cb_data.prompt_info = uri;
if (ENGINE_init(e)) {
pkey = ENGINE_load_private_key(e, file,
pkey = ENGINE_load_private_key(e, uri,
(UI_METHOD *)get_ui_method(),
&cb_data);
ENGINE_finish(e);
}
if (pkey == NULL && desc != NULL) {
if (pkey == NULL) {
BIO_printf(bio_err, "Cannot load %s from engine\n", desc);
ERR_print_errors(bio_err);
}
#else
BIO_printf(bio_err, "Engines not supported\n");
BIO_printf(bio_err, "Engines not supported for loading %s\n", desc);
#endif
}
goto end;
}
if (file == NULL && maybe_stdin) {
unbuffer(stdin);
key = dup_bio_in(format);
} else {
key = bio_open_default(file, 'r', format);
}
if (key == NULL)
goto end;
if (format == FORMAT_ASN1) {
pkey = d2i_PrivateKey_bio(key, NULL);
} else if (format == FORMAT_PEM) {
pkey = PEM_read_bio_PrivateKey(key, NULL, wrap_password_callback, &cb_data);
} else if (format == FORMAT_PKCS12) {
if (!load_pkcs12(key, desc,
(pem_password_cb *)password_callback, &cb_data,
&pkey, NULL, NULL))
goto end;
#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) && !defined (OPENSSL_NO_RC4)
} else if (format == FORMAT_MSBLOB) {
pkey = b2i_PrivateKey_bio(key);
} else if (format == FORMAT_PVK) {
pkey = b2i_PVK_bio(key, wrap_password_callback, &cb_data);
#endif
} else {
print_format_error(format, OPT_FMT_PEMDER | OPT_FMT_PKCS12
#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) && !defined (OPENSSL_NO_RC4)
| OPT_FMT_MSBLOB | FORMAT_PVK
#endif
#ifndef OPENSSL_NO_ENGINE
| OPT_FMT_ENGINE
#endif
);
(void)load_key_cert_crl(uri, may_stdin, pass, desc, &pkey, NULL, NULL);
}
end:
BIO_free(key);
if (pkey == NULL && desc != NULL) {
if (pkey == NULL) {
BIO_printf(bio_err, "Unable to load %s\n", desc);
ERR_print_errors(bio_err);
}
return pkey;
}
EVP_PKEY *load_pubkey(const char *file, 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)
{
BIO *key = NULL;
EVP_PKEY *pkey = NULL;
PW_CB_DATA cb_data;
cb_data.password = pass;
cb_data.prompt_info = file;
if (desc == NULL)
desc = "public key";
if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE)) {
BIO_printf(bio_err, "No keyfile specified\n");
goto end;
}
if (format == FORMAT_ENGINE) {
if (e == NULL) {
BIO_printf(bio_err, "No engine specified\n");
BIO_printf(bio_err, "No engine specified for loading %s\n", desc);
} else {
#ifndef OPENSSL_NO_ENGINE
pkey = ENGINE_load_public_key(e, file, (UI_METHOD *)get_ui_method(),
PW_CB_DATA cb_data;
cb_data.password = pass;
cb_data.prompt_info = uri;
pkey = ENGINE_load_public_key(e, uri, (UI_METHOD *)get_ui_method(),
&cb_data);
if (pkey == NULL && desc != NULL) {
if (pkey == NULL) {
BIO_printf(bio_err, "Cannot load %s from engine\n", desc);
ERR_print_errors(bio_err);
}
#else
BIO_printf(bio_err, "Engines not supported\n");
BIO_printf(bio_err, "Engines not supported for loading %s\n", desc);
#endif
}
goto end;
}
if (file == NULL && maybe_stdin) {
unbuffer(stdin);
key = dup_bio_in(format);
} else {
key = bio_open_default(file, 'r', format);
(void)load_key_cert_crl(uri, maybe_stdin, pass, desc, &pkey,
NULL, NULL);
}
if (key == NULL)
goto end;
if (format == FORMAT_ASN1) {
pkey = d2i_PUBKEY_bio(key, NULL);
} else if (format == FORMAT_ASN1RSA) {
#ifndef OPENSSL_NO_RSA
RSA *rsa;
rsa = d2i_RSAPublicKey_bio(key, NULL);
if (rsa) {
pkey = EVP_PKEY_new();
if (pkey != NULL)
EVP_PKEY_set1_RSA(pkey, rsa);
RSA_free(rsa);
} else
#else
BIO_printf(bio_err, "RSA keys not supported\n");
#endif
pkey = NULL;
} else if (format == FORMAT_PEMRSA) {
#ifndef OPENSSL_NO_RSA
RSA *rsa;
rsa = PEM_read_bio_RSAPublicKey(key, NULL,
(pem_password_cb *)password_callback,
&cb_data);
if (rsa != NULL) {
pkey = EVP_PKEY_new();
if (pkey != NULL)
EVP_PKEY_set1_RSA(pkey, rsa);
RSA_free(rsa);
} else
#else
BIO_printf(bio_err, "RSA keys not supported\n");
#endif
pkey = NULL;
} else if (format == FORMAT_PEM) {
pkey = PEM_read_bio_PUBKEY(key, NULL,
(pem_password_cb *)password_callback,
&cb_data);
#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA)
} else if (format == FORMAT_MSBLOB) {
pkey = b2i_PublicKey_bio(key);
#endif
} else {
print_format_error(format, OPT_FMT_PEMDER
#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA)
| OPT_FMT_MSBLOB
#endif
);
}
end:
BIO_free(key);
if (pkey == NULL && desc != NULL) {
if (pkey == NULL) {
BIO_printf(bio_err, "Unable to load %s\n", desc);
ERR_print_errors(bio_err);
}
@ -807,11 +665,8 @@ static int load_certs_crls(const char *file, int format,
sk_X509_CRL_pop_free(*pcrls, X509_CRL_free);
*pcrls = NULL;
}
if (desc != NULL) {
BIO_printf(bio_err, "Unable to load %s for %s\n",
pcerts ? "certificates" : "CRLs", desc);
ERR_print_errors(bio_err);
}
BIO_printf(bio_err, "Unable to load %s\n", desc != NULL ? desc :
pcerts != NULL ? "certificates" : "CRLs");
}
return rv;
}
@ -847,6 +702,102 @@ int load_crls(const char *file, STACK_OF(X509_CRL) **crls, int format,
return load_certs_crls(file, format, pass, desc, NULL, crls);
}
/*
* Load those types of credentials for which the result pointer is not NULL.
* Reads from stdio if uri is NULL and maybe_stdin is nonzero.
* For each type the first credential found in the store is loaded.
* May yield partial result even if rv == 0.
*/
int load_key_cert_crl(const char *uri, int maybe_stdin,
const char *pass, const char *desc,
EVP_PKEY **ppkey, X509 **pcert, X509_CRL **pcrl)
{
PW_CB_DATA uidata;
OSSL_STORE_CTX *ctx = NULL;
int ret = 0;
/* TODO make use of the engine reference 'eng' when loading pkeys */
if (ppkey != NULL)
*ppkey = NULL;
if (pcert != NULL)
*pcert = NULL;
if (pcrl != NULL)
*pcrl = NULL;
if (desc == NULL)
desc = "key/certificate/CRL";
uidata.password = pass;
uidata.prompt_info = uri;
if (uri == NULL) {
BIO *bio;
if (!maybe_stdin) {
BIO_printf(bio_err, "No filename or uri specified for loading %s\n",
desc);
goto end;
}
unbuffer(stdin);
bio = BIO_new_fp(stdin, 0);
if (bio != NULL)
ctx = OSSL_STORE_attach(bio, NULL, "file", NULL,
get_ui_method(), &uidata, NULL, NULL);
uri = "<stdin>";
} else {
ctx = OSSL_STORE_open(uri, get_ui_method(), &uidata, NULL, NULL);
}
if (ctx == NULL) {
BIO_printf(bio_err, "Could not open file or uri %s for loading %s\n",
uri, desc);
goto end;
}
for (;;) {
OSSL_STORE_INFO *info = OSSL_STORE_load(ctx);
int type = info == NULL ? 0 : OSSL_STORE_INFO_get_type(info);
const char *infostr =
info == NULL ? NULL : OSSL_STORE_INFO_type_string(type);
int err = 0;
if (info == NULL) {
if (OSSL_STORE_eof(ctx))
ret = 1;
break;
}
switch (type) {
case OSSL_STORE_INFO_PKEY:
if (ppkey != NULL && *ppkey == NULL)
err = ((*ppkey = OSSL_STORE_INFO_get1_PKEY(info)) == NULL);
break;
case OSSL_STORE_INFO_CERT:
if (pcert != NULL && *pcert == NULL)
err = ((*pcert = OSSL_STORE_INFO_get1_CERT(info)) == NULL);
break;
case OSSL_STORE_INFO_CRL:
if (pcrl != NULL && *pcrl == NULL)
err = ((*pcrl = OSSL_STORE_INFO_get1_CRL(info)) == NULL);
break;
default:
/* skip any other type */
break;
}
OSSL_STORE_INFO_free(info);
if (err) {
BIO_printf(bio_err, "Could not read %s of %s from %s\n",
infostr, desc, uri);
break;
}
}
end:
OSSL_STORE_close(ctx);
if (!ret)
ERR_print_errors(bio_err);
return ret;
}
#define X509V3_EXT_UNKNOWN_MASK (0xfL << 16)
/* Return error for unknown extensions */
#define X509V3_EXT_DEFAULT 0

@ -1094,11 +1094,11 @@ int args_excert(int opt, SSL_EXCERT **pexc)
exc->build_chain = 1;
break;
case OPT_X_CERTFORM:
if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &exc->certform))
if (!opt_format(opt_arg(), OPT_FMT_ANY, &exc->certform))
return 0;
break;
case OPT_X_KEYFORM:
if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &exc->keyform))
if (!opt_format(opt_arg(), OPT_FMT_ANY, &exc->keyform))
return 0;
break;
}

@ -404,7 +404,8 @@ int ocsp_main(int argc, char **argv)
path = opt_arg();
break;
case OPT_ISSUER:
issuer = load_cert(opt_arg(), FORMAT_PEM, "issuer certificate");
issuer = load_cert(opt_arg(), FORMAT_UNDEF,
"issuer certificate");
if (issuer == NULL)
goto end;
if (issuers == NULL) {
@ -416,7 +417,7 @@ int ocsp_main(int argc, char **argv)
break;
case OPT_CERT:
X509_free(cert);
cert = load_cert(opt_arg(), FORMAT_PEM, "certificate");
cert = load_cert(opt_arg(), FORMAT_UNDEF, "certificate");
if (cert == NULL)
goto end;
if (cert_id_md == NULL)
@ -560,7 +561,8 @@ int ocsp_main(int argc, char **argv)
if (rsignfile != NULL) {
if (rkeyfile == NULL)
rkeyfile = rsignfile;
rsigner = load_cert(rsignfile, FORMAT_PEM, "responder certificate");
rsigner = load_cert(rsignfile, FORMAT_UNDEF,
"responder certificate");
if (rsigner == NULL) {
BIO_printf(bio_err, "Error loading responder certificate\n");
goto end;
@ -653,7 +655,7 @@ redo_accept:
if (signfile != NULL) {
if (keyfile == NULL)
keyfile = signfile;
signer = load_cert(signfile, FORMAT_PEM, "signer certificate");
signer = load_cert(signfile, FORMAT_UNDEF, "signer certificate");
if (signer == NULL) {
BIO_printf(bio_err, "Error loading signer certificate\n");
goto end;

@ -57,7 +57,7 @@ const OPTIONS pkey_options[] = {
OPT_SECTION("Input"),
{"in", OPT_IN, 's', "Input key"},
{"inform", OPT_INFORM, 'f', "Input format (DER or PEM)"},
{"inform", OPT_INFORM, 'f', "Input format (DER/PEM/P12/ENGINE)"},
{"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
{"pubin", OPT_PUBIN, '-',
"Read public key from input (default is private key)"},

@ -71,11 +71,11 @@ const OPTIONS pkeyutl_options[] = {
{"inkey", OPT_INKEY, 's', "Input private key file"},
{"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
{"peerkey", OPT_PEERKEY, 's', "Peer key file used in key derivation"},
{"peerform", OPT_PEERFORM, 'E', "Peer key format - default PEM"},
{"peerform", OPT_PEERFORM, 'E', "Peer key format (DER/PEM/P12/ENGINE)"},
{"certin", OPT_CERTIN, '-', "Input is a cert with a public key"},
{"rev", OPT_REV, '-', "Reverse the order of the input buffer"},
{"sigfile", OPT_SIGFILE, '<', "Signature file (verify operation only)"},
{"keyform", OPT_KEYFORM, 'E', "Private key format - default PEM"},
{"keyform", OPT_KEYFORM, 'E', "Private key format (ENGINE, other values ignored)"},
OPT_SECTION("Output"),
{"out", OPT_OUT, '>', "Output file - default stdout"},
@ -157,11 +157,11 @@ int pkeyutl_main(int argc, char **argv)
passinarg = opt_arg();
break;
case OPT_PEERFORM:
if (!opt_format(opt_arg(), OPT_FMT_PDE, &peerform))
if (!opt_format(opt_arg(), OPT_FMT_ANY, &peerform))
goto opthelp;
break;
case OPT_KEYFORM:
if (!opt_format(opt_arg(), OPT_FMT_PDE, &keyform))
if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform))
goto opthelp;
break;
case OPT_R_CASES:
@ -519,7 +519,7 @@ static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize,
break;
case KEY_CERT:
x = load_cert(keyfile, keyform, "Certificate");
x = load_cert(keyfile, FORMAT_UNDEF, "Certificate");
if (x) {
pkey = X509_get_pubkey(x);
X509_free(x);

@ -137,7 +137,7 @@ const OPTIONS req_options[] = {
OPT_SECTION("Keys and Signing"),
{"key", OPT_KEY, 's', "Private key to use"},
{"keyform", OPT_KEYFORM, 'f', "Key file format"},
{"keyform", OPT_KEYFORM, 'f', "Key file format (ENGINE, other values ignored)"},
{"pubkey", OPT_PUBKEY, '-', "Output public key"},
{"keyout", OPT_KEYOUT, '>', "File to send the key to"},
{"passin", OPT_PASSIN, 's', "Private key password source"},

@ -45,7 +45,7 @@ const OPTIONS rsa_options[] = {
OPT_SECTION("Input"),
{"in", OPT_IN, 's', "Input file"},
{"inform", OPT_INFORM, 'f', "Input format, one of DER PEM"},
{"inform", OPT_INFORM, 'f', "Input format (DER/PEM/P12/ENGINE"},
{"pubin", OPT_PUBIN, '-', "Expect a public key in input file"},
{"RSAPublicKey_in", OPT_RSAPUBKEY_IN, '-', "Input is an RSAPublicKey"},
{"passin", OPT_PASSIN, 's', "Input file pass phrase source"},

@ -51,7 +51,7 @@ const OPTIONS rsautl_options[] = {
OPT_SECTION("Input"),
{"in", OPT_IN, '<', "Input file"},
{"inkey", OPT_INKEY, 's', "Input key"},
{"keyform", OPT_KEYFORM, 'E', "Private key format - default PEM"},
{"keyform", OPT_KEYFORM, 'E', "Private key format (ENGINE, other values ignored)"},
{"pubin", OPT_PUBIN, '-', "Input is an RSA public"},
{"certin", OPT_CERTIN, '-', "Input is a cert carrying an RSA public key"},
{"rev", OPT_REV, '-', "Reverse the order of the input buffer"},
@ -101,7 +101,7 @@ int rsautl_main(int argc, char **argv)
ret = 0;
goto end;
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_IN:
@ -197,7 +197,7 @@ int rsautl_main(int argc, char **argv)
break;
case KEY_CERT:
x = load_cert(keyfile, keyformat, "Certificate");
x = load_cert(keyfile, FORMAT_UNDEF, "Certificate");
if (x) {
pkey = X509_get_pubkey(x);
X509_free(x);

@ -636,12 +636,12 @@ const OPTIONS s_client_options[] = {
OPT_SECTION("Identity"),
{"cert", OPT_CERT, '<', "Client certificate file to use"},
{"certform", OPT_CERTFORM, 'F',
"Client certificate file format (PEM or DER) PEM default"},
"Client certificate file format (PEM/DER/P12); has no effect"},
{"cert_chain", OPT_CERT_CHAIN, '<',
"Client certificate chain file (in PEM format)"},
{"build_chain", OPT_BUILD_CHAIN, '-', "Build client certificate chain"},
{"key", OPT_KEY, 's', "Private key file to use; default is: -cert file"},
{"keyform", OPT_KEYFORM, 'E', "Key format (PEM, DER or engine) PEM default"},
{"keyform", OPT_KEYFORM, 'E', "Key format (ENGINE, other values ignored)"},
{"pass", OPT_PASS, 's', "Private key file pass phrase source"},
{"verify", OPT_VERIFY, 'p', "Turn on peer certificate verification"},
{"nameopt", OPT_NAMEOPT, 's', "Certificate subject/issuer name printing options"},
@ -1144,7 +1144,7 @@ int s_client_main(int argc, char **argv)
sess_in = opt_arg();
break;
case OPT_CERTFORM:
if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &cert_format))
if (!opt_format(opt_arg(), OPT_FMT_ANY, &cert_format))
goto opthelp;
break;
case OPT_CRLFORM:
@ -1378,7 +1378,7 @@ int s_client_main(int argc, char **argv)
fallback_scsv = 1;
break;
case OPT_KEYFORM:
if (!opt_format(opt_arg(), OPT_FMT_PDE, &key_format))
if (!opt_format(opt_arg(), OPT_FMT_ANY, &key_format))
goto opthelp;
break;
case OPT_PASS:
@ -3137,8 +3137,7 @@ int s_client_main(int argc, char **argv)
OPENSSL_clear_free(cbuf, BUFSIZZ);
OPENSSL_clear_free(sbuf, BUFSIZZ);
OPENSSL_clear_free(mbuf, BUFSIZZ);
if (proxypass != NULL)
OPENSSL_clear_free(proxypass, strlen(proxypass));
clear_free(proxypass);
release_engine(e);
BIO_free(bio_c_out);
bio_c_out = NULL;

@ -813,7 +813,7 @@ const OPTIONS s_server_options[] = {
{"cert2", OPT_CERT2, '<',
"Certificate file to use for servername; default is" TEST_CERT2},
{"certform", OPT_CERTFORM, 'F',
"Server certificate file format (PEM or DER) PEM default"},
"Server certificate file format (PEM/DER/P12); has no effect"},
{"cert_chain", OPT_CERT_CHAIN, '<',
"Server certificate chain file in PEM format"},
{"build_chain", OPT_BUILD_CHAIN, '-', "Build server certificate chain"},
@ -823,19 +823,18 @@ const OPTIONS s_server_options[] = {
"Private key file to use; default is -cert file or else" TEST_CERT},
{"key2", OPT_KEY2, '<',
"-Private Key file to use for servername if not in -cert2"},
{"keyform", OPT_KEYFORM, 'f',
"Key format (PEM, DER or ENGINE) PEM default"},
{"keyform", OPT_KEYFORM, 'f', "Key format (ENGINE, other values ignored)"},
{"pass", OPT_PASS, 's', "Private key file pass phrase source"},
{"dcert", OPT_DCERT, '<',
"Second server certificate file to use (usually for DSA)"},
{"dcertform", OPT_DCERTFORM, 'F',
"Second server certificate file format (PEM or DER) PEM default"},
"Second server certificate file format (PEM/DER/P12); has no effect"},
{"dcert_chain", OPT_DCERT_CHAIN, '<',
"second server certificate chain file in PEM format"},
{"dkey", OPT_DKEY, '<',
"Second private key file to use (usually for DSA)"},
{"dkeyform", OPT_DKEYFORM, 'F',
"Second key file format (PEM, DER or ENGINE) PEM default"},
"Second key file format (ENGINE, other values ignored)"},
{"dpass", OPT_DPASS, 's', "Second private key file pass phrase source"},
{"dhparam", OPT_DHPARAM, '<', "DH parameters file to use"},
{"servername", OPT_SERVERNAME, 's',
@ -1246,14 +1245,14 @@ int s_server_main(int argc, char *argv[])
s_serverinfo_file = opt_arg();
break;
case OPT_CERTFORM:
if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &s_cert_format))
if (!opt_format(opt_arg(), OPT_FMT_ANY, &s_cert_format))
goto opthelp;
break;
case OPT_KEY:
s_key_file = opt_arg();
break;
case OPT_KEYFORM:
if (!opt_format(opt_arg(), OPT_FMT_PDE, &s_key_format))
if (!opt_format(opt_arg(), OPT_FMT_ANY, &s_key_format))
goto opthelp;
break;
case OPT_PASS:
@ -1268,14 +1267,14 @@ int s_server_main(int argc, char *argv[])
#endif
break;
case OPT_DCERTFORM:
if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &s_dcert_format))
if (!opt_format(opt_arg(), OPT_FMT_ANY, &s_dcert_format))
goto opthelp;
break;
case OPT_DCERT:
s_dcert_file = opt_arg();
break;
case OPT_DKEYFORM:
if (!opt_format(opt_arg(), OPT_FMT_PDE, &s_dkey_format))
if (!opt_format(opt_arg(), OPT_FMT_ANY, &s_dkey_format))
goto opthelp;
break;
case OPT_DPASS:

@ -63,7 +63,7 @@ const OPTIONS smime_options[] = {
"Output format SMIME (default), PEM or DER"},
{"inkey", OPT_INKEY, 's',
"Input private key (if not signer or recipient)"},
{"keyform", OPT_KEYFORM, 'f', "Input private key format (PEM or ENGINE)"},
{"keyform", OPT_KEYFORM, 'f', "Input private key format (ENGINE, other values ignored)"},
#ifndef OPENSSL_NO_ENGINE
{"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
#endif
@ -429,7 +429,7 @@ int smime_main(int argc, char **argv)
if (encerts == NULL)
goto end;
while (*argv != NULL) {
cert = load_cert(*argv, FORMAT_PEM,
cert = load_cert(*argv, FORMAT_UNDEF,
"recipient certificate file");
if (cert == NULL)
goto end;
@ -448,7 +448,7 @@ int smime_main(int argc, char **argv)
}
if (recipfile != NULL && (operation == SMIME_DECRYPT)) {
if ((recip = load_cert(recipfile, FORMAT_PEM,
if ((recip = load_cert(recipfile, FORMAT_UNDEF,
"recipient certificate file")) == NULL) {
ERR_print_errors(bio_err);
goto end;
@ -548,7 +548,7 @@ int smime_main(int argc, char **argv)
for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) {
signerfile = sk_OPENSSL_STRING_value(sksigners, i);
keyfile = sk_OPENSSL_STRING_value(skkeys, i);
signer = load_cert(signerfile, FORMAT_PEM,
signer = load_cert(signerfile, FORMAT_UNDEF,
"signer certificate");
if (signer == NULL)
goto end;

@ -40,7 +40,7 @@ const OPTIONS spkac_options[] = {