xref: /optee_os/core/crypto/rng_fortuna.c (revision cbda709118504f8b9b6812419d14f8360c40ad27)
16e954a6eSJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
26e954a6eSJens Wiklander /* Copyright (c) 2018, Linaro Limited */
36e954a6eSJens Wiklander 
46e954a6eSJens Wiklander /*
56e954a6eSJens Wiklander  * This is an implementation of the Fortuna cryptographic PRNG as defined in
66e954a6eSJens Wiklander  * https://www.schneier.com/academic/paperfiles/fortuna.pdf
76e954a6eSJens Wiklander  * There's one small exception, see comment in restart_pool() below.
86e954a6eSJens Wiklander  */
96e954a6eSJens Wiklander 
106e954a6eSJens Wiklander #include <assert.h>
116e954a6eSJens Wiklander #include <crypto/crypto.h>
126e954a6eSJens Wiklander #include <kernel/mutex.h>
136e954a6eSJens Wiklander #include <kernel/refcount.h>
146e954a6eSJens Wiklander #include <kernel/spinlock.h>
156e954a6eSJens Wiklander #include <kernel/tee_time.h>
166e954a6eSJens Wiklander #include <string.h>
176e954a6eSJens Wiklander #include <types_ext.h>
186e954a6eSJens Wiklander #include <utee_defines.h>
196e954a6eSJens Wiklander #include <util.h>
206e954a6eSJens Wiklander 
216e954a6eSJens Wiklander #define NUM_POOLS		32
226e954a6eSJens Wiklander #define BLOCK_SIZE		16
236e954a6eSJens Wiklander #define KEY_SIZE		32
246e954a6eSJens Wiklander #define CIPHER_ALGO		TEE_ALG_AES_ECB_NOPAD
256e954a6eSJens Wiklander #define HASH_ALGO		TEE_ALG_SHA256
266e954a6eSJens Wiklander #define MIN_POOL_SIZE		64
276e954a6eSJens Wiklander #define MAX_EVENT_DATA_LEN	32U
286e954a6eSJens Wiklander #define RING_BUF_DATA_SIZE	4U
296e954a6eSJens Wiklander 
306e954a6eSJens Wiklander /*
316e954a6eSJens Wiklander  * struct fortuna_state - state of the Fortuna PRNG
326e954a6eSJens Wiklander  * @ctx:		Cipher context used to produce the random numbers
336e954a6eSJens Wiklander  * @counter:		Counter which is encrypted to produce the random numbers
346e954a6eSJens Wiklander  * @pool0_length:	Amount of data added to pool0
356e954a6eSJens Wiklander  * @pool_ctx:		One hash context for each pool
366e954a6eSJens Wiklander  * @reseed_ctx:		Hash context used while reseeding
376e954a6eSJens Wiklander  * @reseed_count:	Number of time we've reseeded the PRNG, used to tell
386e954a6eSJens Wiklander  *			which pools should be used in the reseed process
396e954a6eSJens Wiklander  * @next_reseed_time:	If we have a secure time, the earliest next time we
406e954a6eSJens Wiklander  *			may reseed
416e954a6eSJens Wiklander  *
426e954a6eSJens Wiklander  * To minimize the delay in crypto_rng_add_event() there's @pool_spin_lock
436e954a6eSJens Wiklander  * which protects everything needed by this function.
446e954a6eSJens Wiklander  *
456e954a6eSJens Wiklander  * @next_reseed_time is used as a rate limiter for reseeding.
466e954a6eSJens Wiklander  */
476e954a6eSJens Wiklander static struct fortuna_state {
486e954a6eSJens Wiklander 	void *ctx;
496e954a6eSJens Wiklander 	uint64_t counter[2];
506e954a6eSJens Wiklander 	unsigned int pool0_length;
516e954a6eSJens Wiklander 	void *pool_ctx[NUM_POOLS];
526e954a6eSJens Wiklander 	void *reseed_ctx;
536e954a6eSJens Wiklander 	uint32_t reseed_count;
546e954a6eSJens Wiklander #ifndef CFG_SECURE_TIME_SOURCE_REE
556e954a6eSJens Wiklander 	TEE_Time next_reseed_time;
566e954a6eSJens Wiklander #endif
576e954a6eSJens Wiklander } state;
586e954a6eSJens Wiklander 
596e954a6eSJens Wiklander static struct mutex state_mu = MUTEX_INITIALIZER;
606e954a6eSJens Wiklander 
616e954a6eSJens Wiklander static struct {
626e954a6eSJens Wiklander 	struct {
636e954a6eSJens Wiklander 		uint8_t snum;
646e954a6eSJens Wiklander 		uint8_t pnum;
656e954a6eSJens Wiklander 		uint8_t dlen;
666e954a6eSJens Wiklander 		uint8_t data[RING_BUF_DATA_SIZE];
676e954a6eSJens Wiklander 	} elem[8];
686e954a6eSJens Wiklander 	unsigned int begin;
696e954a6eSJens Wiklander 	unsigned int end;
706e954a6eSJens Wiklander } ring_buffer;
716e954a6eSJens Wiklander 
726e954a6eSJens Wiklander unsigned int ring_buffer_spin_lock;
736e954a6eSJens Wiklander 
inc_counter(uint64_t counter[2])746e954a6eSJens Wiklander static void inc_counter(uint64_t counter[2])
756e954a6eSJens Wiklander {
766e954a6eSJens Wiklander 	counter[0]++;
776e954a6eSJens Wiklander 	if (!counter[0])
786e954a6eSJens Wiklander 		counter[1]++;
796e954a6eSJens Wiklander }
806e954a6eSJens Wiklander 
hash_init(void * ctx)816e954a6eSJens Wiklander static TEE_Result hash_init(void *ctx)
826e954a6eSJens Wiklander {
836b3a371cSJens Wiklander 	return crypto_hash_init(ctx);
846e954a6eSJens Wiklander }
856e954a6eSJens Wiklander 
hash_update(void * ctx,const void * data,size_t dlen)866e954a6eSJens Wiklander static TEE_Result hash_update(void *ctx, const void *data, size_t dlen)
876e954a6eSJens Wiklander {
886b3a371cSJens Wiklander 	return crypto_hash_update(ctx, data, dlen);
896e954a6eSJens Wiklander }
906e954a6eSJens Wiklander 
hash_final(void * ctx,uint8_t digest[KEY_SIZE])916e954a6eSJens Wiklander static TEE_Result hash_final(void *ctx, uint8_t digest[KEY_SIZE])
926e954a6eSJens Wiklander {
936b3a371cSJens Wiklander 	return crypto_hash_final(ctx, digest, KEY_SIZE);
946e954a6eSJens Wiklander }
956e954a6eSJens Wiklander 
key_from_data(void * ctx,const void * data,size_t dlen,uint8_t key[KEY_SIZE])966e954a6eSJens Wiklander static TEE_Result key_from_data(void *ctx, const void *data, size_t dlen,
976e954a6eSJens Wiklander 				uint8_t key[KEY_SIZE])
986e954a6eSJens Wiklander {
996e954a6eSJens Wiklander 	TEE_Result res;
1006e954a6eSJens Wiklander 
1016e954a6eSJens Wiklander 	res = hash_init(ctx);
1026e954a6eSJens Wiklander 	if (res)
1036e954a6eSJens Wiklander 		return res;
1046e954a6eSJens Wiklander 	res = hash_update(ctx, data, dlen);
1056e954a6eSJens Wiklander 	if (res)
1066e954a6eSJens Wiklander 		return res;
1076e954a6eSJens Wiklander 	return hash_final(ctx, key);
1086e954a6eSJens Wiklander }
1096e954a6eSJens Wiklander 
cipher_init(void * ctx,uint8_t key[KEY_SIZE])1106e954a6eSJens Wiklander static TEE_Result cipher_init(void *ctx, uint8_t key[KEY_SIZE])
1116e954a6eSJens Wiklander {
112*cbda7091SJens Wiklander 	return crypto_cipher_init(ctx, TEE_MODE_ENCRYPT,
1136e954a6eSJens Wiklander 				  key, KEY_SIZE, NULL, 0, NULL, 0);
1146e954a6eSJens Wiklander }
1156e954a6eSJens Wiklander 
fortuna_done(void)1166e954a6eSJens Wiklander static void fortuna_done(void)
1176e954a6eSJens Wiklander {
1186e954a6eSJens Wiklander 	size_t n;
1196e954a6eSJens Wiklander 
1206e954a6eSJens Wiklander 	for (n = 0; n < NUM_POOLS; n++) {
1216b3a371cSJens Wiklander 		crypto_hash_free_ctx(state.pool_ctx[n]);
1226e954a6eSJens Wiklander 		state.pool_ctx[n] = NULL;
1236e954a6eSJens Wiklander 	}
1246b3a371cSJens Wiklander 	crypto_hash_free_ctx(state.reseed_ctx);
1256e954a6eSJens Wiklander 	state.reseed_ctx = NULL;
126*cbda7091SJens Wiklander 	crypto_cipher_free_ctx(state.ctx);
1276e954a6eSJens Wiklander 	state.ctx = NULL;
1286e954a6eSJens Wiklander }
1296e954a6eSJens Wiklander 
crypto_rng_init(const void * data,size_t dlen)1306e954a6eSJens Wiklander TEE_Result crypto_rng_init(const void *data, size_t dlen)
1316e954a6eSJens Wiklander {
1326e954a6eSJens Wiklander 	TEE_Result res;
1336e954a6eSJens Wiklander 	uint8_t key[KEY_SIZE];
1346e954a6eSJens Wiklander 	void *ctx;
1356e954a6eSJens Wiklander 	size_t n;
1366e954a6eSJens Wiklander 
1376e954a6eSJens Wiklander 	COMPILE_TIME_ASSERT(sizeof(state.counter) == BLOCK_SIZE);
1386e954a6eSJens Wiklander 
1396e954a6eSJens Wiklander 	if (state.ctx)
1406e954a6eSJens Wiklander 		return TEE_ERROR_BAD_STATE;
1416e954a6eSJens Wiklander 
1426e954a6eSJens Wiklander 	memset(&state, 0, sizeof(state));
1436e954a6eSJens Wiklander 
1446e954a6eSJens Wiklander 	for (n = 0; n < NUM_POOLS; n++) {
1456e954a6eSJens Wiklander 		res = crypto_hash_alloc_ctx(&state.pool_ctx[n], HASH_ALGO);
1466e954a6eSJens Wiklander 		if (res)
1476e954a6eSJens Wiklander 			goto err;
1486b3a371cSJens Wiklander 		res = crypto_hash_init(state.pool_ctx[n]);
1496e954a6eSJens Wiklander 		if (res)
1506e954a6eSJens Wiklander 			goto err;
1516e954a6eSJens Wiklander 	}
1526e954a6eSJens Wiklander 
1536e954a6eSJens Wiklander 	res = crypto_hash_alloc_ctx(&state.reseed_ctx, HASH_ALGO);
1546e954a6eSJens Wiklander 	if (res)
1556e954a6eSJens Wiklander 		goto err;
1566e954a6eSJens Wiklander 
1576e954a6eSJens Wiklander 	res = key_from_data(state.reseed_ctx, data, dlen, key);
1586e954a6eSJens Wiklander 	if (res)
1596e954a6eSJens Wiklander 		return res;
1606e954a6eSJens Wiklander 
1616e954a6eSJens Wiklander 	res = crypto_cipher_alloc_ctx(&ctx, CIPHER_ALGO);
1626e954a6eSJens Wiklander 	if (res)
1636e954a6eSJens Wiklander 		return res;
1646e954a6eSJens Wiklander 	res = cipher_init(ctx, key);
1656e954a6eSJens Wiklander 	if (res)
1666e954a6eSJens Wiklander 		return res;
1676e954a6eSJens Wiklander 	inc_counter(state.counter);
1686e954a6eSJens Wiklander 	state.ctx = ctx;
1696e954a6eSJens Wiklander 	return TEE_SUCCESS;
1706e954a6eSJens Wiklander err:
1716e954a6eSJens Wiklander 	fortuna_done();
1726e954a6eSJens Wiklander 	return res;
1736e954a6eSJens Wiklander }
1746e954a6eSJens Wiklander 
push_ring_buffer(uint8_t snum,uint8_t pnum,const void * data,size_t dlen)1756e954a6eSJens Wiklander static void push_ring_buffer(uint8_t snum, uint8_t pnum, const void *data,
1766e954a6eSJens Wiklander 			     size_t dlen)
1776e954a6eSJens Wiklander {
1786e954a6eSJens Wiklander 	uint8_t dl = MIN(RING_BUF_DATA_SIZE, dlen);
1796e954a6eSJens Wiklander 	unsigned int next_begin;
1806e954a6eSJens Wiklander 	uint32_t old_itr_status;
1816e954a6eSJens Wiklander 
1826e954a6eSJens Wiklander 	/* Spinlock to serialize writers */
1836e954a6eSJens Wiklander 	old_itr_status = cpu_spin_lock_xsave(&ring_buffer_spin_lock);
1846e954a6eSJens Wiklander 
1856e954a6eSJens Wiklander 	next_begin = (ring_buffer.begin + 1) % ARRAY_SIZE(ring_buffer.elem);
1866e954a6eSJens Wiklander 	if (next_begin == atomic_load_uint(&ring_buffer.end))
1876e954a6eSJens Wiklander 		goto out; /* buffer is full */
1886e954a6eSJens Wiklander 
1896e954a6eSJens Wiklander 	ring_buffer.elem[next_begin].snum = snum;
1906e954a6eSJens Wiklander 	ring_buffer.elem[next_begin].pnum = pnum;
1916e954a6eSJens Wiklander 	ring_buffer.elem[next_begin].dlen = dl;
1926e954a6eSJens Wiklander 	memcpy(ring_buffer.elem[next_begin].data, data, dl);
1936e954a6eSJens Wiklander 
1946e954a6eSJens Wiklander 	atomic_store_uint(&ring_buffer.begin, next_begin);
1956e954a6eSJens Wiklander 
1966e954a6eSJens Wiklander out:
1976e954a6eSJens Wiklander 	cpu_spin_unlock_xrestore(&ring_buffer_spin_lock, old_itr_status);
1986e954a6eSJens Wiklander }
1996e954a6eSJens Wiklander 
pop_ring_buffer(uint8_t * snum,uint8_t * pnum,uint8_t data[RING_BUF_DATA_SIZE])2006e954a6eSJens Wiklander static size_t pop_ring_buffer(uint8_t *snum, uint8_t *pnum,
2016e954a6eSJens Wiklander 			      uint8_t data[RING_BUF_DATA_SIZE])
2026e954a6eSJens Wiklander {
2036e954a6eSJens Wiklander 	unsigned int next_end;
2046e954a6eSJens Wiklander 	size_t dlen;
2056e954a6eSJens Wiklander 
2066e954a6eSJens Wiklander 	if (atomic_load_uint(&ring_buffer.begin) == ring_buffer.end)
2076e954a6eSJens Wiklander 		return 0;
2086e954a6eSJens Wiklander 
2096e954a6eSJens Wiklander 	next_end = (ring_buffer.end + 1) % ARRAY_SIZE(ring_buffer.elem);
2106e954a6eSJens Wiklander 
2116e954a6eSJens Wiklander 	*snum = ring_buffer.elem[ring_buffer.end].snum;
2126e954a6eSJens Wiklander 	*pnum = ring_buffer.elem[ring_buffer.end].pnum;
2136e954a6eSJens Wiklander 	dlen = MIN(ring_buffer.elem[ring_buffer.end].dlen, RING_BUF_DATA_SIZE);
2146e954a6eSJens Wiklander 	assert(ring_buffer.elem[ring_buffer.end].dlen == dlen);
2156e954a6eSJens Wiklander 	memcpy(data, ring_buffer.elem[ring_buffer.end].data, dlen);
2166e954a6eSJens Wiklander 
2176e954a6eSJens Wiklander 	atomic_store_uint(&ring_buffer.end, next_end);
2186e954a6eSJens Wiklander 
2196e954a6eSJens Wiklander 	return dlen;
2206e954a6eSJens Wiklander }
2216e954a6eSJens Wiklander 
add_event(uint8_t snum,uint8_t pnum,const void * data,size_t dlen)2226e954a6eSJens Wiklander static TEE_Result add_event(uint8_t snum, uint8_t pnum,
2236e954a6eSJens Wiklander 			    const void *data, size_t dlen)
2246e954a6eSJens Wiklander {
2256e954a6eSJens Wiklander 	TEE_Result res;
2266e954a6eSJens Wiklander 	size_t dl = MIN(MAX_EVENT_DATA_LEN, dlen);
2276e954a6eSJens Wiklander 	uint8_t v[] = { snum, dl };
2286e954a6eSJens Wiklander 
2296e954a6eSJens Wiklander 	if (pnum >= NUM_POOLS)
2306e954a6eSJens Wiklander 		return TEE_ERROR_BAD_PARAMETERS;
2316e954a6eSJens Wiklander 
2326e954a6eSJens Wiklander 	res = hash_update(state.pool_ctx[pnum], v, sizeof(v));
2336e954a6eSJens Wiklander 	if (res)
2346e954a6eSJens Wiklander 		return res;
2356e954a6eSJens Wiklander 	res = hash_update(state.pool_ctx[pnum], data, dl);
2366e954a6eSJens Wiklander 	if (res)
2376e954a6eSJens Wiklander 		return res;
2386e954a6eSJens Wiklander 	if (!pnum) {
2396e954a6eSJens Wiklander 		unsigned int l;
2406e954a6eSJens Wiklander 
2416e954a6eSJens Wiklander 		if (!ADD_OVERFLOW(state.pool0_length, dl, &l))
2426e954a6eSJens Wiklander 			state.pool0_length = l;
2436e954a6eSJens Wiklander 	}
2446e954a6eSJens Wiklander 
2456e954a6eSJens Wiklander 	return TEE_SUCCESS;
2466e954a6eSJens Wiklander }
2476e954a6eSJens Wiklander 
drain_ring_buffer(void)2486e954a6eSJens Wiklander static TEE_Result drain_ring_buffer(void)
2496e954a6eSJens Wiklander {
2506e954a6eSJens Wiklander 	while (true) {
2516e954a6eSJens Wiklander 		TEE_Result res;
2526e954a6eSJens Wiklander 		uint8_t snum;
2536e954a6eSJens Wiklander 		uint8_t pnum;
2546e954a6eSJens Wiklander 		uint8_t data[RING_BUF_DATA_SIZE];
2556e954a6eSJens Wiklander 		size_t dlen;
2566e954a6eSJens Wiklander 
2576e954a6eSJens Wiklander 		dlen = pop_ring_buffer(&snum, &pnum, data);
2586e954a6eSJens Wiklander 		if (!dlen)
2596e954a6eSJens Wiklander 			return TEE_SUCCESS;
2606e954a6eSJens Wiklander 
2616e954a6eSJens Wiklander 		res = add_event(snum, pnum, data, dlen);
2626e954a6eSJens Wiklander 		if (res)
2636e954a6eSJens Wiklander 			return res;
2646e954a6eSJens Wiklander 	}
2656e954a6eSJens Wiklander }
2666e954a6eSJens Wiklander 
get_next_pnum(unsigned int * pnum)2676e954a6eSJens Wiklander static unsigned int get_next_pnum(unsigned int *pnum)
2686e954a6eSJens Wiklander {
2696e954a6eSJens Wiklander 	unsigned int nval;
2706e954a6eSJens Wiklander 	unsigned int oval = atomic_load_uint(pnum);
2716e954a6eSJens Wiklander 
2726e954a6eSJens Wiklander 	while (true) {
2736e954a6eSJens Wiklander 		nval = (oval + 1) % NUM_POOLS;
2746e954a6eSJens Wiklander 
2756e954a6eSJens Wiklander 		if (atomic_cas_uint(pnum, &oval, nval)) {
2766e954a6eSJens Wiklander 			/*
2776e954a6eSJens Wiklander 			 * *pnum is normally initialized to 0 and we'd like
2786e954a6eSJens Wiklander 			 * to start feeding pool number 0 as that's the
2796e954a6eSJens Wiklander 			 * most important one.
2806e954a6eSJens Wiklander 			 *
2816e954a6eSJens Wiklander 			 * If we where to take just *pnum and increase it
2826e954a6eSJens Wiklander 			 * later multiple updaters could end up with the
2836e954a6eSJens Wiklander 			 * same number.
2846e954a6eSJens Wiklander 			 *
2856e954a6eSJens Wiklander 			 * By increasing first we get the number unique for
2866e954a6eSJens Wiklander 			 * next update and by subtracting one (using
2876e954a6eSJens Wiklander 			 * modulus) we get the number for this update.
2886e954a6eSJens Wiklander 			 */
2896e954a6eSJens Wiklander 			return (nval + NUM_POOLS - 1) % NUM_POOLS;
2906e954a6eSJens Wiklander 		}
2916e954a6eSJens Wiklander 		/*
2926e954a6eSJens Wiklander 		 * At this point atomic_cas_uint() has updated oval to the
2936e954a6eSJens Wiklander 		 * current *pnum.
2946e954a6eSJens Wiklander 		 */
2956e954a6eSJens Wiklander 	}
2966e954a6eSJens Wiklander }
2976e954a6eSJens Wiklander 
crypto_rng_add_event(enum crypto_rng_src sid,unsigned int * pnum,const void * data,size_t dlen)2986e954a6eSJens Wiklander void crypto_rng_add_event(enum crypto_rng_src sid, unsigned int *pnum,
2996e954a6eSJens Wiklander 			  const void *data, size_t dlen)
3006e954a6eSJens Wiklander {
3016e954a6eSJens Wiklander 	unsigned int pn = get_next_pnum(pnum);
3026e954a6eSJens Wiklander 	uint8_t snum = sid >> 1;
3036e954a6eSJens Wiklander 
3046e954a6eSJens Wiklander 	if (CRYPTO_RNG_SRC_IS_QUICK(sid)) {
3056e954a6eSJens Wiklander 		push_ring_buffer(snum, pn, data, dlen);
3066e954a6eSJens Wiklander 	} else {
3076e954a6eSJens Wiklander 		mutex_lock(&state_mu);
3086e954a6eSJens Wiklander 		add_event(snum, pn, data, dlen);
3096e954a6eSJens Wiklander 		drain_ring_buffer();
3106e954a6eSJens Wiklander 		mutex_unlock(&state_mu);
3116e954a6eSJens Wiklander 	}
3126e954a6eSJens Wiklander }
3136e954a6eSJens Wiklander 
3146e954a6eSJens Wiklander /* GenerateBlocks */
generate_blocks(void * block,size_t nblocks)3156e954a6eSJens Wiklander static TEE_Result generate_blocks(void *block, size_t nblocks)
3166e954a6eSJens Wiklander {
3176e954a6eSJens Wiklander 	uint8_t *b = block;
3186e954a6eSJens Wiklander 	size_t n;
3196e954a6eSJens Wiklander 
3206e954a6eSJens Wiklander 	for (n = 0; n < nblocks; n++) {
321*cbda7091SJens Wiklander 		TEE_Result res = crypto_cipher_update(state.ctx,
3226e954a6eSJens Wiklander 						      TEE_MODE_ENCRYPT, false,
3236e954a6eSJens Wiklander 						      (void *)state.counter,
3246e954a6eSJens Wiklander 						      BLOCK_SIZE,
3256e954a6eSJens Wiklander 						      b + n * BLOCK_SIZE);
3266e954a6eSJens Wiklander 
3276e954a6eSJens Wiklander 		/*
3286e954a6eSJens Wiklander 		 * Make sure to increase the counter before returning an
3296e954a6eSJens Wiklander 		 * eventual errors, we must never re-use the counter with
3306e954a6eSJens Wiklander 		 * the same key.
3316e954a6eSJens Wiklander 		 */
3326e954a6eSJens Wiklander 		inc_counter(state.counter);
3336e954a6eSJens Wiklander 		if (res)
3346e954a6eSJens Wiklander 			return res;
3356e954a6eSJens Wiklander 	}
3366e954a6eSJens Wiklander 
3376e954a6eSJens Wiklander 	return TEE_SUCCESS;
3386e954a6eSJens Wiklander }
3396e954a6eSJens Wiklander 
3406e954a6eSJens Wiklander /* GenerateRandomData */
generate_random_data(void * buf,size_t blen)3416e954a6eSJens Wiklander static TEE_Result generate_random_data(void *buf, size_t blen)
3426e954a6eSJens Wiklander {
3436e954a6eSJens Wiklander 	TEE_Result res;
3446e954a6eSJens Wiklander 
3456e954a6eSJens Wiklander 	res = generate_blocks(buf, blen / BLOCK_SIZE);
3466e954a6eSJens Wiklander 	if (res)
3476e954a6eSJens Wiklander 		return res;
3486e954a6eSJens Wiklander 	if (blen % BLOCK_SIZE) {
3496e954a6eSJens Wiklander 		uint8_t block[BLOCK_SIZE];
3506e954a6eSJens Wiklander 		uint8_t *b = (uint8_t *)buf + ROUNDDOWN(blen, BLOCK_SIZE);
3516e954a6eSJens Wiklander 
3526e954a6eSJens Wiklander 		res = generate_blocks(block, 1);
3536e954a6eSJens Wiklander 		if (res)
3546e954a6eSJens Wiklander 			return res;
3556e954a6eSJens Wiklander 		memcpy(b, block, blen % BLOCK_SIZE);
3566e954a6eSJens Wiklander 	}
3576e954a6eSJens Wiklander 
3586e954a6eSJens Wiklander 	return TEE_SUCCESS;
3596e954a6eSJens Wiklander }
3606e954a6eSJens Wiklander 
3616e954a6eSJens Wiklander #ifdef CFG_SECURE_TIME_SOURCE_REE
reseed_rate_limiting(void)3626e954a6eSJens Wiklander static bool reseed_rate_limiting(void)
3636e954a6eSJens Wiklander {
3646e954a6eSJens Wiklander 	/*
3656e954a6eSJens Wiklander 	 * There's no point in checking REE time for reseed rate limiting,
3666e954a6eSJens Wiklander 	 * and also it makes it less complicated if we can avoid doing RPC
3676e954a6eSJens Wiklander 	 * here.
3686e954a6eSJens Wiklander 	 */
3696e954a6eSJens Wiklander 	return false;
3706e954a6eSJens Wiklander }
3716e954a6eSJens Wiklander #else
reseed_rate_limiting(void)3726e954a6eSJens Wiklander static bool reseed_rate_limiting(void)
3736e954a6eSJens Wiklander {
3746e954a6eSJens Wiklander 	TEE_Result res;
3756e954a6eSJens Wiklander 	TEE_Time time;
3766e954a6eSJens Wiklander 	const TEE_Time time_100ms = { 0, 100 };
3776e954a6eSJens Wiklander 
3786e954a6eSJens Wiklander 	res = tee_time_get_sys_time(&time);
3796e954a6eSJens Wiklander 	/*
3806e954a6eSJens Wiklander 	 * Failure to read time must result in allowing reseed or we could
3816e954a6eSJens Wiklander 	 * block reseeding forever.
3826e954a6eSJens Wiklander 	 */
3836e954a6eSJens Wiklander 	if (res)
3846e954a6eSJens Wiklander 		return false;
3856e954a6eSJens Wiklander 
3866e954a6eSJens Wiklander 	if (TEE_TIME_LT(time, state.next_reseed_time))
3876e954a6eSJens Wiklander 		return true;
3886e954a6eSJens Wiklander 
3896e954a6eSJens Wiklander 	/* Time to reseed, calculate next time reseed is OK */
3906e954a6eSJens Wiklander 	TEE_TIME_ADD(time, time_100ms, state.next_reseed_time);
3916e954a6eSJens Wiklander 	return false;
3926e954a6eSJens Wiklander }
3936e954a6eSJens Wiklander #endif
3946e954a6eSJens Wiklander 
restart_pool(void * pool_ctx,uint8_t pool_digest[KEY_SIZE])3956e954a6eSJens Wiklander static TEE_Result restart_pool(void *pool_ctx, uint8_t pool_digest[KEY_SIZE])
3966e954a6eSJens Wiklander {
3976e954a6eSJens Wiklander 	TEE_Result res = hash_final(pool_ctx, pool_digest);
3986e954a6eSJens Wiklander 
3996e954a6eSJens Wiklander 	if (res)
4006e954a6eSJens Wiklander 		return res;
4016e954a6eSJens Wiklander 
4026e954a6eSJens Wiklander 	res = hash_init(pool_ctx);
4036e954a6eSJens Wiklander 	if (res)
4046e954a6eSJens Wiklander 		return res;
4056e954a6eSJens Wiklander 
4066e954a6eSJens Wiklander 	/*
4076e954a6eSJens Wiklander 	 * Restart the pool with the digest of the old pool. This is an
4086e954a6eSJens Wiklander 	 * extension to Fortuna. In the original Fortuna all pools was
4096e954a6eSJens Wiklander 	 * restarted from scratch. This extension is one more defense
4106e954a6eSJens Wiklander 	 * against spamming of the pools with known data which could lead
4116e954a6eSJens Wiklander 	 * to the spammer knowing the state of the pools.
4126e954a6eSJens Wiklander 	 *
4136e954a6eSJens Wiklander 	 * This extra precaution could be useful since OP-TEE sometimes
4146e954a6eSJens Wiklander 	 * have very few sources of good entropy and at the same time has
4156e954a6eSJens Wiklander 	 * sources that could quite easily be predicted by an attacker.
4166e954a6eSJens Wiklander 	 */
4176e954a6eSJens Wiklander 	return hash_update(pool_ctx, pool_digest, KEY_SIZE);
4186e954a6eSJens Wiklander }
4196e954a6eSJens Wiklander 
reseed_from_pool(uint32_t reseed_count,size_t pool_num)4206e954a6eSJens Wiklander static bool reseed_from_pool(uint32_t reseed_count, size_t pool_num)
4216e954a6eSJens Wiklander {
4226e954a6eSJens Wiklander 	/*
4236e954a6eSJens Wiklander 	 * Specification says: use pool if
4246e954a6eSJens Wiklander 	 * 2^pool_num is a divisor of reseed_count
4256e954a6eSJens Wiklander 	 *
4266e954a6eSJens Wiklander 	 * in order to avoid an expensive modulus operation we're
4276e954a6eSJens Wiklander 	 * optimizing this below.
4286e954a6eSJens Wiklander 	 */
4296e954a6eSJens Wiklander 	return !pool_num || !((reseed_count >> (pool_num - 1)) & 1);
4306e954a6eSJens Wiklander }
4316e954a6eSJens Wiklander 
maybe_reseed(void)4326e954a6eSJens Wiklander static TEE_Result maybe_reseed(void)
4336e954a6eSJens Wiklander {
4346e954a6eSJens Wiklander 	TEE_Result res;
4356e954a6eSJens Wiklander 	size_t n;
4366e954a6eSJens Wiklander 	uint8_t pool_digest[KEY_SIZE];
4376e954a6eSJens Wiklander 
4386e954a6eSJens Wiklander 	if (state.pool0_length < MIN_POOL_SIZE)
4396e954a6eSJens Wiklander 		return TEE_SUCCESS;
4406e954a6eSJens Wiklander 
4416e954a6eSJens Wiklander 	if (reseed_rate_limiting())
4426e954a6eSJens Wiklander 		return TEE_SUCCESS;
4436e954a6eSJens Wiklander 
4446e954a6eSJens Wiklander 	state.reseed_count++;
4456e954a6eSJens Wiklander 
4466e954a6eSJens Wiklander 	res = hash_init(state.reseed_ctx);
4476e954a6eSJens Wiklander 	if (res)
4486e954a6eSJens Wiklander 		return res;
4496e954a6eSJens Wiklander 
4506e954a6eSJens Wiklander 	for (n = 0;
4516e954a6eSJens Wiklander 	     n < NUM_POOLS && reseed_from_pool(state.reseed_count, n); n++) {
4526e954a6eSJens Wiklander 		res = restart_pool(state.pool_ctx[n], pool_digest);
4536e954a6eSJens Wiklander 		if (res)
4546e954a6eSJens Wiklander 			return res;
4556e954a6eSJens Wiklander 		if (!n)
4566e954a6eSJens Wiklander 			state.pool0_length = 0;
4576e954a6eSJens Wiklander 
4586e954a6eSJens Wiklander 		res = hash_update(state.reseed_ctx, pool_digest, KEY_SIZE);
4596e954a6eSJens Wiklander 		if (res)
4606e954a6eSJens Wiklander 			return res;
4616e954a6eSJens Wiklander 	}
4626e954a6eSJens Wiklander 	res = hash_final(state.reseed_ctx, pool_digest);
4636e954a6eSJens Wiklander 	if (res)
4646e954a6eSJens Wiklander 		return res;
4656e954a6eSJens Wiklander 
466*cbda7091SJens Wiklander 	crypto_cipher_final(state.ctx);
467*cbda7091SJens Wiklander 	res = crypto_cipher_init(state.ctx, TEE_MODE_ENCRYPT,
4686e954a6eSJens Wiklander 				 pool_digest, KEY_SIZE, NULL, 0, NULL, 0);
4696e954a6eSJens Wiklander 	if (res)
4706e954a6eSJens Wiklander 		return res;
4716e954a6eSJens Wiklander 	inc_counter(state.counter);
4726e954a6eSJens Wiklander 
4736e954a6eSJens Wiklander 	return TEE_SUCCESS;
4746e954a6eSJens Wiklander }
4756e954a6eSJens Wiklander 
fortuna_read(void * buf,size_t blen)4766e954a6eSJens Wiklander static TEE_Result fortuna_read(void *buf, size_t blen)
4776e954a6eSJens Wiklander {
4786e954a6eSJens Wiklander 	TEE_Result res;
4796e954a6eSJens Wiklander 
4806e954a6eSJens Wiklander 	if (!state.ctx)
4816e954a6eSJens Wiklander 		return TEE_ERROR_BAD_STATE;
4826e954a6eSJens Wiklander 
4836e954a6eSJens Wiklander 	mutex_lock(&state_mu);
4846e954a6eSJens Wiklander 
4856e954a6eSJens Wiklander 	res = maybe_reseed();
4866e954a6eSJens Wiklander 	if (res)
4876e954a6eSJens Wiklander 		goto out;
4886e954a6eSJens Wiklander 
4896e954a6eSJens Wiklander 	if (blen) {
4906e954a6eSJens Wiklander 		uint8_t new_key[KEY_SIZE];
4916e954a6eSJens Wiklander 
4926e954a6eSJens Wiklander 		res = generate_random_data(buf, blen);
4936e954a6eSJens Wiklander 		if (res)
4946e954a6eSJens Wiklander 			goto out;
4956e954a6eSJens Wiklander 
4966e954a6eSJens Wiklander 		res = generate_blocks(new_key, KEY_SIZE / BLOCK_SIZE);
4976e954a6eSJens Wiklander 		if (res)
4986e954a6eSJens Wiklander 			goto out;
499*cbda7091SJens Wiklander 		crypto_cipher_final(state.ctx);
5006e954a6eSJens Wiklander 		res = cipher_init(state.ctx, new_key);
5016e954a6eSJens Wiklander 		if (res)
5026e954a6eSJens Wiklander 			goto out;
5036e954a6eSJens Wiklander 	}
5046e954a6eSJens Wiklander 
5056e954a6eSJens Wiklander 	res = drain_ring_buffer();
5066e954a6eSJens Wiklander out:
5076e954a6eSJens Wiklander 	if (res)
5086e954a6eSJens Wiklander 		fortuna_done();
5096e954a6eSJens Wiklander 	mutex_unlock(&state_mu);
5106e954a6eSJens Wiklander 
5116e954a6eSJens Wiklander 	return res;
5126e954a6eSJens Wiklander }
5136e954a6eSJens Wiklander 
crypto_rng_read(void * buf,size_t blen)5146e954a6eSJens Wiklander TEE_Result crypto_rng_read(void *buf, size_t blen)
5156e954a6eSJens Wiklander {
5166e954a6eSJens Wiklander 	size_t offs = 0;
5176e954a6eSJens Wiklander 
5186e954a6eSJens Wiklander 	while (true) {
5196e954a6eSJens Wiklander 		TEE_Result res;
5206e954a6eSJens Wiklander 		size_t n;
5216e954a6eSJens Wiklander 
5226e954a6eSJens Wiklander 		/* Draw at most 1 MiB of random on a single key */
5236e954a6eSJens Wiklander 		n = MIN(blen - offs, SIZE_1M);
5246e954a6eSJens Wiklander 		if (!n)
5256e954a6eSJens Wiklander 			return TEE_SUCCESS;
5266e954a6eSJens Wiklander 		res = fortuna_read((uint8_t *)buf + offs, n);
5276e954a6eSJens Wiklander 		if (res)
5286e954a6eSJens Wiklander 			return res;
5296e954a6eSJens Wiklander 		offs += n;
5306e954a6eSJens Wiklander 	}
5316e954a6eSJens Wiklander }
532