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)16static 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)58TEE_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)77void 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