From: Jakub Zelenka Date: Tue, 7 Jul 2026 14:37:49 +0000 (+0200) Subject: rand: add mfail tests for generation and seeding X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=171e4e7eb64f243f78a1040f725ed80a31df7702;p=thirdparty%2Fopenssl.git rand: add mfail tests for generation and seeding Add memory-failure injection coverage to rand_test for the full RAND_bytes_ex/RAND_priv_bytes_ex stack on a fresh library context, the SEED-SRC entropy acquisition and the CTR-DRBG operations with a TEST-RAND parent. The cipher fetches used by the DRBG setup are warmed up outside the injection window so that the injection targets the RAND machinery itself. Assisted-by: Claude:claude-fable-5 Reviewed-by: Paul Dale Reviewed-by: Nikola Pajkovsky MergeDate: Fri Jul 10 15:47:16 2026 (Merged from https://github.com/openssl/openssl/pull/31885) --- diff --git a/test/rand_test.c b/test/rand_test.c index 0fbd89542f2..e5c889a9e9d 100644 --- a/test/rand_test.c +++ b/test/rand_test.c @@ -275,6 +275,142 @@ err: return res; } +/* Warm up the DRBG cipher fetch caches outside the mfail injection window */ +static int rand_drbg_fetch_warmup(EVP_RAND *drbg_alg) +{ + EVP_RAND_CTX *warm; + OSSL_PARAM params[3]; + int ret; + + params[0] = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_CIPHER, + (char *)"AES-256-CTR", 0); + params[1] = OSSL_PARAM_construct_utf8_string(OSSL_PROV_PARAM_CORE_PROV_NAME, + (char *)"default", 0); + params[2] = OSSL_PARAM_construct_end(); + + if (!TEST_ptr(warm = EVP_RAND_CTX_new(drbg_alg, NULL))) + return 0; + ret = TEST_true(EVP_RAND_CTX_set_params(warm, params)); + EVP_RAND_CTX_free(warm); + return ret; +} + +/* + * Memory-failure coverage for the whole random generation stack on a fresh + * library context: the seed source and DRBG chain creation and seeding. + */ +static int test_rand_bytes_mfail(int idx) +{ + OSSL_LIB_CTX *ctx = NULL; + EVP_RAND *drbg = NULL, *seed = NULL; + unsigned char buf[16]; + int rc = -1; + + if (!TEST_ptr(ctx = OSSL_LIB_CTX_new()) + || !TEST_ptr(drbg = EVP_RAND_fetch(ctx, "CTR-DRBG", NULL)) + || !rand_drbg_fetch_warmup(drbg)) + goto end; + /* The default seed source may be unavailable in some configurations */ + ERR_set_mark(); + seed = EVP_RAND_fetch(ctx, "SEED-SRC", NULL); + ERR_pop_to_mark(); + + MFAIL_start(); + rc = (idx == 0 ? RAND_bytes_ex(ctx, buf, sizeof(buf), 0) + : RAND_priv_bytes_ex(ctx, buf, sizeof(buf), 0)) + > 0; + MFAIL_end(); + +end: + EVP_RAND_free(seed); + EVP_RAND_free(drbg); + OSSL_LIB_CTX_free(ctx); + return rc; +} + +/* Memory-failure coverage for the seed source entropy acquisition. */ +static int test_rand_seed_src_mfail(void) +{ + OSSL_LIB_CTX *ctx = NULL; + EVP_RAND *rand = NULL; + EVP_RAND_CTX *seed = NULL; + unsigned char buf[64]; + int rc = -1; + + if (!TEST_ptr(ctx = OSSL_LIB_CTX_new()) + || !TEST_ptr(rand = EVP_RAND_fetch(ctx, "SEED-SRC", NULL))) + goto end; + + MFAIL_start(); + rc = (seed = EVP_RAND_CTX_new(rand, NULL)) != NULL + && EVP_RAND_instantiate(seed, 0, 0, NULL, 0, NULL) + && EVP_RAND_generate(seed, buf, sizeof(buf), 0, 0, NULL, 0); + MFAIL_end(); + +end: + EVP_RAND_CTX_free(seed); + EVP_RAND_free(rand); + OSSL_LIB_CTX_free(ctx); + return rc; +} + +/* Memory-failure coverage for the DRBG operations with a TEST-RAND parent */ +static int test_rand_drbg_mfail(void) +{ + OSSL_LIB_CTX *ctx = NULL; + EVP_RAND *parent_alg = NULL, *drbg_alg = NULL; + EVP_RAND_CTX *parent = NULL, *drbg = NULL; + unsigned int strength = 256, generate = 1; + unsigned char entropy[128]; + unsigned char buf[32]; + OSSL_PARAM parent_params[4], drbg_params[3]; + size_t i; + int rc = -1; + + for (i = 0; i < sizeof(entropy); i++) + entropy[i] = 0xff & i; + parent_params[0] = OSSL_PARAM_construct_uint(OSSL_RAND_PARAM_STRENGTH, + &strength); + parent_params[1] = OSSL_PARAM_construct_uint(OSSL_RAND_PARAM_GENERATE, + &generate); + parent_params[2] = OSSL_PARAM_construct_octet_string( + OSSL_RAND_PARAM_TEST_ENTROPY, entropy, sizeof(entropy)); + parent_params[3] = OSSL_PARAM_construct_end(); + + drbg_params[0] = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_CIPHER, + (char *)"AES-256-CTR", 0); + drbg_params[1] = OSSL_PARAM_construct_utf8_string( + OSSL_PROV_PARAM_CORE_PROV_NAME, (char *)"default", 0); + drbg_params[2] = OSSL_PARAM_construct_end(); + + if (!TEST_ptr(ctx = OSSL_LIB_CTX_new()) + || !TEST_ptr(parent_alg = EVP_RAND_fetch(ctx, "TEST-RAND", NULL)) + || !TEST_ptr(drbg_alg = EVP_RAND_fetch(ctx, "CTR-DRBG", NULL)) + || !rand_drbg_fetch_warmup(drbg_alg) + || !TEST_ptr(parent = EVP_RAND_CTX_new(parent_alg, NULL)) + || !TEST_true(EVP_RAND_instantiate(parent, 0, 0, NULL, 0, + parent_params))) + goto end; + + MFAIL_start(); + rc = (drbg = EVP_RAND_CTX_new(drbg_alg, parent)) != NULL + && EVP_RAND_instantiate(drbg, 0, 0, (unsigned char *)"abc", 3, + drbg_params) + && EVP_RAND_generate(drbg, buf, sizeof(buf), 0, 0, NULL, 0) + && EVP_RAND_reseed(drbg, 0, NULL, 0, (unsigned char *)"xyz", 3) + && EVP_RAND_generate(drbg, buf, sizeof(buf), 0, 0, + (unsigned char *)"adin", 4); + MFAIL_end(); + +end: + EVP_RAND_CTX_free(drbg); + EVP_RAND_CTX_free(parent); + EVP_RAND_free(parent_alg); + EVP_RAND_free(drbg_alg); + OSSL_LIB_CTX_free(ctx); + return rc; +} + int setup_tests(void) { if (!test_skip_common_options()) { @@ -301,5 +437,9 @@ int setup_tests(void) if (!OSSL_PROVIDER_available(NULL, "fips") || fips_provider_version_ge(NULL, 3, 5, 1)) ADD_TEST(test_rand_get0_primary); + + ADD_MFAIL_ALL_TESTS(test_rand_bytes_mfail, 2); + ADD_MFAIL_TEST(test_rand_seed_src_mfail); + ADD_MFAIL_TEST(test_rand_drbg_mfail); return 1; }