From: Richard Levitte Date: Thu, 27 Feb 2020 09:51:45 +0000 (+0100) Subject: EVP: Check that key methods aren't foreign when exporting X-Git-Tag: openssl-3.0.0-alpha1~302 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=df13defd4fd4c5a7afff69bc9733e7526e07959a;p=thirdparty%2Fopenssl.git 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 (Merged from https://github.com/openssl/openssl/pull/11193) --- diff --git a/crypto/dh/dh_ameth.c b/crypto/dh/dh_ameth.c index 14c08424558..ecec5fbcf6d 100644 --- a/crypto/dh/dh_ameth.c +++ b/crypto/dh/dh_ameth.c @@ -20,6 +20,7 @@ #include "dh_local.h" #include #include "crypto/asn1.h" +#include "crypto/dh.h" #include "crypto/evp.h" #include #include @@ -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; diff --git a/crypto/dsa/dsa_ameth.c b/crypto/dsa/dsa_ameth.c index 9715a75d0dc..94f3f43b8ea 100644 --- a/crypto/dsa/dsa_ameth.c +++ b/crypto/dsa/dsa_ameth.c @@ -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; diff --git a/crypto/ec/ec_ameth.c b/crypto/ec/ec_ameth.c index d6807661ffb..652086a93ad 100644 --- a/crypto/ec/ec_ameth.c +++ b/crypto/ec/ec_ameth.c @@ -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 */ diff --git a/crypto/evp/m_sigver.c b/crypto/evp/m_sigver.c index 225017b5095..4b2cb4eb35f 100644 --- a/crypto/evp/m_sigver.c +++ b/crypto/evp/m_sigver.c @@ -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; /* diff --git a/crypto/evp/pmeth_fn.c b/crypto/evp/pmeth_fn.c index ca0790fcd62..5d0e21ed687 100644 --- a/crypto/evp/pmeth_fn.c +++ b/crypto/evp/pmeth_fn.c @@ -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; /* diff --git a/crypto/evp/signature.c b/crypto/evp/signature.c index c01f0766098..acbe76592f7 100644 --- a/crypto/evp/signature.c +++ b/crypto/evp/signature.c @@ -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; /* diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c index f34eacf552b..3411b734e5e 100644 --- a/crypto/rsa/rsa_ameth.c +++ b/crypto/rsa/rsa_ameth.c @@ -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;