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