1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2022, Vaisala Oyj 4 */ 5 6 #include <assert.h> 7 #include <io.h> 8 #include <kernel/boot.h> 9 #include <kernel/delay.h> 10 #include <kernel/dt.h> 11 #include <kernel/dt_driver.h> 12 #include <kernel/spinlock.h> 13 #include <libfdt.h> 14 #include <platform_config.h> 15 #include <rng_support.h> 16 #include <string.h> 17 #include <tee/tee_cryp_utl.h> 18 19 #define CONTROL_REG 0x00000000 20 #define STATUS_REG 0x00000004 21 #define RAND_REG 0x00000000 22 23 #define HOST_TO_TRNG_RESET 0x00000001 24 #define HOST_TO_TRNG_RELEASE_RESET 0x00000002 25 #define HOST_TO_TRNG_ENABLE 0x80000000 26 #define HOST_TO_TRNG_ZEROIZE 0x80000004 27 #define HOST_TO_TRNG_ACK_ZEROIZE 0x80000008 28 #define HOST_TO_TRNG_READ 0x8000000F 29 30 /* trng statuses */ 31 #define TRNG_ACK_RESET 0x000000AC 32 #define TRNG_SUCCESSFUL_STARTUP 0x00000057 33 #define TRNG_FAILED_STARTUP 0x000000FA 34 #define TRNG_NEW_RAND_AVAILABLE 0x000000ED 35 36 static unsigned int trng_lock = SPINLOCK_UNLOCK; 37 38 static vaddr_t xiphera_trng_base; 39 40 static uint32_t xiphera_trng_read32(void) 41 { 42 uint32_t value = 0; 43 uint32_t exceptions = 0; 44 uint32_t status = 0; 45 46 exceptions = cpu_spin_lock_xsave(&trng_lock); 47 48 while (true) { 49 /* Wait until we have value available */ 50 status = io_read32(xiphera_trng_base + STATUS_REG); 51 if (status != TRNG_NEW_RAND_AVAILABLE) 52 continue; 53 54 value = io_read32(xiphera_trng_base + RAND_REG); 55 56 /* 57 * Ack that RNG value has been consumed and trigger new one to 58 * be generated 59 */ 60 io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_READ); 61 io_write32(xiphera_trng_base + CONTROL_REG, 62 HOST_TO_TRNG_ENABLE); 63 64 break; 65 } 66 67 cpu_spin_unlock_xrestore(&trng_lock, exceptions); 68 69 return value; 70 } 71 72 /* This is a true RNG, no need for seeding */ 73 void plat_rng_init(void) 74 { 75 } 76 77 TEE_Result crypto_rng_read(void *buf, size_t len) 78 { 79 uint8_t *rngbuf = buf; 80 uint32_t val = 0; 81 size_t len_to_copy = 0; 82 83 assert(buf); 84 assert(xiphera_trng_base); 85 86 while (len) { 87 val = xiphera_trng_read32(); 88 len_to_copy = MIN(len, sizeof(uint32_t)); 89 memcpy(rngbuf, &val, len_to_copy); 90 rngbuf += len_to_copy; 91 len -= len_to_copy; 92 } 93 94 return TEE_SUCCESS; 95 } 96 97 uint8_t hw_get_random_byte(void) 98 { 99 uint8_t data = 0; 100 101 assert(xiphera_trng_base); 102 103 data = xiphera_trng_read32() & 0xFF; 104 105 return data; 106 } 107 108 static TEE_Result xiphera_trng_probe(const void *fdt, int node, 109 const void *compat_data __unused) 110 { 111 int dt_status = _fdt_get_status(fdt, node); 112 uint32_t status = 0; 113 size_t size = 0; 114 115 /* Skip non-secure instances */ 116 if (dt_status != DT_STATUS_OK_SEC) 117 return TEE_ERROR_NODE_DISABLED; 118 119 if (xiphera_trng_base) { 120 EMSG("Only one secure instance is supported"); 121 return TEE_ERROR_GENERIC; 122 } 123 124 if (dt_map_dev(fdt, node, &xiphera_trng_base, &size) < 0) 125 return TEE_ERROR_GENERIC; 126 127 /* 128 * The TRNG needs to be first reset in order to provide stable 129 * operation. 130 * 131 * Reset of the chip should complete within 200 us but in some cases it 132 * could take up to 400 us. If it is not ready within 400 us assume 133 * there is problem. 134 */ 135 io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_RESET); 136 udelay(200); 137 138 status = io_read32(xiphera_trng_base + STATUS_REG); 139 if (status != TRNG_ACK_RESET) { 140 /* 141 * Give it additional 200 us to allow it to reset. 142 * 143 * If still not done -> error out. 144 */ 145 udelay(200); 146 status = io_read32(xiphera_trng_base + STATUS_REG); 147 if (status != TRNG_ACK_RESET) { 148 EMSG("Failed to reset TRNG\n"); 149 return TEE_ERROR_GENERIC; 150 } 151 } 152 153 /* 154 * Now TRNG should be internally stable. 155 * 156 * Clear internal random number generation engine to start in stable 157 * state and give it 20 ms to enable good random number entropy and 158 * then check that random number engine is ready. 159 */ 160 io_write32(xiphera_trng_base + CONTROL_REG, 161 HOST_TO_TRNG_RELEASE_RESET); 162 io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_ENABLE); 163 io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_ZEROIZE); 164 mdelay(20); 165 166 status = io_read32(xiphera_trng_base + STATUS_REG); 167 if (status != TRNG_SUCCESSFUL_STARTUP) { 168 /* 169 * Check specifically if there were startup test errors to aid 170 * in debugging TRNG implementation in FPGA 171 */ 172 if (status == TRNG_FAILED_STARTUP) { 173 EMSG("Startup tests have failed\n"); 174 return TEE_ERROR_GENERIC; 175 } 176 177 EMSG("Startup tests yielded no response -> TRNG stuck\n"); 178 return TEE_ERROR_GENERIC; 179 } 180 181 io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_ACK_ZEROIZE); 182 183 DMSG("TRNG initialized\n"); 184 185 return TEE_SUCCESS; 186 } 187 188 static const struct dt_device_match xiphera_trng_match_table[] = { 189 { .compatible = "xiphera,xip8001b-trng" }, 190 { } 191 }; 192 193 DEFINE_DT_DRIVER(xiphera_trng_dt_driver) = { 194 .name = "xiphera_trng", 195 .type = DT_DRIVER_NOTYPE, 196 .match_table = xiphera_trng_match_table, 197 .probe = xiphera_trng_probe, 198 }; 199