#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>
#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
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;
};
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);
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);
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);
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;
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);
crypto_rng_free:
crypto_unregister_rng(&xtrng_trng_alg);
+end:
return ret;
}