xref: /optee_os/core/drivers/stm32_rng.c (revision f63f11bd1763a2f01e7e56c5c48d57bba9090082)
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