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