1df9a39eaSdp-arm /* 2fd116b9fSRoberto 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> 8*543f0d8bSAndre Przywara #include <stdbool.h> 9*543f0d8bSAndre Przywara #include <stdint.h> 10df9a39eaSdp-arm #include <string.h> 1109d40e0eSAntonio Nino Diaz 1209d40e0eSAntonio Nino Diaz #include <lib/mmio.h> 1309d40e0eSAntonio Nino Diaz #include <lib/utils_def.h> 14234bc7f8SAntonio Nino Diaz #include <platform_def.h> 1509d40e0eSAntonio Nino Diaz 16fd116b9fSRoberto Vargas #include "juno_decl.h" 17df9a39eaSdp-arm 18df9a39eaSdp-arm #define NSAMPLE_CLOCKS 1 /* min 1 cycle, max 231 cycles */ 19df9a39eaSdp-arm #define NRETRIES 5 20df9a39eaSdp-arm 21*543f0d8bSAndre Przywara /* initialised to false */ 22*543f0d8bSAndre Przywara static bool juno_trng_initialized; 23*543f0d8bSAndre Przywara 24*543f0d8bSAndre Przywara static bool output_valid(void) 25df9a39eaSdp-arm { 26df9a39eaSdp-arm int i; 27df9a39eaSdp-arm 28df9a39eaSdp-arm for (i = 0; i < NRETRIES; i++) { 29df9a39eaSdp-arm uint32_t val; 30df9a39eaSdp-arm 31df9a39eaSdp-arm val = mmio_read_32(TRNG_BASE + TRNG_STATUS); 32df9a39eaSdp-arm if (val & 1U) 33*543f0d8bSAndre Przywara return true; 34df9a39eaSdp-arm } 35*543f0d8bSAndre Przywara return false; /* No output data available. */ 36df9a39eaSdp-arm } 37df9a39eaSdp-arm 38df9a39eaSdp-arm /* 39*543f0d8bSAndre Przywara * This function fills `buf` with 8 bytes of entropy. 40df9a39eaSdp-arm * It uses the Trusted Entropy Source peripheral on Juno. 41*543f0d8bSAndre Przywara * Returns 'true' when the buffer has been filled with entropy 42*543f0d8bSAndre Przywara * successfully, or 'false' otherwise. 43df9a39eaSdp-arm */ 44*543f0d8bSAndre Przywara bool juno_getentropy(uint64_t *buf) 45df9a39eaSdp-arm { 46*543f0d8bSAndre Przywara uint64_t ret; 47df9a39eaSdp-arm 48df9a39eaSdp-arm assert(buf); 49*543f0d8bSAndre Przywara assert(!check_uptr_overflow((uintptr_t)buf, sizeof(*buf))); 50df9a39eaSdp-arm 51*543f0d8bSAndre Przywara if (!juno_trng_initialized) { 52df9a39eaSdp-arm /* Disable interrupt mode. */ 53df9a39eaSdp-arm mmio_write_32(TRNG_BASE + TRNG_INTMASK, 0); 54df9a39eaSdp-arm /* Program TRNG to sample for `NSAMPLE_CLOCKS`. */ 55df9a39eaSdp-arm mmio_write_32(TRNG_BASE + TRNG_CONFIG, NSAMPLE_CLOCKS); 56*543f0d8bSAndre Przywara /* Abort any potentially pending sampling. */ 57*543f0d8bSAndre Przywara mmio_write_32(TRNG_BASE + TRNG_CONTROL, 2); 58*543f0d8bSAndre Przywara /* Reset TRNG outputs. */ 59*543f0d8bSAndre Przywara mmio_write_32(TRNG_BASE + TRNG_STATUS, 1); 60df9a39eaSdp-arm 61*543f0d8bSAndre Przywara juno_trng_initialized = true; 62*543f0d8bSAndre Przywara } 63df9a39eaSdp-arm 64*543f0d8bSAndre Przywara if (!output_valid()) { 65df9a39eaSdp-arm /* Start TRNG. */ 66df9a39eaSdp-arm mmio_write_32(TRNG_BASE + TRNG_CONTROL, 1); 67df9a39eaSdp-arm 68df9a39eaSdp-arm if (!output_valid()) 69*543f0d8bSAndre Przywara return false; 70df9a39eaSdp-arm } 71df9a39eaSdp-arm 72*543f0d8bSAndre Przywara /* XOR each two 32-bit registers together, combine the pairs */ 73*543f0d8bSAndre Przywara ret = mmio_read_32(TRNG_BASE + 0); 74*543f0d8bSAndre Przywara ret ^= mmio_read_32(TRNG_BASE + 4); 75*543f0d8bSAndre Przywara ret <<= 32; 76*543f0d8bSAndre Przywara 77*543f0d8bSAndre Przywara ret |= mmio_read_32(TRNG_BASE + 8); 78*543f0d8bSAndre Przywara ret ^= mmio_read_32(TRNG_BASE + 12); 79*543f0d8bSAndre Przywara *buf = ret; 80*543f0d8bSAndre Przywara 81*543f0d8bSAndre Przywara /* Acknowledge current cycle, clear output registers. */ 82df9a39eaSdp-arm mmio_write_32(TRNG_BASE + TRNG_STATUS, 1); 83*543f0d8bSAndre Przywara /* Trigger next TRNG cycle. */ 84*543f0d8bSAndre Przywara mmio_write_32(TRNG_BASE + TRNG_CONTROL, 1); 85df9a39eaSdp-arm 86*543f0d8bSAndre Przywara return true; 87df9a39eaSdp-arm } 88