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