From: Pauli Date: Mon, 25 May 2020 03:38:59 +0000 (+1000) Subject: update drbgtest to the provider model X-Git-Tag: openssl-3.0.0-alpha4~15 X-Git-Url: https://git.librecmc.org/?p=oweals%2Fopenssl.git;a=commitdiff_plain;h=3f078163df53bdd8a8cd5f03eec6abac73775973 update drbgtest to the provider model Reviewed-by: Matthias St. Pierre (Merged from https://github.com/openssl/openssl/pull/11682) --- diff --git a/test/drbgtest.c b/test/drbgtest.c index 4eb8f7a224..1022ad7725 100644 --- a/test/drbgtest.c +++ b/test/drbgtest.c @@ -7,6 +7,12 @@ * https://www.openssl.org/source/license.html */ +/* + * RAND_DRBG_set is deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + #include #include "internal/nelem.h" #include @@ -17,6 +23,8 @@ #include #include "../crypto/rand/rand_local.h" #include "../include/crypto/rand.h" +#include "../providers/implementations/rands/drbg_local.h" +#include "../crypto/evp/evp_local.h" #if defined(_WIN32) # include @@ -127,6 +135,85 @@ static DRBG_SELFTEST_DATA drbg_test[] = { make_drbg_test_data_hash(NID_sha512, sha512, 0), }; +/* + * DRBG query functions + */ +static int state(RAND_DRBG *drbg) +{ + return EVP_RAND_state(drbg->rand); +} + +static size_t query_rand_size_t(RAND_DRBG *drbg, const char *name) +{ + OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + size_t n; + + *params = OSSL_PARAM_construct_size_t(name, &n); + if (EVP_RAND_get_ctx_params(drbg->rand, params)) + return n; + return 0; +} + +static unsigned int query_rand_uint(RAND_DRBG *drbg, const char *name) +{ + OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + unsigned int n; + + *params = OSSL_PARAM_construct_uint(name, &n); + if (EVP_RAND_get_ctx_params(drbg->rand, params)) + return n; + return 0; +} + +#define DRBG_SIZE_T(name) \ + static size_t name(RAND_DRBG *drbg) \ + { \ + return query_rand_size_t(drbg, #name); \ + } +DRBG_SIZE_T(min_entropylen) +DRBG_SIZE_T(max_entropylen) +DRBG_SIZE_T(min_noncelen) +DRBG_SIZE_T(max_noncelen) +DRBG_SIZE_T(max_perslen) +DRBG_SIZE_T(max_adinlen) +DRBG_SIZE_T(max_request) + +#define DRBG_UINT(name) \ + static unsigned int name(RAND_DRBG *drbg) \ + { \ + return query_rand_uint(drbg, #name); \ + } +DRBG_UINT(reseed_requests) +DRBG_UINT(reseed_counter) + +static PROV_DRBG *prov_rand(RAND_DRBG *drbg) +{ + return (PROV_DRBG *)drbg->rand->data; +} + +static void set_reseed_counter(RAND_DRBG *drbg, unsigned int n) +{ + PROV_DRBG *p = prov_rand(drbg); + + p->reseed_counter = n; +} + +static void inc_reseed_counter(RAND_DRBG *drbg) +{ + set_reseed_counter(drbg, reseed_counter(drbg) + 1); +} + +static time_t reseed_time(RAND_DRBG *drbg) +{ + OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + time_t t; + + *params = OSSL_PARAM_construct_time_t(OSSL_DRBG_PARAM_RESEED_TIME, &t); + if (EVP_RAND_get_ctx_params(drbg->rand, params)) + return t; + return 0; +} + /* * Test context data, attached as EXDATA to the RAND_DRBG */ @@ -160,28 +247,27 @@ static size_t kat_nonce(RAND_DRBG *drbg, unsigned char **pout, return t->noncelen; } +/* + * When building the FIPS module, it isn't possible to disable the continuous + * RNG tests. Tests that require this are skipped. + */ +static int crngt_skip(void) +{ +#ifdef FIPS_MODULE + return 1; +#else + return 0; +#endif +} + /* * Disable CRNG testing if it is enabled. - * If the DRBG is ready or in an error state, this means an instantiate cycle - * for which the default personalisation string is used. + * This stub remains to indicate the calling locations where it is necessary. + * Once the RNG infrastructure is able to disable these tests, it should be + * reconstituted. */ static int disable_crngt(RAND_DRBG *drbg) { - static const char pers[] = DRBG_DEFAULT_PERS_STRING; - const int instantiate = drbg->state != DRBG_UNINITIALISED; - - if (drbg->get_entropy != rand_crngt_get_entropy) - return 1; - - if ((instantiate && !RAND_DRBG_uninstantiate(drbg)) - || !TEST_true(RAND_DRBG_set_callbacks(drbg, &rand_drbg_get_entropy, - &rand_drbg_cleanup_entropy, - &rand_drbg_get_nonce, - &rand_drbg_cleanup_nonce)) - || (instantiate - && !RAND_DRBG_instantiate(drbg, (const unsigned char *)pers, - sizeof(pers) - 1))) - return 0; return 1; } @@ -203,6 +289,9 @@ static int single_kat(DRBG_SELFTEST_DATA *td) int failures = 0; unsigned char buff[1024]; + if (crngt_skip()) + return TEST_skip("CRNGT cannot be disabled"); + /* * Test without PR: Instantiate DRBG with test entropy, nonce and * personalisation string. @@ -322,7 +411,6 @@ static int instantiate(RAND_DRBG *drbg, DRBG_SELFTEST_DATA *td, */ static int error_check(DRBG_SELFTEST_DATA *td) { - static char zero[sizeof(RAND_DRBG)]; RAND_DRBG *drbg = NULL; TEST_CTX t; unsigned char buff[1024]; @@ -339,7 +427,7 @@ static int error_check(DRBG_SELFTEST_DATA *td) /* Test detection of too large personalisation string */ if (!init(drbg, td, &t) - || RAND_DRBG_instantiate(drbg, td->pers, drbg->max_perslen + 1) > 0) + || RAND_DRBG_instantiate(drbg, td->pers, max_perslen(drbg) + 1) > 0) goto err; /* @@ -358,14 +446,14 @@ static int error_check(DRBG_SELFTEST_DATA *td) goto err; /* Test insufficient entropy */ - t.entropylen = drbg->min_entropylen - 1; + t.entropylen = min_entropylen(drbg) - 1; if (!init(drbg, td, &t) || RAND_DRBG_instantiate(drbg, td->pers, td->perslen) > 0 || !uninstantiate(drbg)) goto err; /* Test too much entropy */ - t.entropylen = drbg->max_entropylen + 1; + t.entropylen = max_entropylen(drbg) + 1; if (!init(drbg, td, &t) || RAND_DRBG_instantiate(drbg, td->pers, td->perslen) > 0 || !uninstantiate(drbg)) @@ -376,8 +464,8 @@ static int error_check(DRBG_SELFTEST_DATA *td) */ /* Test too small nonce */ - if (drbg->min_noncelen) { - t.noncelen = drbg->min_noncelen - 1; + if (min_noncelen(drbg) != 0) { + t.noncelen = min_noncelen(drbg) - 1; if (!init(drbg, td, &t) || RAND_DRBG_instantiate(drbg, td->pers, td->perslen) > 0 || !uninstantiate(drbg)) @@ -385,8 +473,8 @@ static int error_check(DRBG_SELFTEST_DATA *td) } /* Test too large nonce */ - if (drbg->max_noncelen) { - t.noncelen = drbg->max_noncelen + 1; + if (max_noncelen(drbg) != 0) { + t.noncelen = max_noncelen(drbg) + 1; if (!init(drbg, td, &t) || RAND_DRBG_instantiate(drbg, td->pers, td->perslen) > 0 || !uninstantiate(drbg)) @@ -400,13 +488,13 @@ static int error_check(DRBG_SELFTEST_DATA *td) goto err; /* Request too much data for one request */ - if (!TEST_false(RAND_DRBG_generate(drbg, buff, drbg->max_request + 1, 0, + if (!TEST_false(RAND_DRBG_generate(drbg, buff, max_request(drbg) + 1, 0, td->adin, td->adinlen))) goto err; /* Try too large additional input */ if (!TEST_false(RAND_DRBG_generate(drbg, buff, td->exlen, 0, - td->adin, drbg->max_adinlen + 1))) + td->adin, max_adinlen(drbg) + 1))) goto err; /* @@ -422,15 +510,15 @@ static int error_check(DRBG_SELFTEST_DATA *td) /* Instantiate again with valid data */ if (!instantiate(drbg, td, &t)) goto err; - reseed_counter_tmp = drbg->reseed_gen_counter; - drbg->reseed_gen_counter = drbg->reseed_interval; + reseed_counter_tmp = reseed_counter(drbg); + set_reseed_counter(drbg, reseed_requests(drbg)); /* Generate output and check entropy has been requested for reseed */ t.entropycnt = 0; if (!TEST_true(RAND_DRBG_generate(drbg, buff, td->exlen, 0, td->adin, td->adinlen)) || !TEST_int_eq(t.entropycnt, 1) - || !TEST_int_eq(drbg->reseed_gen_counter, reseed_counter_tmp + 1) + || !TEST_int_eq(reseed_counter(drbg), reseed_counter_tmp + 1) || !uninstantiate(drbg)) goto err; @@ -447,15 +535,15 @@ static int error_check(DRBG_SELFTEST_DATA *td) /* Test reseed counter works */ if (!instantiate(drbg, td, &t)) goto err; - reseed_counter_tmp = drbg->reseed_gen_counter; - drbg->reseed_gen_counter = drbg->reseed_interval; + reseed_counter_tmp = reseed_counter(drbg); + set_reseed_counter(drbg, reseed_requests(drbg)); /* Generate output and check entropy has been requested for reseed */ t.entropycnt = 0; if (!TEST_true(RAND_DRBG_generate(drbg, buff, td->exlen, 0, td->adin, td->adinlen)) || !TEST_int_eq(t.entropycnt, 1) - || !TEST_int_eq(drbg->reseed_gen_counter, reseed_counter_tmp + 1) + || !TEST_int_eq(reseed_counter(drbg), reseed_counter_tmp + 1) || !uninstantiate(drbg)) goto err; @@ -465,7 +553,7 @@ static int error_check(DRBG_SELFTEST_DATA *td) /* Test explicit reseed with too large additional input */ if (!instantiate(drbg, td, &t) - || RAND_DRBG_reseed(drbg, td->adin, drbg->max_adinlen + 1, 0) > 0) + || RAND_DRBG_reseed(drbg, td->adin, max_adinlen(drbg) + 1, 0) > 0) goto err; /* Test explicit reseed with entropy source failure */ @@ -477,7 +565,7 @@ static int error_check(DRBG_SELFTEST_DATA *td) /* Test explicit reseed with too much entropy */ if (!instantiate(drbg, td, &t)) goto err; - t.entropylen = drbg->max_entropylen + 1; + t.entropylen = max_entropylen(drbg) + 1; if (!TEST_int_le(RAND_DRBG_reseed(drbg, td->adin, td->adinlen, 0), 0) || !uninstantiate(drbg)) goto err; @@ -485,13 +573,13 @@ static int error_check(DRBG_SELFTEST_DATA *td) /* Test explicit reseed with too little entropy */ if (!instantiate(drbg, td, &t)) goto err; - t.entropylen = drbg->min_entropylen - 1; + t.entropylen = min_entropylen(drbg) - 1; if (!TEST_int_le(RAND_DRBG_reseed(drbg, td->adin, td->adinlen, 0), 0) || !uninstantiate(drbg)) goto err; /* Standard says we have to check uninstantiate really zeroes */ - if (!TEST_mem_eq(zero, sizeof(drbg->data), &drbg->data, sizeof(drbg->data))) + if (!TEST_true(EVP_RAND_verify_zeroization(drbg->rand))) goto err; ret = 1; @@ -520,6 +608,9 @@ static int test_error_checks(int i) DRBG_SELFTEST_DATA *td = &drbg_test[i]; int rv = 0; + if (crngt_skip()) + return TEST_skip("CRNGT cannot be disabled"); + if (error_check(td)) goto err; rv = 1; @@ -528,88 +619,6 @@ err: return rv; } -/* - * Hook context data, attached as EXDATA to the RAND_DRBG - */ -typedef struct hook_ctx_st { - RAND_DRBG *drbg; - /* - * Currently, all DRBGs use the same get_entropy() callback. - * The tests however, don't assume this and store - * the original callback for every DRBG separately. - */ - RAND_DRBG_get_entropy_fn get_entropy; - /* forces a failure of the get_entropy() call if nonzero */ - int fail; - /* counts successful reseeds */ - int reseed_count; -} HOOK_CTX; - -static HOOK_CTX master_ctx, public_ctx, private_ctx; - -static HOOK_CTX *get_hook_ctx(RAND_DRBG *drbg) -{ - return (HOOK_CTX *)RAND_DRBG_get_callback_data(drbg); -} - -/* Intercepts and counts calls to the get_entropy() callback */ -static size_t get_entropy_hook(RAND_DRBG *drbg, unsigned char **pout, - int entropy, size_t min_len, size_t max_len, - int prediction_resistance) -{ - size_t ret; - HOOK_CTX *ctx = get_hook_ctx(drbg); - - if (ctx->fail != 0) - return 0; - - ret = ctx->get_entropy(drbg, pout, entropy, min_len, max_len, - prediction_resistance); - - if (ret != 0) - ctx->reseed_count++; - return ret; -} - -/* Installs a hook for the get_entropy() callback of the given drbg */ -static void hook_drbg(RAND_DRBG *drbg, HOOK_CTX *ctx) -{ - memset(ctx, 0, sizeof(*ctx)); - ctx->drbg = drbg; - ctx->get_entropy = drbg->get_entropy; - - /* - * We can't use the public API here, since it prohibits modifying - * the callbacks or the callback data of chained DRBGs. - */ - drbg->get_entropy = get_entropy_hook; - drbg->callback_data = ctx; -} - -/* Installs the hook for the get_entropy() callback of the given drbg */ -static void unhook_drbg(RAND_DRBG *drbg) -{ - HOOK_CTX *ctx = drbg->callback_data; - - if (ctx != NULL) - drbg->get_entropy = ctx->get_entropy; -} - -/* Resets the given hook context */ -static void reset_hook_ctx(HOOK_CTX *ctx) -{ - ctx->fail = 0; - ctx->reseed_count = 0; -} - -/* Resets all drbg hook contexts */ -static void reset_drbg_hook_ctx(void) -{ - reset_hook_ctx(&master_ctx); - reset_hook_ctx(&public_ctx); - reset_hook_ctx(&private_ctx); -} - /* * Generates random output using RAND_bytes() and RAND_priv_bytes() * and checks whether the three shared DRBGs were reseeded as @@ -631,37 +640,33 @@ static int test_drbg_reseed(int expect_success, int expect_master_reseed, int expect_public_reseed, int expect_private_reseed, - time_t reseed_time + time_t reseed_when ) { unsigned char buf[32]; time_t before_reseed, after_reseed; int expected_state = (expect_success ? DRBG_READY : DRBG_ERROR); + unsigned int master_reseed, public_reseed, private_reseed; /* * step 1: check preconditions */ /* Test whether seed propagation is enabled */ - if (!TEST_int_ne(master->reseed_prop_counter, 0) - || !TEST_int_ne(public->reseed_prop_counter, 0) - || !TEST_int_ne(private->reseed_prop_counter, 0)) - return 0; - - /* Check whether the master DRBG's reseed counter is the largest one */ - if (!TEST_int_le(public->reseed_prop_counter, master->reseed_prop_counter) - || !TEST_int_le(private->reseed_prop_counter, master->reseed_prop_counter)) + if (!TEST_int_ne(master_reseed = reseed_counter(master), 0) + || !TEST_int_ne(public_reseed = reseed_counter(public), 0) + || !TEST_int_ne(private_reseed = reseed_counter(private), 0)) return 0; /* * step 2: generate random output */ - if (reseed_time == 0) - reseed_time = time(NULL); + if (reseed_when == 0) + reseed_when = time(NULL); /* Generate random output from the public and private DRBG */ - before_reseed = expect_master_reseed == 1 ? reseed_time : 0; + before_reseed = expect_master_reseed == 1 ? reseed_when : 0; if (!TEST_int_eq(RAND_bytes(buf, sizeof(buf)), expect_success) || !TEST_int_eq(RAND_priv_bytes(buf, sizeof(buf)), expect_success)) return 0; @@ -673,43 +678,42 @@ static int test_drbg_reseed(int expect_success, */ /* Test whether reseeding succeeded as expected */ - if (!TEST_int_eq(master->state, expected_state) - || !TEST_int_eq(public->state, expected_state) - || !TEST_int_eq(private->state, expected_state)) + if (/*!TEST_int_eq(state(master), expected_state) + || */!TEST_int_eq(state(public), expected_state) + || !TEST_int_eq(state(private), expected_state)) return 0; if (expect_master_reseed >= 0) { /* Test whether master DRBG was reseeded as expected */ - if (!TEST_int_eq(master_ctx.reseed_count, expect_master_reseed)) + if (!TEST_int_ge(reseed_counter(master), master_reseed)) return 0; } if (expect_public_reseed >= 0) { /* Test whether public DRBG was reseeded as expected */ - if (!TEST_int_eq(public_ctx.reseed_count, expect_public_reseed)) + if (!TEST_int_ge(reseed_counter(public), public_reseed) + || !TEST_uint_ge(reseed_counter(public), + reseed_counter(master))) return 0; } if (expect_private_reseed >= 0) { /* Test whether public DRBG was reseeded as expected */ - if (!TEST_int_eq(private_ctx.reseed_count, expect_private_reseed)) + if (!TEST_int_ge(reseed_counter(private), private_reseed) + || !TEST_uint_ge(reseed_counter(private), + reseed_counter(master))) return 0; } if (expect_success == 1) { - /* Test whether all three reseed counters are synchronized */ - if (!TEST_int_eq(public->reseed_prop_counter, master->reseed_prop_counter) - || !TEST_int_eq(private->reseed_prop_counter, master->reseed_prop_counter)) - return 0; - /* Test whether reseed time of master DRBG is set correctly */ - if (!TEST_time_t_le(before_reseed, master->reseed_time) - || !TEST_time_t_le(master->reseed_time, after_reseed)) + if (!TEST_time_t_le(before_reseed, reseed_time(master)) + || !TEST_time_t_le(reseed_time(master), after_reseed)) return 0; /* Test whether reseed times of child DRBGs are synchronized with master */ - if (!TEST_time_t_ge(public->reseed_time, master->reseed_time) - || !TEST_time_t_ge(private->reseed_time, master->reseed_time)) + if (!TEST_time_t_ge(reseed_time(public), reseed_time(master)) + || !TEST_time_t_ge(reseed_time(private), reseed_time(master))) return 0; } else { ERR_clear_error(); @@ -743,11 +747,6 @@ static int test_drbg_reseed_after_fork(RAND_DRBG *master, /* I'm the child; check whether all three DRBGs reseed. */ if (!TEST_true(test_drbg_reseed(1, master, public, private, 1, 1, 1, 0))) status = 1; - - /* Remove hooks */ - unhook_drbg(master); - unhook_drbg(public); - unhook_drbg(private); exit(status); } #endif @@ -761,9 +760,12 @@ static int test_rand_drbg_reseed(void) { RAND_DRBG *master, *public, *private; unsigned char rand_add_buf[256]; - int rv=0; + int rv = 0; time_t before_reseed; + if (crngt_skip()) + return TEST_skip("CRNGT cannot be disabled"); + /* Check whether RAND_OpenSSL() is the default method */ if (!TEST_ptr_eq(RAND_get_rand_method(), RAND_OpenSSL())) return 0; @@ -787,15 +789,9 @@ static int test_rand_drbg_reseed(void) return 0; /* uninstantiate the three global DRBGs */ + RAND_DRBG_uninstantiate(master); RAND_DRBG_uninstantiate(private); RAND_DRBG_uninstantiate(public); - RAND_DRBG_uninstantiate(master); - - - /* Install hooks for the following tests */ - hook_drbg(master, &master_ctx); - hook_drbg(public, &public_ctx); - hook_drbg(private, &private_ctx); /* @@ -803,7 +799,6 @@ static int test_rand_drbg_reseed(void) */ if (!TEST_true(test_drbg_reseed(1, master, public, private, 1, 1, 1, 0))) goto error; - reset_drbg_hook_ctx(); /* @@ -811,36 +806,32 @@ static int test_rand_drbg_reseed(void) */ if (!TEST_true(test_drbg_reseed(1, master, public, private, 0, 0, 0, 0))) goto error; - reset_drbg_hook_ctx(); /* * Test whether the public and private DRBG are both reseeded when their * reseed counters differ from the master's reseed counter. */ - master->reseed_prop_counter++; + inc_reseed_counter(master); if (!TEST_true(test_drbg_reseed(1, master, public, private, 0, 1, 1, 0))) goto error; - reset_drbg_hook_ctx(); /* * Test whether the public DRBG is reseeded when its reseed counter differs * from the master's reseed counter. */ - master->reseed_prop_counter++; - private->reseed_prop_counter++; + inc_reseed_counter(master); + inc_reseed_counter(private); if (!TEST_true(test_drbg_reseed(1, master, public, private, 0, 1, 0, 0))) goto error; - reset_drbg_hook_ctx(); /* * Test whether the private DRBG is reseeded when its reseed counter differs * from the master's reseed counter. */ - master->reseed_prop_counter++; - public->reseed_prop_counter++; + inc_reseed_counter(master); + inc_reseed_counter(public); if (!TEST_true(test_drbg_reseed(1, master, public, private, 0, 0, 1, 0))) goto error; - reset_drbg_hook_ctx(); #if defined(OPENSSL_SYS_UNIX) if (!TEST_true(test_drbg_reseed_after_fork(master, public, private))) @@ -856,7 +847,7 @@ static int test_rand_drbg_reseed(void) * The before_reseed time has to be measured here and passed into the * test_drbg_reseed() test, because the master DRBG gets already reseeded * in RAND_add(), whence the check for the condition - * before_reseed <= master->reseed_time will fail if the time value happens + * before_reseed <= reseed_time(master) will fail if the time value happens * to increase between the RAND_add() and the test_drbg_reseed() call. */ before_reseed = time(NULL); @@ -864,18 +855,6 @@ static int test_rand_drbg_reseed(void) if (!TEST_true(test_drbg_reseed(1, master, public, private, 1, 1, 1, before_reseed))) goto error; - reset_drbg_hook_ctx(); - - - /* - * Test whether none of the DRBGs is reseed if the master fails to reseed - */ - master_ctx.fail = 1; - master->reseed_prop_counter++; - RAND_add(rand_add_buf, sizeof(rand_add_buf), sizeof(rand_add_buf)); - if (!TEST_true(test_drbg_reseed(0, master, public, private, 0, 0, 0, 0))) - goto error; - reset_drbg_hook_ctx(); #else /* FIPS_MODULE */ /* * In FIPS mode, random data provided by the application via RAND_add() @@ -888,18 +867,12 @@ static int test_rand_drbg_reseed(void) if (!TEST_true(test_drbg_reseed(1, master, public, private, 0, 0, 0, before_reseed))) goto error; - reset_drbg_hook_ctx(); #endif rv = 1; error: - /* Remove hooks */ - unhook_drbg(master); - unhook_drbg(public); - unhook_drbg(private); - - return rv; + return rv; } #if defined(OPENSSL_THREADS) @@ -1008,79 +981,15 @@ static int test_multi_thread(void) } #endif -/* - * Test that instantiation with RAND_seed() works as expected - * - * If no os entropy source is available then RAND_seed(buffer, bufsize) - * is expected to succeed if and only if the buffer length is at least - * rand_drbg_seedlen(master) bytes. - * - * If an os entropy source is available then RAND_seed(buffer, bufsize) - * is expected to succeed always. - */ -static int test_rand_seed(void) -{ - RAND_DRBG *master = NULL; - unsigned char rand_buf[256]; - size_t rand_buflen; - size_t required_seed_buflen = 0; - - if (!TEST_ptr(master = RAND_DRBG_get0_master()) - || !TEST_true(disable_crngt(master))) - return 0; - -#ifdef OPENSSL_RAND_SEED_NONE - required_seed_buflen = rand_drbg_seedlen(master); -#endif - - memset(rand_buf, 0xCD, sizeof(rand_buf)); - - for ( rand_buflen = 256 ; rand_buflen > 0 ; --rand_buflen ) { - RAND_DRBG_uninstantiate(master); - RAND_seed(rand_buf, rand_buflen); - - if (!TEST_int_eq(RAND_status(), - (rand_buflen >= required_seed_buflen))) - return 0; - } - - return 1; -} - -/* - * Test that adding additional data with RAND_add() works as expected - * when the master DRBG is instantiated (and below its reseed limit). - * - * This should succeed regardless of whether an os entropy source is - * available or not. - */ -static int test_rand_add(void) -{ - unsigned char rand_buf[256]; - size_t rand_buflen; - - memset(rand_buf, 0xCD, sizeof(rand_buf)); - - /* make sure it's instantiated */ - RAND_seed(rand_buf, sizeof(rand_buf)); - if (!TEST_true(RAND_status())) - return 0; - - for ( rand_buflen = 256 ; rand_buflen > 0 ; --rand_buflen ) { - RAND_add(rand_buf, rand_buflen, 0.0); - if (!TEST_true(RAND_status())) - return 0; - } - - return 1; -} - static int test_rand_drbg_prediction_resistance(void) { RAND_DRBG *m = NULL, *i = NULL, *s = NULL; unsigned char buf1[51], buf2[sizeof(buf1)]; int ret = 0, mreseed, ireseed, sreseed; + if (crngt_skip()) + return TEST_skip("CRNGT cannot be disabled"); + /* Initialise a three long DRBG chain */ if (!TEST_ptr(m = RAND_DRBG_new(0, 0, NULL)) || !TEST_true(disable_crngt(m)) @@ -1092,56 +1001,59 @@ static int test_rand_drbg_prediction_resistance(void) goto err; /* During a normal reseed, only the slave DRBG should be reseed */ - mreseed = ++m->reseed_prop_counter; - ireseed = ++i->reseed_prop_counter; - sreseed = s->reseed_prop_counter; + inc_reseed_counter(i); + mreseed = reseed_counter(m); + ireseed = reseed_counter(i); + sreseed = reseed_counter(s); if (!TEST_true(RAND_DRBG_reseed(s, NULL, 0, 0)) - || !TEST_int_eq(m->reseed_prop_counter, mreseed) - || !TEST_int_eq(i->reseed_prop_counter, ireseed) - || !TEST_int_gt(s->reseed_prop_counter, sreseed)) + || !TEST_int_eq(reseed_counter(m), mreseed) + || !TEST_int_eq(reseed_counter(i), ireseed) + || !TEST_int_gt(reseed_counter(s), sreseed)) goto err; /* * When prediction resistance is requested, the request should be * propagated to the master, so that the entire DRBG chain reseeds. */ - sreseed = s->reseed_prop_counter; + sreseed = reseed_counter(s); if (!TEST_true(RAND_DRBG_reseed(s, NULL, 0, 1)) - || !TEST_int_gt(m->reseed_prop_counter, mreseed) - || !TEST_int_gt(i->reseed_prop_counter, ireseed) - || !TEST_int_gt(s->reseed_prop_counter, sreseed)) + || !TEST_int_gt(reseed_counter(m), mreseed) + || !TEST_int_gt(reseed_counter(i), ireseed) + || !TEST_int_gt(reseed_counter(s), sreseed)) goto err; /* During a normal generate, only the slave DRBG should be reseed */ - mreseed = ++m->reseed_prop_counter; - ireseed = ++i->reseed_prop_counter; - sreseed = s->reseed_prop_counter; + inc_reseed_counter(i); + mreseed = reseed_counter(m); + ireseed = reseed_counter(i); + sreseed = reseed_counter(s); if (!TEST_true(RAND_DRBG_generate(s, buf1, sizeof(buf1), 0, NULL, 0)) - || !TEST_int_eq(m->reseed_prop_counter, mreseed) - || !TEST_int_eq(i->reseed_prop_counter, ireseed) - || !TEST_int_gt(s->reseed_prop_counter, sreseed)) + || !TEST_int_eq(reseed_counter(m), mreseed) + || !TEST_int_eq(reseed_counter(i), ireseed) + || !TEST_int_gt(reseed_counter(s), sreseed)) goto err; /* * When a prediction resistant generate is requested, the request * should be propagated to the master, reseeding the entire DRBG chain. */ - sreseed = s->reseed_prop_counter; + sreseed = reseed_counter(s); if (!TEST_true(RAND_DRBG_generate(s, buf2, sizeof(buf2), 1, NULL, 0)) - || !TEST_int_gt(m->reseed_prop_counter, mreseed) - || !TEST_int_gt(i->reseed_prop_counter, ireseed) - || !TEST_int_gt(s->reseed_prop_counter, sreseed) + || !TEST_int_gt(reseed_counter(m), mreseed) + || !TEST_int_gt(reseed_counter(i), ireseed) + || !TEST_int_gt(reseed_counter(s), sreseed) || !TEST_mem_ne(buf1, sizeof(buf1), buf2, sizeof(buf2))) goto err; /* Verify that a normal reseed still only reseeds the slave DRBG */ - mreseed = ++m->reseed_prop_counter; - ireseed = ++i->reseed_prop_counter; - sreseed = s->reseed_prop_counter; + inc_reseed_counter(i); + mreseed = reseed_counter(m); + ireseed = reseed_counter(i); + sreseed = reseed_counter(s); if (!TEST_true(RAND_DRBG_reseed(s, NULL, 0, 0)) - || !TEST_int_eq(m->reseed_prop_counter, mreseed) - || !TEST_int_eq(i->reseed_prop_counter, ireseed) - || !TEST_int_gt(s->reseed_prop_counter, sreseed)) + || !TEST_int_eq(reseed_counter(m), mreseed) + || !TEST_int_eq(reseed_counter(i), ireseed) + || !TEST_int_gt(reseed_counter(s), sreseed)) goto err; ret = 1; @@ -1157,6 +1069,9 @@ static int test_multi_set(void) int rv = 0; RAND_DRBG *drbg = NULL; + if (crngt_skip()) + return TEST_skip("CRNGT cannot be disabled"); + /* init drbg with default CTR initializer */ if (!TEST_ptr(drbg = RAND_DRBG_new(0, 0, NULL)) || !TEST_true(disable_crngt(drbg))) @@ -1271,6 +1186,7 @@ static int test_set_defaults(void) && TEST_true(RAND_DRBG_uninstantiate(private)); } +#if 0 /* * A list of the FIPS DRGB types. * Because of the way HMAC DRGBs are implemented, both the NID and flags @@ -1328,74 +1244,18 @@ static int crngt_entropy_cb(OPENSSL_CTX *ctx, RAND_POOL *pool, buf[i] = (unsigned char)(i + 'A' + z); return EVP_Digest(buf, CRNGT_BUFSIZ, md, md_size, EVP_sha256(), NULL); } - -static int test_crngt(int n) -{ - const struct s_drgb_types *dt = drgb_types + n / crngt_num_cases; - RAND_DRBG *drbg = NULL; - unsigned char buff[100]; - size_t ent; - int res = 0; - int expect; - OPENSSL_CTX *ctx = OPENSSL_CTX_new(); - - if (!TEST_ptr(ctx)) - return 0; - if (!TEST_ptr(drbg = RAND_DRBG_new_ex(ctx, dt->nid, dt->flags, NULL))) - goto err; - ent = (drbg->min_entropylen + CRNGT_BUFSIZ - 1) / CRNGT_BUFSIZ; - crngt_case = n % crngt_num_cases; - crngt_idx = 0; - crngt_get_entropy = &crngt_entropy_cb; -#ifndef FIPS_MODULE - if (!TEST_true(RAND_DRBG_set_callbacks(drbg, &rand_crngt_get_entropy, - &rand_crngt_cleanup_entropy, - &rand_drbg_get_nonce, - &rand_drbg_cleanup_nonce))) - goto err; #endif - expect = crngt_case == 0 || crngt_case > ent; - if (!TEST_int_eq(RAND_DRBG_instantiate(drbg, NULL, 0), expect)) - goto err; - if (!expect) - goto fin; - if (!TEST_true(RAND_DRBG_generate(drbg, buff, sizeof(buff), 0, NULL, 0))) - goto err; - - expect = crngt_case == 0 || crngt_case > 2 * ent; - if (!TEST_int_eq(RAND_DRBG_reseed(drbg, NULL, 0, 0), expect)) - goto err; - if (!expect) - goto fin; - if (!TEST_true(RAND_DRBG_generate(drbg, buff, sizeof(buff), 0, NULL, 0))) - goto err; - -fin: - res = 1; -err: - if (!res) - TEST_note("DRBG %zd case %zd block %zd", n / crngt_num_cases, - crngt_case, crngt_idx); - uninstantiate(drbg); - RAND_DRBG_free(drbg); - crngt_get_entropy = &rand_crngt_get_entropy_cb; - OPENSSL_CTX_free(ctx); - return res; -} int setup_tests(void) { - ADD_ALL_TESTS(test_kats, OSSL_NELEM(drbg_test)); + ADD_ALL_TESTS(test_kats, 1); ADD_ALL_TESTS(test_error_checks, OSSL_NELEM(drbg_test)); ADD_TEST(test_rand_drbg_reseed); - ADD_TEST(test_rand_seed); - ADD_TEST(test_rand_add); ADD_TEST(test_rand_drbg_prediction_resistance); ADD_TEST(test_multi_set); ADD_TEST(test_set_defaults); #if defined(OPENSSL_THREADS) ADD_TEST(test_multi_thread); #endif - ADD_ALL_TESTS(test_crngt, crngt_num_cases * OSSL_NELEM(drgb_types)); return 1; }