From b533510f3bc70957dbf447f7ea8ec20765c5b314 Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Wed, 13 May 2020 17:17:35 +0100 Subject: [PATCH] Fail if we fail to fetch the EVP_KEYMGMT If we failed to fetch an EVP_KEYMGMT then we were falling back to legacy. This is because some algorithms (such as MACs and KDFs used via an old style EVP_PKEY) have not been transferred to providers. Unfortunately this means that you cannot stop some algorithms from being used by not loading the provider. For example if you wanted to prevent RSA from being used, you might expect to just not load any providers that make it available. Unfortunately that doesn't work because we simply fall back to legacy if we fail to fetch the EVP_KEYMGMT. Instead we should fail *unless* the key type is one of those legacy key types that we have not transferred. Reviewed-by: Richard Levitte (Merged from https://github.com/openssl/openssl/pull/11826) --- crypto/evp/pmeth_lib.c | 50 +++++++++++++++++++++++++++++++++++++++--- test/evp_test.c | 3 ++- 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c index 355565de63..ea8bdec388 100644 --- a/crypto/evp/pmeth_lib.c +++ b/crypto/evp/pmeth_lib.c @@ -137,6 +137,40 @@ EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags) } #endif /* FIPS_MODULE */ +static int is_legacy_alg(int id, const char *keytype) +{ +#ifndef FIPS_MODULE + /* Certain EVP_PKEY keytypes are only available in legacy form */ + if (id == -1) { + id = OBJ_sn2nid(keytype); + if (id == NID_undef) + id = OBJ_ln2nid(keytype); + if (id == NID_undef) + return 0; + } + switch (id) { + /* + * TODO(3.0): Remove SM2 and DHX when they are converted to have provider + * support + */ + case EVP_PKEY_SM2: + case EVP_PKEY_DHX: + case EVP_PKEY_SCRYPT: + case EVP_PKEY_TLS1_PRF: + case EVP_PKEY_HKDF: + case EVP_PKEY_CMAC: + case EVP_PKEY_HMAC: + case EVP_PKEY_SIPHASH: + case EVP_PKEY_POLY1305: + return 1; + default: + return 0; + } +#else + return 0; +#endif +} + static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx, EVP_PKEY *pkey, ENGINE *e, const char *keytype, const char *propquery, @@ -228,10 +262,20 @@ static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx, * implementation. */ if (e == NULL && keytype != NULL) { - /* This could fail so ignore errors */ - ERR_set_mark(); + int legacy = is_legacy_alg(id, keytype); + + if (legacy) { + /* This could fail so ignore errors */ + ERR_set_mark(); + } + keymgmt = EVP_KEYMGMT_fetch(libctx, keytype, propquery); - ERR_pop_to_mark(); + if (legacy) { + ERR_pop_to_mark(); + } else if (keymgmt == NULL) { + EVPerr(EVP_F_INT_CTX_NEW, EVP_R_FETCH_FAILED); + return NULL; + } } ret = OPENSSL_zalloc(sizeof(*ret)); diff --git a/test/evp_test.c b/test/evp_test.c index 813218a42a..6ed5bafba6 100644 --- a/test/evp_test.c +++ b/test/evp_test.c @@ -2995,7 +2995,8 @@ static int key_unsupported(void) long err = ERR_peek_error(); if (ERR_GET_LIB(err) == ERR_LIB_EVP - && ERR_GET_REASON(err) == EVP_R_UNSUPPORTED_ALGORITHM) { + && (ERR_GET_REASON(err) == EVP_R_UNSUPPORTED_ALGORITHM + || ERR_GET_REASON(err) == EVP_R_FETCH_FAILED)) { ERR_clear_error(); return 1; } -- 2.25.1