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
output_valid(void)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 */
juno_getentropy(void * buf,size_t len)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