From dfddd1381b45b893998a3123ffde2219142c105a Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Wed, 19 Feb 2020 19:12:59 +0000 Subject: [PATCH] testcrypt: allow random_read() to use a full PRNG. This still isn't the true random generator used in the live tools: it's deterministic, for repeatable testing. The Python side of testcrypt can now call random_make_prng(), which will instantiate a PRNG with the given seed. random_clear() still gets rid of it. So I can still have some tests control the precise random numbers received by the function under test, but for others (especially key generation, with its uncertainty about how much randomness it will actually use) I can just say 'here, have a seed, generate as much stuff from that seed as you need'. --- test/cryptsuite.py | 6 ++++++ testcrypt.c | 24 ++++++++++++++++++++++-- testcrypt.h | 1 + 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/test/cryptsuite.py b/test/cryptsuite.py index 02f77d56..e6f638d6 100755 --- a/test/cryptsuite.py +++ b/test/cryptsuite.py @@ -103,6 +103,12 @@ def queued_specific_random_data(data): yield None random_clear() +@contextlib.contextmanager +def random_prng(seed): + random_make_prng('sha256', seed) + yield None + random_clear() + def hash_str(alg, message): h = ssh_hash_new(alg) ssh_hash_update(h, message) diff --git a/testcrypt.c b/testcrypt.c index 94d9baaf..e01ed606 100644 --- a/testcrypt.c +++ b/testcrypt.c @@ -55,10 +55,15 @@ static bool old_keyfile_warning_given; void old_keyfile_warning(void) { old_keyfile_warning_given = true; } static bufchain random_data_queue; +static prng *test_prng; void random_read(void *buf, size_t size) { - if (!bufchain_try_fetch_consume(&random_data_queue, buf, size)) - fatal_error("No random data in queue"); + if (test_prng) { + prng_read(test_prng, buf, size); + } else { + if (!bufchain_try_fetch_consume(&random_data_queue, buf, size)) + fatal_error("No random data in queue"); + } } uint64_t prng_reseed_time_ms(void) @@ -673,9 +678,24 @@ static size_t random_queue_len(void) static void random_clear(void) { + if (test_prng) { + prng_free(test_prng); + test_prng = NULL; + } + bufchain_clear(&random_data_queue); } +static void random_make_prng(const ssh_hashalg *hashalg, ptrlen seed) +{ + random_clear(); + + test_prng = prng_new(hashalg); + prng_seed_begin(test_prng); + put_datapl(test_prng, seed); + prng_seed_finish(test_prng); +} + mp_int *monty_identity_wrapper(MontyContext *mc) { return mp_copy(monty_identity(mc)); diff --git a/testcrypt.h b/testcrypt.h index 2fec0ba2..4ed190af 100644 --- a/testcrypt.h +++ b/testcrypt.h @@ -290,4 +290,5 @@ FUNC2(boolean, crcda_detect, val_string_ptrlen, val_string_ptrlen) */ FUNC1(void, random_queue, val_string_ptrlen) FUNC0(uint, random_queue_len) +FUNC2(void, random_make_prng, hashalg, val_string_ptrlen) FUNC0(void, random_clear)