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