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