xref: /optee_os/core/drivers/stm32_rng.c (revision cb5f271c1eaed4c18fd26873f152afc0590b0413)
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 = io_read32(rng_base + RNG_DR);
217 		size_t sz = MIN(len, sizeof(uint32_t));
218 
219 		/* Late seed error case: DR being 0 is an error status */
220 		if (!data32) {
221 			conceal_seed_error();
222 			return TEE_ERROR_NO_DATA;
223 		}
224 
225 		memcpy(buf, &data32, sz);
226 		buf += sz;
227 		len -= sz;
228 	}
229 
230 	*size = req_size;
231 
232 	return TEE_SUCCESS;
233 }
234 
235 static uint32_t stm32_rng_clock_freq_restrain(void)
236 {
237 	struct stm32_rng_instance *dev = stm32_rng;
238 	unsigned long clock_rate = 0;
239 	uint32_t clock_div = 0;
240 
241 	clock_rate = clk_get_rate(dev->clock);
242 
243 	/*
244 	 * Get the exponent to apply on the CLKDIV field in RNG_CR register
245 	 * No need to handle the case when clock-div > 0xF as it is physically
246 	 * impossible
247 	 */
248 	while ((clock_rate >> clock_div) > RNG_MAX_NOISE_CLK_FREQ)
249 		clock_div++;
250 
251 	DMSG("RNG clk rate : %lu", clk_get_rate(dev->clock) >> clock_div);
252 
253 	return clock_div;
254 }
255 
256 static TEE_Result init_rng(void)
257 {
258 	vaddr_t rng_base = get_base();
259 	uint64_t timeout_ref = 0;
260 	uint32_t cr_ced_mask = 0;
261 
262 	if (!stm32_rng->clock_error)
263 		cr_ced_mask = RNG_CR_CED;
264 
265 	/* Clean error indications */
266 	io_write32(rng_base + RNG_SR, 0);
267 
268 	if (stm32_rng->ddata->has_cond_reset) {
269 		uint32_t clock_div = stm32_rng_clock_freq_restrain();
270 
271 		/* Update configuration fields */
272 		io_clrsetbits32(rng_base + RNG_CR, RNG_NIST_CONFIG_MASK,
273 				RNG_NIST_CONFIG_B | RNG_CR_CONDRST |
274 				cr_ced_mask);
275 		io_clrsetbits32(rng_base + RNG_CR, RNG_CR_CLKDIV,
276 				clock_div << RNG_CR_CLKDIV_SHIFT);
277 
278 		/* No need to wait for RNG_CR_CONDRST toggle as we enable clk */
279 		io_clrsetbits32(rng_base + RNG_CR, RNG_CR_CONDRST,
280 				RNG_CR_RNGEN);
281 	} else {
282 		io_setbits32(rng_base + RNG_CR, RNG_CR_RNGEN | cr_ced_mask);
283 	}
284 
285 	timeout_ref = timeout_init_us(RNG_READY_TIMEOUT_US);
286 	while (!(io_read32(rng_base + RNG_SR) & RNG_SR_DRDY))
287 		if (timeout_elapsed(timeout_ref))
288 			break;
289 
290 	if (!(io_read32(rng_base + RNG_SR) & RNG_SR_DRDY))
291 		return TEE_ERROR_GENERIC;
292 
293 	return TEE_SUCCESS;
294 }
295 
296 static TEE_Result stm32_rng_read(uint8_t *out, size_t size)
297 {
298 	TEE_Result rc = TEE_ERROR_GENERIC;
299 	bool burst_timeout = false;
300 	uint64_t timeout_ref = 0;
301 	uint32_t exceptions = 0;
302 	uint8_t *out_ptr = out;
303 	vaddr_t rng_base = 0;
304 	size_t out_size = 0;
305 
306 	if (!stm32_rng) {
307 		DMSG("No RNG");
308 		return TEE_ERROR_NOT_SUPPORTED;
309 	}
310 
311 	clk_enable(stm32_rng->clock);
312 	rng_base = get_base();
313 
314 	/* Arm timeout */
315 	timeout_ref = timeout_init_us(RNG_READY_TIMEOUT_US);
316 	burst_timeout = false;
317 
318 	while (out_size < size) {
319 		/* Read by chunks of the size the RNG FIFO depth */
320 		size_t sz = size - out_size;
321 
322 		exceptions = may_spin_lock(&stm32_rng->lock);
323 
324 		rc = read_available(rng_base, out_ptr, &sz);
325 
326 		/* Raise timeout only if we failed to get some samples */
327 		assert(!rc || rc == TEE_ERROR_NO_DATA);
328 		if (rc)
329 			burst_timeout = timeout_elapsed(timeout_ref);
330 
331 		may_spin_unlock(&stm32_rng->lock, exceptions);
332 
333 		if (burst_timeout) {
334 			rc = TEE_ERROR_GENERIC;
335 			goto out;
336 		}
337 
338 		if (!rc) {
339 			out_size += sz;
340 			out_ptr += sz;
341 			/* Re-arm timeout */
342 			timeout_ref = timeout_init_us(RNG_READY_TIMEOUT_US);
343 			burst_timeout = false;
344 		}
345 	}
346 
347 out:
348 	assert(!rc || rc == TEE_ERROR_GENERIC);
349 	clk_disable(stm32_rng->clock);
350 
351 	return rc;
352 }
353 
354 #ifdef CFG_WITH_SOFTWARE_PRNG
355 /* Override weak plat_rng_init with platform handler to seed PRNG */
356 void plat_rng_init(void)
357 {
358 	uint8_t seed[RNG_FIFO_BYTE_DEPTH] = { };
359 
360 	if (stm32_rng_read(seed, sizeof(seed)))
361 		panic();
362 
363 	if (crypto_rng_init(seed, sizeof(seed)))
364 		panic();
365 
366 	DMSG("PRNG seeded with RNG");
367 }
368 #else
369 TEE_Result hw_get_random_bytes(void *out, size_t size)
370 {
371 	return stm32_rng_read(out, size);
372 }
373 
374 void plat_rng_init(void)
375 {
376 }
377 #endif
378 
379 static TEE_Result stm32_rng_pm_resume(uint32_t pm_cr)
380 {
381 	vaddr_t base = get_base();
382 
383 	/* Clean error indications */
384 	io_write32(base + RNG_SR, 0);
385 
386 	if (stm32_rng->ddata->has_cond_reset) {
387 		/*
388 		 * Correct configuration in bits [29:4] must be set in the same
389 		 * access that set RNG_CR_CONDRST bit. Else config setting is
390 		 * not taken into account.
391 		 */
392 		io_write32(base + RNG_CR, pm_cr | RNG_CR_CONDRST);
393 
394 		io_clrsetbits32(base + RNG_CR, RNG_CR_CONDRST, RNG_CR_RNGEN);
395 	} else {
396 		io_write32(base + RNG_CR, RNG_CR_RNGEN | pm_cr);
397 	}
398 
399 	return TEE_SUCCESS;
400 }
401 
402 static TEE_Result
403 stm32_rng_pm(enum pm_op op, unsigned int pm_hint __unused,
404 	     const struct pm_callback_handle *pm_handle __unused)
405 {
406 	static uint32_t pm_cr;
407 	TEE_Result res = TEE_ERROR_GENERIC;
408 
409 	assert(stm32_rng && (op == PM_OP_SUSPEND || op == PM_OP_RESUME));
410 
411 	res = clk_enable(stm32_rng->clock);
412 	if (res)
413 		return res;
414 
415 	if (op == PM_OP_SUSPEND)
416 		pm_cr = io_read32(get_base() + RNG_CR);
417 	else
418 		res = stm32_rng_pm_resume(pm_cr);
419 
420 	clk_disable(stm32_rng->clock);
421 
422 	return res;
423 }
424 DECLARE_KEEP_PAGER(stm32_rng_pm);
425 
426 #ifdef CFG_EMBED_DTB
427 static TEE_Result stm32_rng_parse_fdt(const void *fdt, int node)
428 {
429 	TEE_Result res = TEE_ERROR_GENERIC;
430 	struct dt_node_info dt_rng = { };
431 
432 	_fdt_fill_device_info(fdt, &dt_rng, node);
433 	if (dt_rng.reg == DT_INFO_INVALID_REG)
434 		return TEE_ERROR_BAD_PARAMETERS;
435 
436 	stm32_rng->base.pa = dt_rng.reg;
437 	stm32_rng->base.va = io_pa_or_va_secure(&stm32_rng->base,
438 						dt_rng.reg_size);
439 	assert(stm32_rng->base.va);
440 
441 	res = rstctrl_dt_get_by_index(fdt, node, 0, &stm32_rng->rstctrl);
442 	if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND)
443 		return res;
444 
445 	res = clk_dt_get_by_index(fdt, node, 0, &stm32_rng->clock);
446 	if (res)
447 		return res;
448 
449 	if (fdt_getprop(fdt, node, "clock-error-detect", NULL))
450 		stm32_rng->clock_error = true;
451 
452 	/* Release device if not used at runtime or for pm transitions */
453 	stm32_rng->release_post_boot = IS_ENABLED(CFG_WITH_SOFTWARE_PRNG) &&
454 				       !IS_ENABLED(CFG_PM);
455 
456 	return TEE_SUCCESS;
457 }
458 
459 static TEE_Result stm32_rng_probe(const void *fdt, int offs,
460 				  const void *compat_data __unused)
461 {
462 	TEE_Result res = TEE_ERROR_GENERIC;
463 
464 	/* Expect a single RNG instance */
465 	assert(!stm32_rng);
466 
467 	stm32_rng = calloc(1, sizeof(*stm32_rng));
468 	if (!stm32_rng)
469 		panic();
470 
471 	res = stm32_rng_parse_fdt(fdt, offs);
472 	if (res)
473 		goto err;
474 
475 	stm32_rng->ddata = compat_data;
476 	assert(stm32_rng->ddata);
477 
478 	res = clk_enable(stm32_rng->clock);
479 	if (res)
480 		goto err;
481 
482 	if (stm32_rng->rstctrl &&
483 	    rstctrl_assert_to(stm32_rng->rstctrl, RNG_RESET_TIMEOUT_US)) {
484 		res = TEE_ERROR_GENERIC;
485 		goto err_clk;
486 	}
487 
488 	if (stm32_rng->rstctrl &&
489 	    rstctrl_deassert_to(stm32_rng->rstctrl, RNG_RESET_TIMEOUT_US)) {
490 		res = TEE_ERROR_GENERIC;
491 		goto err_clk;
492 	}
493 
494 	res = init_rng();
495 	if (res)
496 		goto err_clk;
497 
498 	clk_disable(stm32_rng->clock);
499 
500 	if (stm32_rng->release_post_boot)
501 		stm32mp_register_non_secure_periph_iomem(stm32_rng->base.pa);
502 	else
503 		stm32mp_register_secure_periph_iomem(stm32_rng->base.pa);
504 
505 	register_pm_core_service_cb(stm32_rng_pm, &stm32_rng, "rng-service");
506 
507 	return TEE_SUCCESS;
508 
509 err_clk:
510 	clk_disable(stm32_rng->clock);
511 err:
512 	free(stm32_rng);
513 	stm32_rng = NULL;
514 
515 	return res;
516 }
517 
518 static const struct stm32_rng_driver_data mp13_data[] = {
519 	{ .has_cond_reset = true },
520 };
521 
522 static const struct stm32_rng_driver_data mp15_data[] = {
523 	{ .has_cond_reset = false },
524 };
525 DECLARE_KEEP_PAGER(mp15_data);
526 
527 static const struct dt_device_match rng_match_table[] = {
528 	{ .compatible = "st,stm32-rng", .compat_data = &mp15_data },
529 	{ .compatible = "st,stm32mp13-rng", .compat_data = &mp13_data },
530 	{ }
531 };
532 
533 DEFINE_DT_DRIVER(stm32_rng_dt_driver) = {
534 	.name = "stm32_rng",
535 	.match_table = rng_match_table,
536 	.probe = stm32_rng_probe,
537 };
538 
539 static TEE_Result stm32_rng_release(void)
540 {
541 	if (stm32_rng && stm32_rng->release_post_boot) {
542 		DMSG("Release RNG driver");
543 		free(stm32_rng);
544 		stm32_rng = NULL;
545 	}
546 
547 	return TEE_SUCCESS;
548 }
549 
550 release_init_resource(stm32_rng_release);
551 #endif /*CFG_EMBED_DTB*/
552