xref: /optee_os/core/drivers/riscv_zkr_rng.c (revision 47fd72092aa569f9da13393ed5387af5945e7ef5)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2024 Andes Technology Corporation
4  */
5 
6 #include <crypto/crypto.h>
7 #include <encoding.h>
8 #include <kernel/delay.h>
9 #include <kernel/panic.h>
10 #include <riscv.h>
11 #include <rng_support.h>
12 #include <tee/tee_cryp_utl.h>
13 
14 #define RNG_TIMEOUT_US	1000000
15 
seed_get_random_u16(uint16_t * val)16 static bool __must_check seed_get_random_u16(uint16_t *val)
17 {
18 	uint64_t timeout = timeout_init_us(RNG_TIMEOUT_US);
19 	uint32_t seed = 0;
20 	uint32_t opst = 0;
21 
22 	do {
23 		/*
24 		 * The seed register must be accessed using CSR
25 		 * read-write instructions. The write operation
26 		 * is ignored and serves to indicate polling and
27 		 * flushing.
28 		 */
29 		seed = swap_csr(CSR_SEED, 0);
30 		opst = seed & SEED_OPST;
31 
32 		switch (opst) {
33 		case SEED_OPST_ES16:
34 			*val = seed & SEED_ENTROPY;
35 			return true;
36 		case SEED_OPST_DEAD:
37 			/* Unrecoverable self-test error */
38 			return false;
39 		case SEED_OPST_BIST:
40 		case SEED_OPST_WAIT:
41 		default:
42 			riscv_cpu_pause();
43 		}
44 	} while (!timeout_elapsed(timeout));
45 
46 	/* Consider timeout case due to normal world scheduler */
47 	seed = swap_csr(CSR_SEED, 0);
48 	if ((seed & SEED_OPST) == SEED_OPST_ES16) {
49 		*val = seed & SEED_ENTROPY;
50 		return true;
51 	}
52 
53 	EMSG("Failed to produce a sufficient amount of entropy");
54 
55 	return false;
56 }
57 
hw_get_random_bytes(void * buf,size_t len)58 TEE_Result hw_get_random_bytes(void *buf, size_t len)
59 {
60 	uint8_t *ptr = buf;
61 	uint16_t seed = 0;
62 
63 	while (len > 0) {
64 		if (!seed_get_random_u16(&seed))
65 			return TEE_ERROR_ACCESS_DENIED;
66 		*ptr++ = seed & 0xff;
67 		len--;
68 		if (len > 0) {
69 			*ptr++ = seed >> 8;
70 			len--;
71 		}
72 	}
73 
74 	return TEE_SUCCESS;
75 }
76 
plat_rng_init(void)77 void plat_rng_init(void)
78 {
79 	if (!riscv_detect_csr_seed())
80 		panic("RISC-V Zkr is not supported or unavailable in S-mode");
81 }
82