1df9a39eaSdp-arm /* 2df9a39eaSdp-arm * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. 3df9a39eaSdp-arm * 4*82cb2c1aSdp-arm * SPDX-License-Identifier: BSD-3-Clause 5df9a39eaSdp-arm */ 6df9a39eaSdp-arm 7df9a39eaSdp-arm #include <assert.h> 8df9a39eaSdp-arm #include <mmio.h> 9df9a39eaSdp-arm #include <string.h> 1053d9c9c8SScott Branden #include <utils_def.h> 11df9a39eaSdp-arm #include "juno_def.h" 12df9a39eaSdp-arm 13df9a39eaSdp-arm #define NSAMPLE_CLOCKS 1 /* min 1 cycle, max 231 cycles */ 14df9a39eaSdp-arm #define NRETRIES 5 15df9a39eaSdp-arm 16df9a39eaSdp-arm static inline int output_valid(void) 17df9a39eaSdp-arm { 18df9a39eaSdp-arm int i; 19df9a39eaSdp-arm 20df9a39eaSdp-arm for (i = 0; i < NRETRIES; i++) { 21df9a39eaSdp-arm uint32_t val; 22df9a39eaSdp-arm 23df9a39eaSdp-arm val = mmio_read_32(TRNG_BASE + TRNG_STATUS); 24df9a39eaSdp-arm if (val & 1U) 25df9a39eaSdp-arm break; 26df9a39eaSdp-arm } 27df9a39eaSdp-arm if (i >= NRETRIES) 28df9a39eaSdp-arm return 0; /* No output data available. */ 29df9a39eaSdp-arm return 1; 30df9a39eaSdp-arm } 31df9a39eaSdp-arm 32df9a39eaSdp-arm /* 33df9a39eaSdp-arm * This function fills `buf` with `len` bytes of entropy. 34df9a39eaSdp-arm * It uses the Trusted Entropy Source peripheral on Juno. 35df9a39eaSdp-arm * Returns 0 when the buffer has been filled with entropy 36df9a39eaSdp-arm * successfully and -1 otherwise. 37df9a39eaSdp-arm */ 38df9a39eaSdp-arm int juno_getentropy(void *buf, size_t len) 39df9a39eaSdp-arm { 40df9a39eaSdp-arm uint8_t *bp = buf; 41df9a39eaSdp-arm 42df9a39eaSdp-arm assert(buf); 43df9a39eaSdp-arm assert(len); 44df9a39eaSdp-arm assert(!check_uptr_overflow((uintptr_t)bp, len)); 45df9a39eaSdp-arm 46df9a39eaSdp-arm /* Disable interrupt mode. */ 47df9a39eaSdp-arm mmio_write_32(TRNG_BASE + TRNG_INTMASK, 0); 48df9a39eaSdp-arm /* Program TRNG to sample for `NSAMPLE_CLOCKS`. */ 49df9a39eaSdp-arm mmio_write_32(TRNG_BASE + TRNG_CONFIG, NSAMPLE_CLOCKS); 50df9a39eaSdp-arm 51df9a39eaSdp-arm while (len > 0) { 52df9a39eaSdp-arm int i; 53df9a39eaSdp-arm 54df9a39eaSdp-arm /* Start TRNG. */ 55df9a39eaSdp-arm mmio_write_32(TRNG_BASE + TRNG_CONTROL, 1); 56df9a39eaSdp-arm 57df9a39eaSdp-arm /* Check if output is valid. */ 58df9a39eaSdp-arm if (!output_valid()) 59df9a39eaSdp-arm return -1; 60df9a39eaSdp-arm 61df9a39eaSdp-arm /* Fill entropy buffer. */ 62df9a39eaSdp-arm for (i = 0; i < TRNG_NOUTPUTS; i++) { 63df9a39eaSdp-arm size_t n; 64df9a39eaSdp-arm uint32_t val; 65df9a39eaSdp-arm 66df9a39eaSdp-arm val = mmio_read_32(TRNG_BASE + i * sizeof(uint32_t)); 67df9a39eaSdp-arm n = MIN(len, sizeof(uint32_t)); 68df9a39eaSdp-arm memcpy(bp, &val, n); 69df9a39eaSdp-arm bp += n; 70df9a39eaSdp-arm len -= n; 71df9a39eaSdp-arm if (len == 0) 72df9a39eaSdp-arm break; 73df9a39eaSdp-arm } 74df9a39eaSdp-arm 75df9a39eaSdp-arm /* Reset TRNG outputs. */ 76df9a39eaSdp-arm mmio_write_32(TRNG_BASE + TRNG_STATUS, 1); 77df9a39eaSdp-arm } 78df9a39eaSdp-arm 79df9a39eaSdp-arm return 0; 80df9a39eaSdp-arm } 81