Commit 1a098379 authored by Harsh Jain's avatar Harsh Jain Committed by Herbert Xu
Browse files

crypto: xilinx-trng - Add CTR_DRBG DF processing of seed



Versal TRNG IP does not support Derivation Function (DF) of seed.
Add DF processing for CTR_DRBG mode.

Signed-off-by: default avatarHarsh Jain <h.jain@amd.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent ba0570bd
Loading
Loading
Loading
Loading
+31 −6
Original line number Diff line number Diff line
@@ -8,7 +8,6 @@
#include <linux/clk.h>
#include <linux/crypto.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/firmware/xlnx-zynqmp.h>
#include <linux/hw_random.h>
#include <linux/io.h>
@@ -18,10 +17,11 @@
#include <linux/mutex.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/string.h>
#include <crypto/aes.h>
#include <crypto/df_sp80090a.h>
#include <crypto/internal/drbg.h>
#include <crypto/internal/cipher.h>
#include <crypto/internal/rng.h>
#include <crypto/aes.h>

/* TRNG Registers Offsets */
#define TRNG_STATUS_OFFSET			0x4U
@@ -59,6 +59,8 @@
struct xilinx_rng {
	void __iomem *rng_base;
	struct device *dev;
	unsigned char *scratchpadbuf;
	struct crypto_aes_ctx *aesctx;
	struct mutex lock;	/* Protect access to TRNG device */
	struct hwrng trng;
};
@@ -182,9 +184,13 @@ static void xtrng_enable_entropy(struct xilinx_rng *rng)
static int xtrng_reseed_internal(struct xilinx_rng *rng)
{
	u8 entropy[TRNG_ENTROPY_SEED_LEN_BYTES];
	struct drbg_string data;
	LIST_HEAD(seedlist);
	u32 val;
	int ret;

	drbg_string_fill(&data, entropy, TRNG_SEED_LEN_BYTES);
	list_add_tail(&data.list, &seedlist);
	memset(entropy, 0, sizeof(entropy));
	xtrng_enable_entropy(rng);

@@ -192,9 +198,14 @@ static int xtrng_reseed_internal(struct xilinx_rng *rng)
	ret = xtrng_collect_random_data(rng, entropy, TRNG_SEED_LEN_BYTES, true);
	if (ret != TRNG_SEED_LEN_BYTES)
		return -EINVAL;
	ret = crypto_drbg_ctr_df(rng->aesctx, rng->scratchpadbuf,
				 TRNG_SEED_LEN_BYTES, &seedlist, AES_BLOCK_SIZE,
				 TRNG_SEED_LEN_BYTES);
	if (ret)
		return ret;

	xtrng_write_multiple_registers(rng->rng_base + TRNG_EXT_SEED_OFFSET,
				       (u32 *)entropy, TRNG_NUM_INIT_REGS);
				       (u32 *)rng->scratchpadbuf, TRNG_NUM_INIT_REGS);
	/* select reseed operation */
	iowrite32(TRNG_CTRL_PRNGXS_MASK, rng->rng_base + TRNG_CTRL_OFFSET);

@@ -324,6 +335,7 @@ static void xtrng_hwrng_unregister(struct hwrng *trng)
static int xtrng_probe(struct platform_device *pdev)
{
	struct xilinx_rng *rng;
	size_t sb_size;
	int ret;

	rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL);
@@ -337,11 +349,22 @@ static int xtrng_probe(struct platform_device *pdev)
		return PTR_ERR(rng->rng_base);
	}

	rng->aesctx = devm_kzalloc(&pdev->dev, sizeof(*rng->aesctx), GFP_KERNEL);
	if (!rng->aesctx)
		return -ENOMEM;

	sb_size = crypto_drbg_ctr_df_datalen(TRNG_SEED_LEN_BYTES, AES_BLOCK_SIZE);
	rng->scratchpadbuf = devm_kzalloc(&pdev->dev, sb_size, GFP_KERNEL);
	if (!rng->scratchpadbuf) {
		ret = -ENOMEM;
		goto end;
	}

	xtrng_trng_reset(rng->rng_base);
	ret = xtrng_reseed_internal(rng);
	if (ret) {
		dev_err(&pdev->dev, "TRNG Seed fail\n");
		return ret;
		goto end;
	}

	xilinx_rng_dev = rng;
@@ -349,8 +372,9 @@ static int xtrng_probe(struct platform_device *pdev)
	ret = crypto_register_rng(&xtrng_trng_alg);
	if (ret) {
		dev_err(&pdev->dev, "Crypto Random device registration failed: %d\n", ret);
		return ret;
		goto end;
	}

	ret = xtrng_hwrng_register(&rng->trng);
	if (ret) {
		dev_err(&pdev->dev, "HWRNG device registration failed: %d\n", ret);
@@ -363,6 +387,7 @@ static int xtrng_probe(struct platform_device *pdev)
crypto_rng_free:
	crypto_unregister_rng(&xtrng_trng_alg);

end:
	return ret;
}