2 * Copyright (c) 2014 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Alex Hornung <alex@alexhornung.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #include <sys/spinlock.h>
38 #include <sys/spinlock2.h>
39 #include <sys/csprng.h>
42 * Minimum amount of bytes in pool before we consider it
44 * It's 64 + the hash digest size because we always
45 * reinitialize the pools with a hash of the previous chunk
48 #define MIN_POOL_SIZE 64 + SHA256_DIGEST_LENGTH
50 /* Minimum reseed interval */
51 #define MIN_RESEED_INTERVAL hz/10
54 #define POOL_LOCK_INIT(pool) \
55 spin_init(&(pool)->lock, "csprng_poollock")
57 #define POOL_LOCK(pool) \
58 spin_lock(&pool->lock)
60 #define POOL_TRYLOCK(pool) \
61 spin_trylock(&pool->lock)
63 #define POOL_UNLOCK(pool) \
64 spin_unlock(&pool->lock)
67 #define STATE_LOCK_INIT(state) \
68 spin_init(&state->lock, "csprng_statelock")
70 #define STATE_LOCK(state) \
71 spin_lock(&state->lock)
73 #define STATE_UNLOCK(state) \
74 spin_unlock(&state->lock)
76 #define STATE_SLEEP(state, wmesg, timo) \
77 ssleep(state, &state->lock, 0, wmesg, timo)
79 #define STATE_WAKEUP(state) \
82 static void csprng_reseed_callout(void *arg
);
83 static int csprng_reseed(struct csprng_state
*state
);
85 static struct timeval csprng_reseed_interval
= { 0, 100000 };
89 csprng_pool_init(struct csprng_pool
*pool
, uint8_t *buf
, size_t len
)
92 SHA256_Init(&pool
->hash_ctx
);
95 SHA256_Update(&pool
->hash_ctx
, buf
, len
);
101 csprng_init(struct csprng_state
*state
)
105 bzero(state
->key
, sizeof(state
->key
));
106 bzero(&state
->cipher_ctx
, sizeof(state
->cipher_ctx
));
107 bzero(state
->src_pool_idx
, sizeof(state
->src_pool_idx
));
108 bzero(&state
->last_reseed
, sizeof(state
->last_reseed
));
112 state
->reseed_cnt
= 0;
113 state
->failed_reseeds
= 0;
114 state
->callout_based_reseed
= 0;
116 STATE_LOCK_INIT(state
);
118 for (i
= 0; i
< 32; i
++) {
119 r
= csprng_pool_init(&state
->pool
[i
], NULL
, 0);
122 POOL_LOCK_INIT(&state
->pool
[i
]);
129 csprng_init_reseed(struct csprng_state
*state
)
131 state
->callout_based_reseed
= 1;
133 callout_init_mp(&state
->reseed_callout
);
134 callout_reset(&state
->reseed_callout
, MIN_RESEED_INTERVAL
,
135 csprng_reseed_callout
, state
);
142 * Sources don't really a uniquely-allocated src id...
143 * another way we could do that is by simply using
144 * (uint8_t)__LINE__ as the source id... cheap & cheerful.
149 encrypt_bytes(struct csprng_state
*state
, uint8_t *out
, uint8_t *in
, size_t bytes
)
151 /* Update nonce whenever the counter is about to overflow */
152 if (chacha_check_counter(&state
->cipher_ctx
)) {
154 chacha_ivsetup(&state
->cipher_ctx
, (const uint8_t *)&state
->nonce
);
157 chacha_encrypt_bytes(&state
->cipher_ctx
, in
, out
, (uint32_t)bytes
);
163 * XXX: flags is currently unused, but could be used to know whether
164 * it's a /dev/random or /dev/urandom read, and make sure that
165 * enough entropy has been collected recently, etc.
168 csprng_get_random(struct csprng_state
*state
, uint8_t *out
, int bytes
,
175 * XXX: can optimize a bit by digging into chacha_encrypt_bytes
176 * and removing the xor of the stream with the input - that
177 * way we don't have to xor the output (which we provide
185 if (!state
->callout_based_reseed
&&
186 ratecheck(&state
->last_reseed
, &csprng_reseed_interval
)) {
187 csprng_reseed(state
);
191 * If no reseed has occurred yet, we can't possibly give out
193 * Sleep until entropy is added to the pools (or a callout-based
194 * reseed, if enabled, occurs).
196 if (state
->reseed_cnt
== 0) {
197 STATE_SLEEP(state
, "csprngrsd", 0);
202 /* Limit amount of output without rekeying to 2^20 */
203 cnt
= (bytes
> (1 << 20)) ? (1 << 20) : bytes
;
205 encrypt_bytes(state
, out
, out
, cnt
);
207 /* Update key and rekey cipher */
208 encrypt_bytes(state
, state
->key
, state
->key
, sizeof(state
->key
));
209 chacha_keysetup(&state
->cipher_ctx
, state
->key
,
210 8*sizeof(state
->key
));
224 csprng_reseed(struct csprng_state
*state
)
227 struct csprng_pool
*pool
;
229 uint8_t digest
[SHA256_DIGEST_LENGTH
];
232 * If there's not enough entropy in the first
233 * pool, don't reseed.
235 if (state
->pool
[0].bytes
< MIN_POOL_SIZE
) {
236 ++state
->failed_reseeds
;
240 SHA256_Init(&hash_ctx
);
243 * Update hash that will result in new key with the
246 SHA256_Update(&hash_ctx
, state
->key
, sizeof(state
->key
));
250 for (i
= 0; i
< 32; i
++) {
251 if ((state
->reseed_cnt
% (1 << i
)) != 0)
254 pool
= &state
->pool
[i
];
258 * Finalize hash of the entropy in this pool.
260 SHA256_Final(digest
, &pool
->hash_ctx
);
263 * Reinitialize pool with a hash of the old pool digest.
264 * This is a slight deviation from Fortuna as per reference,
265 * but is in line with other Fortuna implementations.
267 csprng_pool_init(pool
, digest
, sizeof(digest
));
272 * Update hash that will result in new key with this
273 * pool's hashed entropy.
275 SHA256_Update(&hash_ctx
, digest
, sizeof(digest
));
278 SHA256_Final(state
->key
, &hash_ctx
);
280 /* Update key and rekey cipher */
281 chacha_keysetup(&state
->cipher_ctx
, state
->key
,
282 8*sizeof(state
->key
));
284 /* Increment the nonce if the counter overflows */
285 if (chacha_incr_counter(&state
->cipher_ctx
)) {
287 chacha_ivsetup(&state
->cipher_ctx
, (const uint8_t *)&state
->nonce
);
295 csprng_reseed_callout(void *arg
)
297 struct csprng_state
*state
= (struct csprng_state
*)arg
;
298 int reseed_interval
= MIN_RESEED_INTERVAL
;
307 callout_reset(&state
->reseed_callout
, reseed_interval
,
308 csprng_reseed_callout
, state
);
312 csprng_add_entropy(struct csprng_state
*state
, int src_id
,
313 const uint8_t *entropy
, size_t bytes
, int flags
)
315 struct csprng_pool
*pool
;
319 * Pick the next pool for this source on a round-robin
323 pool_id
= state
->src_pool_idx
[src_id
]++ & 0x1f;
324 pool
= &state
->pool
[pool_id
];
326 if (flags
& CSPRNG_TRYLOCK
) {
328 * If we are asked to just try the lock instead
329 * of spinning until we get it, return if we
330 * can't get a hold of the lock right now.
332 if (!POOL_TRYLOCK(pool
))
338 SHA256_Update(&pool
->hash_ctx
, (const uint8_t *)&src_id
, sizeof(src_id
));
339 SHA256_Update(&pool
->hash_ctx
, (const uint8_t *)&bytes
, sizeof(bytes
));
340 SHA256_Update(&pool
->hash_ctx
, entropy
, bytes
);
342 pool
->bytes
+= bytes
;
347 * If a wakeup is missed, it doesn't matter too much - it'll get woken
348 * up by the next add_entropy() call.