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