From: Karol Brzuskiewicz Date: Mon, 10 Jun 2024 08:48:31 +0000 (-0700) Subject: Fix usage of deallocated EVP_RAND_CTX after execution of FIPS on-demand self tests X-Git-Tag: openssl-3.4.0-alpha1~452 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=42a8ef844e5fca55abb608beb62695abe80c6b6d;p=thirdparty%2Fopenssl.git Fix usage of deallocated EVP_RAND_CTX after execution of FIPS on-demand self tests Once RNG is used, triggering FIPS on-demand self tests (via OSSL_PROVIDER_self_test() API) crashes the application. This happens because the RNG context is stored before self tests, and restored after their execution. In the meantime - before context restoration - RAND_set0_private() function is called, which decrements the stored RNG context reference counter and frees it. To resolve the issue, the stored RNG context refcount has been incremented via the EVP_RAND_CTX_up_ref() API to avoid its deallocation during the RNG context switch performed by the self test function. The provider_status_test test has been updated to reproduce the issue as a regression test. Signed-off-by: Karol Brzuskiewicz Reviewed-by: Shane Lontis Reviewed-by: Tom Cosgrove Reviewed-by: Paul Dale Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/24599) --- diff --git a/providers/fips/self_test_kats.c b/providers/fips/self_test_kats.c index f13c41abd67..8baa8cc6b1d 100644 --- a/providers/fips/self_test_kats.c +++ b/providers/fips/self_test_kats.c @@ -858,8 +858,12 @@ int SELF_TEST_kats(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx) EVP_RAND_CTX *saved_rand = ossl_rand_get0_private_noncreating(libctx); int ret = 1; + if (saved_rand != NULL && !EVP_RAND_CTX_up_ref(saved_rand)) + return 0; if (!setup_main_random(libctx) || !RAND_set0_private(libctx, main_rand)) { + /* Decrement saved_rand reference counter */ + EVP_RAND_CTX_free(saved_rand); EVP_RAND_CTX_free(main_rand); return 0; } diff --git a/test/provider_status_test.c b/test/provider_status_test.c index 551277c8e0b..362ae3803a7 100644 --- a/test/provider_status_test.c +++ b/test/provider_status_test.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "testutil.h" typedef enum OPTION_choice { @@ -147,6 +148,8 @@ static int test_provider_status(void) OSSL_PROVIDER *prov = NULL; OSSL_PARAM params[2]; EVP_MD *fetch = NULL; + EVP_PKEY_CTX *pctx = NULL; + EVP_PKEY *pkey = NULL; if (!TEST_ptr(prov = OSSL_PROVIDER_load(libctx, provider_name))) goto err; @@ -163,6 +166,16 @@ static int test_provider_status(void) goto err; EVP_MD_free(fetch); fetch = NULL; + /* Use RNG before triggering on-demand self tests */ + if (!TEST_ptr((pctx = EVP_PKEY_CTX_new_from_name(libctx, "RSA", NULL))) + || !TEST_int_gt(EVP_PKEY_keygen_init(pctx), 0) + || !TEST_int_gt(EVP_PKEY_CTX_set_rsa_keygen_bits(pctx, 2048), 0) + || !TEST_int_gt(EVP_PKEY_keygen(pctx, &pkey), 0)) + goto err; + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(pctx); + pkey = NULL; + pctx = NULL; /* Test that the provider self test is ok */ self_test_args.count = 0;