Message ID | 20200625121905.4475-7-michael@walle.cc |
---|---|
State | Superseded |
Headers | show |
Series | crypto/fsl: add RNG support | expand |
On 25.06.20 14:19, Michael Walle wrote: > 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 at walle.cc> > --- > drivers/crypto/fsl/Kconfig | 14 ++++++ > drivers/crypto/fsl/Makefile | 1 + > drivers/crypto/fsl/jobdesc.c | 10 +++++ > drivers/crypto/fsl/jobdesc.h | 3 ++ > drivers/crypto/fsl/jr.c | 9 ++++ > drivers/crypto/fsl/rng.c | 86 ++++++++++++++++++++++++++++++++++++ > 6 files changed, 123 insertions(+) > create mode 100644 drivers/crypto/fsl/rng.c > > diff --git a/drivers/crypto/fsl/Kconfig b/drivers/crypto/fsl/Kconfig > index 181a1e5e99..5ed6140da3 100644 > --- a/drivers/crypto/fsl/Kconfig > +++ b/drivers/crypto/fsl/Kconfig > @@ -45,3 +45,17 @@ config SYS_FSL_SEC_COMPAT > > config SYS_FSL_SEC_LE > 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 Should FSL_CAAM imply DM_RNG? This way you would not have to update the defconfigs of the NXP boards. For new files there should be a maintainer. It would be great if somebody at NXP could take charge of the drivers/crypto/fsl directory. Best regards Heinrich
On 6/25/20 2:19 PM, Michael Walle wrote: > 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 at walle.cc> > --- > drivers/crypto/fsl/Kconfig | 14 ++++++ > drivers/crypto/fsl/Makefile | 1 + > drivers/crypto/fsl/jobdesc.c | 10 +++++ > drivers/crypto/fsl/jobdesc.h | 3 ++ > drivers/crypto/fsl/jr.c | 9 ++++ > drivers/crypto/fsl/rng.c | 86 ++++++++++++++++++++++++++++++++++++ > 6 files changed, 123 insertions(+) > create mode 100644 drivers/crypto/fsl/rng.c > > diff --git a/drivers/crypto/fsl/Kconfig b/drivers/crypto/fsl/Kconfig > index 181a1e5e99..5ed6140da3 100644 > --- a/drivers/crypto/fsl/Kconfig > +++ b/drivers/crypto/fsl/Kconfig > @@ -45,3 +45,17 @@ config SYS_FSL_SEC_COMPAT > > config SYS_FSL_SEC_LE > 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 > diff --git a/drivers/crypto/fsl/Makefile b/drivers/crypto/fsl/Makefile > index cfb36f3bb9..a5e8d38e38 100644 > --- a/drivers/crypto/fsl/Makefile > +++ b/drivers/crypto/fsl/Makefile > @@ -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_DEKBLOB) += fsl_blob.o > obj-$(CONFIG_RSA_FREESCALE_EXP) += fsl_rsa.o > +obj-$(CONFIG_FSL_CAAM_RNG) += rng.o > diff --git a/drivers/crypto/fsl/jobdesc.c b/drivers/crypto/fsl/jobdesc.c > index d9554c550b..decde64078 100644 > --- a/drivers/crypto/fsl/jobdesc.c > +++ b/drivers/crypto/fsl/jobdesc.c > @@ -296,6 +296,16 @@ void inline_cnstr_jobdesc_rng_deinstantiation(u32 *desc, int handle) > (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*/ > void inline_cnstr_jobdesc_pkha_rsaexp(uint32_t *desc, > struct pk_in_params *pkin, uint8_t *out, > diff --git a/drivers/crypto/fsl/jobdesc.h b/drivers/crypto/fsl/jobdesc.h > index 5185ddd535..c4501abd26 100644 > --- a/drivers/crypto/fsl/jobdesc.h > +++ b/drivers/crypto/fsl/jobdesc.h > @@ -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(u32 *desc, void *data_out, u32 size); > + > void inline_cnstr_jobdesc_pkha_rsaexp(uint32_t *desc, > struct pk_in_params *pkin, uint8_t *out, > uint32_t out_siz); > + > #endif > diff --git a/drivers/crypto/fsl/jr.c b/drivers/crypto/fsl/jr.c > index 00a3244b18..9ada1d625b 100644 > --- a/drivers/crypto/fsl/jr.c > +++ b/drivers/crypto/fsl/jr.c > @@ -20,6 +20,7 @@ > #include <asm/cache.h> > #include <asm/fsl_pamu.h> > #endif > +#include <dm/lists.h> > > #define CIRC_CNT(head, tail, size) (((head) - (tail)) & (size - 1)) > #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); > 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); > } > #endif > diff --git a/drivers/crypto/fsl/rng.c b/drivers/crypto/fsl/rng.c > new file mode 100644 > index 0000000000..136b2cdcd7 > --- /dev/null > +++ b/drivers/crypto/fsl/rng.c > @@ -0,0 +1,86 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* > + * Copyright (c) 2020 Michael Walle <michael at 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 "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_platdata { > + 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_platdata *pdata) > +{ > + int size = CAAM_RNG_MAX_FIFO_STORE_SIZE; This should be int size = ALIGN(CAAM_RNG_MAX_FIFO_STORE_SIZE, ARCH_DMA_MINALIGN); > + int ret; > + > + ret = run_descriptor_jr(pdata->desc); > + if (ret < 0) > + return -EIO; > + > + invalidate_dcache_range((unsigned long)pdata->data, > + (unsigned long)pdata->data + size); This fails on the i.MX6 Wandboard with CACHE: Misaligned operation at range [8e596f68, 8e596f78] because pdata is not ARCH_DMA_MINALIGN aligned. > + > + return 0; > +} > + > +static int caam_rng_read(struct udevice *dev, void *data, size_t len) > +{ > + struct caam_rng_platdata *pdata = dev_get_platdata(dev); > + u8 *buffer = data; > + size_t size; > + int ret; > + > + while (len) { > + ret = caam_rng_read_one(pdata); > + if (ret) > + return ret; > + > + size = min(len, (size_t)CAAM_RNG_MAX_FIFO_STORE_SIZE); > + > + memcpy(buffer, pdata->data, size); > + buffer += size; > + len -= size; > + } > + > + return 0; > +} > + > +static int caam_rng_probe(struct udevice *dev) > +{ > + struct caam_rng_platdata *pdata = dev_get_platdata(dev); > + > + inline_cnstr_jobdesc_rng(pdata->desc, pdata->data, > + CAAM_RNG_MAX_FIFO_STORE_SIZE); > + flush_dcache_range((unsigned long)pdata->desc, > + (unsigned long)pdata->desc + CAAM_RNG_DESC_LEN); You should round CAAM_RNG_DESC_LEN up to a multiple of ARCH_DMA_MINALIGN. > + > + 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, > + .platdata_auto_alloc_size = sizeof(struct caam_rng_platdata), > + .flags = DM_FLAG_ALLOC_PRIV_DMA, This flag is for private data. It does not provide aligned platform data. So you should use: .priv_auto_alloc_size = sizeof(struct caam_rng_platdata), and struct caam_rng_priv *priv = dev_get_priv(dev) Best regards Heinrich > +}; >
diff --git a/drivers/crypto/fsl/Kconfig b/drivers/crypto/fsl/Kconfig index 181a1e5e99..5ed6140da3 100644 --- a/drivers/crypto/fsl/Kconfig +++ b/drivers/crypto/fsl/Kconfig @@ -45,3 +45,17 @@ config SYS_FSL_SEC_COMPAT config SYS_FSL_SEC_LE 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 diff --git a/drivers/crypto/fsl/Makefile b/drivers/crypto/fsl/Makefile index cfb36f3bb9..a5e8d38e38 100644 --- a/drivers/crypto/fsl/Makefile +++ b/drivers/crypto/fsl/Makefile @@ -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_DEKBLOB) += fsl_blob.o obj-$(CONFIG_RSA_FREESCALE_EXP) += fsl_rsa.o +obj-$(CONFIG_FSL_CAAM_RNG) += rng.o diff --git a/drivers/crypto/fsl/jobdesc.c b/drivers/crypto/fsl/jobdesc.c index d9554c550b..decde64078 100644 --- a/drivers/crypto/fsl/jobdesc.c +++ b/drivers/crypto/fsl/jobdesc.c @@ -296,6 +296,16 @@ void inline_cnstr_jobdesc_rng_deinstantiation(u32 *desc, int handle) (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*/ void inline_cnstr_jobdesc_pkha_rsaexp(uint32_t *desc, struct pk_in_params *pkin, uint8_t *out, diff --git a/drivers/crypto/fsl/jobdesc.h b/drivers/crypto/fsl/jobdesc.h index 5185ddd535..c4501abd26 100644 --- a/drivers/crypto/fsl/jobdesc.h +++ b/drivers/crypto/fsl/jobdesc.h @@ -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(u32 *desc, void *data_out, u32 size); + void inline_cnstr_jobdesc_pkha_rsaexp(uint32_t *desc, struct pk_in_params *pkin, uint8_t *out, uint32_t out_siz); + #endif diff --git a/drivers/crypto/fsl/jr.c b/drivers/crypto/fsl/jr.c index 00a3244b18..9ada1d625b 100644 --- a/drivers/crypto/fsl/jr.c +++ b/drivers/crypto/fsl/jr.c @@ -20,6 +20,7 @@ #include <asm/cache.h> #include <asm/fsl_pamu.h> #endif +#include <dm/lists.h> #define CIRC_CNT(head, tail, size) (((head) - (tail)) & (size - 1)) #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); 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); } #endif diff --git a/drivers/crypto/fsl/rng.c b/drivers/crypto/fsl/rng.c new file mode 100644 index 0000000000..136b2cdcd7 --- /dev/null +++ b/drivers/crypto/fsl/rng.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2020 Michael Walle <michael at 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 "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_platdata { + 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_platdata *pdata) +{ + int size = CAAM_RNG_MAX_FIFO_STORE_SIZE; + int ret; + + ret = run_descriptor_jr(pdata->desc); + if (ret < 0) + return -EIO; + + invalidate_dcache_range((unsigned long)pdata->data, + (unsigned long)pdata->data + size); + + return 0; +} + +static int caam_rng_read(struct udevice *dev, void *data, size_t len) +{ + struct caam_rng_platdata *pdata = dev_get_platdata(dev); + u8 *buffer = data; + size_t size; + int ret; + + while (len) { + ret = caam_rng_read_one(pdata); + if (ret) + return ret; + + size = min(len, (size_t)CAAM_RNG_MAX_FIFO_STORE_SIZE); + + memcpy(buffer, pdata->data, size); + buffer += size; + len -= size; + } + + return 0; +} + +static int caam_rng_probe(struct udevice *dev) +{ + struct caam_rng_platdata *pdata = dev_get_platdata(dev); + + inline_cnstr_jobdesc_rng(pdata->desc, pdata->data, + CAAM_RNG_MAX_FIFO_STORE_SIZE); + flush_dcache_range((unsigned long)pdata->desc, + (unsigned long)pdata->desc + CAAM_RNG_DESC_LEN); + + 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, + .platdata_auto_alloc_size = sizeof(struct caam_rng_platdata), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +};
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 at walle.cc> --- drivers/crypto/fsl/Kconfig | 14 ++++++ drivers/crypto/fsl/Makefile | 1 + drivers/crypto/fsl/jobdesc.c | 10 +++++ drivers/crypto/fsl/jobdesc.h | 3 ++ drivers/crypto/fsl/jr.c | 9 ++++ drivers/crypto/fsl/rng.c | 86 ++++++++++++++++++++++++++++++++++++ 6 files changed, 123 insertions(+) create mode 100644 drivers/crypto/fsl/rng.c