1 // SPDX-License-Identifier: BSD-3-Clause 2 /* 3 * Copyright (c) 2018-2023, STMicroelectronics 4 */ 5 6 #include <assert.h> 7 #include <drivers/clk.h> 8 #include <drivers/clk_dt.h> 9 #include <drivers/rstctrl.h> 10 #include <drivers/stm32_rng.h> 11 #include <io.h> 12 #include <kernel/delay.h> 13 #include <kernel/dt.h> 14 #include <kernel/dt_driver.h> 15 #include <kernel/boot.h> 16 #include <kernel/panic.h> 17 #include <kernel/thread.h> 18 #include <libfdt.h> 19 #include <mm/core_memprot.h> 20 #include <rng_support.h> 21 #include <stdbool.h> 22 #include <stm32_util.h> 23 #include <string.h> 24 #include <tee/tee_cryp_utl.h> 25 26 #define RNG_CR U(0x00) 27 #define RNG_SR U(0x04) 28 #define RNG_DR U(0x08) 29 30 #define RNG_CR_RNGEN BIT(2) 31 #define RNG_CR_IE BIT(3) 32 #define RNG_CR_CED BIT(5) 33 34 #define RNG_SR_DRDY BIT(0) 35 #define RNG_SR_CECS BIT(1) 36 #define RNG_SR_SECS BIT(2) 37 #define RNG_SR_CEIS BIT(5) 38 #define RNG_SR_SEIS BIT(6) 39 40 #if TRACE_LEVEL > TRACE_DEBUG 41 #define RNG_READY_TIMEOUT_US U(100000) 42 #else 43 #define RNG_READY_TIMEOUT_US U(10000) 44 #endif 45 #define RNG_RESET_TIMEOUT_US U(1000) 46 47 #define RNG_FIFO_BYTE_DEPTH U(16) 48 49 struct stm32_rng_instance { 50 struct io_pa_va base; 51 struct clk *clock; 52 struct rstctrl *rstctrl; 53 unsigned int lock; 54 bool release_post_boot; 55 }; 56 57 /* Expect at most a single RNG instance */ 58 static struct stm32_rng_instance *stm32_rng; 59 60 static vaddr_t get_base(void) 61 { 62 assert(stm32_rng); 63 64 return io_pa_or_va(&stm32_rng->base, 1); 65 } 66 67 /* 68 * Extracts from the STM32 RNG specification: 69 * 70 * When a noise source (or seed) error occurs, the RNG stops generating 71 * random numbers and sets to “1” both SEIS and SECS bits to indicate 72 * that a seed error occurred. (...) 73 74 * The following sequence shall be used to fully recover from a seed 75 * error after the RNG initialization: 76 * 1. Clear the SEIS bit by writing it to “0”. 77 * 2. Read out 12 words from the RNG_DR register, and discard each of 78 * them in order to clean the pipeline. 79 * 3. Confirm that SEIS is still cleared. Random number generation is 80 * back to normal. 81 */ 82 static void conceal_seed_error(vaddr_t rng_base) 83 { 84 if (io_read32(rng_base + RNG_SR) & (RNG_SR_SECS | RNG_SR_SEIS)) { 85 size_t i = 0; 86 87 io_mask32(rng_base + RNG_SR, 0, RNG_SR_SEIS); 88 89 for (i = 12; i != 0; i--) 90 (void)io_read32(rng_base + RNG_DR); 91 92 if (io_read32(rng_base + RNG_SR) & RNG_SR_SEIS) 93 panic("RNG noise"); 94 } 95 } 96 97 static TEE_Result read_available(vaddr_t rng_base, uint8_t *out, size_t *size) 98 { 99 uint8_t *buf = NULL; 100 size_t req_size = 0; 101 size_t len = 0; 102 103 conceal_seed_error(rng_base); 104 105 if (!(io_read32(rng_base + RNG_SR) & RNG_SR_DRDY)) { 106 FMSG("RNG not ready"); 107 return TEE_ERROR_NO_DATA; 108 } 109 110 if (io_read32(rng_base + RNG_SR) & RNG_SR_SEIS) { 111 FMSG("RNG noise error"); 112 return TEE_ERROR_NO_DATA; 113 } 114 115 buf = out; 116 req_size = MIN(RNG_FIFO_BYTE_DEPTH, *size); 117 len = req_size; 118 119 /* RNG is ready: read up to 4 32bit words */ 120 while (len) { 121 uint32_t data32 = io_read32(rng_base + RNG_DR); 122 size_t sz = MIN(len, sizeof(uint32_t)); 123 124 memcpy(buf, &data32, sz); 125 buf += sz; 126 len -= sz; 127 } 128 129 *size = req_size; 130 131 return TEE_SUCCESS; 132 } 133 134 static TEE_Result init_rng(void) 135 { 136 vaddr_t rng_base = get_base(); 137 uint64_t timeout_ref = 0; 138 139 /* Clean error indications */ 140 io_write32(rng_base + RNG_SR, 0); 141 142 io_setbits32(rng_base + RNG_CR, RNG_CR_RNGEN | RNG_CR_CED); 143 144 timeout_ref = timeout_init_us(RNG_READY_TIMEOUT_US); 145 while (!(io_read32(rng_base + RNG_SR) & RNG_SR_DRDY)) 146 if (timeout_elapsed(timeout_ref)) 147 break; 148 149 if (!(io_read32(rng_base + RNG_SR) & RNG_SR_DRDY)) 150 return TEE_ERROR_GENERIC; 151 152 return TEE_SUCCESS; 153 } 154 155 TEE_Result stm32_rng_read(uint8_t *out, size_t size) 156 { 157 TEE_Result rc = TEE_ERROR_GENERIC; 158 bool burst_timeout = false; 159 uint64_t timeout_ref = 0; 160 uint32_t exceptions = 0; 161 uint8_t *out_ptr = out; 162 vaddr_t rng_base = 0; 163 size_t out_size = 0; 164 165 if (!stm32_rng) { 166 DMSG("No RNG"); 167 return TEE_ERROR_NOT_SUPPORTED; 168 } 169 170 clk_enable(stm32_rng->clock); 171 rng_base = get_base(); 172 173 /* Arm timeout */ 174 timeout_ref = timeout_init_us(RNG_READY_TIMEOUT_US); 175 burst_timeout = false; 176 177 while (out_size < size) { 178 /* Read by chunks of the size the RNG FIFO depth */ 179 size_t sz = size - out_size; 180 181 exceptions = may_spin_lock(&stm32_rng->lock); 182 183 rc = read_available(rng_base, out_ptr, &sz); 184 185 /* Raise timeout only if we failed to get some samples */ 186 assert(!rc || rc == TEE_ERROR_NO_DATA); 187 if (rc) 188 burst_timeout = timeout_elapsed(timeout_ref); 189 190 may_spin_unlock(&stm32_rng->lock, exceptions); 191 192 if (burst_timeout) { 193 rc = TEE_ERROR_GENERIC; 194 goto out; 195 } 196 197 if (!rc) { 198 out_size += sz; 199 out_ptr += sz; 200 /* Re-arm timeout */ 201 timeout_ref = timeout_init_us(RNG_READY_TIMEOUT_US); 202 burst_timeout = false; 203 } 204 } 205 206 out: 207 assert(!rc || rc == TEE_ERROR_GENERIC); 208 clk_disable(stm32_rng->clock); 209 210 return rc; 211 } 212 213 #ifdef CFG_WITH_SOFTWARE_PRNG 214 /* Override weak plat_rng_init with platform handler to seed PRNG */ 215 void plat_rng_init(void) 216 { 217 uint8_t seed[RNG_FIFO_BYTE_DEPTH] = { }; 218 219 if (stm32_rng_read(seed, sizeof(seed))) 220 panic(); 221 222 if (crypto_rng_init(seed, sizeof(seed))) 223 panic(); 224 225 DMSG("PRNG seeded with RNG"); 226 } 227 #else 228 TEE_Result hw_get_random_bytes(void *out, size_t size) 229 { 230 return stm32_rng_read(out, size); 231 } 232 #endif 233 234 #ifdef CFG_EMBED_DTB 235 static TEE_Result stm32_rng_parse_fdt(const void *fdt, int node) 236 { 237 TEE_Result res = TEE_ERROR_GENERIC; 238 struct dt_node_info dt_rng = { }; 239 240 _fdt_fill_device_info(fdt, &dt_rng, node); 241 if (dt_rng.reg == DT_INFO_INVALID_REG) 242 return TEE_ERROR_BAD_PARAMETERS; 243 244 stm32_rng->base.pa = dt_rng.reg; 245 stm32_rng->base.va = io_pa_or_va_secure(&stm32_rng->base, 246 dt_rng.reg_size); 247 assert(stm32_rng->base.va); 248 249 res = rstctrl_dt_get_by_index(fdt, node, 0, &stm32_rng->rstctrl); 250 if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND) 251 return res; 252 253 res = clk_dt_get_by_index(fdt, node, 0, &stm32_rng->clock); 254 if (res) 255 return res; 256 257 /* Release device if not used at runtime or for pm transitions */ 258 stm32_rng->release_post_boot = IS_ENABLED(CFG_WITH_SOFTWARE_PRNG) && 259 !IS_ENABLED(CFG_PM); 260 261 return TEE_SUCCESS; 262 } 263 264 static TEE_Result stm32_rng_probe(const void *fdt, int offs, 265 const void *compat_data __unused) 266 { 267 TEE_Result res = TEE_ERROR_GENERIC; 268 269 /* Expect a single RNG instance */ 270 assert(!stm32_rng); 271 272 stm32_rng = calloc(1, sizeof(*stm32_rng)); 273 if (!stm32_rng) 274 panic(); 275 276 res = stm32_rng_parse_fdt(fdt, offs); 277 if (res) 278 goto err; 279 280 res = clk_enable(stm32_rng->clock); 281 if (res) 282 goto err; 283 284 if (stm32_rng->rstctrl && 285 rstctrl_assert_to(stm32_rng->rstctrl, RNG_RESET_TIMEOUT_US)) { 286 res = TEE_ERROR_GENERIC; 287 goto err_clk; 288 } 289 290 if (stm32_rng->rstctrl && 291 rstctrl_deassert_to(stm32_rng->rstctrl, RNG_RESET_TIMEOUT_US)) { 292 res = TEE_ERROR_GENERIC; 293 goto err_clk; 294 } 295 296 res = init_rng(); 297 if (res) 298 goto err_clk; 299 300 clk_disable(stm32_rng->clock); 301 302 if (stm32_rng->release_post_boot) 303 stm32mp_register_non_secure_periph_iomem(stm32_rng->base.pa); 304 else 305 stm32mp_register_secure_periph_iomem(stm32_rng->base.pa); 306 307 return TEE_SUCCESS; 308 309 err_clk: 310 clk_disable(stm32_rng->clock); 311 err: 312 free(stm32_rng); 313 stm32_rng = NULL; 314 315 return res; 316 } 317 318 static const struct dt_device_match rng_match_table[] = { 319 { .compatible = "st,stm32-rng" }, 320 { .compatible = "st,stm32mp13-rng" }, 321 { } 322 }; 323 324 DEFINE_DT_DRIVER(stm32_rng_dt_driver) = { 325 .name = "stm32_rng", 326 .match_table = rng_match_table, 327 .probe = stm32_rng_probe, 328 }; 329 330 static TEE_Result stm32_rng_release(void) 331 { 332 if (stm32_rng && stm32_rng->release_post_boot) { 333 DMSG("Release RNG driver"); 334 free(stm32_rng); 335 stm32_rng = NULL; 336 } 337 338 return TEE_SUCCESS; 339 } 340 341 release_init_resource(stm32_rng_release); 342 #endif /*CFG_EMBED_DTB*/ 343