mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-30 15:43:32 +01:00
Improve test coverage of our strongest-rng code.
This commit is contained in:
parent
148f0004e1
commit
7a5f15b6e0
@ -2571,6 +2571,11 @@ crypto_seed_weak_rng(tor_weak_rng_t *rng)
|
||||
tor_init_weak_random(rng, seed);
|
||||
}
|
||||
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
int break_strongest_rng_syscall = 0;
|
||||
int break_strongest_rng_fallback = 0;
|
||||
#endif
|
||||
|
||||
/** Try to get <b>out_len</b> bytes of the strongest entropy we can generate,
|
||||
* via system calls, storing it into <b>out</b>. Return 0 on success, -1 on
|
||||
* failure. A maximum request size of 256 bytes is imposed.
|
||||
@ -2580,6 +2585,11 @@ crypto_strongest_rand_syscall(uint8_t *out, size_t out_len)
|
||||
{
|
||||
tor_assert(out_len <= MAX_STRONGEST_RAND_SIZE);
|
||||
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
if (break_strongest_rng_syscall)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
static int provider_set = 0;
|
||||
static HCRYPTPROV provider;
|
||||
@ -2664,6 +2674,11 @@ crypto_strongest_rand_syscall(uint8_t *out, size_t out_len)
|
||||
static int
|
||||
crypto_strongest_rand_fallback(uint8_t *out, size_t out_len)
|
||||
{
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
if (break_strongest_rng_fallback)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
/* Windows exclusively uses crypto_strongest_rand_syscall(). */
|
||||
(void)out;
|
||||
@ -2701,7 +2716,7 @@ crypto_strongest_rand_fallback(uint8_t *out, size_t out_len)
|
||||
* storing it into <b>out</b>. Return 0 on success, -1 on failure. A maximum
|
||||
* request size of 256 bytes is imposed.
|
||||
*/
|
||||
static int
|
||||
STATIC int
|
||||
crypto_strongest_rand_raw(uint8_t *out, size_t out_len)
|
||||
{
|
||||
static const size_t sanity_min_size = 16;
|
||||
@ -2735,13 +2750,17 @@ crypto_strongest_rand_raw(uint8_t *out, size_t out_len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We tried max_attempts times to fill a buffer >= 128 bits long,
|
||||
/* LCOV_EXCL_START
|
||||
*
|
||||
* We tried max_attempts times to fill a buffer >= 128 bits long,
|
||||
* and each time it returned all '0's. Either the system entropy
|
||||
* source is busted, or the user should go out and buy a ticket to
|
||||
* every lottery on the planet.
|
||||
*/
|
||||
log_warn(LD_CRYPTO, "Strong OS entropy returned all zero buffer.");
|
||||
|
||||
return -1;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
/** Try to get <b>out_len</b> bytes of the strongest entropy we can generate,
|
||||
|
@ -317,6 +317,7 @@ void crypto_add_spaces_to_fp(char *out, size_t outlen, const char *in);
|
||||
|
||||
#ifdef CRYPTO_PRIVATE
|
||||
STATIC int crypto_force_rand_ssleay(void);
|
||||
STATIC int crypto_strongest_rand_raw(uint8_t *out, size_t out_len);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -190,6 +190,67 @@ test_crypto_rng_range(void *arg)
|
||||
;
|
||||
}
|
||||
|
||||
extern int break_strongest_rng_fallback;
|
||||
extern int break_strongest_rng_syscall;
|
||||
|
||||
static void
|
||||
test_crypto_rng_strongest(void *arg)
|
||||
{
|
||||
const char *how = arg;
|
||||
int broken = 0;
|
||||
|
||||
if (how == NULL) {
|
||||
;
|
||||
} else if (!strcmp(how, "nosyscall")) {
|
||||
break_strongest_rng_syscall = 1;
|
||||
} else if (!strcmp(how, "nofallback")) {
|
||||
break_strongest_rng_fallback = 1;
|
||||
} else if (!strcmp(how, "broken")) {
|
||||
broken = break_strongest_rng_syscall = break_strongest_rng_fallback = 1;
|
||||
}
|
||||
|
||||
#define N 128
|
||||
uint8_t combine_and[N];
|
||||
uint8_t combine_or[N];
|
||||
int i, j;
|
||||
|
||||
memset(combine_and, 0xff, N);
|
||||
memset(combine_or, 0, N);
|
||||
|
||||
for (i = 0; i < 100; ++i) { /* 2^-100 chances just don't happen. */
|
||||
uint8_t output[N];
|
||||
memset(output, 0, N);
|
||||
if (how == NULL) {
|
||||
/* this one can't fail. */
|
||||
crypto_strongest_rand(output, sizeof(output));
|
||||
} else {
|
||||
int r = crypto_strongest_rand_raw(output, sizeof(output));
|
||||
if (r == -1) {
|
||||
if (broken) {
|
||||
goto done; /* we're fine. */
|
||||
}
|
||||
/* This function is allowed to break, but only if it always breaks. */
|
||||
tt_int_op(i, OP_EQ, 0);
|
||||
tt_skip();
|
||||
} else {
|
||||
tt_assert(! broken);
|
||||
}
|
||||
}
|
||||
for (j = 0; j < N; ++j) {
|
||||
combine_and[j] &= output[j];
|
||||
combine_or[j] |= output[j];
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < N; ++j) {
|
||||
tt_int_op(combine_and[j], OP_EQ, 0);
|
||||
tt_int_op(combine_or[j], OP_EQ, 0xff);
|
||||
}
|
||||
done:
|
||||
;
|
||||
#undef N
|
||||
}
|
||||
|
||||
/* Test for rectifying openssl RAND engine. */
|
||||
static void
|
||||
test_crypto_rng_engine(void *arg)
|
||||
@ -2750,6 +2811,13 @@ struct testcase_t crypto_tests[] = {
|
||||
CRYPTO_LEGACY(rng),
|
||||
{ "rng_range", test_crypto_rng_range, 0, NULL, NULL },
|
||||
{ "rng_engine", test_crypto_rng_engine, TT_FORK, NULL, NULL },
|
||||
{ "rng_strongest", test_crypto_rng_strongest, TT_FORK, NULL, NULL },
|
||||
{ "rng_strongest_nosyscall", test_crypto_rng_strongest, TT_FORK,
|
||||
&passthrough_setup, (void*)"nosyscall" },
|
||||
{ "rng_strongest_nofallback", test_crypto_rng_strongest, TT_FORK,
|
||||
&passthrough_setup, (void*)"nofallback" },
|
||||
{ "rng_strongest_broken", test_crypto_rng_strongest, TT_FORK,
|
||||
&passthrough_setup, (void*)"broken" },
|
||||
{ "openssl_version", test_crypto_openssl_version, TT_FORK, NULL, NULL },
|
||||
{ "aes_AES", test_crypto_aes, TT_FORK, &passthrough_setup, (void*)"aes" },
|
||||
{ "aes_EVP", test_crypto_aes, TT_FORK, &passthrough_setup, (void*)"evp" },
|
||||
|
Loading…
Reference in New Issue
Block a user