3 #include <sys/kernel.h>
4 #include <sys/spinlock.h>
5 #include <sys/spinlock2.h>
6 #include <sys/csprng.h>
9 * Minimum amount of bytes in pool before we consider it
11 * It's 64 + the hash digest size because we always
12 * reinitialize the pools with a hash of the previous chunk
15 #define MIN_POOL_SIZE 64 + SHA256_DIGEST_LENGTH
17 /* Minimum reseed interval */
18 #define MIN_RESEED_INTERVAL hz/10
21 #define POOL_LOCK_INIT(pool) \
22 spin_init(&(pool)->lock)
24 #define POOL_LOCK(pool) \
25 spin_lock(&pool->lock)
27 #define POOL_TRYLOCK(pool) \
28 spin_trylock(&pool->lock)
30 #define POOL_UNLOCK(pool) \
31 spin_unlock(&pool->lock)
34 #define STATE_LOCK_INIT(state) \
35 spin_init(&state->lock)
37 #define STATE_LOCK(state) \
38 spin_lock(&state->lock)
40 #define STATE_UNLOCK(state) \
41 spin_unlock(&state->lock)
43 #define STATE_SLEEP(state, wmesg, timo) \
44 ssleep(state, &state->lock, 0, wmesg, timo)
46 #define STATE_WAKEUP(state) \
49 static void csprng_reseed_callout(void *arg);
50 static int csprng_reseed(struct csprng_state *state);
52 static struct timeval csprng_reseed_interval = { 0, 100000 };
56 csprng_pool_init(struct csprng_pool *pool, uint8_t *buf, size_t len)
59 SHA256_Init(&pool->hash_ctx);
62 SHA256_Update(&pool->hash_ctx, buf, len);
68 csprng_init(struct csprng_state *state)
72 bzero(state->key, sizeof(state->key));
73 bzero(&state->cipher_ctx, sizeof(state->cipher_ctx));
74 bzero(state->src_pool_idx, sizeof(state->src_pool_idx));
75 bzero(&state->last_reseed, sizeof(state->last_reseed));
79 state->reseed_cnt = 0;
80 state->failed_reseeds = 0;
81 state->callout_based_reseed = 0;
83 STATE_LOCK_INIT(state);
85 for (i = 0; i < 32; i++) {
86 r = csprng_pool_init(&state->pool[i], NULL, 0);
89 POOL_LOCK_INIT(&state->pool[i]);
96 csprng_init_reseed(struct csprng_state *state)
98 state->callout_based_reseed = 1;
100 callout_init_mp(&state->reseed_callout);
101 callout_reset(&state->reseed_callout, MIN_RESEED_INTERVAL,
102 csprng_reseed_callout, state);
109 * Sources don't really a uniquely-allocated src id...
110 * another way we could do that is by simply using
111 * (uint8_t)__LINE__ as the source id... cheap & cheerful.
116 encrypt_bytes(struct csprng_state *state, uint8_t *out, uint8_t *in, size_t bytes)
118 /* Update nonce whenever the counter is about to overflow */
119 if (chacha_check_counter(&state->cipher_ctx)) {
121 chacha_ivsetup(&state->cipher_ctx, (const uint8_t *)&state->nonce);
124 chacha_encrypt_bytes(&state->cipher_ctx, in, out, (uint32_t)bytes);
130 * XXX: flags is currently unused, but could be used to know whether
131 * it's a /dev/random or /dev/urandom read, and make sure that
132 * enough entropy has been collected recently, etc.
135 csprng_get_random(struct csprng_state *state, uint8_t *out, int bytes,
143 * XXX: can optimize a bit by digging into chacha_encrypt_bytes
144 * and removing the xor of the stream with the input - that
145 * way we don't have to xor the output (which we provide
153 if (!state->callout_based_reseed &&
154 ratecheck(&state->last_reseed, &csprng_reseed_interval)) {
155 if ((r = csprng_reseed(state)) != 0) {
156 STATE_SLEEP(state, "csprngrsd", 0);
161 KKASSERT(state->reseed_cnt >= 0);
163 if (state->reseed_cnt == 0) {
164 STATE_SLEEP(state, "csprngrsd", 0);
169 /* Limit amount of output without rekeying to 2^20 */
170 cnt = (bytes > (1 << 20)) ? (1 << 20) : bytes;
172 encrypt_bytes(state, out, out, cnt);
174 /* Update key and rekey cipher */
175 encrypt_bytes(state, state->key, state->key, sizeof(state->key));
176 chacha_keysetup(&state->cipher_ctx, state->key,
177 8*sizeof(state->key));
191 csprng_reseed(struct csprng_state *state)
194 struct csprng_pool *pool;
196 uint8_t digest[SHA256_DIGEST_LENGTH];
199 * If there's not enough entropy in the first
200 * pool, don't reseed.
202 if (state->pool[0].bytes < MIN_POOL_SIZE) {
203 ++state->failed_reseeds;
207 SHA256_Init(&hash_ctx);
210 * Update hash that will result in new key with the
213 SHA256_Update(&hash_ctx, state->key, sizeof(state->key));
217 for (i = 0; i < 32; i++) {
218 if ((state->reseed_cnt % (1 << i)) != 0)
221 pool = &state->pool[i];
225 * Finalize hash of the entropy in this pool.
227 SHA256_Final(digest, &pool->hash_ctx);
230 * Reinitialize pool with a hash of the old pool digest.
231 * This is a slight deviation from Fortuna as per reference,
232 * but is in line with other Fortuna implementations.
234 csprng_pool_init(pool, digest, sizeof(digest));
239 * Update hash that will result in new key with this
240 * pool's hashed entropy.
242 SHA256_Update(&hash_ctx, digest, sizeof(digest));
245 SHA256_Final(state->key, &hash_ctx);
247 /* Update key and rekey cipher */
248 chacha_keysetup(&state->cipher_ctx, state->key,
249 8*sizeof(state->key));
251 /* Increment the nonce if the counter overflows */
252 if (chacha_incr_counter(&state->cipher_ctx)) {
254 chacha_ivsetup(&state->cipher_ctx, (const uint8_t *)&state->nonce);
262 csprng_reseed_callout(void *arg)
264 struct csprng_state *state = (struct csprng_state *)arg;
265 int reseed_interval = MIN_RESEED_INTERVAL;
274 callout_reset(&state->reseed_callout, reseed_interval,
275 csprng_reseed_callout, state);
279 csprng_add_entropy(struct csprng_state *state, int src_id,
280 const uint8_t *entropy, size_t bytes, int flags)
282 struct csprng_pool *pool;
286 * Pick the next pool for this source on a round-robin
290 pool_id = state->src_pool_idx[src_id]++ & 0x1f;
291 pool = &state->pool[pool_id];
293 if (flags & CSPRNG_TRYLOCK) {
295 * If we are asked to just try the lock instead
296 * of spinning until we get it, return if we
297 * can't get a hold of the lock right now.
299 if (!POOL_TRYLOCK(pool))
305 SHA256_Update(&pool->hash_ctx, (const uint8_t *)&src_id, sizeof(src_id));
306 SHA256_Update(&pool->hash_ctx, (const uint8_t *)&bytes, sizeof(bytes));
307 SHA256_Update(&pool->hash_ctx, entropy, bytes);
309 pool->bytes += bytes;
314 * If a wakeup is missed, it doesn't matter too much - it'll get woken
315 * up by the next add_entropy() call.