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 csprng_reseed(state);
158 KKASSERT(state->reseed_cnt >= 0);
160 if (state->reseed_cnt == 0) {
161 STATE_SLEEP(state, "csprngrsd", 0);
166 /* Limit amount of output without rekeying to 2^20 */
167 cnt = (bytes > (1 << 20)) ? (1 << 20) : bytes;
169 encrypt_bytes(state, out, out, cnt);
171 /* Update key and rekey cipher */
172 encrypt_bytes(state, state->key, state->key, sizeof(state->key));
173 chacha_keysetup(&state->cipher_ctx, state->key,
174 8*sizeof(state->key));
188 csprng_reseed(struct csprng_state *state)
191 struct csprng_pool *pool;
193 uint8_t digest[SHA256_DIGEST_LENGTH];
196 * If there's not enough entropy in the first
197 * pool, don't reseed.
199 if (state->pool[0].bytes < MIN_POOL_SIZE) {
200 ++state->failed_reseeds;
204 SHA256_Init(&hash_ctx);
207 * Update hash that will result in new key with the
210 SHA256_Update(&hash_ctx, state->key, sizeof(state->key));
214 for (i = 0; i < 32; i++) {
215 if ((state->reseed_cnt % (1 << i)) != 0)
218 pool = &state->pool[i];
222 * Finalize hash of the entropy in this pool.
224 SHA256_Final(digest, &pool->hash_ctx);
227 * Reinitialize pool with a hash of the old pool digest.
228 * This is a slight deviation from Fortuna as per reference,
229 * but is in line with other Fortuna implementations.
231 csprng_pool_init(pool, digest, sizeof(digest));
236 * Update hash that will result in new key with this
237 * pool's hashed entropy.
239 SHA256_Update(&hash_ctx, digest, sizeof(digest));
242 SHA256_Final(state->key, &hash_ctx);
244 /* Update key and rekey cipher */
245 chacha_keysetup(&state->cipher_ctx, state->key,
246 8*sizeof(state->key));
248 /* Increment the nonce if the counter overflows */
249 if (chacha_incr_counter(&state->cipher_ctx)) {
251 chacha_ivsetup(&state->cipher_ctx, (const uint8_t *)&state->nonce);
259 csprng_reseed_callout(void *arg)
261 struct csprng_state *state = (struct csprng_state *)arg;
262 int reseed_interval = MIN_RESEED_INTERVAL;
271 callout_reset(&state->reseed_callout, reseed_interval,
272 csprng_reseed_callout, state);
276 csprng_add_entropy(struct csprng_state *state, int src_id,
277 const uint8_t *entropy, size_t bytes, int flags)
279 struct csprng_pool *pool;
283 * Pick the next pool for this source on a round-robin
287 pool_id = state->src_pool_idx[src_id]++ & 0x1f;
288 pool = &state->pool[pool_id];
290 if (flags & CSPRNG_TRYLOCK) {
292 * If we are asked to just try the lock instead
293 * of spinning until we get it, return if we
294 * can't get a hold of the lock right now.
296 if (!POOL_TRYLOCK(pool))
302 SHA256_Update(&pool->hash_ctx, (const uint8_t *)&src_id, sizeof(src_id));
303 SHA256_Update(&pool->hash_ctx, (const uint8_t *)&bytes, sizeof(bytes));
304 SHA256_Update(&pool->hash_ctx, entropy, bytes);
306 pool->bytes += bytes;
311 * If a wakeup is missed, it doesn't matter too much - it'll get woken
312 * up by the next add_entropy() call.