xref: /linux/drivers/crypto/xilinx/xilinx-trng.c (revision a619fe35ab41fded440d3762d4fbad84ff86a4d4)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * AMD Versal True Random Number Generator driver
4  * Copyright (c) 2024 - 2025 Advanced Micro Devices, Inc.
5  */
6 
7 #include <linux/bitfield.h>
8 #include <linux/clk.h>
9 #include <linux/crypto.h>
10 #include <linux/delay.h>
11 #include <linux/firmware/xlnx-zynqmp.h>
12 #include <linux/hw_random.h>
13 #include <linux/io.h>
14 #include <linux/iopoll.h>
15 #include <linux/kernel.h>
16 #include <linux/module.h>
17 #include <linux/mutex.h>
18 #include <linux/mod_devicetable.h>
19 #include <linux/platform_device.h>
20 #include <crypto/aes.h>
21 #include <crypto/df_sp80090a.h>
22 #include <crypto/internal/drbg.h>
23 #include <crypto/internal/cipher.h>
24 #include <crypto/internal/rng.h>
25 
26 /* TRNG Registers Offsets */
27 #define TRNG_STATUS_OFFSET			0x4U
28 #define TRNG_CTRL_OFFSET			0x8U
29 #define TRNG_EXT_SEED_OFFSET			0x40U
30 #define TRNG_PER_STRNG_OFFSET			0x80U
31 #define TRNG_CORE_OUTPUT_OFFSET			0xC0U
32 #define TRNG_RESET_OFFSET			0xD0U
33 #define TRNG_OSC_EN_OFFSET			0xD4U
34 
35 /* Mask values */
36 #define TRNG_RESET_VAL_MASK			BIT(0)
37 #define TRNG_OSC_EN_VAL_MASK			BIT(0)
38 #define TRNG_CTRL_PRNGSRST_MASK			BIT(0)
39 #define TRNG_CTRL_EUMODE_MASK			BIT(8)
40 #define TRNG_CTRL_TRSSEN_MASK			BIT(2)
41 #define TRNG_CTRL_PRNGSTART_MASK		BIT(5)
42 #define TRNG_CTRL_PRNGXS_MASK			BIT(3)
43 #define TRNG_CTRL_PRNGMODE_MASK			BIT(7)
44 #define TRNG_STATUS_DONE_MASK			BIT(0)
45 #define TRNG_STATUS_QCNT_MASK			GENMASK(11, 9)
46 #define TRNG_STATUS_QCNT_16_BYTES		0x800
47 
48 /* Sizes in bytes */
49 #define TRNG_SEED_LEN_BYTES			48U
50 #define TRNG_ENTROPY_SEED_LEN_BYTES		64U
51 #define TRNG_SEC_STRENGTH_SHIFT			5U
52 #define TRNG_SEC_STRENGTH_BYTES			BIT(TRNG_SEC_STRENGTH_SHIFT)
53 #define TRNG_BYTES_PER_REG			4U
54 #define TRNG_RESET_DELAY			10
55 #define TRNG_NUM_INIT_REGS			12U
56 #define TRNG_READ_4_WORD			4
57 #define TRNG_DATA_READ_DELAY			8000
58 
59 struct xilinx_rng {
60 	void __iomem *rng_base;
61 	struct device *dev;
62 	unsigned char *scratchpadbuf;
63 	struct crypto_aes_ctx *aesctx;
64 	struct mutex lock;	/* Protect access to TRNG device */
65 	struct hwrng trng;
66 };
67 
68 struct xilinx_rng_ctx {
69 	struct xilinx_rng *rng;
70 };
71 
72 static struct xilinx_rng *xilinx_rng_dev;
73 
xtrng_readwrite32(void __iomem * addr,u32 mask,u8 value)74 static void xtrng_readwrite32(void __iomem *addr, u32 mask, u8 value)
75 {
76 	u32 val;
77 
78 	val = ioread32(addr);
79 	val = (val & (~mask)) | (mask & value);
80 	iowrite32(val, addr);
81 }
82 
xtrng_trng_reset(void __iomem * addr)83 static void xtrng_trng_reset(void __iomem *addr)
84 {
85 	xtrng_readwrite32(addr + TRNG_RESET_OFFSET, TRNG_RESET_VAL_MASK, TRNG_RESET_VAL_MASK);
86 	udelay(TRNG_RESET_DELAY);
87 	xtrng_readwrite32(addr + TRNG_RESET_OFFSET, TRNG_RESET_VAL_MASK, 0);
88 }
89 
xtrng_hold_reset(void __iomem * addr)90 static void xtrng_hold_reset(void __iomem *addr)
91 {
92 	xtrng_readwrite32(addr + TRNG_CTRL_OFFSET, TRNG_CTRL_PRNGSRST_MASK,
93 			  TRNG_CTRL_PRNGSRST_MASK);
94 	iowrite32(TRNG_RESET_VAL_MASK, addr + TRNG_RESET_OFFSET);
95 	udelay(TRNG_RESET_DELAY);
96 }
97 
xtrng_softreset(struct xilinx_rng * rng)98 static void xtrng_softreset(struct xilinx_rng *rng)
99 {
100 	xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET, TRNG_CTRL_PRNGSRST_MASK,
101 			  TRNG_CTRL_PRNGSRST_MASK);
102 	udelay(TRNG_RESET_DELAY);
103 	xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET, TRNG_CTRL_PRNGSRST_MASK, 0);
104 }
105 
106 /* Return no. of bytes read */
xtrng_readblock32(void __iomem * rng_base,__be32 * buf,int blocks32,bool wait)107 static size_t xtrng_readblock32(void __iomem *rng_base, __be32 *buf, int blocks32, bool wait)
108 {
109 	int read = 0, ret;
110 	int timeout = 1;
111 	int i, idx;
112 	u32 val;
113 
114 	if (wait)
115 		timeout = TRNG_DATA_READ_DELAY;
116 
117 	for (i = 0; i < (blocks32 * 2); i++) {
118 		/* TRNG core generate data in 16 bytes. Read twice to complete 32 bytes read */
119 		ret = readl_poll_timeout(rng_base + TRNG_STATUS_OFFSET, val,
120 					 (val & TRNG_STATUS_QCNT_MASK) ==
121 					 TRNG_STATUS_QCNT_16_BYTES, !!wait, timeout);
122 		if (ret)
123 			break;
124 
125 		for (idx = 0; idx < TRNG_READ_4_WORD; idx++) {
126 			*(buf + read) = cpu_to_be32(ioread32(rng_base + TRNG_CORE_OUTPUT_OFFSET));
127 			read += 1;
128 		}
129 	}
130 	return read * 4;
131 }
132 
xtrng_collect_random_data(struct xilinx_rng * rng,u8 * rand_gen_buf,int no_of_random_bytes,bool wait)133 static int xtrng_collect_random_data(struct xilinx_rng *rng, u8 *rand_gen_buf,
134 				     int no_of_random_bytes, bool wait)
135 {
136 	u8 randbuf[TRNG_SEC_STRENGTH_BYTES];
137 	int byteleft, blocks, count = 0;
138 	int ret;
139 
140 	byteleft = no_of_random_bytes & (TRNG_SEC_STRENGTH_BYTES - 1);
141 	blocks = no_of_random_bytes >> TRNG_SEC_STRENGTH_SHIFT;
142 	xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET, TRNG_CTRL_PRNGSTART_MASK,
143 			  TRNG_CTRL_PRNGSTART_MASK);
144 	if (blocks) {
145 		ret = xtrng_readblock32(rng->rng_base, (__be32 *)rand_gen_buf, blocks, wait);
146 		if (!ret)
147 			return 0;
148 		count += ret;
149 	}
150 
151 	if (byteleft) {
152 		ret = xtrng_readblock32(rng->rng_base, (__be32 *)randbuf, 1, wait);
153 		if (!ret)
154 			return count;
155 		memcpy(rand_gen_buf + (blocks * TRNG_SEC_STRENGTH_BYTES), randbuf, byteleft);
156 		count += byteleft;
157 	}
158 
159 	xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET,
160 			  TRNG_CTRL_PRNGMODE_MASK | TRNG_CTRL_PRNGSTART_MASK, 0U);
161 
162 	return count;
163 }
164 
xtrng_write_multiple_registers(void __iomem * base_addr,u32 * values,size_t n)165 static void xtrng_write_multiple_registers(void __iomem *base_addr, u32 *values, size_t n)
166 {
167 	void __iomem *reg_addr;
168 	size_t i;
169 
170 	/* Write seed value into EXTERNAL_SEED Registers in big endian format */
171 	for (i = 0; i < n; i++) {
172 		reg_addr = (base_addr + ((n - 1 - i) * TRNG_BYTES_PER_REG));
173 		iowrite32((u32 __force)(cpu_to_be32(values[i])), reg_addr);
174 	}
175 }
176 
xtrng_enable_entropy(struct xilinx_rng * rng)177 static void xtrng_enable_entropy(struct xilinx_rng *rng)
178 {
179 	iowrite32(TRNG_OSC_EN_VAL_MASK, rng->rng_base + TRNG_OSC_EN_OFFSET);
180 	xtrng_softreset(rng);
181 	iowrite32(TRNG_CTRL_EUMODE_MASK | TRNG_CTRL_TRSSEN_MASK, rng->rng_base + TRNG_CTRL_OFFSET);
182 }
183 
xtrng_reseed_internal(struct xilinx_rng * rng)184 static int xtrng_reseed_internal(struct xilinx_rng *rng)
185 {
186 	u8 entropy[TRNG_ENTROPY_SEED_LEN_BYTES];
187 	struct drbg_string data;
188 	LIST_HEAD(seedlist);
189 	u32 val;
190 	int ret;
191 
192 	drbg_string_fill(&data, entropy, TRNG_SEED_LEN_BYTES);
193 	list_add_tail(&data.list, &seedlist);
194 	memset(entropy, 0, sizeof(entropy));
195 	xtrng_enable_entropy(rng);
196 
197 	/* collect random data to use it as entropy (input for DF) */
198 	ret = xtrng_collect_random_data(rng, entropy, TRNG_SEED_LEN_BYTES, true);
199 	if (ret != TRNG_SEED_LEN_BYTES)
200 		return -EINVAL;
201 	ret = crypto_drbg_ctr_df(rng->aesctx, rng->scratchpadbuf,
202 				 TRNG_SEED_LEN_BYTES, &seedlist, AES_BLOCK_SIZE,
203 				 TRNG_SEED_LEN_BYTES);
204 	if (ret)
205 		return ret;
206 
207 	xtrng_write_multiple_registers(rng->rng_base + TRNG_EXT_SEED_OFFSET,
208 				       (u32 *)rng->scratchpadbuf, TRNG_NUM_INIT_REGS);
209 	/* select reseed operation */
210 	iowrite32(TRNG_CTRL_PRNGXS_MASK, rng->rng_base + TRNG_CTRL_OFFSET);
211 
212 	/* Start the reseed operation with above configuration and wait for STATUS.Done bit to be
213 	 * set. Monitor STATUS.CERTF bit, if set indicates SP800-90B entropy health test has failed.
214 	 */
215 	xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET, TRNG_CTRL_PRNGSTART_MASK,
216 			  TRNG_CTRL_PRNGSTART_MASK);
217 
218 	ret = readl_poll_timeout(rng->rng_base + TRNG_STATUS_OFFSET, val,
219 				 (val & TRNG_STATUS_DONE_MASK) == TRNG_STATUS_DONE_MASK,
220 				  1U, 15000U);
221 	if (ret)
222 		return ret;
223 
224 	xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET, TRNG_CTRL_PRNGSTART_MASK, 0U);
225 
226 	return 0;
227 }
228 
xtrng_random_bytes_generate(struct xilinx_rng * rng,u8 * rand_buf_ptr,u32 rand_buf_size,int wait)229 static int xtrng_random_bytes_generate(struct xilinx_rng *rng, u8 *rand_buf_ptr,
230 				       u32 rand_buf_size, int wait)
231 {
232 	int nbytes;
233 	int ret;
234 
235 	xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET,
236 			  TRNG_CTRL_PRNGMODE_MASK | TRNG_CTRL_PRNGXS_MASK,
237 			  TRNG_CTRL_PRNGMODE_MASK | TRNG_CTRL_PRNGXS_MASK);
238 	nbytes = xtrng_collect_random_data(rng, rand_buf_ptr, rand_buf_size, wait);
239 
240 	ret = xtrng_reseed_internal(rng);
241 	if (ret) {
242 		dev_err(rng->dev, "Re-seed fail\n");
243 		return ret;
244 	}
245 
246 	return nbytes;
247 }
248 
xtrng_trng_generate(struct crypto_rng * tfm,const u8 * src,u32 slen,u8 * dst,u32 dlen)249 static int xtrng_trng_generate(struct crypto_rng *tfm, const u8 *src, u32 slen,
250 			       u8 *dst, u32 dlen)
251 {
252 	struct xilinx_rng_ctx *ctx = crypto_rng_ctx(tfm);
253 	int ret;
254 
255 	mutex_lock(&ctx->rng->lock);
256 	ret = xtrng_random_bytes_generate(ctx->rng, dst, dlen, true);
257 	mutex_unlock(&ctx->rng->lock);
258 
259 	return ret < 0 ? ret : 0;
260 }
261 
xtrng_trng_seed(struct crypto_rng * tfm,const u8 * seed,unsigned int slen)262 static int xtrng_trng_seed(struct crypto_rng *tfm, const u8 *seed, unsigned int slen)
263 {
264 	return 0;
265 }
266 
xtrng_trng_init(struct crypto_tfm * rtfm)267 static int xtrng_trng_init(struct crypto_tfm *rtfm)
268 {
269 	struct xilinx_rng_ctx *ctx = crypto_tfm_ctx(rtfm);
270 
271 	ctx->rng = xilinx_rng_dev;
272 
273 	return 0;
274 }
275 
276 static struct rng_alg xtrng_trng_alg = {
277 	.generate = xtrng_trng_generate,
278 	.seed = xtrng_trng_seed,
279 	.seedsize = 0,
280 	.base = {
281 		.cra_name = "stdrng",
282 		.cra_driver_name = "xilinx-trng",
283 		.cra_priority = 300,
284 		.cra_ctxsize = sizeof(struct xilinx_rng_ctx),
285 		.cra_module = THIS_MODULE,
286 		.cra_init = xtrng_trng_init,
287 	},
288 };
289 
xtrng_hwrng_trng_read(struct hwrng * hwrng,void * data,size_t max,bool wait)290 static int xtrng_hwrng_trng_read(struct hwrng *hwrng, void *data, size_t max, bool wait)
291 {
292 	u8 buf[TRNG_SEC_STRENGTH_BYTES];
293 	struct xilinx_rng *rng;
294 	int ret = -EINVAL, i = 0;
295 
296 	rng = container_of(hwrng, struct xilinx_rng, trng);
297 	/* Return in case wait not set and lock not available. */
298 	if (!mutex_trylock(&rng->lock) && !wait)
299 		return 0;
300 	else if (!mutex_is_locked(&rng->lock) && wait)
301 		mutex_lock(&rng->lock);
302 
303 	while (i < max) {
304 		ret = xtrng_random_bytes_generate(rng, buf, TRNG_SEC_STRENGTH_BYTES, wait);
305 		if (ret < 0)
306 			break;
307 
308 		memcpy(data + i, buf, min_t(int, ret, (max - i)));
309 		i += min_t(int, ret, (max - i));
310 	}
311 	mutex_unlock(&rng->lock);
312 
313 	return ret;
314 }
315 
xtrng_hwrng_register(struct hwrng * trng)316 static int xtrng_hwrng_register(struct hwrng *trng)
317 {
318 	int ret;
319 
320 	trng->name = "Xilinx Versal Crypto Engine TRNG";
321 	trng->read = xtrng_hwrng_trng_read;
322 
323 	ret = hwrng_register(trng);
324 	if (ret)
325 		pr_err("Fail to register the TRNG\n");
326 
327 	return ret;
328 }
329 
xtrng_hwrng_unregister(struct hwrng * trng)330 static void xtrng_hwrng_unregister(struct hwrng *trng)
331 {
332 	hwrng_unregister(trng);
333 }
334 
xtrng_probe(struct platform_device * pdev)335 static int xtrng_probe(struct platform_device *pdev)
336 {
337 	struct xilinx_rng *rng;
338 	size_t sb_size;
339 	int ret;
340 
341 	rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL);
342 	if (!rng)
343 		return -ENOMEM;
344 
345 	rng->dev = &pdev->dev;
346 	rng->rng_base = devm_platform_ioremap_resource(pdev, 0);
347 	if (IS_ERR(rng->rng_base)) {
348 		dev_err(&pdev->dev, "Failed to map resource %pe\n", rng->rng_base);
349 		return PTR_ERR(rng->rng_base);
350 	}
351 
352 	rng->aesctx = devm_kzalloc(&pdev->dev, sizeof(*rng->aesctx), GFP_KERNEL);
353 	if (!rng->aesctx)
354 		return -ENOMEM;
355 
356 	sb_size = crypto_drbg_ctr_df_datalen(TRNG_SEED_LEN_BYTES, AES_BLOCK_SIZE);
357 	rng->scratchpadbuf = devm_kzalloc(&pdev->dev, sb_size, GFP_KERNEL);
358 	if (!rng->scratchpadbuf) {
359 		ret = -ENOMEM;
360 		goto end;
361 	}
362 
363 	xtrng_trng_reset(rng->rng_base);
364 	ret = xtrng_reseed_internal(rng);
365 	if (ret) {
366 		dev_err(&pdev->dev, "TRNG Seed fail\n");
367 		goto end;
368 	}
369 
370 	xilinx_rng_dev = rng;
371 	mutex_init(&rng->lock);
372 	ret = crypto_register_rng(&xtrng_trng_alg);
373 	if (ret) {
374 		dev_err(&pdev->dev, "Crypto Random device registration failed: %d\n", ret);
375 		goto end;
376 	}
377 
378 	ret = xtrng_hwrng_register(&rng->trng);
379 	if (ret) {
380 		dev_err(&pdev->dev, "HWRNG device registration failed: %d\n", ret);
381 		goto crypto_rng_free;
382 	}
383 	platform_set_drvdata(pdev, rng);
384 
385 	return 0;
386 
387 crypto_rng_free:
388 	crypto_unregister_rng(&xtrng_trng_alg);
389 
390 end:
391 	return ret;
392 }
393 
xtrng_remove(struct platform_device * pdev)394 static void xtrng_remove(struct platform_device *pdev)
395 {
396 	struct xilinx_rng *rng;
397 	u32 zero[TRNG_NUM_INIT_REGS] = { };
398 
399 	rng = platform_get_drvdata(pdev);
400 	xtrng_hwrng_unregister(&rng->trng);
401 	crypto_unregister_rng(&xtrng_trng_alg);
402 	xtrng_write_multiple_registers(rng->rng_base + TRNG_EXT_SEED_OFFSET, zero,
403 				       TRNG_NUM_INIT_REGS);
404 	xtrng_write_multiple_registers(rng->rng_base + TRNG_PER_STRNG_OFFSET, zero,
405 				       TRNG_NUM_INIT_REGS);
406 	xtrng_hold_reset(rng->rng_base);
407 	xilinx_rng_dev = NULL;
408 }
409 
410 static const struct of_device_id xtrng_of_match[] = {
411 	{ .compatible = "xlnx,versal-trng", },
412 	{},
413 };
414 
415 MODULE_DEVICE_TABLE(of, xtrng_of_match);
416 
417 static struct platform_driver xtrng_driver = {
418 	.driver = {
419 		.name = "xlnx,versal-trng",
420 		.of_match_table	= xtrng_of_match,
421 	},
422 	.probe = xtrng_probe,
423 	.remove = xtrng_remove,
424 };
425 
426 module_platform_driver(xtrng_driver);
427 MODULE_LICENSE("GPL");
428 MODULE_AUTHOR("Harsh Jain <h.jain@amd.com>");
429 MODULE_AUTHOR("Mounika Botcha <mounika.botcha@amd.com>");
430 MODULE_DESCRIPTION("True Random Number Generator Driver");
431