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