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()) {
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;
}