[PATCH v1] 2: Uboot RNG Driver using Data Co-processor
Simon Glass
sjg at chromium.org
Thu Sep 8 20:19:00 CEST 2022
Hi Kshitiz,
On Thu, 8 Sept 2022 at 02:59, Kshitiz Varshney <kshitiz.varshney at nxp.com> wrote:
>
> From: Kshitiz <kshitiz.varshney at nxp.com>
>
> This commit introduces Random number generator to uboot. It uses DCP
> driver for number generation.
> RNG driver can be invoked by using below command on uboot prompt:-
> rng <number of bytes>
>
> Signed-off-by: Kshitiz Varshney <kshitiz.varshney at nxp.com>
> Reviewed-by: Ye Li <ye.li at nxp.com>
> ---
> drivers/crypto/fsl/Kconfig | 10 ++
> drivers/crypto/fsl/Makefile | 1 +
> drivers/crypto/fsl/dcp_rng.c | 184 +++++++++++++++++++++++++++++++++++
> 3 files changed, 195 insertions(+)
> create mode 100644 drivers/crypto/fsl/dcp_rng.c
Reviewed-by: Simon Glass <sjg at chromium.org>
but please see below
>
> diff --git a/drivers/crypto/fsl/Kconfig b/drivers/crypto/fsl/Kconfig
> index 702d204a3d..da5955e31d 100644
> --- a/drivers/crypto/fsl/Kconfig
> +++ b/drivers/crypto/fsl/Kconfig
> @@ -96,3 +96,13 @@ config RNG_SELF_TEST
> must be run before running any RNG based crypto implementation.
>
> endif
> +
> +config FSL_DCP_RNG
> + bool "Enable Random Number Generator support"
> + depends on DM_RNG
> + default n
> + help
> + Enable support for the hardware based random number generator
> + module of the DCP.It uses the True Random Number Generator (TRNG)
Space before It
> + and a Pseudo-Random Number Generator (PRNG) to achieve a true
> + randomness and cryptographic strength.
> diff --git a/drivers/crypto/fsl/Makefile b/drivers/crypto/fsl/Makefile
> index 926300e2ab..c653208d23 100644
> --- a/drivers/crypto/fsl/Makefile
> +++ b/drivers/crypto/fsl/Makefile
> @@ -7,6 +7,7 @@ obj-$(CONFIG_FSL_CAAM) += jr.o fsl_hash.o jobdesc.o error.o
> obj-$(CONFIG_FSL_BLOB) += fsl_blob.o
> obj-$(CONFIG_RSA_FREESCALE_EXP) += fsl_rsa.o
> obj-$(CONFIG_FSL_CAAM_RNG) += rng.o
> +obj-$(CONFIG_FSL_DCP_RNG) += dcp_rng.o
> obj-$(CONFIG_IMX_CAAM_MFG_PROT) += fsl_mfgprot.o
> obj-$(CONFIG_RNG_SELF_TEST) += rng_self_test.o
> obj-$(CONFIG_CMD_PROVISION_KEY) += fsl_aes.o tag_object.o
> diff --git a/drivers/crypto/fsl/dcp_rng.c b/drivers/crypto/fsl/dcp_rng.c
> new file mode 100644
> index 0000000000..a797710c2e
> --- /dev/null
> +++ b/drivers/crypto/fsl/dcp_rng.c
> @@ -0,0 +1,184 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * RNG driver for Freescale RNGC
> + *
> + * Copyright (C) 2008-2012 Freescale Semiconductor, Inc.
> + * Copyright (C) 2017 Martin Kaiser <martin at kaiser.cx>
> + * Copyright 2022 NXP
> + *
> + * Based on RNGC driver in drivers/char/hw_random/imx-rngc.c in Linux
> + */
> +
> +#include <asm/cache.h>
> +#include <common.h>
> +#include <cpu_func.h>
> +#include <dm.h>
> +#include <rng.h>
> +#include <linux/kernel.h>
> +#include <linux/delay.h>
> +#include <asm/io.h>
> +#include <dm/root.h>
Should be:
> +#include <common.h>
> +#include <cpu_func.h>
> +#include <dm.h>
> +#include <rng.h>
> +#include <asm/cache.h>
> +#include <asm/io.h>
> +#include <dm/root.h>
> +#include <linux/delay.h>
> +#include <linux/kernel.h>
> +
> +#define DCP_RNG_MAX_FIFO_STORE_SIZE 4
> +#define RNGC_VER_ID 0x0000
> +#define RNGC_COMMAND 0x0004
> +#define RNGC_CONTROL 0x0008
> +#define RNGC_STATUS 0x000C
> +#define RNGC_ERROR 0x0010
> +#define RNGC_FIFO 0x0014
> +
> +/* the fields in the ver id register */
> +#define RNGC_TYPE_SHIFT 28
> +
> +/* the rng_type field */
> +#define RNGC_TYPE_RNGB 0x1
> +#define RNGC_TYPE_RNGC 0x2
> +
> +#define RNGC_CMD_CLR_ERR 0x00000020
> +#define RNGC_CMD_SEED 0x00000002
> +
> +#define RNGC_CTRL_AUTO_SEED 0x00000010
> +
> +#define RNGC_STATUS_ERROR 0x00010000
> +#define RNGC_STATUS_FIFO_LEVEL_MASK 0x00000f00
> +#define RNGC_STATUS_FIFO_LEVEL_SHIFT 8
> +#define RNGC_STATUS_SEED_DONE 0x00000020
> +#define RNGC_STATUS_ST_DONE 0x00000010
Why all the leading zeroes?
> +
> +#define RNGC_ERROR_STATUS_STAT_ERR 0x00000008
> +
> +#define RNGC_TIMEOUT 3000000U /* 3 sec */
> +
> +struct imx_rngc {
Normally the priv data should have a _priv suffix.
> + unsigned long base;
> +};
> +
> +static int rngc_read(struct udevice *dev, void *data, size_t len)
> +{
> + struct imx_rngc *rngc = dev_get_priv(dev);
Normally the var should be called priv
> + u8 buffer[DCP_RNG_MAX_FIFO_STORE_SIZE];
> + u32 status, level;
> + size_t size;
> +
> + while (len) {
> + status = readl(rngc->base + RNGC_STATUS);
> +
> + /* is there some error while reading this random number? */
> + if (status & RNGC_STATUS_ERROR)
> + break;
> + /* how many random numbers are in FIFO? [0-16] */
> + level = (status & RNGC_STATUS_FIFO_LEVEL_MASK) >>
> + RNGC_STATUS_FIFO_LEVEL_SHIFT;
> +
> + if (level) {
> + /* retrieve a random number from FIFO */
> + *(u32 *)buffer = readl(rngc->base + RNGC_FIFO);
> + size = min(len, sizeof(u32));
> + memcpy(data, buffer, size);
> + data += size;
> + len -= size;
> + }
> + }
> +
> + return len ? -EIO : 0;
> +}
> +
> +static int rngc_init(struct imx_rngc *rngc)
> +{
> + u32 cmd, ctrl, status, err_reg = 0;
> + unsigned long long timeval = 0;
> + unsigned long long timeout = RNGC_TIMEOUT;
> +
> + /* clear error */
> + cmd = readl(rngc->base + RNGC_COMMAND);
> + writel(cmd | RNGC_CMD_CLR_ERR, rngc->base + RNGC_COMMAND);
> +
> + /* create seed, repeat while there is some statistical error */
> + do {
> + /* seed creation */
> + cmd = readl(rngc->base + RNGC_COMMAND);
> + writel(cmd | RNGC_CMD_SEED, rngc->base + RNGC_COMMAND);
> +
> + udelay(1);
> + timeval += 1;
> +
> + status = readl(rngc->base + RNGC_STATUS);
> + err_reg = readl(rngc->base + RNGC_ERROR);
> +
> + if (status & (RNGC_STATUS_SEED_DONE | RNGC_STATUS_ST_DONE))
> + break;
> +
> + if (timeval > timeout) {
> + debug("rngc timed out\n");
> + return -ETIMEDOUT;
> + }
> + } while (err_reg == RNGC_ERROR_STATUS_STAT_ERR);
> +
> + if (err_reg)
> + return -EIO;
> +
> + /*
> + * enable automatic seeding, the rngc creates a new seed automatically
> + * after serving 2^20 random 160-bit words
> + */
> + ctrl = readl(rngc->base + RNGC_CONTROL);
> + ctrl |= RNGC_CTRL_AUTO_SEED;
> + writel(ctrl, rngc->base + RNGC_CONTROL);
setbits_le32(rngc->base + RNGC_CONTROL, RNGC_CTRL_AUTO_SEED);
> + return 0;
> +}
> +
> +static int rngc_probe(struct udevice *dev)
> +{
> + struct imx_rngc *rngc = dev_get_priv(dev);
> + fdt_addr_t addr;
> + u32 ver_id;
> + u8 rng_type;
> + int ret;
> +
> + addr = dev_read_addr(dev);
> + if (addr == FDT_ADDR_T_NONE) {
> + ret = -EINVAL;
> + goto err;
> + }
> +
> + rngc->base = addr;
> + ver_id = readl(rngc->base + RNGC_VER_ID);
> + rng_type = ver_id >> RNGC_TYPE_SHIFT;
> + /*
> + * This driver supports only RNGC and RNGB. (There's a different
> + * driver for RNGA.)
> + */
> + if (rng_type != RNGC_TYPE_RNGC && rng_type != RNGC_TYPE_RNGB) {
> + ret = -ENODEV;
> + goto err;
> + }
> +
> + ret = rngc_init(rngc);
> + if (ret)
> + goto err;
> +
> + return 0;
> +
> +err:
> + printf("%s error = %d\n", __func__, ret);
> + return ret;
> +}
> +
> +static const struct dm_rng_ops rngc_ops = {
> + .read = rngc_read,
> +};
> +
> +static const struct udevice_id rngc_dt_ids[] = {
> + { .compatible = "fsl,imx25-rngb" },
> + { }
> +};
> +
> +U_BOOT_DRIVER(dcp_rng) = {
> + .name = "dcp_rng",
> + .id = UCLASS_RNG,
> + .of_match = rngc_dt_ids,
> + .ops = &rngc_ops,
> + .probe = rngc_probe,
> + .priv_auto = sizeof(struct imx_rngc),
> + .flags = DM_FLAG_ALLOC_PRIV_DMA,
> +};
> --
> 2.25.1
>
Regards,
Simon
More information about the U-Boot
mailing list