From 22131a51fa9790fb57dc9d6cf783535e85e6edc8 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sun, 10 Feb 2019 13:43:14 +0000 Subject: [PATCH] Windows PuTTYgen: bound entropy input by PRNG state size. Although I've reinstated the tedious manual mouse input, I can at least reduce the amount of it that the user is required to provide: the new PRNG has a hard limit on the size of its seed, so once we've generated enough entropy to fill that up, there's no point in collecting more, even if we're generating a particularly large key. --- putty.h | 2 ++ ssh.h | 1 + sshprng.c | 6 ++++++ sshrand.c | 6 ++++++ windows/winpgen.c | 6 ++++++ 5 files changed, 21 insertions(+) diff --git a/putty.h b/putty.h index 0726d057..975b4504 100644 --- a/putty.h +++ b/putty.h @@ -1709,6 +1709,8 @@ void random_setup_special(); /* Manually drop a random seed into the random number generator, e.g. * just before generating a key. */ void random_reseed(ptrlen seed); +/* Limit on how much entropy is worth putting into the generator (bits). */ +size_t random_seed_bits(void); /* * Exports from pinger.c. diff --git a/ssh.h b/ssh.h index 4445bed1..82539d5d 100644 --- a/ssh.h +++ b/ssh.h @@ -902,6 +902,7 @@ void prng_seed_begin(prng *p); void prng_seed_finish(prng *p); void prng_read(prng *p, void *vout, size_t size); void prng_add_entropy(prng *p, unsigned source_id, ptrlen data); +size_t prng_seed_bits(prng *p); /* This function must be implemented by the platform, and returns a * timer in milliseconds that the PRNG can use to know whether it's diff --git a/sshprng.c b/sshprng.c index ee1e0df2..ea40c99f 100644 --- a/sshprng.c +++ b/sshprng.c @@ -284,3 +284,9 @@ void prng_add_entropy(prng *pr, unsigned source_id, ptrlen data) prng_seed_finish(&pi->Prng); } } + +size_t prng_seed_bits(prng *pr) +{ + prng_impl *pi = container_of(pr, prng_impl, Prng); + return pi->hashalg->hlen * 8; +} diff --git a/sshrand.c b/sshrand.c index 292956e4..994c7cfc 100644 --- a/sshrand.c +++ b/sshrand.c @@ -123,4 +123,10 @@ void random_get_savedata(void **data, int *len) *data = buf; } +size_t random_seed_bits(void) +{ + assert(random_active > 0); + return prng_seed_bits(global_prng); +} + #endif /* FUZZING */ diff --git a/windows/winpgen.c b/windows/winpgen.c index 7f6a232a..818bc728 100644 --- a/windows/winpgen.c +++ b/windows/winpgen.c @@ -1166,6 +1166,12 @@ static INT_PTR CALLBACK MainDlgProc(HWND hwnd, UINT msg, else raw_entropy_required = 256; + /* Bound the entropy collection above by the amount of + * data we can actually fit into the PRNG. Any more + * than that and it's doing no more good. */ + if (raw_entropy_required > random_seed_bits()) + raw_entropy_required = random_seed_bits(); + raw_entropy_buf = snewn(raw_entropy_required, unsigned char); if (win_read_random(raw_entropy_buf, raw_entropy_required)) { /*