X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/putty/blobdiff_plain/93b581bd031b2270deb7f45440e61a1044fe94da..e99bb8bfc8d2c1a47b6ae90ef43683d191c30f66:/sshrand.c diff --git a/sshrand.c b/sshrand.c index 7c401af4..4c33f4a0 100644 --- a/sshrand.c +++ b/sshrand.c @@ -2,7 +2,12 @@ * cryptographic random number generator for PuTTY's ssh client */ +#include "putty.h" #include "ssh.h" +#include + +/* Collect environmental noise every 5 minutes */ +#define NOISE_REGULAR_INTERVAL (5*60*TICKSPERSEC) void noise_get_heavy(void (*func) (void *, int)); void noise_get_light(void (*func) (void *, int)); @@ -36,17 +41,28 @@ struct RandPool { unsigned char incomingb[HASHINPUT]; int incomingpos; + + int stir_pending; }; static struct RandPool pool; int random_active = 0; +long next_noise_collection; -void random_stir(void) +static void random_stir(void) { word32 block[HASHINPUT / sizeof(word32)]; word32 digest[HASHSIZE / sizeof(word32)]; int i, j, k; + /* + * noise_get_light will call random_add_noise, which may call + * back to here. Prevent recursive stirs. + */ + if (pool.stir_pending) + return; + pool.stir_pending = TRUE; + noise_get_light(random_add_noise); SHATransform((word32 *) pool.incoming, (word32 *) pool.incomingb); @@ -110,6 +126,8 @@ void random_stir(void) memcpy(pool.incoming, digest, sizeof(digest)); pool.poolpos = sizeof(pool.incoming); + + pool.stir_pending = FALSE; } void random_add_noise(void *noise, int length) @@ -181,14 +199,37 @@ static void random_add_heavynoise_bitbybit(void *noise, int length) pool.poolpos = i; } -void random_init(void) +static void random_timer(void *ctx, unsigned long now) +{ + if (random_active > 0 && now == next_noise_collection) { + noise_regular(); + next_noise_collection = + schedule_timer(NOISE_REGULAR_INTERVAL, random_timer, &pool); + } +} + +void random_ref(void) { - memset(&pool, 0, sizeof(pool)); /* just to start with */ + if (!random_active) { + memset(&pool, 0, sizeof(pool)); /* just to start with */ - random_active = 1; + noise_get_heavy(random_add_heavynoise_bitbybit); + random_stir(); - noise_get_heavy(random_add_heavynoise_bitbybit); - random_stir(); + next_noise_collection = + schedule_timer(NOISE_REGULAR_INTERVAL, random_timer, &pool); + } + + random_active++; +} + +void random_unref(void) +{ + random_active--; + assert(random_active >= 0); + if (random_active) return; + + expire_timer_context(&pool); } int random_byte(void) @@ -201,7 +242,10 @@ int random_byte(void) void random_get_savedata(void **data, int *len) { + void *buf = snewn(POOLSIZE / 2, char); random_stir(); - *data = pool.pool + pool.poolpos; + memcpy(buf, pool.pool + pool.poolpos, POOLSIZE / 2); *len = POOLSIZE / 2; + *data = buf; + random_stir(); }