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