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:
Michael Walle 2020-06-27 22:58:53 +02:00 committed by Priyanka Jain
parent b980f9e259
commit ea95f2142e
6 changed files with 125 additions and 0 deletions

View file

@ -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

View file

@ -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

View file

@ -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,

View file

@ -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

View file

@ -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

88
drivers/crypto/fsl/rng.c Normal file
View file

@ -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,
};