diff options
-rw-r--r-- | crypto/evp/asymcipher.c | 70 | ||||
-rw-r--r-- | crypto/evp/exchange.c | 84 | ||||
-rw-r--r-- | crypto/evp/kem.c | 56 | ||||
-rw-r--r-- | crypto/evp/keymgmt_lib.c | 19 | ||||
-rw-r--r-- | crypto/evp/m_sigver.c | 64 | ||||
-rw-r--r-- | crypto/evp/pmeth_lib.c | 15 | ||||
-rw-r--r-- | crypto/evp/signature.c | 64 | ||||
-rw-r--r-- | include/crypto/evp.h | 3 |
8 files changed, 216 insertions, 159 deletions
diff --git a/crypto/evp/asymcipher.c b/crypto/evp/asymcipher.c index 3150bfa94b..41aea6b1d8 100644 --- a/crypto/evp/asymcipher.c +++ b/crypto/evp/asymcipher.c @@ -40,55 +40,53 @@ static int evp_pkey_asym_cipher_init(EVP_PKEY_CTX *ctx, int operation, goto legacy; /* - * Ensure that the key is provided, either natively, or as a cached export. - * If not, go legacy + * Try to derive the supported asym cipher from |ctx->keymgmt|. */ - tmp_keymgmt = ctx->keymgmt; - provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx, - &tmp_keymgmt, ctx->propquery); - if (provkey == NULL) - goto legacy; - if (!EVP_KEYMGMT_up_ref(tmp_keymgmt)) { + if (!ossl_assert(ctx->pkey->keymgmt == NULL + || ctx->pkey->keymgmt == ctx->keymgmt)) { + ERR_clear_last_mark(); + ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR); + goto err; + } + supported_ciph + = evp_keymgmt_util_query_operation_name(ctx->keymgmt, + OSSL_OP_ASYM_CIPHER); + if (supported_ciph == NULL) { ERR_clear_last_mark(); ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); goto err; } - EVP_KEYMGMT_free(ctx->keymgmt); - ctx->keymgmt = tmp_keymgmt; - - if (ctx->keymgmt->query_operation_name != NULL) - supported_ciph = - ctx->keymgmt->query_operation_name(OSSL_OP_ASYM_CIPHER); - - /* - * If we didn't get a supported ciph, assume there is one with the - * same name as the key type. - */ - if (supported_ciph == NULL) - supported_ciph = ctx->keytype; /* * Because we cleared out old ops, we shouldn't need to worry about * checking if cipher is already there. */ - cipher = - EVP_ASYM_CIPHER_fetch(ctx->libctx, supported_ciph, ctx->propquery); + cipher = EVP_ASYM_CIPHER_fetch(ctx->libctx, supported_ciph, + ctx->propquery); - if (cipher == NULL - || (EVP_KEYMGMT_get0_provider(ctx->keymgmt) - != EVP_ASYM_CIPHER_get0_provider(cipher))) { - /* - * We don't need to free ctx->keymgmt here, as it's not necessarily - * tied to this operation. It will be freed by EVP_PKEY_CTX_free(). - */ - EVP_ASYM_CIPHER_free(cipher); + if (cipher == NULL) goto legacy; - } /* - * If we don't have the full support we need with provided methods, - * let's go see if legacy does. + * Ensure that the key is provided, either natively, or as a cached export. + * We start by fetching the keymgmt with the same name as |ctx->pkey|, + * but from the provider of the asym cipher method, using the same property + * query as when fetching the asym cipher method. + * With the keymgmt we found (if we did), we try to export |ctx->pkey| + * to it (evp_pkey_export_to_provider() is smart enough to only actually + + * export it if |tmp_keymgmt| is different from |ctx->pkey|'s keymgmt) */ + tmp_keymgmt + = evp_keymgmt_fetch_from_prov(EVP_ASYM_CIPHER_get0_provider(cipher), + EVP_KEYMGMT_get0_name(ctx->keymgmt), + ctx->propquery); + if (tmp_keymgmt != NULL) + provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx, + &tmp_keymgmt, ctx->propquery); + if (provkey == NULL) + goto legacy; + ERR_pop_to_mark(); /* No more legacy from here down to legacy: */ @@ -125,6 +123,7 @@ static int evp_pkey_asym_cipher_init(EVP_PKEY_CTX *ctx, int operation, if (ret <= 0) goto err; + EVP_KEYMGMT_free(tmp_keymgmt); return 1; legacy: @@ -133,6 +132,8 @@ static int evp_pkey_asym_cipher_init(EVP_PKEY_CTX *ctx, int operation, * let's go see if legacy does. */ ERR_pop_to_mark(); + EVP_KEYMGMT_free(tmp_keymgmt); + tmp_keymgmt = NULL; if (ctx->pmeth == NULL || ctx->pmeth->encrypt == NULL) { ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); @@ -159,6 +160,7 @@ static int evp_pkey_asym_cipher_init(EVP_PKEY_CTX *ctx, int operation, evp_pkey_ctx_free_old_ops(ctx); ctx->operation = EVP_PKEY_OP_UNDEFINED; } + EVP_KEYMGMT_free(tmp_keymgmt); return ret; } diff --git a/crypto/evp/exchange.c b/crypto/evp/exchange.c index ca8a049a1b..14e734dde8 100644 --- a/crypto/evp/exchange.c +++ b/crypto/evp/exchange.c @@ -10,6 +10,7 @@ #include <openssl/crypto.h> #include <openssl/evp.h> #include <openssl/err.h> +#include "internal/cryptlib.h" #include "internal/refcount.h" #include "internal/provider.h" #include "internal/core.h" @@ -207,73 +208,69 @@ int EVP_PKEY_derive_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]) goto legacy; /* - * Ensure that the key is provided, either natively, or as a cached export. - * If not, goto legacy + * Some algorithms (e.g. legacy KDFs) don't have a pkey - so we create + * a blank one. */ - tmp_keymgmt = ctx->keymgmt; if (ctx->pkey == NULL) { - /* - * Some algorithms (e.g. legacy KDFs) don't have a pkey - so we create - * a blank one. - */ EVP_PKEY *pkey = EVP_PKEY_new(); - if (pkey == NULL || !EVP_PKEY_set_type_by_keymgmt(pkey, tmp_keymgmt)) { + if (pkey == NULL + || !EVP_PKEY_set_type_by_keymgmt(pkey, ctx->keymgmt) + || (pkey->keydata = evp_keymgmt_newdata(ctx->keymgmt)) == NULL) { ERR_clear_last_mark(); EVP_PKEY_free(pkey); ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); goto err; } - provkey = pkey->keydata = evp_keymgmt_newdata(tmp_keymgmt); - if (provkey == NULL) - EVP_PKEY_free(pkey); - else - ctx->pkey = pkey; - } else { - provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx, - &tmp_keymgmt, ctx->propquery); + ctx->pkey = pkey; } - if (provkey == NULL) - goto legacy; - if (!EVP_KEYMGMT_up_ref(tmp_keymgmt)) { + + /* + * Try to derive the supported exch from |ctx->keymgmt|. + */ + if (!ossl_assert(ctx->pkey->keymgmt == NULL + || ctx->pkey->keymgmt == ctx->keymgmt)) { + ERR_clear_last_mark(); + ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR); + goto err; + } + supported_exch = evp_keymgmt_util_query_operation_name(ctx->keymgmt, + OSSL_OP_KEYEXCH); + if (supported_exch == NULL) { ERR_clear_last_mark(); ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); goto err; } - EVP_KEYMGMT_free(ctx->keymgmt); - ctx->keymgmt = tmp_keymgmt; - if (ctx->keymgmt->query_operation_name != NULL) - supported_exch = ctx->keymgmt->query_operation_name(OSSL_OP_KEYEXCH); - - /* - * If we didn't get a supported exch, assume there is one with the - * same name as the key type. - */ - if (supported_exch == NULL) - supported_exch = ctx->keytype; /* * Because we cleared out old ops, we shouldn't need to worry about * checking if exchange is already there. */ exchange = EVP_KEYEXCH_fetch(ctx->libctx, supported_exch, ctx->propquery); - - if (exchange == NULL - || (EVP_KEYMGMT_get0_provider(ctx->keymgmt) - != EVP_KEYEXCH_get0_provider(exchange))) { - /* - * We don't need to free ctx->keymgmt here, as it's not necessarily - * tied to this operation. It will be freed by EVP_PKEY_CTX_free(). - */ - EVP_KEYEXCH_free(exchange); + if (exchange == NULL) goto legacy; - } /* - * If we don't have the full support we need with provided methods, - * let's go see if legacy does. + * Ensure that the key is provided, either natively, or as a cached export. + * We start by fetching the keymgmt with the same name as |ctx->pkey|, + * but from the provider of the exch method, using the same property + * query as when fetching the exch method. + * With the keymgmt we found (if we did), we try to export |ctx->pkey| + * to it (evp_pkey_export_to_provider() is smart enough to only actually + + * export it if |tmp_keymgmt| is different from |ctx->pkey|'s keymgmt) */ + tmp_keymgmt + = evp_keymgmt_fetch_from_prov(EVP_KEYEXCH_get0_provider(exchange), + EVP_KEYMGMT_get0_name(ctx->keymgmt), + ctx->propquery); + if (tmp_keymgmt != NULL) + provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx, + &tmp_keymgmt, ctx->propquery); + if (provkey == NULL) + goto legacy; + ERR_pop_to_mark(); /* No more legacy from here down to legacy: */ @@ -287,10 +284,12 @@ int EVP_PKEY_derive_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]) } ret = exchange->init(ctx->op.kex.algctx, provkey, params); + EVP_KEYMGMT_free(tmp_keymgmt); return ret ? 1 : 0; err: evp_pkey_ctx_free_old_ops(ctx); ctx->operation = EVP_PKEY_OP_UNDEFINED; + EVP_KEYMGMT_free(tmp_keymgmt); return 0; legacy: @@ -313,6 +312,7 @@ int EVP_PKEY_derive_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]) ret = ctx->pmeth->derive_init(ctx); if (ret <= 0) ctx->operation = EVP_PKEY_OP_UNDEFINED; + EVP_KEYMGMT_free(tmp_keymgmt); return ret; #endif } diff --git a/crypto/evp/kem.c b/crypto/evp/kem.c index cb904a6b26..0640e31144 100644 --- a/crypto/evp/kem.c +++ b/crypto/evp/kem.c @@ -35,37 +35,49 @@ static int evp_kem_init(EVP_PKEY_CTX *ctx, int operation, ctx->operation = operation; /* - * Ensure that the key is provided, either natively, or as a cached export. + * Try to derive the supported kem from |ctx->keymgmt|. */ - tmp_keymgmt = ctx->keymgmt; - provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx, - &tmp_keymgmt, ctx->propquery); - if (provkey == NULL - || !EVP_KEYMGMT_up_ref(tmp_keymgmt)) { + if (!ossl_assert(ctx->pkey->keymgmt == NULL + || ctx->pkey->keymgmt == ctx->keymgmt)) { + ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR); + goto err; + } + supported_kem = evp_keymgmt_util_query_operation_name(ctx->keymgmt, + OSSL_OP_KEM); + if (supported_kem == NULL) { ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); goto err; } - EVP_KEYMGMT_free(ctx->keymgmt); - ctx->keymgmt = tmp_keymgmt; - - if (ctx->keymgmt->query_operation_name != NULL) - supported_kem = ctx->keymgmt->query_operation_name(OSSL_OP_KEM); - - /* - * If we didn't get a supported kem, assume there is one with the - * same name as the key type. - */ - if (supported_kem == NULL) - supported_kem = ctx->keytype; kem = EVP_KEM_fetch(ctx->libctx, supported_kem, ctx->propquery); - if (kem == NULL - || (EVP_KEYMGMT_get0_provider(ctx->keymgmt) != EVP_KEM_get0_provider(kem))) { + if (kem == NULL) { ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); ret = -2; goto err; } + /* + * Ensure that the key is provided, either natively, or as a cached export. + * We start by fetching the keymgmt with the same name as |ctx->pkey|, + * but from the provider of the kem method, using the same property + * query as when fetching the kem method. + * With the keymgmt we found (if we did), we try to export |ctx->pkey| + * to it (evp_pkey_export_to_provider() is smart enough to only actually + + * export it if |tmp_keymgmt| is different from |ctx->pkey|'s keymgmt) + */ + tmp_keymgmt + = evp_keymgmt_fetch_from_prov(EVP_KEM_get0_provider(kem), + EVP_KEYMGMT_get0_name(ctx->keymgmt), + ctx->propquery); + if (tmp_keymgmt != NULL) + provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx, + &tmp_keymgmt, ctx->propquery); + if (provkey == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); + goto err; + } + ctx->op.encap.kem = kem; ctx->op.encap.algctx = kem->newctx(ossl_provider_ctx(kem->prov)); if (ctx->op.encap.algctx == NULL) { @@ -96,6 +108,9 @@ static int evp_kem_init(EVP_PKEY_CTX *ctx, int operation, goto err; } + EVP_KEYMGMT_free(tmp_keymgmt); + tmp_keymgmt = NULL; + if (ret > 0) return 1; err: @@ -103,6 +118,7 @@ static int evp_kem_init(EVP_PKEY_CTX *ctx, int operation, evp_pkey_ctx_free_old_ops(ctx); ctx->operation = EVP_PKEY_OP_UNDEFINED; } + EVP_KEYMGMT_free(tmp_keymgmt); return ret; } diff --git a/crypto/evp/keymgmt_lib.c b/crypto/evp/keymgmt_lib.c index 875c9a83de..2a73e9a2be 100644 --- a/crypto/evp/keymgmt_lib.c +++ b/crypto/evp/keymgmt_lib.c @@ -562,3 +562,22 @@ int evp_keymgmt_util_get_deflt_digest_name(EVP_KEYMGMT *keymgmt, OPENSSL_strlcpy(mdname, result, mdname_sz); return rv; } + +/* + * If |keymgmt| has the method function |query_operation_name|, use it to get + * the name of a supported operation identity. Otherwise, return the keytype, + * assuming that it works as a default operation name. + */ +const char *evp_keymgmt_util_query_operation_name(EVP_KEYMGMT *keymgmt, + int op_id) +{ + const char *name = NULL; + + if (keymgmt != NULL) { + if (keymgmt->query_operation_name != NULL) + name = keymgmt->query_operation_name(op_id); + if (name == NULL) + name = EVP_KEYMGMT_get0_name(keymgmt); + } + return name; +} diff --git a/crypto/evp/m_sigver.c b/crypto/evp/m_sigver.c index 70669c3e6d..55675c36e1 100644 --- a/crypto/evp/m_sigver.c +++ b/crypto/evp/m_sigver.c @@ -81,34 +81,21 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, goto legacy; /* - * Ensure that the key is provided, either natively, or as a cached export. + * Try to derive the supported signature from |locpctx->keymgmt|. */ - tmp_keymgmt = locpctx->keymgmt; - provkey = evp_pkey_export_to_provider(locpctx->pkey, locpctx->libctx, - &tmp_keymgmt, locpctx->propquery); - if (provkey == NULL) { + if (!ossl_assert(locpctx->pkey->keymgmt == NULL + || locpctx->pkey->keymgmt == locpctx->keymgmt)) { ERR_clear_last_mark(); - ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); + ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR); goto err; } - if (!EVP_KEYMGMT_up_ref(tmp_keymgmt)) { + supported_sig = evp_keymgmt_util_query_operation_name(locpctx->keymgmt, + OSSL_OP_SIGNATURE); + if (supported_sig == NULL) { ERR_clear_last_mark(); ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); goto err; } - EVP_KEYMGMT_free(locpctx->keymgmt); - locpctx->keymgmt = tmp_keymgmt; - - if (locpctx->keymgmt->query_operation_name != NULL) - supported_sig = - locpctx->keymgmt->query_operation_name(OSSL_OP_SIGNATURE); - - /* - * If we didn't get a supported sig, assume there is one with the - * same name as the key type. - */ - if (supported_sig == NULL) - supported_sig = locpctx->keytype; /* * Because we cleared out old ops, we shouldn't need to worry about @@ -117,21 +104,32 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, signature = EVP_SIGNATURE_fetch(locpctx->libctx, supported_sig, locpctx->propquery); - if (signature == NULL - || (EVP_KEYMGMT_get0_provider(locpctx->keymgmt) - != EVP_SIGNATURE_get0_provider(signature))) { - /* - * We don't need to free ctx->keymgmt here, as it's not necessarily - * tied to this operation. It will be freed by EVP_PKEY_CTX_free(). - */ - EVP_SIGNATURE_free(signature); + if (signature == NULL) goto legacy; - } /* - * If we don't have the full support we need with provided methods, - * let's go see if legacy does. + * Ensure that the key is provided, either natively, or as a cached export. + * We start by fetching the keymgmt with the same name as |locpctx->pkey|, + * but from the provider of the signature method, using the same property + * query as when fetching the signature method. + * With the keymgmt we found (if we did), we try to export |locpctx->pkey| + * to it (evp_pkey_export_to_provider() is smart enough to only actually + + * export it if |tmp_keymgmt| is different from |locpctx->pkey|'s keymgmt) */ + tmp_keymgmt + = evp_keymgmt_fetch_from_prov(EVP_SIGNATURE_get0_provider(signature), + EVP_KEYMGMT_get0_name(locpctx->keymgmt), + locpctx->propquery); + if (tmp_keymgmt != NULL) + provkey = evp_pkey_export_to_provider(locpctx->pkey, locpctx->libctx, + &tmp_keymgmt, locpctx->propquery); + if (provkey == NULL) { + ERR_clear_last_mark(); + ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); + goto err; + } + ERR_pop_to_mark(); /* No more legacy from here down to legacy: */ @@ -221,6 +219,7 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, err: evp_pkey_ctx_free_old_ops(locpctx); locpctx->operation = EVP_PKEY_OP_UNDEFINED; + EVP_KEYMGMT_free(tmp_keymgmt); return 0; legacy: @@ -229,6 +228,8 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, * let's go see if legacy does. */ ERR_pop_to_mark(); + EVP_KEYMGMT_free(tmp_keymgmt); + tmp_keymgmt = NULL; if (type == NULL && mdname != NULL) type = evp_get_digestbyname_ex(locpctx->libctx, mdname); @@ -299,6 +300,7 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, ret = evp_pkey_ctx_use_cached_data(locpctx); #endif + EVP_KEYMGMT_free(tmp_keymgmt); return ret > 0 ? 1 : 0; } diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c index 1af1628823..2b9c6c2351 100644 --- a/crypto/evp/pmeth_lib.c +++ b/crypto/evp/pmeth_lib.c @@ -265,7 +265,20 @@ static EVP_PKEY_CTX *int_ctx_new(OSSL_LIB_CTX *libctx, * fetching a provider implementation. */ if (e == NULL && app_pmeth == NULL && keytype != NULL) { - keymgmt = EVP_KEYMGMT_fetch(libctx, keytype, propquery); + /* + * If |pkey| is given and is provided, we take a reference to its + * keymgmt. Otherwise, we fetch one for the keytype we got. This + * is to ensure that operation init functions can access what they + * need through this single pointer. + */ + if (pkey != NULL && pkey->keymgmt != NULL) { + if (!EVP_KEYMGMT_up_ref(pkey->keymgmt)) + ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); + else + keymgmt = pkey->keymgmt; + } else { + keymgmt = EVP_KEYMGMT_fetch(libctx, keytype, propquery); + } if (keymgmt == NULL) return NULL; /* EVP_KEYMGMT_fetch() recorded an error */ diff --git a/crypto/evp/signature.c b/crypto/evp/signature.c index b636889c3b..b893a2fc12 100644 --- a/crypto/evp/signature.c +++ b/crypto/evp/signature.c @@ -402,31 +402,21 @@ static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, int operation, goto legacy; /* - * Ensure that the key is provided, either natively, or as a cached export. - * If not, go legacy + * Try to derive the supported signature from |ctx->keymgmt|. */ - tmp_keymgmt = ctx->keymgmt; - provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx, - &tmp_keymgmt, ctx->propquery); - if (tmp_keymgmt == NULL) - goto legacy; - if (!EVP_KEYMGMT_up_ref(tmp_keymgmt)) { + if (!ossl_assert(ctx->pkey->keymgmt == NULL + || ctx->pkey->keymgmt == ctx->keymgmt)) { + ERR_clear_last_mark(); + ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR); + goto err; + } + supported_sig = evp_keymgmt_util_query_operation_name(ctx->keymgmt, + OSSL_OP_SIGNATURE); + if (supported_sig == NULL) { ERR_clear_last_mark(); ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); goto err; } - EVP_KEYMGMT_free(ctx->keymgmt); - ctx->keymgmt = tmp_keymgmt; - - if (ctx->keymgmt->query_operation_name != NULL) - supported_sig = ctx->keymgmt->query_operation_name(OSSL_OP_SIGNATURE); - - /* - * If we didn't get a supported sig, assume there is one with the - * same name as the key type. - */ - if (supported_sig == NULL) - supported_sig = ctx->keytype; /* * Because we cleared out old ops, we shouldn't need to worry about @@ -435,21 +425,29 @@ static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, int operation, signature = EVP_SIGNATURE_fetch(ctx->libctx, supported_sig, ctx->propquery); - if (signature == NULL - || (EVP_KEYMGMT_get0_provider(ctx->keymgmt) - != EVP_SIGNATURE_get0_provider(signature))) { - /* - * We don't need to free ctx->keymgmt here, as it's not necessarily - * tied to this operation. It will be freed by EVP_PKEY_CTX_free(). - */ - EVP_SIGNATURE_free(signature); + if (signature == NULL) goto legacy; - } /* - * If we don't have the full support we need with provided methods, - * let's go see if legacy does. + * Ensure that the key is provided, either natively, or as a cached export. + * We start by fetching the keymgmt with the same name as |ctx->pkey|, + * but from the provider of the signature method, using the same property + * query as when fetching the signature method. + * With the keymgmt we found (if we did), we try to export |ctx->pkey| + * to it (evp_pkey_export_to_provider() is smart enough to only actually + + * export it if |tmp_keymgmt| is different from |ctx->pkey|'s keymgmt) */ + tmp_keymgmt + = evp_keymgmt_fetch_from_prov(EVP_SIGNATURE_get0_provider(signature), + EVP_KEYMGMT_get0_name(ctx->keymgmt), + ctx->propquery); + if (tmp_keymgmt != NULL) + provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx, + &tmp_keymgmt, ctx->propquery); + if (provkey == NULL) + goto legacy; + ERR_pop_to_mark(); /* No more legacy from here down to legacy: */ @@ -507,6 +505,8 @@ static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, int operation, * let's go see if legacy does. */ ERR_pop_to_mark(); + EVP_KEYMGMT_free(tmp_keymgmt); + tmp_keymgmt = NULL; if (ctx->pmeth == NULL || (operation == EVP_PKEY_OP_SIGN && ctx->pmeth->sign == NULL) @@ -545,10 +545,12 @@ static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, int operation, ret = evp_pkey_ctx_use_cached_data(ctx); #endif + EVP_KEYMGMT_free(tmp_keymgmt); return ret; err: evp_pkey_ctx_free_old_ops(ctx); ctx->operation = EVP_PKEY_OP_UNDEFINED; + EVP_KEYMGMT_free(tmp_keymgmt); return ret; } diff --git a/include/crypto/evp.h b/include/crypto/evp.h index 41ac80ed9d..c5d3a930f7 100644 --- a/include/crypto/evp.h +++ b/include/crypto/evp.h @@ -38,6 +38,7 @@ struct evp_pkey_ctx_st { OSSL_LIB_CTX *libctx; char *propquery; const char *keytype; + /* If |pkey| below is set, this field is always a reference to its keymgmt */ EVP_KEYMGMT *keymgmt; union { @@ -794,6 +795,8 @@ void *evp_keymgmt_util_gen(EVP_PKEY *target, EVP_KEYMGMT *keymgmt, int evp_keymgmt_util_get_deflt_digest_name(EVP_KEYMGMT *keymgmt, void *keydata, char *mdname, size_t mdname_sz); +const char *evp_keymgmt_util_query_operation_name(EVP_KEYMGMT *keymgmt, + int op_id); /* * KEYMGMT provider interface functions |