crypto/fsl: add RNG support
Register the random number generator with the rng subsystem in u-boot. This way it can be used by EFI as well as for the 'rng' command. Signed-off-by: Michael Walle <michael@walle.cc> Tested-by: Heinrich Schuchardt <xypron.glpk@gmx.de> Reviewed-by: Priyanka Jain <priyanka.jain@nxp.com>
This commit is contained in:
		
							parent
							
								
									b980f9e259
								
							
						
					
					
						commit
						ea95f2142e
					
				|  | @ -45,3 +45,17 @@ config SYS_FSL_SEC_COMPAT | ||||||
| 
 | 
 | ||||||
| config SYS_FSL_SEC_LE | config SYS_FSL_SEC_LE | ||||||
| 	bool "Little-endian access to Freescale Secure Boot" | 	bool "Little-endian access to Freescale Secure Boot" | ||||||
|  | 
 | ||||||
|  | if FSL_CAAM | ||||||
|  | 
 | ||||||
|  | config FSL_CAAM_RNG | ||||||
|  | 	bool "Enable Random Number Generator support" | ||||||
|  | 	depends on DM_RNG | ||||||
|  | 	default y | ||||||
|  | 	help | ||||||
|  | 	  Enable support for the hardware based random number generator | ||||||
|  | 	  module of the CAAM. The random data is fetched from the DRGB | ||||||
|  | 	  using the prediction resistance flag which means the DRGB is | ||||||
|  | 	  reseeded from the TRNG every time random data is generated. | ||||||
|  | 
 | ||||||
|  | endif | ||||||
|  |  | ||||||
|  | @ -7,3 +7,4 @@ obj-$(CONFIG_FSL_CAAM) += jr.o fsl_hash.o jobdesc.o error.o | ||||||
| obj-$(CONFIG_CMD_BLOB) += fsl_blob.o | obj-$(CONFIG_CMD_BLOB) += fsl_blob.o | ||||||
| obj-$(CONFIG_CMD_DEKBLOB) += fsl_blob.o | obj-$(CONFIG_CMD_DEKBLOB) += fsl_blob.o | ||||||
| obj-$(CONFIG_RSA_FREESCALE_EXP) += fsl_rsa.o | obj-$(CONFIG_RSA_FREESCALE_EXP) += fsl_rsa.o | ||||||
|  | obj-$(CONFIG_FSL_CAAM_RNG) += rng.o | ||||||
|  |  | ||||||
|  | @ -296,6 +296,16 @@ void inline_cnstr_jobdesc_rng_deinstantiation(u32 *desc, int handle) | ||||||
| 			 (handle << OP_ALG_AAI_SHIFT) | OP_ALG_AS_INITFINAL); | 			 (handle << OP_ALG_AAI_SHIFT) | OP_ALG_AS_INITFINAL); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void inline_cnstr_jobdesc_rng(u32 *desc, void *data_out, u32 size) | ||||||
|  | { | ||||||
|  | 	dma_addr_t dma_data_out = virt_to_phys(data_out); | ||||||
|  | 
 | ||||||
|  | 	init_job_desc(desc, 0); | ||||||
|  | 	append_operation(desc, OP_ALG_ALGSEL_RNG | OP_TYPE_CLASS1_ALG | | ||||||
|  | 			 OP_ALG_PR_ON); | ||||||
|  | 	append_fifo_store(desc, dma_data_out, size, FIFOST_TYPE_RNGSTORE); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /* Change key size to bytes form bits in calling function*/ | /* Change key size to bytes form bits in calling function*/ | ||||||
| void inline_cnstr_jobdesc_pkha_rsaexp(uint32_t *desc, | void inline_cnstr_jobdesc_pkha_rsaexp(uint32_t *desc, | ||||||
| 				      struct pk_in_params *pkin, uint8_t *out, | 				      struct pk_in_params *pkin, uint8_t *out, | ||||||
|  |  | ||||||
|  | @ -43,7 +43,10 @@ void inline_cnstr_jobdesc_rng_instantiation(u32 *desc, int handle, int do_sk); | ||||||
| 
 | 
 | ||||||
| void inline_cnstr_jobdesc_rng_deinstantiation(u32 *desc, int handle); | void inline_cnstr_jobdesc_rng_deinstantiation(u32 *desc, int handle); | ||||||
| 
 | 
 | ||||||
|  | void inline_cnstr_jobdesc_rng(u32 *desc, void *data_out, u32 size); | ||||||
|  | 
 | ||||||
| void inline_cnstr_jobdesc_pkha_rsaexp(uint32_t *desc, | void inline_cnstr_jobdesc_pkha_rsaexp(uint32_t *desc, | ||||||
| 				      struct pk_in_params *pkin, uint8_t *out, | 				      struct pk_in_params *pkin, uint8_t *out, | ||||||
| 				      uint32_t out_siz); | 				      uint32_t out_siz); | ||||||
|  | 
 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -20,6 +20,7 @@ | ||||||
| #include <asm/cache.h> | #include <asm/cache.h> | ||||||
| #include <asm/fsl_pamu.h> | #include <asm/fsl_pamu.h> | ||||||
| #endif | #endif | ||||||
|  | #include <dm/lists.h> | ||||||
| 
 | 
 | ||||||
| #define CIRC_CNT(head, tail, size)	(((head) - (tail)) & (size - 1)) | #define CIRC_CNT(head, tail, size)	(((head) - (tail)) & (size - 1)) | ||||||
| #define CIRC_SPACE(head, tail, size)	CIRC_CNT((tail), (head) + 1, (size)) | #define CIRC_SPACE(head, tail, size)	CIRC_CNT((tail), (head) + 1, (size)) | ||||||
|  | @ -721,6 +722,14 @@ int sec_init_idx(uint8_t sec_idx) | ||||||
| 			printf("SEC%u:  RNG instantiation failed\n", sec_idx); | 			printf("SEC%u:  RNG instantiation failed\n", sec_idx); | ||||||
| 			return -1; | 			return -1; | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
|  | 		if (IS_ENABLED(CONFIG_DM_RNG)) { | ||||||
|  | 			ret = device_bind_driver(NULL, "caam-rng", "caam-rng", | ||||||
|  | 						 NULL); | ||||||
|  | 			if (ret) | ||||||
|  | 				printf("Couldn't bind rng driver (%d)\n", ret); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		printf("SEC%u:  RNG instantiated\n", sec_idx); | 		printf("SEC%u:  RNG instantiated\n", sec_idx); | ||||||
| 	} | 	} | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -0,0 +1,88 @@ | ||||||
|  | // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||||
|  | /*
 | ||||||
|  |  * Copyright (c) 2020 Michael Walle <michael@walle.cc> | ||||||
|  |  * | ||||||
|  |  * Driver for Freescale Cryptographic Accelerator and Assurance | ||||||
|  |  * Module (CAAM) hardware random number generator. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <asm/cache.h> | ||||||
|  | #include <common.h> | ||||||
|  | #include <cpu_func.h> | ||||||
|  | #include <dm.h> | ||||||
|  | #include <rng.h> | ||||||
|  | #include <linux/kernel.h> | ||||||
|  | #include "desc_constr.h" | ||||||
|  | #include "jobdesc.h" | ||||||
|  | #include "jr.h" | ||||||
|  | 
 | ||||||
|  | #define CAAM_RNG_MAX_FIFO_STORE_SIZE 16 | ||||||
|  | #define CAAM_RNG_DESC_LEN (3 * CAAM_CMD_SZ + CAAM_PTR_SZ) | ||||||
|  | 
 | ||||||
|  | struct caam_rng_priv { | ||||||
|  | 	u32 desc[CAAM_RNG_DESC_LEN / 4]; | ||||||
|  | 	u8 data[CAAM_RNG_MAX_FIFO_STORE_SIZE] __aligned(ARCH_DMA_MINALIGN); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static int caam_rng_read_one(struct caam_rng_priv *priv) | ||||||
|  | { | ||||||
|  | 	int size = ALIGN(CAAM_RNG_MAX_FIFO_STORE_SIZE, ARCH_DMA_MINALIGN); | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	ret = run_descriptor_jr(priv->desc); | ||||||
|  | 	if (ret < 0) | ||||||
|  | 		return -EIO; | ||||||
|  | 
 | ||||||
|  | 	invalidate_dcache_range((unsigned long)priv->data, | ||||||
|  | 				(unsigned long)priv->data + size); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int caam_rng_read(struct udevice *dev, void *data, size_t len) | ||||||
|  | { | ||||||
|  | 	struct caam_rng_priv *priv = dev_get_priv(dev); | ||||||
|  | 	u8 *buffer = data; | ||||||
|  | 	size_t size; | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	while (len) { | ||||||
|  | 		ret = caam_rng_read_one(priv); | ||||||
|  | 		if (ret) | ||||||
|  | 			return ret; | ||||||
|  | 
 | ||||||
|  | 		size = min(len, (size_t)CAAM_RNG_MAX_FIFO_STORE_SIZE); | ||||||
|  | 
 | ||||||
|  | 		memcpy(buffer, priv->data, size); | ||||||
|  | 		buffer += size; | ||||||
|  | 		len -= size; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int caam_rng_probe(struct udevice *dev) | ||||||
|  | { | ||||||
|  | 	struct caam_rng_priv *priv = dev_get_priv(dev); | ||||||
|  | 	ulong size = ALIGN(CAAM_RNG_DESC_LEN, ARCH_DMA_MINALIGN); | ||||||
|  | 
 | ||||||
|  | 	inline_cnstr_jobdesc_rng(priv->desc, priv->data, | ||||||
|  | 				 CAAM_RNG_MAX_FIFO_STORE_SIZE); | ||||||
|  | 	flush_dcache_range((unsigned long)priv->desc, | ||||||
|  | 			   (unsigned long)priv->desc + size); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static const struct dm_rng_ops caam_rng_ops = { | ||||||
|  | 	.read = caam_rng_read, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | U_BOOT_DRIVER(caam_rng) = { | ||||||
|  | 	.name = "caam-rng", | ||||||
|  | 	.id = UCLASS_RNG, | ||||||
|  | 	.ops = &caam_rng_ops, | ||||||
|  | 	.probe = caam_rng_probe, | ||||||
|  | 	.priv_auto_alloc_size = sizeof(struct caam_rng_priv), | ||||||
|  | 	.flags = DM_FLAG_ALLOC_PRIV_DMA, | ||||||
|  | }; | ||||||
		Loading…
	
		Reference in New Issue