1 // SPDX-License-Identifier: BSD-2-Clause
2 /* Copyright (c) 2021, EPAM Systems. All rights reserved. */
3 
4 #include <assert.h>
5 #include <kernel/panic.h>
6 #include <kernel/spinlock.h>
7 #include <platform_config.h>
8 #include <rng_support.h>
9 #include <trace.h>
10 
11 #include "romapi.h"
12 
13 #define SCRATCH_BUF_SZ		4096
14 
15 static uint8_t scratch_buf[SCRATCH_BUF_SZ] __nex_bss
16 					__aligned(RCAR_CACHE_LINE_SZ);
17 static unsigned int spin_lock __nex_data = SPINLOCK_UNLOCK;
18 
19 /*
20  * It is inefficient to call ROM_GetRndVector() every time we want 8 bits of
21  * random data, so we will cache the unused values for latter use.
22  */
23 static uint8_t rng_cache[PLAT_RND_VECTOR_SZ] __nex_bss
24 					__aligned(RCAR_CACHE_LINE_SZ);
25 static uint8_t rng_cache_pos __nex_data;
26 
hw_get_random_bytes(void * buf,size_t len)27 TEE_Result hw_get_random_bytes(void *buf, size_t len)
28 {
29 	uint32_t exceptions;
30 	uint8_t *buffer = buf;
31 	size_t buffer_pos = 0;
32 	uint8_t ret_val = 0;
33 
34 	assert(rng_cache_pos < PLAT_RND_VECTOR_SZ);
35 
36 	while (buffer_pos < len) {
37 		exceptions = cpu_spin_lock_xsave(&spin_lock);
38 		/* Refill our FIFO */
39 		if (rng_cache_pos == 0) {
40 			uint32_t ret = plat_rom_getrndvector(rng_cache,
41 							scratch_buf,
42 							sizeof(scratch_buf));
43 			if (ret != 0)
44 				panic("ROM_GetRndVector() returned error!");
45 		}
46 
47 		buffer[buffer_pos++] = rng_cache[rng_cache_pos++];
48 		if (rng_cache_pos == PLAT_RND_VECTOR_SZ)
49 			rng_cache_pos = 0;
50 
51 		cpu_spin_unlock_xrestore(&spin_lock, exceptions);
52 	}
53 
54 	return ret_val;
55 }
56