From: Matt Caswell Date: Fri, 24 Apr 2020 10:33:33 +0000 (+0100) Subject: Make EVP_new_raw_[private|public]_key provider aware X-Git-Tag: openssl-3.0.0-alpha2~92 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=1c4f340dd35f0ca48e263ab85399a965e1125ac6;p=oweals%2Fopenssl.git Make EVP_new_raw_[private|public]_key provider aware We also introduce variants which are OPENSSL_CTX aware Reviewed-by: Shane Lontis (Merged from https://github.com/openssl/openssl/pull/11635) --- diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c index bbeb7276fe..ea74253bdd 100644 --- a/crypto/evp/p_lib.c +++ b/crypto/evp/p_lib.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -320,64 +321,156 @@ int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b) return -2; } -EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *e, - const unsigned char *priv, - size_t len) + +static EVP_PKEY *new_raw_key_int(OPENSSL_CTX *libctx, + const char *strtype, + const char *propq, + int nidtype, + ENGINE *e, + const unsigned char *key, + size_t len, + int key_is_priv) { - EVP_PKEY *ret = EVP_PKEY_new(); + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *ctx = NULL; + const EVP_PKEY_ASN1_METHOD *ameth = NULL; + int result = 0; - if (ret == NULL - || !pkey_set_type(ret, e, type, NULL, -1, NULL)) { - /* EVPerr already called */ - goto err; - } +# ifndef OPENSSL_NO_ENGINE + /* Check if there is an Engine for this type */ + if (e == NULL) { + ENGINE *tmpe = NULL; - if (ret->ameth->set_priv_key == NULL) { - EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PRIVATE_KEY, - EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); - goto err; - } + if (strtype != NULL) + ameth = EVP_PKEY_asn1_find_str(&tmpe, strtype, -1); + else if (nidtype != EVP_PKEY_NONE) + ameth = EVP_PKEY_asn1_find(&tmpe, nidtype); - if (!ret->ameth->set_priv_key(ret, priv, len)) { - EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PRIVATE_KEY, EVP_R_KEY_SETUP_FAILED); - goto err; + /* If tmpe is NULL then no engine is claiming to support this type */ + if (tmpe == NULL) + ameth = NULL; + + ENGINE_finish(tmpe); } +# endif - return ret; + if (e == NULL && ameth == NULL) { + /* + * No engine is claiming to support this type, so lets see if we have + * a provider. + */ + ctx = EVP_PKEY_CTX_new_from_name(libctx, + strtype != NULL ? strtype + : OBJ_nid2sn(nidtype), + propq); + if (ctx == NULL) { + EVPerr(0, ERR_R_MALLOC_FAILURE); + goto err; + } + /* May fail if no provider available */ + ERR_set_mark(); + if (EVP_PKEY_key_fromdata_init(ctx) == 1) { + OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END }; + + ERR_clear_last_mark(); + params[0] = OSSL_PARAM_construct_octet_string( + key_is_priv ? OSSL_PKEY_PARAM_PRIV_KEY + : OSSL_PKEY_PARAM_PUB_KEY, + (void *)key, len); + + if (EVP_PKEY_fromdata(ctx, &pkey, params) != 1) { + EVPerr(0, EVP_R_KEY_SETUP_FAILED); + goto err; + } - err: - EVP_PKEY_free(ret); - return NULL; -} + EVP_PKEY_CTX_free(ctx); -EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *e, - const unsigned char *pub, - size_t len) -{ - EVP_PKEY *ret = EVP_PKEY_new(); + return pkey; + } + ERR_pop_to_mark(); + /* else not supported so fallback to legacy */ + } - if (ret == NULL - || !pkey_set_type(ret, e, type, NULL, -1, NULL)) { - /* EVPerr already called */ + /* Legacy code path */ + + pkey = EVP_PKEY_new(); + if (pkey == NULL) { + EVPerr(0, ERR_R_MALLOC_FAILURE); goto err; } - if (ret->ameth->set_pub_key == NULL) { - EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PUBLIC_KEY, - EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + if (!pkey_set_type(pkey, e, nidtype, strtype, -1, NULL)) { + /* EVPerr already called */ goto err; } - if (!ret->ameth->set_pub_key(ret, pub, len)) { - EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PUBLIC_KEY, EVP_R_KEY_SETUP_FAILED); + if (!ossl_assert(pkey->ameth != NULL)) goto err; - } - return ret; + if (key_is_priv) { + if (pkey->ameth->set_priv_key == NULL) { + EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + goto err; + } + if (!pkey->ameth->set_priv_key(pkey, key, len)) { + EVPerr(0, EVP_R_KEY_SETUP_FAILED); + goto err; + } + } else { + if (pkey->ameth->set_pub_key == NULL) { + EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + goto err; + } + + if (!pkey->ameth->set_pub_key(pkey, key, len)) { + EVPerr(0, EVP_R_KEY_SETUP_FAILED); + goto err; + } + } + + result = 1; err: - EVP_PKEY_free(ret); - return NULL; + if (!result) { + EVP_PKEY_free(pkey); + pkey = NULL; + } + EVP_PKEY_CTX_free(ctx); + return pkey; +} + +EVP_PKEY *EVP_PKEY_new_raw_private_key_with_libctx(OPENSSL_CTX *libctx, + const char *keytype, + const char *propq, + const unsigned char *priv, + size_t len) +{ + return new_raw_key_int(libctx, keytype, propq, EVP_PKEY_NONE, NULL, priv, + len, 1); +} + +EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *e, + const unsigned char *priv, + size_t len) +{ + return new_raw_key_int(NULL, NULL, NULL, type, e, priv, len, 1); +} + +EVP_PKEY *EVP_PKEY_new_raw_public_key_with_libctx(OPENSSL_CTX *libctx, + const char *keytype, + const char *propq, + const unsigned char *pub, + size_t len) +{ + return new_raw_key_int(libctx, keytype, propq, EVP_PKEY_NONE, NULL, pub, + len, 0); +} + +EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *e, + const unsigned char *pub, + size_t len) +{ + return new_raw_key_int(NULL, NULL, NULL, type, e, pub, len, 0); } int EVP_PKEY_get_raw_private_key(const EVP_PKEY *pkey, unsigned char *priv, diff --git a/include/openssl/evp.h b/include/openssl/evp.h index 23cf52df0f..5dc29d1976 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h @@ -1518,9 +1518,19 @@ void EVP_PKEY_CTX_set0_keygen_info(EVP_PKEY_CTX *ctx, int *dat, int datlen); EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e, const unsigned char *key, int keylen); +EVP_PKEY *EVP_PKEY_new_raw_private_key_with_libctx(OPENSSL_CTX *libctx, + const char *keytype, + const char *propq, + const unsigned char *priv, + size_t len); EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *e, const unsigned char *priv, size_t len); +EVP_PKEY *EVP_PKEY_new_raw_public_key_with_libctx(OPENSSL_CTX *libctx, + const char *keytype, + const char *propq, + const unsigned char *pub, + size_t len); EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *e, const unsigned char *pub, size_t len); diff --git a/util/libcrypto.num b/util/libcrypto.num index ec0e6a171b..82ae2e7e84 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5081,3 +5081,5 @@ OSSL_PARAM_modified ? 3_0_0 EXIST::FUNCTION: OSSL_PARAM_set_all_unmodified ? 3_0_0 EXIST::FUNCTION: EVP_default_properties_is_fips_enabled ? 3_0_0 EXIST::FUNCTION: EVP_default_properties_enable_fips ? 3_0_0 EXIST::FUNCTION: +EVP_PKEY_new_raw_private_key_with_libctx ? 3_0_0 EXIST::FUNCTION: +EVP_PKEY_new_raw_public_key_with_libctx ? 3_0_0 EXIST::FUNCTION: