diff --git a/apps/include/apps.h b/apps/include/apps.h index 0ee8e070cd..0e734a528e 100644 --- a/apps/include/apps.h +++ b/apps/include/apps.h @@ -119,7 +119,8 @@ 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); + EVP_PKEY **ppkey, EVP_PKEY **ppubkey, + X509 **pcert, X509_CRL **pcrl); X509_STORE *setup_verify(const char *CAfile, int noCAfile, const char *CApath, int noCApath, const char *CAstore, int noCAstore); diff --git a/apps/lib/apps.c b/apps/lib/apps.c index e8592c4880..d19fdc2126 100644 --- a/apps/lib/apps.c +++ b/apps/lib/apps.c @@ -491,7 +491,8 @@ X509 *load_cert_pass(const char *uri, int maybe_stdin, if (desc == NULL) desc = "certificate"; - (void)load_key_cert_crl(uri, maybe_stdin, pass, desc, NULL, &cert, NULL); + (void)load_key_cert_crl(uri, maybe_stdin, pass, desc, + NULL, NULL, &cert, NULL); if (cert == NULL) { BIO_printf(bio_err, "Unable to load %s\n", desc); ERR_print_errors(bio_err); @@ -512,7 +513,8 @@ X509_CRL *load_crl(const char *uri, int format, const char *desc) if (desc == NULL) desc = "CRL"; - (void)load_key_cert_crl(uri, 0, NULL, desc, NULL, NULL, &crl); + (void)load_key_cert_crl(uri, 0, NULL, desc, + NULL, NULL, NULL, &crl); if (crl == NULL) { BIO_printf(bio_err, "Unable to load %s\n", desc); ERR_print_errors(bio_err); @@ -591,7 +593,8 @@ EVP_PKEY *load_key(const char *uri, int format, int may_stdin, #endif } } else { - (void)load_key_cert_crl(uri, may_stdin, pass, desc, &pkey, NULL, NULL); + (void)load_key_cert_crl(uri, may_stdin, pass, desc, + &pkey, NULL, NULL, NULL); } if (pkey == NULL) { @@ -629,8 +632,8 @@ EVP_PKEY *load_pubkey(const char *uri, int format, int maybe_stdin, #endif } } else { - (void)load_key_cert_crl(uri, maybe_stdin, pass, desc, &pkey, - NULL, NULL); + (void)load_key_cert_crl(uri, maybe_stdin, pass, desc, + NULL, &pkey, NULL, NULL); } if (pkey == NULL) { BIO_printf(bio_err, "Unable to load %s\n", desc); @@ -769,7 +772,8 @@ int load_crls(const char *file, STACK_OF(X509_CRL) **crls, int format, */ 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) + EVP_PKEY **ppkey, EVP_PKEY **ppubkey, + X509 **pcert, X509_CRL **pcrl) { PW_CB_DATA uidata; OSSL_STORE_CTX *ctx = NULL; @@ -780,6 +784,8 @@ int load_key_cert_crl(const char *uri, int maybe_stdin, if (ppkey != NULL) *ppkey = NULL; + if (ppubkey != NULL) + *ppubkey = NULL; if (pcert != NULL) *pcert = NULL; if (pcrl != NULL) @@ -831,6 +837,18 @@ int load_key_cert_crl(const char *uri, int maybe_stdin, case OSSL_STORE_INFO_PKEY: if (ppkey != NULL && *ppkey == NULL) err = ((*ppkey = OSSL_STORE_INFO_get1_PKEY(info)) == NULL); + + /* + * An EVP_PKEY with private parts also holds the public parts, + * so if the caller asked for a public key, and we got a private + * key, we can still pass it back. + */ + if (ppubkey != NULL && *ppubkey == NULL) + err = ((*ppubkey = OSSL_STORE_INFO_get1_PKEY(info)) == NULL); + break; + case OSSL_STORE_INFO_PUBKEY: + if (ppubkey != NULL && *ppubkey == NULL) + err = ((*ppubkey = OSSL_STORE_INFO_get1_PUBKEY(info)) == NULL); break; case OSSL_STORE_INFO_CERT: if (pcert != NULL && *pcert == NULL) diff --git a/apps/storeutl.c b/apps/storeutl.c index 66fd423ab0..3d9498dc46 100644 --- a/apps/storeutl.c +++ b/apps/storeutl.c @@ -450,6 +450,13 @@ static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata, PEM_write_bio_Parameters(out, OSSL_STORE_INFO_get0_PARAMS(info)); break; + case OSSL_STORE_INFO_PUBKEY: + if (text) + EVP_PKEY_print_public(out, OSSL_STORE_INFO_get0_PUBKEY(info), + 0, NULL); + if (!noout) + PEM_write_bio_PUBKEY(out, OSSL_STORE_INFO_get0_PUBKEY(info)); + break; case OSSL_STORE_INFO_PKEY: if (text) EVP_PKEY_print_private(out, OSSL_STORE_INFO_get0_PKEY(info), diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 7431248d8f..e83f1013ec 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -2717,8 +2717,9 @@ OSSL_STORE_R_LOADER_INCOMPLETE:116:loader incomplete OSSL_STORE_R_LOADING_STARTED:117:loading started OSSL_STORE_R_NOT_A_CERTIFICATE:100:not a certificate OSSL_STORE_R_NOT_A_CRL:101:not a crl -OSSL_STORE_R_NOT_A_KEY:102:not a key OSSL_STORE_R_NOT_A_NAME:103:not a name +OSSL_STORE_R_NOT_A_PRIVATE_KEY:102:not a private key +OSSL_STORE_R_NOT_A_PUBLIC_KEY:122:not a public key OSSL_STORE_R_NOT_PARAMETERS:104:not parameters OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR:114:passphrase callback error OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE:108:path must be absolute diff --git a/crypto/store/loader_file.c b/crypto/store/loader_file.c index 3b54ebbcd5..25ce9ba92e 100644 --- a/crypto/store/loader_file.c +++ b/crypto/store/loader_file.c @@ -565,7 +565,7 @@ static OSSL_STORE_INFO *try_decode_PUBKEY(const char *pem_name, if ((pkey = d2i_PUBKEY(NULL, &blob, len)) != NULL) { *matchcount = 1; - store_info = OSSL_STORE_INFO_new_PKEY(pkey); + store_info = OSSL_STORE_INFO_new_PUBKEY(pkey); } return store_info; diff --git a/crypto/store/store_err.c b/crypto/store/store_err.c index 3abb50bb21..320934e6c6 100644 --- a/crypto/store/store_err.c +++ b/crypto/store/store_err.c @@ -32,8 +32,11 @@ static const ERR_STRING_DATA OSSL_STORE_str_reasons[] = { {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_A_CERTIFICATE), "not a certificate"}, {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_A_CRL), "not a crl"}, - {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_A_KEY), "not a key"}, {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_A_NAME), "not a name"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_A_PRIVATE_KEY), + "not a private key"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_A_PUBLIC_KEY), + "not a public key"}, {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_PARAMETERS), "not parameters"}, {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR), diff --git a/crypto/store/store_lib.c b/crypto/store/store_lib.c index 2878358245..2ff92b7984 100644 --- a/crypto/store/store_lib.c +++ b/crypto/store/store_lib.c @@ -307,6 +307,15 @@ OSSL_STORE_INFO *OSSL_STORE_INFO_new_PARAMS(EVP_PKEY *params) return info; } +OSSL_STORE_INFO *OSSL_STORE_INFO_new_PUBKEY(EVP_PKEY *pkey) +{ + OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_PUBKEY, pkey); + + if (info == NULL) + ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE); + return info; +} + OSSL_STORE_INFO *OSSL_STORE_INFO_new_PKEY(EVP_PKEY *pkey) { OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_PKEY, pkey); @@ -408,6 +417,23 @@ EVP_PKEY *OSSL_STORE_INFO_get1_PARAMS(const OSSL_STORE_INFO *info) return NULL; } +EVP_PKEY *OSSL_STORE_INFO_get0_PUBKEY(const OSSL_STORE_INFO *info) +{ + if (info->type == OSSL_STORE_INFO_PUBKEY) + return info->_.pubkey; + return NULL; +} + +EVP_PKEY *OSSL_STORE_INFO_get1_PUBKEY(const OSSL_STORE_INFO *info) +{ + if (info->type == OSSL_STORE_INFO_PUBKEY) { + EVP_PKEY_up_ref(info->_.pubkey); + return info->_.pubkey; + } + OSSL_STOREerr(0, OSSL_STORE_R_NOT_A_PUBLIC_KEY); + return NULL; +} + EVP_PKEY *OSSL_STORE_INFO_get0_PKEY(const OSSL_STORE_INFO *info) { if (info->type == OSSL_STORE_INFO_PKEY) @@ -422,7 +448,7 @@ EVP_PKEY *OSSL_STORE_INFO_get1_PKEY(const OSSL_STORE_INFO *info) return info->_.pkey; } OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_PKEY, - OSSL_STORE_R_NOT_A_KEY); + OSSL_STORE_R_NOT_A_PRIVATE_KEY); return NULL; } @@ -480,6 +506,9 @@ void OSSL_STORE_INFO_free(OSSL_STORE_INFO *info) case OSSL_STORE_INFO_PARAMS: EVP_PKEY_free(info->_.params); break; + case OSSL_STORE_INFO_PUBKEY: + EVP_PKEY_free(info->_.pubkey); + break; case OSSL_STORE_INFO_PKEY: EVP_PKEY_free(info->_.pkey); break; diff --git a/crypto/store/store_local.h b/crypto/store/store_local.h index c9592c38ce..47cba87f86 100644 --- a/crypto/store/store_local.h +++ b/crypto/store/store_local.h @@ -36,6 +36,7 @@ struct ossl_store_info_st { } name; /* when type == OSSL_STORE_INFO_NAME */ EVP_PKEY *params; /* when type == OSSL_STORE_INFO_PARAMS */ + EVP_PKEY *pubkey; /* when type == OSSL_STORE_INFO_PUBKEY */ EVP_PKEY *pkey; /* when type == OSSL_STORE_INFO_PKEY */ X509 *x509; /* when type == OSSL_STORE_INFO_CERT */ X509_CRL *crl; /* when type == OSSL_STORE_INFO_CRL */ diff --git a/crypto/store/store_strings.c b/crypto/store/store_strings.c index 84cfdcfe6b..97497c8a78 100644 --- a/crypto/store/store_strings.c +++ b/crypto/store/store_strings.c @@ -12,6 +12,7 @@ static char *type_strings[] = { "Name", /* OSSL_STORE_INFO_NAME */ "Parameters", /* OSSL_STORE_INFO_PARAMS */ + "Public key", /* OSSL_STORE_INFO_PUBKEY */ "Pkey", /* OSSL_STORE_INFO_PKEY */ "Certificate", /* OSSL_STORE_INFO_CERT */ "CRL" /* OSSL_STORE_INFO_CRL */ diff --git a/doc/man3/OSSL_STORE_INFO.pod b/doc/man3/OSSL_STORE_INFO.pod index c331677954..bc965a77bd 100644 --- a/doc/man3/OSSL_STORE_INFO.pod +++ b/doc/man3/OSSL_STORE_INFO.pod @@ -3,15 +3,17 @@ =head1 NAME OSSL_STORE_INFO, OSSL_STORE_INFO_get_type, OSSL_STORE_INFO_get0_NAME, -OSSL_STORE_INFO_get0_NAME_description, OSSL_STORE_INFO_get0_PARAMS, +OSSL_STORE_INFO_get0_NAME_description, +OSSL_STORE_INFO_get0_PARAMS, OSSL_STORE_INFO_get0_PUBKEY, OSSL_STORE_INFO_get0_PKEY, OSSL_STORE_INFO_get0_CERT, OSSL_STORE_INFO_get0_CRL, OSSL_STORE_INFO_get1_NAME, OSSL_STORE_INFO_get1_NAME_description, -OSSL_STORE_INFO_get1_PARAMS, OSSL_STORE_INFO_get1_PKEY, -OSSL_STORE_INFO_get1_CERT, -OSSL_STORE_INFO_get1_CRL, OSSL_STORE_INFO_type_string, OSSL_STORE_INFO_free, +OSSL_STORE_INFO_get1_PARAMS, OSSL_STORE_INFO_get1_PUBKEY, +OSSL_STORE_INFO_get1_PKEY, OSSL_STORE_INFO_get1_CERT, OSSL_STORE_INFO_get1_CRL, +OSSL_STORE_INFO_type_string, OSSL_STORE_INFO_free, OSSL_STORE_INFO_new_NAME, OSSL_STORE_INFO_set0_NAME_description, -OSSL_STORE_INFO_new_PARAMS, OSSL_STORE_INFO_new_PKEY, OSSL_STORE_INFO_new_CERT, -OSSL_STORE_INFO_new_CRL - Functions to manipulate OSSL_STORE_INFO objects +OSSL_STORE_INFO_new_PARAMS, OSSL_STORE_INFO_new_PUBKEY, +OSSL_STORE_INFO_new_PKEY, OSSL_STORE_INFO_new_CERT, OSSL_STORE_INFO_new_CRL +- Functions to manipulate OSSL_STORE_INFO objects =head1 SYNOPSIS @@ -27,6 +29,8 @@ OSSL_STORE_INFO_new_CRL - Functions to manipulate OSSL_STORE_INFO objects char *OSSL_STORE_INFO_get1_NAME_description(const OSSL_STORE_INFO *store_info); EVP_PKEY *OSSL_STORE_INFO_get0_PARAMS(const OSSL_STORE_INFO *store_info); EVP_PKEY *OSSL_STORE_INFO_get1_PARAMS(const OSSL_STORE_INFO *store_info); + EVP_PKEY *OSSL_STORE_INFO_get0_PUBKEY(const OSSL_STORE_INFO *info); + EVP_PKEY *OSSL_STORE_INFO_get1_PUBKEY(const OSSL_STORE_INFO *info); EVP_PKEY *OSSL_STORE_INFO_get0_PKEY(const OSSL_STORE_INFO *store_info); EVP_PKEY *OSSL_STORE_INFO_get1_PKEY(const OSSL_STORE_INFO *store_info); X509 *OSSL_STORE_INFO_get0_CERT(const OSSL_STORE_INFO *store_info); @@ -41,6 +45,7 @@ OSSL_STORE_INFO_new_CRL - Functions to manipulate OSSL_STORE_INFO objects OSSL_STORE_INFO *OSSL_STORE_INFO_new_NAME(char *name); int OSSL_STORE_INFO_set0_NAME_description(OSSL_STORE_INFO *info, char *desc); OSSL_STORE_INFO *OSSL_STORE_INFO_new_PARAMS(DSA *dsa_params); + OSSL_STORE_INFO *OSSL_STORE_INFO_new_PUBKEY(EVP_PKEY *pubkey); OSSL_STORE_INFO *OSSL_STORE_INFO_new_PKEY(EVP_PKEY *pkey); OSSL_STORE_INFO *OSSL_STORE_INFO_new_CERT(X509 *x509); OSSL_STORE_INFO *OSSL_STORE_INFO_new_CRL(X509_CRL *crl); @@ -76,23 +81,27 @@ STORE_INFO_get_type_string() takes a STORE type number and returns a short string describing it. OSSL_STORE_INFO_get0_NAME(), OSSL_STORE_INFO_get0_NAME_description(), -OSSL_STORE_INFO_get0_PARAMS(), OSSL_STORE_INFO_get0_PKEY(), -OSSL_STORE_INFO_get0_CERT() and OSSL_STORE_INFO_get0_CRL() all take a -B and return the held object of the appropriate OpenSSL -type provided that's what's held. +OSSL_STORE_INFO_get0_PARAMS(), OSSL_STORE_INFO_get0_PUBKEY(), +OSSL_STORE_INFO_get0_PKEY(), OSSL_STORE_INFO_get0_CERT(), +OSSL_STORE_INFO_get0_CRL() +all take a B and return the object it holds if the +B type (as returned by OSSL_STORE_INFO_get_type()) +matches the function, otherwise NULL. OSSL_STORE_INFO_get1_NAME(), OSSL_STORE_INFO_get1_NAME_description(), -OSSL_STORE_INFO_get1_PARAMS(), OSSL_STORE_INFO_get1_PKEY(), -OSSL_STORE_INFO_get1_CERT() and OSSL_STORE_INFO_get1_CRL() all take a -B and return a duplicate of the held object of the -appropriate OpenSSL type provided that's what's held. +OSSL_STORE_INFO_get1_PARAMS(), OSSL_STORE_INFO_get1_PUBKEY(), +OSSL_STORE_INFO_get1_PKEY(), OSSL_STORE_INFO_get1_CERT() and +OSSL_STORE_INFO_get1_CRL() +all take a B and return a duplicate the object it +holds if the B type (as returned by +OSSL_STORE_INFO_get_type()) matches the function, otherwise NULL. OSSL_STORE_INFO_free() frees a B and its contained type. OSSL_STORE_INFO_new_NAME() , OSSL_STORE_INFO_new_PARAMS(), -OSSL_STORE_INFO_new_PKEY(), OSSL_STORE_INFO_new_CERT() and -OSSL_STORE_INFO_new_CRL() create a B -object to hold the given input object. +, OSSL_STORE_INFO_new_PUBKEY(), OSSL_STORE_INFO_new_PKEY(), +OSSL_STORE_INFO_new_CERT() and OSSL_STORE_INFO_new_CRL() +create a B object to hold the given input object. On success the input object is consumed. Additionally, for B` objects, diff --git a/include/openssl/store.h b/include/openssl/store.h index d5e72a0963..b75c79868c 100644 --- a/include/openssl/store.h +++ b/include/openssl/store.h @@ -138,9 +138,10 @@ OSSL_STORE_CTX *OSSL_STORE_attach(BIO *bio, const char *scheme, */ # define OSSL_STORE_INFO_NAME 1 /* char * */ # define OSSL_STORE_INFO_PARAMS 2 /* EVP_PKEY * */ -# define OSSL_STORE_INFO_PKEY 3 /* EVP_PKEY * */ -# define OSSL_STORE_INFO_CERT 4 /* X509 * */ -# define OSSL_STORE_INFO_CRL 5 /* X509_CRL * */ +# define OSSL_STORE_INFO_PUBKEY 3 /* EVP_PKEY * */ +# define OSSL_STORE_INFO_PKEY 4 /* EVP_PKEY * */ +# define OSSL_STORE_INFO_CERT 5 /* X509 * */ +# define OSSL_STORE_INFO_CRL 6 /* X509_CRL * */ /* * Functions to generate OSSL_STORE_INFOs, one function for each type we @@ -152,6 +153,7 @@ OSSL_STORE_CTX *OSSL_STORE_attach(BIO *bio, const char *scheme, OSSL_STORE_INFO *OSSL_STORE_INFO_new_NAME(char *name); int OSSL_STORE_INFO_set0_NAME_description(OSSL_STORE_INFO *info, char *desc); OSSL_STORE_INFO *OSSL_STORE_INFO_new_PARAMS(EVP_PKEY *params); +OSSL_STORE_INFO *OSSL_STORE_INFO_new_PUBKEY(EVP_PKEY *pubkey); OSSL_STORE_INFO *OSSL_STORE_INFO_new_PKEY(EVP_PKEY *pkey); OSSL_STORE_INFO *OSSL_STORE_INFO_new_CERT(X509 *x509); OSSL_STORE_INFO *OSSL_STORE_INFO_new_CRL(X509_CRL *crl); @@ -166,6 +168,8 @@ const char *OSSL_STORE_INFO_get0_NAME_description(const OSSL_STORE_INFO *info); char *OSSL_STORE_INFO_get1_NAME_description(const OSSL_STORE_INFO *info); EVP_PKEY *OSSL_STORE_INFO_get0_PARAMS(const OSSL_STORE_INFO *info); EVP_PKEY *OSSL_STORE_INFO_get1_PARAMS(const OSSL_STORE_INFO *info); +EVP_PKEY *OSSL_STORE_INFO_get0_PUBKEY(const OSSL_STORE_INFO *info); +EVP_PKEY *OSSL_STORE_INFO_get1_PUBKEY(const OSSL_STORE_INFO *info); EVP_PKEY *OSSL_STORE_INFO_get0_PKEY(const OSSL_STORE_INFO *info); EVP_PKEY *OSSL_STORE_INFO_get1_PKEY(const OSSL_STORE_INFO *info); X509 *OSSL_STORE_INFO_get0_CERT(const OSSL_STORE_INFO *info); diff --git a/include/openssl/storeerr.h b/include/openssl/storeerr.h index ed8f7988fe..5213a0b33c 100644 --- a/include/openssl/storeerr.h +++ b/include/openssl/storeerr.h @@ -78,8 +78,9 @@ int ERR_load_OSSL_STORE_strings(void); # define OSSL_STORE_R_LOADING_STARTED 117 # define OSSL_STORE_R_NOT_A_CERTIFICATE 100 # define OSSL_STORE_R_NOT_A_CRL 101 -# define OSSL_STORE_R_NOT_A_KEY 102 # define OSSL_STORE_R_NOT_A_NAME 103 +# define OSSL_STORE_R_NOT_A_PRIVATE_KEY 102 +# define OSSL_STORE_R_NOT_A_PUBLIC_KEY 122 # define OSSL_STORE_R_NOT_PARAMETERS 104 # define OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR 114 # define OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE 108 diff --git a/util/libcrypto.num b/util/libcrypto.num index 6aa0109de3..762e3cc17a 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5263,3 +5263,6 @@ EVP_SIGNATURE_settable_ctx_params ? 3_0_0 EXIST::FUNCTION: EVP_KEYEXCH_gettable_ctx_params ? 3_0_0 EXIST::FUNCTION: EVP_KEYEXCH_settable_ctx_params ? 3_0_0 EXIST::FUNCTION: d2i_PUBKEY_ex ? 3_0_0 EXIST::FUNCTION: +OSSL_STORE_INFO_new_PUBKEY ? 3_0_0 EXIST::FUNCTION: +OSSL_STORE_INFO_get0_PUBKEY ? 3_0_0 EXIST::FUNCTION: +OSSL_STORE_INFO_get1_PUBKEY ? 3_0_0 EXIST::FUNCTION: