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