From d0ddf9b409495e8e2adab8a6b5bc38b34273341a Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Wed, 15 Apr 2020 09:54:11 +0200 Subject: [PATCH] EVP: Fix calls to evp_pkey_export_to_provider() The calls weren't quite right, as this function has changed its behaviour. We also change the internal documentation of this function, and document evp_pkey_downgrade(). Fixes #11549 Reviewed-by: Paul Dale Reviewed-by: Shane Lontis (Merged from https://github.com/openssl/openssl/pull/11550) --- crypto/evp/keymgmt_meth.c | 9 ++++- crypto/evp/pmeth_gn.c | 6 ++- crypto/evp/signature.c | 2 +- .../man3/evp_pkey_export_to_provider.pod | 37 ++++++++----------- 4 files changed, 30 insertions(+), 24 deletions(-) diff --git a/crypto/evp/keymgmt_meth.c b/crypto/evp/keymgmt_meth.c index 7ea414e8dd..7925aeaf43 100644 --- a/crypto/evp/keymgmt_meth.c +++ b/crypto/evp/keymgmt_meth.c @@ -313,8 +313,15 @@ void *evp_keymgmt_gen_init(const EVP_KEYMGMT *keymgmt, int selection) int evp_keymgmt_gen_set_template(const EVP_KEYMGMT *keymgmt, void *genctx, void *template) { + /* + * It's arguable if we actually should return success in this case, as + * it allows the caller to set a template key, which is then ignored. + * However, this is how the legacy methods (EVP_PKEY_METHOD) operate, + * so we do this in the interest of backward compatibility. + * TODO(3.0) Investigate if we should change this behaviour. + */ if (keymgmt->gen_set_template == NULL) - return 0; + return 1; return keymgmt->gen_set_template(genctx, template); } diff --git a/crypto/evp/pmeth_gn.c b/crypto/evp/pmeth_gn.c index 78ed9ec781..95e3185573 100644 --- a/crypto/evp/pmeth_gn.c +++ b/crypto/evp/pmeth_gn.c @@ -170,8 +170,12 @@ int EVP_PKEY_gen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) evp_pkey_export_to_provider(ctx->pkey, ctx->libctx, &tmp_keymgmt, ctx->propquery); - if (keydata == NULL) + if (tmp_keymgmt == NULL) goto not_supported; + /* + * It's ok if keydata is NULL here. The backend is expected to deal + * with that as it sees fit. + */ ret = evp_keymgmt_gen_set_template(ctx->keymgmt, ctx->op.keymgmt.genctx, keydata); } diff --git a/crypto/evp/signature.c b/crypto/evp/signature.c index 1f5e570ff8..2334dcfb41 100644 --- a/crypto/evp/signature.c +++ b/crypto/evp/signature.c @@ -369,7 +369,7 @@ static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, int operation) tmp_keymgmt = ctx->keymgmt; provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx, &tmp_keymgmt, ctx->propquery); - if (provkey == NULL) + if (tmp_keymgmt == NULL) goto legacy; if (!EVP_KEYMGMT_up_ref(tmp_keymgmt)) { ERR_clear_last_mark(); diff --git a/doc/internal/man3/evp_pkey_export_to_provider.pod b/doc/internal/man3/evp_pkey_export_to_provider.pod index 31e8ad02e4..1c80365ca6 100644 --- a/doc/internal/man3/evp_pkey_export_to_provider.pod +++ b/doc/internal/man3/evp_pkey_export_to_provider.pod @@ -2,7 +2,7 @@ =head1 NAME -evp_pkey_export_to_provider, evp_pkey_upgrade_to_provider +evp_pkey_export_to_provider, evp_pkey_downgrade - internal EVP_PKEY support functions for providers =head1 SYNOPSIS @@ -13,9 +13,7 @@ evp_pkey_export_to_provider, evp_pkey_upgrade_to_provider void *evp_pkey_export_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx, EVP_KEYMGMT **keymgmt, const char *propquery); - void *evp_pkey_upgrade_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx, - EVP_KEYMGMT **keymgmt, - const char *propquery); + int evp_pkey_downgrade(EVP_PKEY *pk); =head1 DESCRIPTION @@ -31,29 +29,26 @@ default context), the name of the legacy type of I, and the I If I isn't NULL but I<*keymgmt> is, and the "origin" was successfully exported, then I<*keymgmt> is assigned the implicitly fetched B. -evp_pkey_upgrade_to_provider() exports the legacy "origin" key contained in -I to it's provider side counterpart, then clears the legacy "origin" key -along with other legacy data, and resets all the caches. Otherwise, it works -like evp_pkey_export_to_provider(). - -I -Most of the time, it's sufficient to use evp_pkey_export_to_provider(), but in -case the key needs modification with data coming from a provided key, the key -will need an upgrade. +evp_pkey_downgrade() converts an B with a provider side "origin" key +to one with a legacy "origin", if there's a corresponding legacy implementation. +This clears the operation cache, except for the provider side "origin" key. +This function is used in spots where provider side keys aren't yet supported, +in an attempt to keep operating with available implementations. =head1 RETURN VALUES -evp_pkey_export_to_provider() and evp_pkey_upgrade_to_provider() both return -the provider key data that was exported if the "origin" was successfully -exported to its target. Otherwise, NULL is returned. +evp_pkey_export_to_provider() returns the provider key data if there was any +allocated. It also either sets I<*keymgmt> to the B associated +with the returned key data, or NULL on error. + +evp_pkey_downgrade() returns 1 on success or 0 on error. =head1 NOTES -Some functions calling evp_pkey_export_to_provider() or -evp_pkey_upgrade_to_provider() may have received a const key, and may -therefore have to cast the key to non-const form to call this function. Since -B is always dynamically allocated, this is OK. +Some functions calling evp_pkey_export_to_provider() or evp_pkey_downgrade() +may have received a const key, and may therefore have to cast the key to +non-const form to call this function. Since B is always dynamically +allocated, this is OK. =head1 SEE ALSO -- 2.25.1