Commit 171e4e7eb6 for openssl.org
commit 171e4e7eb64f243f78a1040f725ed80a31df7702
Author: Jakub Zelenka <jakub.zelenka@openssl.foundation>
Date: Tue Jul 7 16:37:49 2026 +0200
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 <paul.dale@oracle.com>
Reviewed-by: Nikola Pajkovsky <nikolap@openssl.org>
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 0fbd89542f..e5c889a9e9 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;
}