xref: /optee_os/core/arch/arm/plat-rcar/hw_rng.c (revision e9c080a6a5679cf4a100e5effd18b5bc79c27aae)
1501ef24eSVolodymyr Babchuk // SPDX-License-Identifier: BSD-2-Clause
2501ef24eSVolodymyr Babchuk /* Copyright (c) 2021, EPAM Systems. All rights reserved. */
3501ef24eSVolodymyr Babchuk 
4501ef24eSVolodymyr Babchuk #include <assert.h>
5501ef24eSVolodymyr Babchuk #include <kernel/panic.h>
6501ef24eSVolodymyr Babchuk #include <kernel/spinlock.h>
7501ef24eSVolodymyr Babchuk #include <platform_config.h>
8501ef24eSVolodymyr Babchuk #include <rng_support.h>
9501ef24eSVolodymyr Babchuk #include <trace.h>
10501ef24eSVolodymyr Babchuk 
11501ef24eSVolodymyr Babchuk #include "romapi.h"
12501ef24eSVolodymyr Babchuk 
13501ef24eSVolodymyr Babchuk #define SCRATCH_BUF_SZ		4096
14501ef24eSVolodymyr Babchuk 
15501ef24eSVolodymyr Babchuk static uint8_t scratch_buf[SCRATCH_BUF_SZ] __nex_bss
16501ef24eSVolodymyr Babchuk 					__aligned(RCAR_CACHE_LINE_SZ);
17501ef24eSVolodymyr Babchuk static unsigned int spin_lock __nex_data = SPINLOCK_UNLOCK;
18501ef24eSVolodymyr Babchuk 
19501ef24eSVolodymyr Babchuk /*
20501ef24eSVolodymyr Babchuk  * It is inefficient to call ROM_GetRndVector() every time we want 8 bits of
21501ef24eSVolodymyr Babchuk  * random data, so we will cache the unused values for latter use.
22501ef24eSVolodymyr Babchuk  */
23501ef24eSVolodymyr Babchuk static uint8_t rng_cache[PLAT_RND_VECTOR_SZ] __nex_bss
24501ef24eSVolodymyr Babchuk 					__aligned(RCAR_CACHE_LINE_SZ);
25*e9c080a6SAndrew Davis static uint8_t rng_cache_pos __nex_data;
26501ef24eSVolodymyr Babchuk 
hw_get_random_bytes(void * buf,size_t len)27*e9c080a6SAndrew Davis TEE_Result hw_get_random_bytes(void *buf, size_t len)
28501ef24eSVolodymyr Babchuk {
29*e9c080a6SAndrew Davis 	uint32_t exceptions;
30*e9c080a6SAndrew Davis 	uint8_t *buffer = buf;
31*e9c080a6SAndrew Davis 	size_t buffer_pos = 0;
32501ef24eSVolodymyr Babchuk 	uint8_t ret_val = 0;
33501ef24eSVolodymyr Babchuk 
34*e9c080a6SAndrew Davis 	assert(rng_cache_pos < PLAT_RND_VECTOR_SZ);
35501ef24eSVolodymyr Babchuk 
36*e9c080a6SAndrew Davis 	while (buffer_pos < len) {
37*e9c080a6SAndrew Davis 		exceptions = cpu_spin_lock_xsave(&spin_lock);
38*e9c080a6SAndrew Davis 		/* Refill our FIFO */
39*e9c080a6SAndrew Davis 		if (rng_cache_pos == 0) {
40*e9c080a6SAndrew Davis 			uint32_t ret = plat_rom_getrndvector(rng_cache,
41*e9c080a6SAndrew Davis 							scratch_buf,
42501ef24eSVolodymyr Babchuk 							sizeof(scratch_buf));
43501ef24eSVolodymyr Babchuk 			if (ret != 0)
44501ef24eSVolodymyr Babchuk 				panic("ROM_GetRndVector() returned error!");
45501ef24eSVolodymyr Babchuk 		}
46501ef24eSVolodymyr Babchuk 
47*e9c080a6SAndrew Davis 		buffer[buffer_pos++] = rng_cache[rng_cache_pos++];
48*e9c080a6SAndrew Davis 		if (rng_cache_pos == PLAT_RND_VECTOR_SZ)
49*e9c080a6SAndrew Davis 			rng_cache_pos = 0;
50*e9c080a6SAndrew Davis 
51501ef24eSVolodymyr Babchuk 		cpu_spin_unlock_xrestore(&spin_lock, exceptions);
52*e9c080a6SAndrew Davis 	}
53501ef24eSVolodymyr Babchuk 
54501ef24eSVolodymyr Babchuk 	return ret_val;
55501ef24eSVolodymyr Babchuk }
56