2 * sshrand.c: manage the global live PRNG instance.
\r
10 /* Collect environmental noise every 5 minutes */
\r
11 #define NOISE_REGULAR_INTERVAL (5*60*TICKSPERSEC)
\r
13 int random_active = 0;
\r
18 * Special dummy version of the RNG for use when fuzzing.
\r
20 void random_add_noise(NoiseSourceId source, const void *noise, int length) { }
\r
21 void random_ref(void) { }
\r
22 void random_setup_custom(const ssh_hashalg *hash) { }
\r
23 void random_unref(void) { }
\r
24 void random_read(void *out, size_t size)
\r
26 memset(out, 0x45, size); /* Chosen by eight fair coin tosses */
\r
28 void random_get_savedata(void **data, int *len) { }
\r
30 #else /* !FUZZING */
\r
32 /* Dummy structure for the sake of having something to expire_timer_context */
\r
33 static struct random_timer_context { int dummy; } random_timer_ctx;
\r
35 static prng *global_prng;
\r
36 static unsigned long next_noise_collection;
\r
38 void random_add_noise(NoiseSourceId source, const void *noise, int length)
\r
43 prng_add_entropy(global_prng, source, make_ptrlen(noise, length));
\r
46 static void random_timer(void *ctx, unsigned long now)
\r
48 if (random_active > 0 && now == next_noise_collection) {
\r
50 next_noise_collection =
\r
51 schedule_timer(NOISE_REGULAR_INTERVAL, random_timer,
\r
56 static void random_seed_callback(void *noise, int length)
\r
58 put_data(global_prng, noise, length);
\r
61 static void random_create(const ssh_hashalg *hashalg)
\r
63 assert(!global_prng);
\r
64 global_prng = prng_new(hashalg);
\r
66 prng_seed_begin(global_prng);
\r
67 noise_get_heavy(random_seed_callback);
\r
68 prng_seed_finish(global_prng);
\r
70 next_noise_collection =
\r
71 schedule_timer(NOISE_REGULAR_INTERVAL, random_timer,
\r
74 /* noise_get_heavy probably read our random seed file.
\r
75 * Therefore (in fact, even if it didn't), we should write a
\r
76 * fresh one, in case another instance of ourself starts up
\r
77 * before we finish, and also in case an attacker gets hold of
\r
78 * the seed data we used. */
\r
82 void random_save_seed(void)
\r
87 if (random_active) {
\r
88 random_get_savedata(&data, &len);
\r
89 write_random_seed(data, len);
\r
94 void random_ref(void)
\r
96 if (!random_active++)
\r
97 random_create(&ssh_sha256);
\r
100 void random_setup_custom(const ssh_hashalg *hash)
\r
103 random_create(hash);
\r
106 void random_reseed(ptrlen seed)
\r
108 prng_seed_begin(global_prng);
\r
109 put_datapl(global_prng, seed);
\r
110 prng_seed_finish(global_prng);
\r
113 void random_clear(void)
\r
116 random_save_seed();
\r
117 expire_timer_context(&random_timer_ctx);
\r
118 prng_free(global_prng);
\r
119 global_prng = NULL;
\r
124 void random_unref(void)
\r
126 assert(random_active > 0);
\r
127 if (--random_active == 0)
\r
131 void random_read(void *buf, size_t size)
\r
133 assert(random_active > 0);
\r
134 prng_read(global_prng, buf, size);
\r
137 void random_get_savedata(void **data, int *len)
\r
139 void *buf = snewn(global_prng->savesize, char);
\r
140 random_read(buf, global_prng->savesize);
\r
141 *len = global_prng->savesize;
\r
145 size_t random_seed_bits(void)
\r
147 assert(random_active > 0);
\r
148 return prng_seed_bits(global_prng);
\r
151 #endif /* FUZZING */
\r