EVP: Check that key methods aren't foreign when exporting

The EVP_PKEY_ASN1_METHOD function export_to() must check that the key
we're trying to export has a known libcrypto method, i.e. is a built
in RSA_METHOD, DSA_METHOD, etc.  Otherwise, the method may be defined
by the calling application, by an engine, by another library, and we
simply cannot know all the quirks hidden behind that method, if we
have access to the key data, or much anything.

Such keys are simply deemed impossible to export to provider keys,
i.e. have export_to() return 0.  This cascades back to functions like
evp_pkey_export_to_provider() and evp_pkey_upgrade_to_provider() and
their callers.  In most cases, this is fine, but if these get mixed in
with provider side keys in any function, that function will fail.

Fixes #11179
Fixes #9915

Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org>
(Merged from https://github.com/openssl/openssl/pull/11193)
This commit is contained in:
Richard Levitte 2020-02-27 10:51:45 +01:00
parent b4dc705a73
commit df13defd4f
7 changed files with 32 additions and 3 deletions

View File

@ -20,6 +20,7 @@
#include "dh_local.h"
#include <openssl/bn.h>
#include "crypto/asn1.h"
#include "crypto/dh.h"
#include "crypto/evp.h"
#include <openssl/cms.h>
#include <openssl/core_names.h>
@ -499,6 +500,13 @@ static int dh_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
OSSL_PARAM *params;
int rv;
/*
* If the DH method is foreign, then we can't be sure of anything, and
* can therefore not export or pretend to export.
*/
if (dh_get_method(dh) != DH_OpenSSL())
return 0;
if (p == NULL || g == NULL)
return 0;

View File

@ -528,6 +528,13 @@ static int dsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
OSSL_PARAM *params;
int rv;
/*
* If the DSA method is foreign, then we can't be sure of anything, and
* can therefore not export or pretend to export.
*/
if (DSA_get_method(dsa) != DSA_OpenSSL())
return 0;
if (p == NULL || q == NULL || g == NULL)
return 0;

View File

@ -637,6 +637,13 @@ int ec_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
|| (ecg = EC_KEY_get0_group(eckey)) == NULL)
return 0;
/*
* If the EC_KEY method is foreign, then we can't be sure of anything,
* and can therefore not export or pretend to export.
*/
if (EC_KEY_get_method(eckey) != EC_KEY_OpenSSL())
return 0;
ossl_param_bld_init(&tmpl);
/* export the domain parameters */

View File

@ -73,7 +73,7 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
*/
ERR_set_mark();
if (locpctx->keytype == NULL)
if (locpctx->engine != NULL || locpctx->keytype == NULL)
goto legacy;
/*

View File

@ -38,7 +38,7 @@ static int evp_pkey_asym_cipher_init(EVP_PKEY_CTX *ctx, int operation)
*/
ERR_set_mark();
if (ctx->keytype == NULL || ctx->engine != NULL)
if (ctx->engine != NULL || ctx->keytype == NULL)
goto legacy;
/*

View File

@ -359,7 +359,7 @@ static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, int operation)
*/
ERR_set_mark();
if (ctx->keytype == NULL)
if (ctx->engine != NULL || ctx->keytype == NULL)
goto legacy;
/*

View File

@ -1092,6 +1092,13 @@ static int rsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
OSSL_PARAM *params = NULL;
int rv = 0;
/*
* If the RSA method is foreign, then we can't be sure of anything, and
* can therefore not export or pretend to export.
*/
if (RSA_get_method(rsa) != RSA_PKCS1_OpenSSL())
return 0;
/* Public parameters must always be present */
if (n == NULL || e == NULL)
goto err;