xref: /optee_os/core/drivers/stm32_rng.c (revision ba2a6adb764f1310ad3c3091d89de84274f86b02)
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 <io.h>
11 #include <kernel/delay.h>
12 #include <kernel/dt.h>
13 #include <kernel/dt_driver.h>
14 #include <kernel/boot.h>
15 #include <kernel/panic.h>
16 #include <kernel/pm.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 #define RNG_CR_CLKDIV		GENMASK_32(19, 16)
34 #define RNG_CR_CLKDIV_SHIFT	U(16)
35 #define RNG_CR_CONDRST		BIT(30)
36 
37 #define RNG_SR_DRDY		BIT(0)
38 #define RNG_SR_CECS		BIT(1)
39 #define RNG_SR_SECS		BIT(2)
40 #define RNG_SR_CEIS		BIT(5)
41 #define RNG_SR_SEIS		BIT(6)
42 
43 #if TRACE_LEVEL > TRACE_DEBUG
44 #define RNG_READY_TIMEOUT_US	U(100000)
45 #else
46 #define RNG_READY_TIMEOUT_US	U(10000)
47 #endif
48 #define RNG_RESET_TIMEOUT_US	U(1000)
49 
50 #define RNG_FIFO_BYTE_DEPTH	U(16)
51 
52 #define RNG_NIST_CONFIG_A	U(0x0F00D00)
53 #define RNG_NIST_CONFIG_B	U(0x1801000)
54 #define RNG_NIST_CONFIG_MASK	GENMASK_32(25, 8)
55 
56 #define RNG_MAX_NOISE_CLK_FREQ	U(3000000)
57 
58 struct stm32_rng_driver_data {
59 	bool has_cond_reset;
60 };
61 
62 struct stm32_rng_instance {
63 	struct io_pa_va base;
64 	struct clk *clock;
65 	struct rstctrl *rstctrl;
66 	const struct stm32_rng_driver_data *ddata;
67 	unsigned int lock;
68 	bool release_post_boot;
69 	bool clock_error;
70 	bool error_conceal;
71 	uint64_t error_to_ref;
72 };
73 
74 /* Expect at most a single RNG instance */
75 static struct stm32_rng_instance *stm32_rng;
76 
77 static vaddr_t get_base(void)
78 {
79 	assert(stm32_rng);
80 
81 	return io_pa_or_va(&stm32_rng->base, 1);
82 }
83 
84 /*
85  * Extracts from the STM32 RNG specification when RNG supports CONDRST.
86  *
87  * When a noise source (or seed) error occurs, the RNG stops generating
88  * random numbers and sets to “1” both SEIS and SECS bits to indicate
89  * that a seed error occurred. (...)
90  *
91  * 1. Software reset by writing CONDRST at 1 and at 0 (see bitfield
92  * description for details). This step is needed only if SECS is set.
93  * Indeed, when SEIS is set and SECS is cleared it means RNG performed
94  * the reset automatically (auto-reset).
95  * 2. If SECS was set in step 1 (no auto-reset) wait for CONDRST
96  * to be cleared in the RNG_CR register, then confirm that SEIS is
97  * cleared in the RNG_SR register. Otherwise just clear SEIS bit in
98  * the RNG_SR register.
99  * 3. If SECS was set in step 1 (no auto-reset) wait for SECS to be
100  * cleared by RNG. The random number generation is now back to normal.
101  */
102 static void conceal_seed_error_cond_reset(void)
103 {
104 	struct stm32_rng_instance *dev = stm32_rng;
105 	vaddr_t rng_base = get_base();
106 
107 	if (!dev->error_conceal) {
108 		uint32_t sr = io_read32(rng_base + RNG_SR);
109 
110 		if (sr & RNG_SR_SECS) {
111 			/* Conceal by resetting the subsystem (step 1.) */
112 			io_setbits32(rng_base + RNG_CR, RNG_CR_CONDRST);
113 			io_clrbits32(rng_base + RNG_CR, RNG_CR_CONDRST);
114 
115 			/* Arm timeout for error_conceal sequence */
116 			dev->error_to_ref =
117 				timeout_init_us(RNG_READY_TIMEOUT_US);
118 			dev->error_conceal = true;
119 		} else {
120 			/* RNG auto-reset (step 2.) */
121 			io_clrbits32(rng_base + RNG_SR, RNG_SR_SEIS);
122 		}
123 	} else {
124 		/* Measure time before possible reschedule */
125 		bool timed_out = timeout_elapsed(dev->error_to_ref);
126 
127 		/* Wait CONDRST is cleared (step 2.) */
128 		if (io_read32(rng_base + RNG_CR) & RNG_CR_CONDRST) {
129 			if (timed_out)
130 				panic();
131 
132 			/* Wait subsystem reset cycle completes */
133 			return;
134 		}
135 
136 		/* Check SEIS is cleared (step 2.) */
137 		if (io_read32(rng_base + RNG_SR) & RNG_SR_SEIS)
138 			panic();
139 
140 		/* Wait SECS is cleared (step 3.) */
141 		if (io_read32(rng_base + RNG_SR) & RNG_SR_SECS) {
142 			if (timed_out)
143 				panic();
144 
145 			/* Wait subsystem reset cycle completes */
146 			return;
147 		}
148 
149 		dev->error_conceal = false;
150 	}
151 }
152 
153 /*
154  * Extracts from the STM32 RNG specification, when CONDRST is not supported
155  *
156  * When a noise source (or seed) error occurs, the RNG stops generating
157  * random numbers and sets to “1” both SEIS and SECS bits to indicate
158  * that a seed error occurred. (...)
159  *
160  * The following sequence shall be used to fully recover from a seed
161  * error after the RNG initialization:
162  * 1. Clear the SEIS bit by writing it to “0”.
163  * 2. Read out 12 words from the RNG_DR register, and discard each of
164  * them in order to clean the pipeline.
165  * 3. Confirm that SEIS is still cleared. Random number generation is
166  * back to normal.
167  */
168 static void conceal_seed_error_sw_reset(void)
169 {
170 	vaddr_t rng_base = get_base();
171 	size_t i = 0;
172 
173 	io_clrbits32(rng_base + RNG_SR, RNG_SR_SEIS);
174 
175 	for (i = 12; i != 0; i--)
176 		(void)io_read32(rng_base + RNG_DR);
177 
178 	if (io_read32(rng_base + RNG_SR) & RNG_SR_SEIS)
179 		panic("RNG noise");
180 }
181 
182 static void conceal_seed_error(void)
183 {
184 	if (stm32_rng->ddata->has_cond_reset)
185 		conceal_seed_error_cond_reset();
186 	else
187 		conceal_seed_error_sw_reset();
188 }
189 
190 static TEE_Result read_available(vaddr_t rng_base, uint8_t *out, size_t *size)
191 {
192 	struct stm32_rng_instance *dev = stm32_rng;
193 	uint8_t *buf = NULL;
194 	size_t req_size = 0;
195 	size_t len = 0;
196 
197 	if (dev->error_conceal || io_read32(rng_base + RNG_SR) & RNG_SR_SEIS)
198 		conceal_seed_error();
199 
200 	if (!(io_read32(rng_base + RNG_SR) & RNG_SR_DRDY)) {
201 		FMSG("RNG not ready");
202 		return TEE_ERROR_NO_DATA;
203 	}
204 
205 	if (io_read32(rng_base + RNG_SR) & RNG_SR_SEIS) {
206 		FMSG("RNG noise error");
207 		return TEE_ERROR_NO_DATA;
208 	}
209 
210 	buf = out;
211 	req_size = MIN(RNG_FIFO_BYTE_DEPTH, *size);
212 	len = req_size;
213 
214 	/* RNG is ready: read up to 4 32bit words */
215 	while (len) {
216 		uint32_t data32 = 0;
217 		size_t sz = MIN(len, sizeof(uint32_t));
218 
219 		if (!(io_read32(rng_base + RNG_SR) & RNG_SR_DRDY))
220 			break;
221 		data32 = io_read32(rng_base + RNG_DR);
222 
223 		/* Late seed error case: DR being 0 is an error status */
224 		if (!data32) {
225 			conceal_seed_error();
226 			return TEE_ERROR_NO_DATA;
227 		}
228 
229 		memcpy(buf, &data32, sz);
230 		buf += sz;
231 		len -= sz;
232 	}
233 
234 	*size = req_size - len;
235 
236 	return TEE_SUCCESS;
237 }
238 
239 static uint32_t stm32_rng_clock_freq_restrain(void)
240 {
241 	struct stm32_rng_instance *dev = stm32_rng;
242 	unsigned long clock_rate = 0;
243 	uint32_t clock_div = 0;
244 
245 	clock_rate = clk_get_rate(dev->clock);
246 
247 	/*
248 	 * Get the exponent to apply on the CLKDIV field in RNG_CR register
249 	 * No need to handle the case when clock-div > 0xF as it is physically
250 	 * impossible
251 	 */
252 	while ((clock_rate >> clock_div) > RNG_MAX_NOISE_CLK_FREQ)
253 		clock_div++;
254 
255 	DMSG("RNG clk rate : %lu", clk_get_rate(dev->clock) >> clock_div);
256 
257 	return clock_div;
258 }
259 
260 static TEE_Result init_rng(void)
261 {
262 	vaddr_t rng_base = get_base();
263 	uint64_t timeout_ref = 0;
264 	uint32_t cr_ced_mask = 0;
265 
266 	if (!stm32_rng->clock_error)
267 		cr_ced_mask = RNG_CR_CED;
268 
269 	/* Clean error indications */
270 	io_write32(rng_base + RNG_SR, 0);
271 
272 	if (stm32_rng->ddata->has_cond_reset) {
273 		uint32_t clock_div = stm32_rng_clock_freq_restrain();
274 
275 		/* Update configuration fields */
276 		io_clrsetbits32(rng_base + RNG_CR, RNG_NIST_CONFIG_MASK,
277 				RNG_NIST_CONFIG_B | RNG_CR_CONDRST |
278 				cr_ced_mask);
279 		io_clrsetbits32(rng_base + RNG_CR, RNG_CR_CLKDIV,
280 				clock_div << RNG_CR_CLKDIV_SHIFT);
281 
282 		/* No need to wait for RNG_CR_CONDRST toggle as we enable clk */
283 		io_clrsetbits32(rng_base + RNG_CR, RNG_CR_CONDRST,
284 				RNG_CR_RNGEN);
285 	} else {
286 		io_setbits32(rng_base + RNG_CR, RNG_CR_RNGEN | cr_ced_mask);
287 	}
288 
289 	timeout_ref = timeout_init_us(RNG_READY_TIMEOUT_US);
290 	while (!(io_read32(rng_base + RNG_SR) & RNG_SR_DRDY))
291 		if (timeout_elapsed(timeout_ref))
292 			break;
293 
294 	if (!(io_read32(rng_base + RNG_SR) & RNG_SR_DRDY))
295 		return TEE_ERROR_GENERIC;
296 
297 	return TEE_SUCCESS;
298 }
299 
300 static TEE_Result stm32_rng_read(uint8_t *out, size_t size)
301 {
302 	TEE_Result rc = TEE_ERROR_GENERIC;
303 	bool burst_timeout = false;
304 	uint64_t timeout_ref = 0;
305 	uint32_t exceptions = 0;
306 	uint8_t *out_ptr = out;
307 	vaddr_t rng_base = 0;
308 	size_t out_size = 0;
309 
310 	if (!stm32_rng) {
311 		DMSG("No RNG");
312 		return TEE_ERROR_NOT_SUPPORTED;
313 	}
314 
315 	clk_enable(stm32_rng->clock);
316 	rng_base = get_base();
317 
318 	/* Arm timeout */
319 	timeout_ref = timeout_init_us(RNG_READY_TIMEOUT_US);
320 	burst_timeout = false;
321 
322 	while (out_size < size) {
323 		/* Read by chunks of the size the RNG FIFO depth */
324 		size_t sz = size - out_size;
325 
326 		exceptions = may_spin_lock(&stm32_rng->lock);
327 
328 		rc = read_available(rng_base, out_ptr, &sz);
329 
330 		/* Raise timeout only if we failed to get some samples */
331 		assert(!rc || rc == TEE_ERROR_NO_DATA);
332 		if (rc)
333 			burst_timeout = timeout_elapsed(timeout_ref);
334 
335 		may_spin_unlock(&stm32_rng->lock, exceptions);
336 
337 		if (burst_timeout) {
338 			rc = TEE_ERROR_GENERIC;
339 			goto out;
340 		}
341 
342 		if (!rc) {
343 			out_size += sz;
344 			out_ptr += sz;
345 			/* Re-arm timeout */
346 			timeout_ref = timeout_init_us(RNG_READY_TIMEOUT_US);
347 			burst_timeout = false;
348 		}
349 	}
350 
351 out:
352 	assert(!rc || rc == TEE_ERROR_GENERIC);
353 	clk_disable(stm32_rng->clock);
354 
355 	return rc;
356 }
357 
358 #ifdef CFG_WITH_SOFTWARE_PRNG
359 /* Override weak plat_rng_init with platform handler to seed PRNG */
360 void plat_rng_init(void)
361 {
362 	uint8_t seed[RNG_FIFO_BYTE_DEPTH] = { };
363 
364 	if (stm32_rng_read(seed, sizeof(seed)))
365 		panic();
366 
367 	if (crypto_rng_init(seed, sizeof(seed)))
368 		panic();
369 
370 	DMSG("PRNG seeded with RNG");
371 }
372 #else
373 TEE_Result hw_get_random_bytes(void *out, size_t size)
374 {
375 	return stm32_rng_read(out, size);
376 }
377 
378 void plat_rng_init(void)
379 {
380 }
381 #endif
382 
383 static TEE_Result stm32_rng_pm_resume(uint32_t pm_cr)
384 {
385 	vaddr_t base = get_base();
386 
387 	/* Clean error indications */
388 	io_write32(base + RNG_SR, 0);
389 
390 	if (stm32_rng->ddata->has_cond_reset) {
391 		/*
392 		 * Correct configuration in bits [29:4] must be set in the same
393 		 * access that set RNG_CR_CONDRST bit. Else config setting is
394 		 * not taken into account.
395 		 */
396 		io_write32(base + RNG_CR, pm_cr | RNG_CR_CONDRST);
397 
398 		io_clrsetbits32(base + RNG_CR, RNG_CR_CONDRST, RNG_CR_RNGEN);
399 	} else {
400 		io_write32(base + RNG_CR, RNG_CR_RNGEN | pm_cr);
401 	}
402 
403 	return TEE_SUCCESS;
404 }
405 
406 static TEE_Result
407 stm32_rng_pm(enum pm_op op, unsigned int pm_hint __unused,
408 	     const struct pm_callback_handle *pm_handle __unused)
409 {
410 	static uint32_t pm_cr;
411 	TEE_Result res = TEE_ERROR_GENERIC;
412 
413 	assert(stm32_rng && (op == PM_OP_SUSPEND || op == PM_OP_RESUME));
414 
415 	res = clk_enable(stm32_rng->clock);
416 	if (res)
417 		return res;
418 
419 	if (op == PM_OP_SUSPEND)
420 		pm_cr = io_read32(get_base() + RNG_CR);
421 	else
422 		res = stm32_rng_pm_resume(pm_cr);
423 
424 	clk_disable(stm32_rng->clock);
425 
426 	return res;
427 }
428 DECLARE_KEEP_PAGER(stm32_rng_pm);
429 
430 static TEE_Result stm32_rng_parse_fdt(const void *fdt, int node)
431 {
432 	TEE_Result res = TEE_ERROR_GENERIC;
433 	struct dt_node_info dt_rng = { };
434 
435 	fdt_fill_device_info(fdt, &dt_rng, node);
436 	if (dt_rng.reg == DT_INFO_INVALID_REG)
437 		return TEE_ERROR_BAD_PARAMETERS;
438 
439 	stm32_rng->base.pa = dt_rng.reg;
440 	stm32_rng->base.va = io_pa_or_va_secure(&stm32_rng->base,
441 						dt_rng.reg_size);
442 	assert(stm32_rng->base.va);
443 
444 	res = rstctrl_dt_get_by_index(fdt, node, 0, &stm32_rng->rstctrl);
445 	if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND)
446 		return res;
447 
448 	res = clk_dt_get_by_index(fdt, node, 0, &stm32_rng->clock);
449 	if (res)
450 		return res;
451 
452 	if (fdt_getprop(fdt, node, "clock-error-detect", NULL))
453 		stm32_rng->clock_error = true;
454 
455 	/* Release device if not used at runtime or for pm transitions */
456 	stm32_rng->release_post_boot = IS_ENABLED(CFG_WITH_SOFTWARE_PRNG) &&
457 				       !IS_ENABLED(CFG_PM);
458 
459 	return TEE_SUCCESS;
460 }
461 
462 static TEE_Result stm32_rng_probe(const void *fdt, int offs,
463 				  const void *compat_data __unused)
464 {
465 	TEE_Result res = TEE_ERROR_GENERIC;
466 
467 	/* Expect a single RNG instance */
468 	assert(!stm32_rng);
469 
470 	stm32_rng = calloc(1, sizeof(*stm32_rng));
471 	if (!stm32_rng)
472 		panic();
473 
474 	res = stm32_rng_parse_fdt(fdt, offs);
475 	if (res)
476 		goto err;
477 
478 	stm32_rng->ddata = compat_data;
479 	assert(stm32_rng->ddata);
480 
481 	res = clk_enable(stm32_rng->clock);
482 	if (res)
483 		goto err;
484 
485 	if (stm32_rng->rstctrl &&
486 	    rstctrl_assert_to(stm32_rng->rstctrl, RNG_RESET_TIMEOUT_US)) {
487 		res = TEE_ERROR_GENERIC;
488 		goto err_clk;
489 	}
490 
491 	if (stm32_rng->rstctrl &&
492 	    rstctrl_deassert_to(stm32_rng->rstctrl, RNG_RESET_TIMEOUT_US)) {
493 		res = TEE_ERROR_GENERIC;
494 		goto err_clk;
495 	}
496 
497 	res = init_rng();
498 	if (res)
499 		goto err_clk;
500 
501 	clk_disable(stm32_rng->clock);
502 
503 	if (stm32_rng->release_post_boot)
504 		stm32mp_register_non_secure_periph_iomem(stm32_rng->base.pa);
505 	else
506 		stm32mp_register_secure_periph_iomem(stm32_rng->base.pa);
507 
508 	register_pm_core_service_cb(stm32_rng_pm, &stm32_rng, "rng-service");
509 
510 	return TEE_SUCCESS;
511 
512 err_clk:
513 	clk_disable(stm32_rng->clock);
514 err:
515 	free(stm32_rng);
516 	stm32_rng = NULL;
517 
518 	return res;
519 }
520 
521 static const struct stm32_rng_driver_data mp13_data[] = {
522 	{ .has_cond_reset = true },
523 };
524 
525 static const struct stm32_rng_driver_data mp15_data[] = {
526 	{ .has_cond_reset = false },
527 };
528 DECLARE_KEEP_PAGER(mp15_data);
529 
530 static const struct dt_device_match rng_match_table[] = {
531 	{ .compatible = "st,stm32-rng", .compat_data = &mp15_data },
532 	{ .compatible = "st,stm32mp13-rng", .compat_data = &mp13_data },
533 	{ }
534 };
535 
536 DEFINE_DT_DRIVER(stm32_rng_dt_driver) = {
537 	.name = "stm32_rng",
538 	.match_table = rng_match_table,
539 	.probe = stm32_rng_probe,
540 };
541 
542 static TEE_Result stm32_rng_release(void)
543 {
544 	if (stm32_rng && stm32_rng->release_post_boot) {
545 		DMSG("Release RNG driver");
546 		free(stm32_rng);
547 		stm32_rng = NULL;
548 	}
549 
550 	return TEE_SUCCESS;
551 }
552 
553 release_init_resource(stm32_rng_release);
554