Home | History | Annotate | Download | only in juno
      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