Skip to content

Commit

Permalink
core: drivers: riscv_zkr_rng: limit seed reading time
Browse files Browse the repository at this point in the history
If the attempts to read SEED exceed 1 second for 16-bit
randomness, we consider it a failure.

Also, move seed CSR field encodings to the header file.

Signed-off-by: Yu Chien Peter Lin <peterlin@andestech.com>
Reviewed-by: Alvin Chang <alvinga@andestech.com>
Tested-by: Alvin Chang <alvinga@andestech.com>
Acked-by: Gatien Chevallier <gatien.chevallier@foss.st.com>
  • Loading branch information
lyctw authored and jforissier committed Sep 3, 2024
1 parent 9f32a1a commit 47fd720
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 28 deletions.
8 changes: 8 additions & 0 deletions core/arch/riscv/include/encoding.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,14 @@
#define MSECCFG_USEED 0x00000100
#define MSECCFG_SSEED 0x00000200

#define SEED_OPST 0xC0000000
#define SEED_ENTROPY 0x0000FFFF

#define SEED_OPST_BIST 0x00000000
#define SEED_OPST_WAIT 0x40000000
#define SEED_OPST_ES16 0x80000000
#define SEED_OPST_DEAD 0xC0000000

#define PRV_U 0
#define PRV_S 1
#define PRV_M 3
Expand Down
23 changes: 23 additions & 0 deletions core/arch/riscv/include/riscv.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,29 @@ static inline __noprof void wfi(void)
asm volatile ("wfi");
}

static inline __noprof void riscv_cpu_pause(void)
{
unsigned long dummy = 0;

/*
* Use a divide instruction to force wait
* for multiple CPU cycles.
* Note: RISC-V does not raise an exception
* on divide by zero.
*/
asm volatile ("div %0, %0, zero" : "=r" (dummy));

/*
* Use the encoding of the 'pause' instruction,
* thus no need to verify toolchain support for
* zihintpause.
* On hardware platforms that do not implement
* this extension, it will simply serve as a no-op.
*/
asm volatile (".4byte 0x100000f"); /* pause */
barrier();
}

static inline __noprof void flush_tlb(void)
{
asm volatile("sfence.vma zero, zero");
Expand Down
80 changes: 52 additions & 28 deletions core/drivers/riscv_zkr_rng.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,46 +4,70 @@
*/

#include <crypto/crypto.h>
#include <encoding.h>
#include <kernel/delay.h>
#include <kernel/panic.h>
#include <riscv.h>
#include <rng_support.h>
#include <tee/tee_cryp_utl.h>

#define OPST_BIST 0b00
#define OPST_WAIT 0b01
#define OPST_ES16 0b10
#define OPST_DEAD 0b11
#define RNG_TIMEOUT_US 1000000

TEE_Result hw_get_random_bytes(void *buf, size_t len)
static bool __must_check seed_get_random_u16(uint16_t *val)
{
uint8_t *ptr = buf;
uint32_t val = 0;
uint64_t timeout = timeout_init_us(RNG_TIMEOUT_US);
uint32_t seed = 0;
uint32_t opst = 0;

while (len > 0) {
do {
/*
* The seed register must be accessed using CSR read-write
* instructions. The write operation is ignored and serves
* to indicate polling and flushing.
* The seed register must be accessed using CSR
* read-write instructions. The write operation
* is ignored and serves to indicate polling and
* flushing.
*/
val = swap_csr(CSR_SEED, val);

switch (val >> 30) {
case OPST_BIST:
case OPST_WAIT:
continue;
case OPST_ES16:
*ptr++ = val & 0xff;
len--;
if (len > 0) {
*ptr++ = val >> 8;
len--;
}
break;
case OPST_DEAD:
seed = swap_csr(CSR_SEED, 0);
opst = seed & SEED_OPST;

switch (opst) {
case SEED_OPST_ES16:
*val = seed & SEED_ENTROPY;
return true;
case SEED_OPST_DEAD:
/* Unrecoverable self-test error */
return TEE_ERROR_BAD_STATE;
return false;
case SEED_OPST_BIST:
case SEED_OPST_WAIT:
default:
break; /* can't happen */
riscv_cpu_pause();
}
} while (!timeout_elapsed(timeout));

/* Consider timeout case due to normal world scheduler */
seed = swap_csr(CSR_SEED, 0);
if ((seed & SEED_OPST) == SEED_OPST_ES16) {
*val = seed & SEED_ENTROPY;
return true;
}

EMSG("Failed to produce a sufficient amount of entropy");

return false;
}

TEE_Result hw_get_random_bytes(void *buf, size_t len)
{
uint8_t *ptr = buf;
uint16_t seed = 0;

while (len > 0) {
if (!seed_get_random_u16(&seed))
return TEE_ERROR_ACCESS_DENIED;
*ptr++ = seed & 0xff;
len--;
if (len > 0) {
*ptr++ = seed >> 8;
len--;
}
}

Expand Down

0 comments on commit 47fd720

Please sign in to comment.