X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/putty/blobdiff_plain/bc0e1c6cb91cbf8bed2ba44e44c5e46209524e90..3980e64ffbb86a37d6810b004a04a21f338a408b:/sshrand.c diff --git a/sshrand.c b/sshrand.c index a7b3dc4e..c26fc757 100644 --- a/sshrand.c +++ b/sshrand.c @@ -4,6 +4,10 @@ #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)); @@ -37,10 +41,17 @@ struct RandPool { unsigned char incomingb[HASHINPUT]; int incomingpos; + + int stir_pending; }; static struct RandPool pool; int random_active = 0; +long next_noise_collection; + +#ifdef RANDOM_DIAGNOSTICS +int random_diagnostics = 0; +#endif static void random_stir(void) { @@ -48,8 +59,40 @@ static void random_stir(void) 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); +#ifdef RANDOM_DIAGNOSTICS + { + int p, q; + printf("random stir starting\npool:\n"); + for (p = 0; p < POOLSIZE; p += HASHSIZE) { + printf(" "); + for (q = 0; q < HASHSIZE; q += 4) { + printf(" %08x", *(word32 *)(pool.pool + p + q)); + } + printf("\n"); + } + printf("incoming:\n "); + for (q = 0; q < HASHSIZE; q += 4) { + printf(" %08x", *(word32 *)(pool.incoming + q)); + } + printf("\nincomingb:\n "); + for (q = 0; q < HASHINPUT; q += 4) { + printf(" %08x", *(word32 *)(pool.incomingb + q)); + } + printf("\n"); + random_diagnostics++; + } +#endif + SHATransform((word32 *) pool.incoming, (word32 *) pool.incomingb); pool.incomingpos = 0; @@ -101,6 +144,29 @@ static void random_stir(void) for (k = 0; k < sizeof(digest) / sizeof(*digest); k++) ((word32 *) (pool.pool + j))[k] = digest[k]; } + +#ifdef RANDOM_DIAGNOSTICS + if (i == 0) { + int p, q; + printf("random stir midpoint\npool:\n"); + for (p = 0; p < POOLSIZE; p += HASHSIZE) { + printf(" "); + for (q = 0; q < HASHSIZE; q += 4) { + printf(" %08x", *(word32 *)(pool.pool + p + q)); + } + printf("\n"); + } + printf("incoming:\n "); + for (q = 0; q < HASHSIZE; q += 4) { + printf(" %08x", *(word32 *)(pool.incoming + q)); + } + printf("\nincomingb:\n "); + for (q = 0; q < HASHINPUT; q += 4) { + printf(" %08x", *(word32 *)(pool.incomingb + q)); + } + printf("\n"); + } +#endif } /* @@ -111,6 +177,32 @@ static void random_stir(void) memcpy(pool.incoming, digest, sizeof(digest)); pool.poolpos = sizeof(pool.incoming); + + pool.stir_pending = FALSE; + +#ifdef RANDOM_DIAGNOSTICS + { + int p, q; + printf("random stir done\npool:\n"); + for (p = 0; p < POOLSIZE; p += HASHSIZE) { + printf(" "); + for (q = 0; q < HASHSIZE; q += 4) { + printf(" %08x", *(word32 *)(pool.pool + p + q)); + } + printf("\n"); + } + printf("incoming:\n "); + for (q = 0; q < HASHSIZE; q += 4) { + printf(" %08x", *(word32 *)(pool.incoming + q)); + } + printf("\nincomingb:\n "); + for (q = 0; q < HASHINPUT; q += 4) { + printf(" %08x", *(word32 *)(pool.incomingb + q)); + } + printf("\n"); + random_diagnostics--; + } +#endif } void random_add_noise(void *noise, int length) @@ -182,20 +274,44 @@ 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) { if (!random_active) { memset(&pool, 0, sizeof(pool)); /* just to start with */ - random_active = 1; + random_active++; noise_get_heavy(random_add_heavynoise_bitbybit); random_stir(); + + next_noise_collection = + schedule_timer(NOISE_REGULAR_INTERVAL, random_timer, &pool); } } +void random_unref(void) +{ + assert(random_active > 0); + if (random_active == 1) { + random_save_seed(); + expire_timer_context(&pool); + } + random_active--; +} + int random_byte(void) { + assert(random_active); + if (pool.poolpos >= POOLSIZE) random_stir();