linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] crypto: caam/rng: Add support for PRNG
@ 2022-03-04 11:41 meenakshi.aggarwal
  2022-03-08 22:49 ` kernel test robot
                   ` (2 more replies)
  0 siblings, 3 replies; 15+ messages in thread
From: meenakshi.aggarwal @ 2022-03-04 11:41 UTC (permalink / raw)
  To: Horia Geanta, Pankaj Gupta, Gaurav Jain, Varun Sethi, Herbert Xu,
	David S . Miller
  Cc: linux-crypto, linux-kernel, linux-imx, Meenakshi Aggarwal

From: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>

Add support for random number generation using PRNG
mode of CAAM and expose the interface through crypto API.

Signed-off-by: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
---
 drivers/crypto/caam/Kconfig    |   9 ++
 drivers/crypto/caam/Makefile   |   1 +
 drivers/crypto/caam/caamprng.c | 238 +++++++++++++++++++++++++++++++++
 drivers/crypto/caam/desc.h     |   1 +
 drivers/crypto/caam/intern.h   |  15 +++
 drivers/crypto/caam/jr.c       |   2 +
 6 files changed, 266 insertions(+)
 create mode 100644 drivers/crypto/caam/caamprng.c

diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig
index 84ea7cba5ee5..d94250348b32 100644
--- a/drivers/crypto/caam/Kconfig
+++ b/drivers/crypto/caam/Kconfig
@@ -151,6 +151,15 @@ config CRYPTO_DEV_FSL_CAAM_RNG_API
 	  Selecting this will register the SEC4 hardware rng to
 	  the hw_random API for supplying the kernel entropy pool.
 
+
+config CRYPTO_DEV_FSL_CAAM_PRNG_API
+	bool "Register Pseudo random number generation implementation with Crypto API"
+	default y
+	select CRYPTO_RNG
+	help
+	  Selecting this will register the SEC hardware prng to
+	  the Crypto API.
+
 endif # CRYPTO_DEV_FSL_CAAM_JR
 
 endif # CRYPTO_DEV_FSL_CAAM
diff --git a/drivers/crypto/caam/Makefile b/drivers/crypto/caam/Makefile
index 3570286eb9ce..59961a0bbfe4 100644
--- a/drivers/crypto/caam/Makefile
+++ b/drivers/crypto/caam/Makefile
@@ -21,6 +21,7 @@ caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI) += caamalg_qi.o
 caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API) += caamhash.o
 caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o
 caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API) += caampkc.o pkc_desc.o
+caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_PRNG_API) += caamprng.o
 
 caam-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI) += qi.o
 ifneq ($(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI),)
diff --git a/drivers/crypto/caam/caamprng.c b/drivers/crypto/caam/caamprng.c
new file mode 100644
index 000000000000..be0cf0e214f0
--- /dev/null
+++ b/drivers/crypto/caam/caamprng.c
@@ -0,0 +1,238 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Driver to expose SEC4 PRNG via crypto RNG API
+ *
+ * Copyright 2022 NXP
+ *
+ */
+
+#include <linux/completion.h>
+#include <crypto/internal/rng.h>
+#include "compat.h"
+#include "regs.h"
+#include "intern.h"
+#include "desc_constr.h"
+#include "jr.h"
+#include "error.h"
+
+/*
+ * Length of used descriptors, see caam_init_desc()
+ */
+#define CAAM_PRNG_DESC_LEN (CAAM_CMD_SZ +				\
+			    CAAM_CMD_SZ +				\
+			    CAAM_CMD_SZ + CAAM_PTR_SZ_MAX)
+
+/* prng per-device context */
+struct caam_prng_ctx {
+	struct device *jrdev;
+	struct completion done;
+};
+
+struct caam_prng_alg {
+	struct rng_alg rng;
+	bool registered;
+};
+
+static void caam_prng_done(struct device *jrdev, u32 *desc, u32 err,
+			  void *context)
+{
+	struct caam_prng_ctx *jctx = context;
+
+	if (err)
+		caam_jr_strstatus(jrdev, err);
+
+	complete(&jctx->done);
+}
+
+static u32 *caam_init_reseed_desc(u32 *desc, dma_addr_t seed_dma, u32 len)
+{
+	init_job_desc(desc, 0);	/* + 1 cmd_sz */
+	/* Generate random bytes: + 1 cmd_sz */
+	append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
+			OP_ALG_AS_FINALIZE | OP_ALG_AI_ON);
+	/* Store bytes: + 1 cmd_sz + caam_ptr_sz  */
+	append_load(desc, seed_dma, len, CLASS_1 | LDST_SRCDST_BYTE_CONTEXT);
+
+	print_hex_dump_debug("prng reseed desc@: ", DUMP_PREFIX_ADDRESS,
+			     16, 4, desc, desc_bytes(desc), 1);
+
+	return desc;
+}
+
+static u32 *caam_init_prng_desc(u32 *desc, dma_addr_t dst_dma, u32 len)
+{
+	init_job_desc(desc, 0);	/* + 1 cmd_sz */
+	/* Generate random bytes: + 1 cmd_sz */
+	append_operation(desc, OP_ALG_ALGSEL_RNG | OP_TYPE_CLASS1_ALG);
+	/* Store bytes: + 1 cmd_sz + caam_ptr_sz  */
+	append_fifo_store(desc, dst_dma,
+			  len, FIFOST_TYPE_RNGSTORE);
+
+	print_hex_dump_debug("prng job desc@: ", DUMP_PREFIX_ADDRESS,
+			     16, 4, desc, desc_bytes(desc), 1);
+
+	return desc;
+}
+
+static int caam_prng_generate(struct crypto_rng *tfm,
+			     const u8 *src, unsigned int slen,
+			     u8 *dst, unsigned int dlen)
+{
+	struct caam_prng_ctx ctx;
+	dma_addr_t dst_dma;
+	u32 *desc;
+	int ret;
+
+	ctx.jrdev = caam_jr_alloc();
+	ret = PTR_ERR_OR_ZERO(ctx.jrdev);
+	if (ret) {
+		pr_err("Job Ring Device allocation failed\n");
+		return ret;
+	}
+
+	desc = kzalloc(CAAM_PRNG_DESC_LEN, GFP_KERNEL | GFP_DMA);
+	if (!desc) {
+		caam_jr_free(ctx.jrdev);
+		return -ENOMEM;
+	}
+
+	dst_dma = dma_map_single(ctx.jrdev, dst, dlen, DMA_FROM_DEVICE);
+	if (dma_mapping_error(ctx.jrdev, dst_dma)) {
+		dev_err(ctx.jrdev, "Failed to map destination buffer memory\n");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	init_completion(&ctx.done);
+	ret = caam_jr_enqueue(ctx.jrdev,
+			      caam_init_prng_desc(desc, dst_dma, dlen),
+			      caam_prng_done, &ctx);
+
+	if (ret == -EINPROGRESS) {
+		wait_for_completion(&ctx.done);
+		ret = 0;
+	}
+
+	dma_unmap_single(ctx.jrdev, dst_dma, dlen, DMA_FROM_DEVICE);
+
+out:
+	kfree(desc);
+	caam_jr_free(ctx.jrdev);
+	return ret;
+}
+
+static void caam_prng_exit(struct crypto_tfm *tfm)
+{
+
+	return;
+}
+
+static int caam_prng_init(struct crypto_tfm *tfm)
+{
+	return 0;
+}
+
+static int caam_prng_seed(struct crypto_rng *tfm,
+			 const u8 *seed, unsigned int slen)
+{
+	struct caam_prng_ctx ctx;
+	dma_addr_t seed_dma;
+	u32 *desc;
+	int ret;
+
+	ctx.jrdev = caam_jr_alloc();
+	ret = PTR_ERR_OR_ZERO(ctx.jrdev);
+	if (ret) {
+		pr_err("Job Ring Device allocation failed\n");
+		return ret;
+	}
+
+	desc = kzalloc(CAAM_PRNG_DESC_LEN, GFP_KERNEL | GFP_DMA);
+	if (!desc) {
+		caam_jr_free(ctx.jrdev);
+		return -ENOMEM;
+	}
+
+	seed_dma = dma_map_single(ctx.jrdev, seed, slen, DMA_FROM_DEVICE);
+	if (dma_mapping_error(ctx.jrdev, seed_dma)) {
+		dev_err(ctx.jrdev, "Failed to map destination buffer memory\n");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	init_completion(&ctx.done);
+	ret = caam_jr_enqueue(ctx.jrdev,
+			      caam_init_reseed_desc(desc, seed_dma, slen),
+			      caam_prng_done, &ctx);
+
+	if (ret == -EINPROGRESS) {
+		wait_for_completion(&ctx.done);
+		ret = 0;
+	}
+
+	dma_unmap_single(ctx.jrdev, seed_dma, slen, DMA_FROM_DEVICE);
+
+out:
+	kfree(desc);
+	caam_jr_free(ctx.jrdev);
+	return ret;
+}
+
+static struct caam_prng_alg caam_prng_alg = {
+	.rng = {
+		.generate = caam_prng_generate,
+		.seed = caam_prng_seed,
+		.seedsize = 32,
+		.base = {
+			.cra_name = "stdrng",
+			.cra_driver_name = "prng-caam",
+			.cra_priority = 500,
+			.cra_ctxsize = sizeof(struct caam_prng_ctx),
+			.cra_module = THIS_MODULE,
+			.cra_init = caam_prng_init,
+			.cra_exit = caam_prng_exit,
+		},
+	}
+};
+
+void caam_prng_unregister(void *data)
+{
+	if (caam_prng_alg.registered)
+		crypto_unregister_rng(&caam_prng_alg.rng);
+}
+
+int caam_prng_register(struct device *ctrldev)
+{
+	struct caam_drv_private *priv = dev_get_drvdata(ctrldev);
+	u32 rng_inst;
+	int ret = 0;
+
+	/* Check for available RNG blocks before registration */
+	if (priv->era < 10)
+		rng_inst = (rd_reg32(&priv->jr[0]->perfmon.cha_num_ls) &
+			    CHA_ID_LS_RNG_MASK) >> CHA_ID_LS_RNG_SHIFT;
+	else
+		rng_inst = rd_reg32(&priv->jr[0]->vreg.rng) & CHA_VER_NUM_MASK;
+
+	if (!rng_inst) {
+		dev_dbg(ctrldev, "RNG block is not available..."
+				"skipping registering rng algorithm\n");
+
+		return ret;
+	}
+
+	ret = crypto_register_rng(&caam_prng_alg.rng);
+	if (ret) {
+		dev_err(ctrldev,
+			"couldn't register rng crypto alg: %d\n",
+			ret);
+		return ret;
+	}
+
+	caam_prng_alg.registered = true;
+
+	dev_info(ctrldev,
+		 "rng crypto API alg registered %s\n", caam_prng_alg.rng.base.cra_name);
+
+	return 0;
+}
diff --git a/drivers/crypto/caam/desc.h b/drivers/crypto/caam/desc.h
index e13470901586..33db8ed2b49e 100644
--- a/drivers/crypto/caam/desc.h
+++ b/drivers/crypto/caam/desc.h
@@ -1255,6 +1255,7 @@
 #define OP_ALG_ICV_ON		(1 << OP_ALG_ICV_SHIFT)
 
 #define OP_ALG_PR_ON		BIT(1)
+#define OP_ALG_AI_ON		BIT(11)
 
 #define OP_ALG_DIR_SHIFT	0
 #define OP_ALG_DIR_MASK		1
diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h
index 7d45b21bd55a..c2f51365df1b 100644
--- a/drivers/crypto/caam/intern.h
+++ b/drivers/crypto/caam/intern.h
@@ -185,6 +185,21 @@ static inline void caam_rng_exit(struct device *dev) {}
 
 #endif /* CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API */
 
+#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_PRNG_API
+
+int caam_prng_register(struct device *dev);
+void caam_prng_unregister(void *data);
+
+#else
+
+static inline int caam_prng_register(struct device *dev)
+{
+	return 0;
+}
+
+static inline void caam_prng_unregister(void *data) {}
+#endif /* CONFIG_CRYPTO_DEV_FSL_CAAM_PRNG_API */
+
 #ifdef CONFIG_CAAM_QI
 
 int caam_qi_algapi_init(struct device *dev);
diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c
index 7f2b1101f567..11849362f912 100644
--- a/drivers/crypto/caam/jr.c
+++ b/drivers/crypto/caam/jr.c
@@ -39,6 +39,7 @@ static void register_algs(struct caam_drv_private_jr *jrpriv,
 	caam_algapi_hash_init(dev);
 	caam_pkc_init(dev);
 	jrpriv->hwrng = !caam_rng_init(dev);
+	caam_prng_register(dev);
 	caam_qi_algapi_init(dev);
 
 algs_unlock:
@@ -56,6 +57,7 @@ static void unregister_algs(void)
 
 	caam_pkc_exit();
 	caam_algapi_hash_exit();
+	caam_prng_unregister(NULL);
 	caam_algapi_exit();
 
 algs_unlock:
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH] crypto: caam/rng: Add support for PRNG
  2022-03-04 11:41 [PATCH] crypto: caam/rng: Add support for PRNG meenakshi.aggarwal
@ 2022-03-08 22:49 ` kernel test robot
  2022-03-16 18:01 ` [PATCH v2 0/1] " meenakshi.aggarwal
  2022-04-20  6:38 ` [PATCH v3 0/1] " meenakshi.aggarwal
  2 siblings, 0 replies; 15+ messages in thread
From: kernel test robot @ 2022-03-08 22:49 UTC (permalink / raw)
  To: meenakshi.aggarwal, Horia Geanta, Pankaj Gupta, Gaurav Jain,
	Varun Sethi, Herbert Xu, David S . Miller
  Cc: kbuild-all, linux-crypto, linux-kernel, linux-imx, Meenakshi Aggarwal

Hi,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on herbert-cryptodev-2.6/master]
[also build test WARNING on herbert-crypto-2.6/master v5.17-rc7 next-20220308]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/meenakshi-aggarwal-nxp-com/crypto-caam-rng-Add-support-for-PRNG/20220307-142401
base:   https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git master
config: arm-multi_v7_defconfig (https://download.01.org/0day-ci/archive/20220309/202203090603.qhbToPLJ-lkp@intel.com/config)
compiler: arm-linux-gnueabi-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/bc27c1a2748de5052fb4c042d90fa1e0e4132043
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review meenakshi-aggarwal-nxp-com/crypto-caam-rng-Add-support-for-PRNG/20220307-142401
        git checkout bc27c1a2748de5052fb4c042d90fa1e0e4132043
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=arm SHELL=/bin/bash drivers/crypto/caam/ drivers/rtc/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   In file included from drivers/crypto/caam/compat.h:18,
                    from drivers/crypto/caam/caamprng.c:11:
   drivers/crypto/caam/caamprng.c: In function 'caam_prng_seed':
>> drivers/crypto/caam/caamprng.c:156:46: warning: passing argument 2 of 'dma_map_single_attrs' discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
     156 |         seed_dma = dma_map_single(ctx.jrdev, seed, slen, DMA_FROM_DEVICE);
         |                                              ^~~~
   include/linux/dma-mapping.h:406:60: note: in definition of macro 'dma_map_single'
     406 | #define dma_map_single(d, a, s, r) dma_map_single_attrs(d, a, s, r, 0)
         |                                                            ^
   include/linux/dma-mapping.h:322:73: note: expected 'void *' but argument is of type 'const u8 *' {aka 'const unsigned char *'}
     322 | static inline dma_addr_t dma_map_single_attrs(struct device *dev, void *ptr,
         |                                                                   ~~~~~~^~~


vim +156 drivers/crypto/caam/caamprng.c

  > 11	#include "compat.h"
    12	#include "regs.h"
    13	#include "intern.h"
    14	#include "desc_constr.h"
    15	#include "jr.h"
    16	#include "error.h"
    17	
    18	/*
    19	 * Length of used descriptors, see caam_init_desc()
    20	 */
    21	#define CAAM_PRNG_DESC_LEN (CAAM_CMD_SZ +				\
    22				    CAAM_CMD_SZ +				\
    23				    CAAM_CMD_SZ + CAAM_PTR_SZ_MAX)
    24	
    25	/* prng per-device context */
    26	struct caam_prng_ctx {
    27		struct device *jrdev;
    28		struct completion done;
    29	};
    30	
    31	struct caam_prng_alg {
    32		struct rng_alg rng;
    33		bool registered;
    34	};
    35	
    36	static void caam_prng_done(struct device *jrdev, u32 *desc, u32 err,
    37				  void *context)
    38	{
    39		struct caam_prng_ctx *jctx = context;
    40	
    41		if (err)
    42			caam_jr_strstatus(jrdev, err);
    43	
    44		complete(&jctx->done);
    45	}
    46	
    47	static u32 *caam_init_reseed_desc(u32 *desc, dma_addr_t seed_dma, u32 len)
    48	{
    49		init_job_desc(desc, 0);	/* + 1 cmd_sz */
    50		/* Generate random bytes: + 1 cmd_sz */
    51		append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
    52				OP_ALG_AS_FINALIZE | OP_ALG_AI_ON);
    53		/* Store bytes: + 1 cmd_sz + caam_ptr_sz  */
    54		append_load(desc, seed_dma, len, CLASS_1 | LDST_SRCDST_BYTE_CONTEXT);
    55	
    56		print_hex_dump_debug("prng reseed desc@: ", DUMP_PREFIX_ADDRESS,
    57				     16, 4, desc, desc_bytes(desc), 1);
    58	
    59		return desc;
    60	}
    61	
    62	static u32 *caam_init_prng_desc(u32 *desc, dma_addr_t dst_dma, u32 len)
    63	{
    64		init_job_desc(desc, 0);	/* + 1 cmd_sz */
    65		/* Generate random bytes: + 1 cmd_sz */
    66		append_operation(desc, OP_ALG_ALGSEL_RNG | OP_TYPE_CLASS1_ALG);
    67		/* Store bytes: + 1 cmd_sz + caam_ptr_sz  */
    68		append_fifo_store(desc, dst_dma,
    69				  len, FIFOST_TYPE_RNGSTORE);
    70	
    71		print_hex_dump_debug("prng job desc@: ", DUMP_PREFIX_ADDRESS,
    72				     16, 4, desc, desc_bytes(desc), 1);
    73	
    74		return desc;
    75	}
    76	
    77	static int caam_prng_generate(struct crypto_rng *tfm,
    78				     const u8 *src, unsigned int slen,
    79				     u8 *dst, unsigned int dlen)
    80	{
    81		struct caam_prng_ctx ctx;
    82		dma_addr_t dst_dma;
    83		u32 *desc;
    84		int ret;
    85	
    86		ctx.jrdev = caam_jr_alloc();
    87		ret = PTR_ERR_OR_ZERO(ctx.jrdev);
    88		if (ret) {
    89			pr_err("Job Ring Device allocation failed\n");
    90			return ret;
    91		}
    92	
    93		desc = kzalloc(CAAM_PRNG_DESC_LEN, GFP_KERNEL | GFP_DMA);
    94		if (!desc) {
    95			caam_jr_free(ctx.jrdev);
    96			return -ENOMEM;
    97		}
    98	
    99		dst_dma = dma_map_single(ctx.jrdev, dst, dlen, DMA_FROM_DEVICE);
   100		if (dma_mapping_error(ctx.jrdev, dst_dma)) {
   101			dev_err(ctx.jrdev, "Failed to map destination buffer memory\n");
   102			ret = -ENOMEM;
   103			goto out;
   104		}
   105	
   106		init_completion(&ctx.done);
   107		ret = caam_jr_enqueue(ctx.jrdev,
   108				      caam_init_prng_desc(desc, dst_dma, dlen),
   109				      caam_prng_done, &ctx);
   110	
   111		if (ret == -EINPROGRESS) {
   112			wait_for_completion(&ctx.done);
   113			ret = 0;
   114		}
   115	
   116		dma_unmap_single(ctx.jrdev, dst_dma, dlen, DMA_FROM_DEVICE);
   117	
   118	out:
   119		kfree(desc);
   120		caam_jr_free(ctx.jrdev);
   121		return ret;
   122	}
   123	
   124	static void caam_prng_exit(struct crypto_tfm *tfm)
   125	{
   126	
   127		return;
   128	}
   129	
   130	static int caam_prng_init(struct crypto_tfm *tfm)
   131	{
   132		return 0;
   133	}
   134	
   135	static int caam_prng_seed(struct crypto_rng *tfm,
   136				 const u8 *seed, unsigned int slen)
   137	{
   138		struct caam_prng_ctx ctx;
   139		dma_addr_t seed_dma;
   140		u32 *desc;
   141		int ret;
   142	
   143		ctx.jrdev = caam_jr_alloc();
   144		ret = PTR_ERR_OR_ZERO(ctx.jrdev);
   145		if (ret) {
   146			pr_err("Job Ring Device allocation failed\n");
   147			return ret;
   148		}
   149	
   150		desc = kzalloc(CAAM_PRNG_DESC_LEN, GFP_KERNEL | GFP_DMA);
   151		if (!desc) {
   152			caam_jr_free(ctx.jrdev);
   153			return -ENOMEM;
   154		}
   155	
 > 156		seed_dma = dma_map_single(ctx.jrdev, seed, slen, DMA_FROM_DEVICE);
   157		if (dma_mapping_error(ctx.jrdev, seed_dma)) {
   158			dev_err(ctx.jrdev, "Failed to map destination buffer memory\n");
   159			ret = -ENOMEM;
   160			goto out;
   161		}
   162	
   163		init_completion(&ctx.done);
   164		ret = caam_jr_enqueue(ctx.jrdev,
   165				      caam_init_reseed_desc(desc, seed_dma, slen),
   166				      caam_prng_done, &ctx);
   167	
   168		if (ret == -EINPROGRESS) {
   169			wait_for_completion(&ctx.done);
   170			ret = 0;
   171		}
   172	
   173		dma_unmap_single(ctx.jrdev, seed_dma, slen, DMA_FROM_DEVICE);
   174	
   175	out:
   176		kfree(desc);
   177		caam_jr_free(ctx.jrdev);
   178		return ret;
   179	}
   180	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v2 0/1] crypto: caam/rng: Add support for PRNG
  2022-03-04 11:41 [PATCH] crypto: caam/rng: Add support for PRNG meenakshi.aggarwal
  2022-03-08 22:49 ` kernel test robot
@ 2022-03-16 18:01 ` meenakshi.aggarwal
  2022-03-16 18:01   ` [PATCH v2 1/1] " meenakshi.aggarwal
  2022-04-20  6:38 ` [PATCH v3 0/1] " meenakshi.aggarwal
  2 siblings, 1 reply; 15+ messages in thread
From: meenakshi.aggarwal @ 2022-03-16 18:01 UTC (permalink / raw)
  To: Horia Geanta, Pankaj Gupta, Gaurav Jain, Varun Sethi, Herbert Xu,
	David S . Miller
  Cc: linux-crypto, linux-kernel, linux-imx, Meenakshi Aggarwal

From: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>

changes in v2:
	- rebase to latest master
        - fixed compile time warning reported by kernel test robot
	- fixed checkpatch warning
	- fixed "rejecting DMA map of vmalloc memory" issue while running
	  "ecdh-nist-p256" algorithm self-test. This test uses caam prng's
	  to generate random number for its key.

Meenakshi Aggarwal (1):
  crypto: caam/rng: Add support for PRNG

 drivers/crypto/caam/Kconfig    |   9 ++
 drivers/crypto/caam/Makefile   |   1 +
 drivers/crypto/caam/caamprng.c | 256 +++++++++++++++++++++++++++++++++
 drivers/crypto/caam/desc.h     |   1 +
 drivers/crypto/caam/intern.h   |  15 ++
 drivers/crypto/caam/jr.c       |   2 +
 6 files changed, 284 insertions(+)
 create mode 100644 drivers/crypto/caam/caamprng.c


base-commit: 56e337f2cf1326323844927a04e9dbce9a244835
-- 
2.25.1


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v2 1/1] crypto: caam/rng: Add support for PRNG
  2022-03-16 18:01 ` [PATCH v2 0/1] " meenakshi.aggarwal
@ 2022-03-16 18:01   ` meenakshi.aggarwal
  2022-04-05 12:31     ` Horia Geantă
  0 siblings, 1 reply; 15+ messages in thread
From: meenakshi.aggarwal @ 2022-03-16 18:01 UTC (permalink / raw)
  To: Horia Geanta, Pankaj Gupta, Gaurav Jain, Varun Sethi, Herbert Xu,
	David S . Miller
  Cc: linux-crypto, linux-kernel, linux-imx, Meenakshi Aggarwal,
	kernel test robot

From: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>

Add support for random number generation using PRNG
mode of CAAM and expose the interface through crypto API.

Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
---
 drivers/crypto/caam/Kconfig    |   9 ++
 drivers/crypto/caam/Makefile   |   1 +
 drivers/crypto/caam/caamprng.c | 256 +++++++++++++++++++++++++++++++++
 drivers/crypto/caam/desc.h     |   1 +
 drivers/crypto/caam/intern.h   |  15 ++
 drivers/crypto/caam/jr.c       |   2 +
 6 files changed, 284 insertions(+)
 create mode 100644 drivers/crypto/caam/caamprng.c

diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig
index 84ea7cba5ee5..d94250348b32 100644
--- a/drivers/crypto/caam/Kconfig
+++ b/drivers/crypto/caam/Kconfig
@@ -151,6 +151,15 @@ config CRYPTO_DEV_FSL_CAAM_RNG_API
 	  Selecting this will register the SEC4 hardware rng to
 	  the hw_random API for supplying the kernel entropy pool.
 
+
+config CRYPTO_DEV_FSL_CAAM_PRNG_API
+	bool "Register Pseudo random number generation implementation with Crypto API"
+	default y
+	select CRYPTO_RNG
+	help
+	  Selecting this will register the SEC hardware prng to
+	  the Crypto API.
+
 endif # CRYPTO_DEV_FSL_CAAM_JR
 
 endif # CRYPTO_DEV_FSL_CAAM
diff --git a/drivers/crypto/caam/Makefile b/drivers/crypto/caam/Makefile
index 3570286eb9ce..59961a0bbfe4 100644
--- a/drivers/crypto/caam/Makefile
+++ b/drivers/crypto/caam/Makefile
@@ -21,6 +21,7 @@ caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI) += caamalg_qi.o
 caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API) += caamhash.o
 caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o
 caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API) += caampkc.o pkc_desc.o
+caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_PRNG_API) += caamprng.o
 
 caam-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI) += qi.o
 ifneq ($(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI),)
diff --git a/drivers/crypto/caam/caamprng.c b/drivers/crypto/caam/caamprng.c
new file mode 100644
index 000000000000..0524017a5e73
--- /dev/null
+++ b/drivers/crypto/caam/caamprng.c
@@ -0,0 +1,256 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Driver to expose SEC4 PRNG via crypto RNG API
+ *
+ * Copyright 2022 NXP
+ *
+ */
+
+#include <linux/completion.h>
+#include <crypto/internal/rng.h>
+#include "compat.h"
+#include "regs.h"
+#include "intern.h"
+#include "desc_constr.h"
+#include "jr.h"
+#include "error.h"
+
+/*
+ * Length of used descriptors, see caam_init_desc()
+ */
+#define CAAM_PRNG_DESC_LEN (CAAM_CMD_SZ +				\
+			    CAAM_CMD_SZ +				\
+			    CAAM_CMD_SZ + CAAM_PTR_SZ_MAX)
+
+/* prng per-device context */
+struct caam_prng_ctx {
+	struct device *jrdev;
+	struct completion done;
+};
+
+struct caam_prng_alg {
+	struct rng_alg rng;
+	bool registered;
+};
+
+static void caam_prng_done(struct device *jrdev, u32 *desc, u32 err,
+			  void *context)
+{
+	struct caam_prng_ctx *jctx = context;
+
+	if (err)
+		caam_jr_strstatus(jrdev, err);
+
+	complete(&jctx->done);
+}
+
+static u32 *caam_init_reseed_desc(u32 *desc, dma_addr_t seed_dma, u32 len)
+{
+	init_job_desc(desc, 0);	/* + 1 cmd_sz */
+	/* Generate random bytes: + 1 cmd_sz */
+	append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
+			OP_ALG_AS_FINALIZE | OP_ALG_AI_ON);
+	/* Store bytes: + 1 cmd_sz + caam_ptr_sz  */
+	append_load(desc, seed_dma, len, CLASS_1 | LDST_SRCDST_BYTE_CONTEXT);
+
+	print_hex_dump_debug("prng reseed desc@: ", DUMP_PREFIX_ADDRESS,
+			     16, 4, desc, desc_bytes(desc), 1);
+
+	return desc;
+}
+
+static u32 *caam_init_prng_desc(u32 *desc, dma_addr_t dst_dma, u32 len)
+{
+	init_job_desc(desc, 0);	/* + 1 cmd_sz */
+	/* Generate random bytes: + 1 cmd_sz */
+	append_operation(desc, OP_ALG_ALGSEL_RNG | OP_TYPE_CLASS1_ALG);
+	/* Store bytes: + 1 cmd_sz + caam_ptr_sz  */
+	append_fifo_store(desc, dst_dma,
+			  len, FIFOST_TYPE_RNGSTORE);
+
+	print_hex_dump_debug("prng job desc@: ", DUMP_PREFIX_ADDRESS,
+			     16, 4, desc, desc_bytes(desc), 1);
+
+	return desc;
+}
+
+static int caam_prng_generate(struct crypto_rng *tfm,
+			     const u8 *src, unsigned int slen,
+			     u8 *dst, unsigned int dlen)
+{
+	struct caam_prng_ctx ctx;
+	dma_addr_t dst_dma;
+	u32 *desc;
+	u8 *buf;
+	int ret;
+
+	buf = kzalloc(dlen, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	ctx.jrdev = caam_jr_alloc();
+	ret = PTR_ERR_OR_ZERO(ctx.jrdev);
+	if (ret) {
+		pr_err("Job Ring Device allocation failed\n");
+		kfree(buf);
+		return ret;
+	}
+
+	desc = kzalloc(CAAM_PRNG_DESC_LEN, GFP_KERNEL | GFP_DMA);
+	if (!desc) {
+		caam_jr_free(ctx.jrdev);
+		kfree(buf);
+		return -ENOMEM;
+	}
+
+	dst_dma = dma_map_single(ctx.jrdev, buf, dlen, DMA_FROM_DEVICE);
+	if (dma_mapping_error(ctx.jrdev, dst_dma)) {
+		dev_err(ctx.jrdev, "Failed to map destination buffer memory\n");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	init_completion(&ctx.done);
+	ret = caam_jr_enqueue(ctx.jrdev,
+			      caam_init_prng_desc(desc, dst_dma, dlen),
+			      caam_prng_done, &ctx);
+
+	if (ret == -EINPROGRESS) {
+		wait_for_completion(&ctx.done);
+		ret = 0;
+	}
+
+	dma_unmap_single(ctx.jrdev, dst_dma, dlen, DMA_FROM_DEVICE);
+
+	memcpy(dst, buf, dlen);
+out:
+	caam_jr_free(ctx.jrdev);
+	kfree(desc);
+	kfree(buf);
+	return ret;
+}
+
+static void caam_prng_exit(struct crypto_tfm *tfm) {}
+
+static int caam_prng_init(struct crypto_tfm *tfm)
+{
+	return 0;
+}
+
+static int caam_prng_seed(struct crypto_rng *tfm,
+			 const u8 *seed, unsigned int slen)
+{
+	struct caam_prng_ctx ctx;
+	dma_addr_t seed_dma;
+	u32 *desc;
+	u8 *buf;
+	int ret = 0;
+
+	if (seed == NULL) {
+		pr_err("Seed not provided\n");
+		return ret;
+	}
+
+	buf = kzalloc(slen, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	ctx.jrdev = caam_jr_alloc();
+	ret = PTR_ERR_OR_ZERO(ctx.jrdev);
+	if (ret) {
+		pr_err("Job Ring Device allocation failed\n");
+		kfree(buf);
+		return ret;
+	}
+
+	desc = kzalloc(CAAM_PRNG_DESC_LEN, GFP_KERNEL | GFP_DMA);
+	if (!desc) {
+		caam_jr_free(ctx.jrdev);
+		kfree(buf);
+		return -ENOMEM;
+	}
+
+	memcpy(buf, seed, slen);
+
+	seed_dma = dma_map_single(ctx.jrdev, buf, slen, DMA_FROM_DEVICE);
+	if (dma_mapping_error(ctx.jrdev, seed_dma)) {
+		dev_err(ctx.jrdev, "Failed to map seed buffer memory\n");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	init_completion(&ctx.done);
+	ret = caam_jr_enqueue(ctx.jrdev,
+			      caam_init_reseed_desc(desc, seed_dma, slen),
+			      caam_prng_done, &ctx);
+
+	if (ret == -EINPROGRESS) {
+		wait_for_completion(&ctx.done);
+		ret = 0;
+	}
+
+	dma_unmap_single(ctx.jrdev, seed_dma, slen, DMA_FROM_DEVICE);
+
+out:
+	caam_jr_free(ctx.jrdev);
+	kfree(desc);
+	kfree(buf);
+	return ret;
+}
+
+static struct caam_prng_alg caam_prng_alg = {
+	.rng = {
+		.generate = caam_prng_generate,
+		.seed = caam_prng_seed,
+		.seedsize = 32,
+		.base = {
+			.cra_name = "stdrng",
+			.cra_driver_name = "prng-caam",
+			.cra_priority = 500,
+			.cra_ctxsize = sizeof(struct caam_prng_ctx),
+			.cra_module = THIS_MODULE,
+			.cra_init = caam_prng_init,
+			.cra_exit = caam_prng_exit,
+		},
+	}
+};
+
+void caam_prng_unregister(void *data)
+{
+	if (caam_prng_alg.registered)
+		crypto_unregister_rng(&caam_prng_alg.rng);
+}
+
+int caam_prng_register(struct device *ctrldev)
+{
+	struct caam_drv_private *priv = dev_get_drvdata(ctrldev);
+	u32 rng_inst;
+	int ret = 0;
+
+	/* Check for available RNG blocks before registration */
+	if (priv->era < 10)
+		rng_inst = (rd_reg32(&priv->jr[0]->perfmon.cha_num_ls) &
+			    CHA_ID_LS_RNG_MASK) >> CHA_ID_LS_RNG_SHIFT;
+	else
+		rng_inst = rd_reg32(&priv->jr[0]->vreg.rng) & CHA_VER_NUM_MASK;
+
+	if (!rng_inst) {
+		dev_dbg(ctrldev, "RNG block is not available... skipping registering algorithm\n");
+		return ret;
+	}
+
+	ret = crypto_register_rng(&caam_prng_alg.rng);
+	if (ret) {
+		dev_err(ctrldev,
+			"couldn't register rng crypto alg: %d\n",
+			ret);
+		return ret;
+	}
+
+	caam_prng_alg.registered = true;
+
+	dev_info(ctrldev,
+		 "rng crypto API alg registered %s\n", caam_prng_alg.rng.base.cra_name);
+
+	return 0;
+}
diff --git a/drivers/crypto/caam/desc.h b/drivers/crypto/caam/desc.h
index e13470901586..33db8ed2b49e 100644
--- a/drivers/crypto/caam/desc.h
+++ b/drivers/crypto/caam/desc.h
@@ -1255,6 +1255,7 @@
 #define OP_ALG_ICV_ON		(1 << OP_ALG_ICV_SHIFT)
 
 #define OP_ALG_PR_ON		BIT(1)
+#define OP_ALG_AI_ON		BIT(11)
 
 #define OP_ALG_DIR_SHIFT	0
 #define OP_ALG_DIR_MASK		1
diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h
index 7d45b21bd55a..c2f51365df1b 100644
--- a/drivers/crypto/caam/intern.h
+++ b/drivers/crypto/caam/intern.h
@@ -185,6 +185,21 @@ static inline void caam_rng_exit(struct device *dev) {}
 
 #endif /* CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API */
 
+#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_PRNG_API
+
+int caam_prng_register(struct device *dev);
+void caam_prng_unregister(void *data);
+
+#else
+
+static inline int caam_prng_register(struct device *dev)
+{
+	return 0;
+}
+
+static inline void caam_prng_unregister(void *data) {}
+#endif /* CONFIG_CRYPTO_DEV_FSL_CAAM_PRNG_API */
+
 #ifdef CONFIG_CAAM_QI
 
 int caam_qi_algapi_init(struct device *dev);
diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c
index 7f2b1101f567..11849362f912 100644
--- a/drivers/crypto/caam/jr.c
+++ b/drivers/crypto/caam/jr.c
@@ -39,6 +39,7 @@ static void register_algs(struct caam_drv_private_jr *jrpriv,
 	caam_algapi_hash_init(dev);
 	caam_pkc_init(dev);
 	jrpriv->hwrng = !caam_rng_init(dev);
+	caam_prng_register(dev);
 	caam_qi_algapi_init(dev);
 
 algs_unlock:
@@ -56,6 +57,7 @@ static void unregister_algs(void)
 
 	caam_pkc_exit();
 	caam_algapi_hash_exit();
+	caam_prng_unregister(NULL);
 	caam_algapi_exit();
 
 algs_unlock:
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 1/1] crypto: caam/rng: Add support for PRNG
  2022-03-16 18:01   ` [PATCH v2 1/1] " meenakshi.aggarwal
@ 2022-04-05 12:31     ` Horia Geantă
  2022-04-20  5:57       ` Meenakshi Aggarwal
  0 siblings, 1 reply; 15+ messages in thread
From: Horia Geantă @ 2022-04-05 12:31 UTC (permalink / raw)
  To: Meenakshi Aggarwal, Pankaj Gupta, Gaurav Jain, Varun Sethi,
	Herbert Xu, David S . Miller
  Cc: linux-crypto, linux-kernel, dl-linux-imx, kernel test robot

On 3/16/2022 8:02 PM, Meenakshi Aggarwal wrote:
> From: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
> 
> Add support for random number generation using PRNG
> mode of CAAM and expose the interface through crypto API.
> 
According to the RM, the HW implementation of the DRBG follows
NIST SP 800-90A specification for DRBG_Hash SHA-256 function
(https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf).
This should be mentioned in the commit message at minimum.

> Reported-by: kernel test robot <lkp@intel.com>
This isn't required and doesn't make sense once you've squashed the fix.

> +/* prng per-device context */
> +struct caam_prng_ctx {
> +	struct device *jrdev;
jrdev doesn't have to be saved in this struct, it's lifetime is very limited.

> +	struct completion done;
> +};
> +
> +struct caam_prng_alg {
> +	struct rng_alg rng;
> +	bool registered;
> +};
> +
> +static void caam_prng_done(struct device *jrdev, u32 *desc, u32 err,
> +			  void *context)
> +{
> +	struct caam_prng_ctx *jctx = context;
> +
> +	if (err)
> +		caam_jr_strstatus(jrdev, err);
The error returned by caam_jr_strstatus() should be propagated back to
who initially enqueued the corresponding.
For this purpose, struct caam_prng_ctx could be extended with an "err" member.

> +
> +	complete(&jctx->done);
> +}
> +

> +static int caam_prng_generate(struct crypto_rng *tfm,
> +			     const u8 *src, unsigned int slen,
> +			     u8 *dst, unsigned int dlen)
> +{
> +	struct caam_prng_ctx ctx;
> +	dma_addr_t dst_dma;
> +	u32 *desc;
> +	u8 *buf;
> +	int ret;
> +
> +	buf = kzalloc(dlen, GFP_KERNEL);
> +	if (!buf)
> +		return -ENOMEM;
> +
> +	ctx.jrdev = caam_jr_alloc();
> +	ret = PTR_ERR_OR_ZERO(ctx.jrdev);
> +	if (ret) {
> +		pr_err("Job Ring Device allocation failed\n");
> +		kfree(buf);
> +		return ret;
> +	}
> +
> +	desc = kzalloc(CAAM_PRNG_DESC_LEN, GFP_KERNEL | GFP_DMA);
> +	if (!desc) {
> +		caam_jr_free(ctx.jrdev);
> +		kfree(buf);
> +		return -ENOMEM;
Please fix the error handling to reuse the free code
at the end of the function.

> +	}
> +
> +	dst_dma = dma_map_single(ctx.jrdev, buf, dlen, DMA_FROM_DEVICE);
> +	if (dma_mapping_error(ctx.jrdev, dst_dma)) {
> +		dev_err(ctx.jrdev, "Failed to map destination buffer memory\n");
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	init_completion(&ctx.done);
> +	ret = caam_jr_enqueue(ctx.jrdev,
> +			      caam_init_prng_desc(desc, dst_dma, dlen),
> +			      caam_prng_done, &ctx);
> +
> +	if (ret == -EINPROGRESS) {
> +		wait_for_completion(&ctx.done);
> +		ret = 0;
> +	}
> +
> +	dma_unmap_single(ctx.jrdev, dst_dma, dlen, DMA_FROM_DEVICE);
> +
> +	memcpy(dst, buf, dlen);
I am a bit worried wrt. performance, considering the memory allocations
and the memcpy on the hotpath.

Previous version of CAAM PRNG driver was getting ~ 200 MB/s on LS
and 50 MB/s on i.MX8.

How does the current version compare?
Given that there's no prefetch buffer and there are memory allocation, copy
operations on the hotpath, I'd expect a hefty penalty.

> +out:
> +	caam_jr_free(ctx.jrdev);
> +	kfree(desc);
> +	kfree(buf);
> +	return ret;
> +}
> +
> +static void caam_prng_exit(struct crypto_tfm *tfm) {}
> +
> +static int caam_prng_init(struct crypto_tfm *tfm)
> +{
> +	return 0;
> +}
> +
> +static int caam_prng_seed(struct crypto_rng *tfm,
> +			 const u8 *seed, unsigned int slen)
> +{
> +	struct caam_prng_ctx ctx;
> +	dma_addr_t seed_dma;
> +	u32 *desc;
> +	u8 *buf;
> +	int ret = 0;
> +
> +	if (seed == NULL) {
> +		pr_err("Seed not provided\n");
> +		return ret;
> +	}
> +
> +	buf = kzalloc(slen, GFP_KERNEL);
> +	if (!buf)
> +		return -ENOMEM;
> +
> +	ctx.jrdev = caam_jr_alloc();
> +	ret = PTR_ERR_OR_ZERO(ctx.jrdev);
> +	if (ret) {
> +		pr_err("Job Ring Device allocation failed\n");
> +		kfree(buf);
> +		return ret;
> +	}
> +
> +	desc = kzalloc(CAAM_PRNG_DESC_LEN, GFP_KERNEL | GFP_DMA);
> +	if (!desc) {
> +		caam_jr_free(ctx.jrdev);
> +		kfree(buf);
> +		return -ENOMEM;
Same here, error handling at the end of the function should be reused.

> +	}
> +
> +	memcpy(buf, seed, slen);
> +
> +	seed_dma = dma_map_single(ctx.jrdev, buf, slen, DMA_FROM_DEVICE);
> +	if (dma_mapping_error(ctx.jrdev, seed_dma)) {
> +		dev_err(ctx.jrdev, "Failed to map seed buffer memory\n");
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	init_completion(&ctx.done);
> +	ret = caam_jr_enqueue(ctx.jrdev,
> +			      caam_init_reseed_desc(desc, seed_dma, slen),
> +			      caam_prng_done, &ctx);
> +
> +	if (ret == -EINPROGRESS) {
> +		wait_for_completion(&ctx.done);
> +		ret = 0;
> +	}
> +
> +	dma_unmap_single(ctx.jrdev, seed_dma, slen, DMA_FROM_DEVICE);
> +
> +out:
> +	caam_jr_free(ctx.jrdev);
> +	kfree(desc);
> +	kfree(buf);
> +	return ret;
> +}
> +
> +static struct caam_prng_alg caam_prng_alg = {
> +	.rng = {
> +		.generate = caam_prng_generate,
> +		.seed = caam_prng_seed,
> +		.seedsize = 32,
seedsize should be set to 0, HW does not need an externally-provided seed
since it fetches it internally from TRNG.

> +int caam_prng_register(struct device *ctrldev)
> +{
> +	struct caam_drv_private *priv = dev_get_drvdata(ctrldev);
> +	u32 rng_inst;
> +	int ret = 0;
> +
> +	/* Check for available RNG blocks before registration */
> +	if (priv->era < 10)
> +		rng_inst = (rd_reg32(&priv->jr[0]->perfmon.cha_num_ls) &
> +			    CHA_ID_LS_RNG_MASK) >> CHA_ID_LS_RNG_SHIFT;
> +	else
> +		rng_inst = rd_reg32(&priv->jr[0]->vreg.rng) & CHA_VER_NUM_MASK;
> +
> +	if (!rng_inst) {
> +		dev_dbg(ctrldev, "RNG block is not available... skipping registering algorithm\n");
> +		return ret;
> +	}
> +
> +	ret = crypto_register_rng(&caam_prng_alg.rng);
> +	if (ret) {
> +		dev_err(ctrldev,
> +			"couldn't register rng crypto alg: %d\n",
> +			ret);
> +		return ret;
> +	}
> +
> +	caam_prng_alg.registered = true;
> +
> +	dev_info(ctrldev,
> +		 "rng crypto API alg registered %s\n", caam_prng_alg.rng.base.cra_name);
driver_name should be printed, it's more specific / unique.

> diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c
> index 7f2b1101f567..11849362f912 100644
> --- a/drivers/crypto/caam/jr.c
> +++ b/drivers/crypto/caam/jr.c
> @@ -39,6 +39,7 @@ static void register_algs(struct caam_drv_private_jr *jrpriv,
>  	caam_algapi_hash_init(dev);
>  	caam_pkc_init(dev);
>  	jrpriv->hwrng = !caam_rng_init(dev);
> +	caam_prng_register(dev);
>  	caam_qi_algapi_init(dev);
>  
>  algs_unlock:
> @@ -56,6 +57,7 @@ static void unregister_algs(void)
>  
>  	caam_pkc_exit();
>  	caam_algapi_hash_exit();
> +	caam_prng_unregister(NULL);
Unregistering order should be the reverse order of registering.

Horia

^ permalink raw reply	[flat|nested] 15+ messages in thread

* RE: [PATCH v2 1/1] crypto: caam/rng: Add support for PRNG
  2022-04-05 12:31     ` Horia Geantă
@ 2022-04-20  5:57       ` Meenakshi Aggarwal
  0 siblings, 0 replies; 15+ messages in thread
From: Meenakshi Aggarwal @ 2022-04-20  5:57 UTC (permalink / raw)
  To: Horia Geanta, Pankaj Gupta, Gaurav Jain, Varun Sethi, Herbert Xu,
	David S . Miller
  Cc: linux-crypto, linux-kernel, dl-linux-imx, kernel test robot

HI,

Thanks for the review.

Will incorporate all suggested changes in v3.

On i.MX8, performance is coming  ~ 42 MB/s

Thanks,
Meenakshi
> -----Original Message-----
> From: Horia Geanta <horia.geanta@nxp.com>
> Sent: Tuesday, April 5, 2022 6:02 PM
> To: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>; Pankaj Gupta
> <pankaj.gupta@nxp.com>; Gaurav Jain <gaurav.jain@nxp.com>; Varun Sethi
> <V.Sethi@nxp.com>; Herbert Xu <herbert@gondor.apana.org.au>; David S .
> Miller <davem@davemloft.net>
> Cc: linux-crypto@vger.kernel.org; linux-kernel@vger.kernel.org; dl-linux-imx
> <linux-imx@nxp.com>; kernel test robot <lkp@intel.com>
> Subject: Re: [PATCH v2 1/1] crypto: caam/rng: Add support for PRNG
> 
> On 3/16/2022 8:02 PM, Meenakshi Aggarwal wrote:
> > From: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
> >
> > Add support for random number generation using PRNG mode of CAAM and
> > expose the interface through crypto API.
> >
> According to the RM, the HW implementation of the DRBG follows NIST SP 800-
> 90A specification for DRBG_Hash SHA-256 function
> (https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf).
> This should be mentioned in the commit message at minimum.
> 
> > Reported-by: kernel test robot <lkp@intel.com>
> This isn't required and doesn't make sense once you've squashed the fix.
> 
> > +/* prng per-device context */
> > +struct caam_prng_ctx {
> > +	struct device *jrdev;
> jrdev doesn't have to be saved in this struct, it's lifetime is very limited.
> 
> > +	struct completion done;
> > +};
> > +
> > +struct caam_prng_alg {
> > +	struct rng_alg rng;
> > +	bool registered;
> > +};
> > +
> > +static void caam_prng_done(struct device *jrdev, u32 *desc, u32 err,
> > +			  void *context)
> > +{
> > +	struct caam_prng_ctx *jctx = context;
> > +
> > +	if (err)
> > +		caam_jr_strstatus(jrdev, err);
> The error returned by caam_jr_strstatus() should be propagated back to who
> initially enqueued the corresponding.
> For this purpose, struct caam_prng_ctx could be extended with an "err" member.
> 
> > +
> > +	complete(&jctx->done);
> > +}
> > +
> 
> > +static int caam_prng_generate(struct crypto_rng *tfm,
> > +			     const u8 *src, unsigned int slen,
> > +			     u8 *dst, unsigned int dlen)
> > +{
> > +	struct caam_prng_ctx ctx;
> > +	dma_addr_t dst_dma;
> > +	u32 *desc;
> > +	u8 *buf;
> > +	int ret;
> > +
> > +	buf = kzalloc(dlen, GFP_KERNEL);
> > +	if (!buf)
> > +		return -ENOMEM;
> > +
> > +	ctx.jrdev = caam_jr_alloc();
> > +	ret = PTR_ERR_OR_ZERO(ctx.jrdev);
> > +	if (ret) {
> > +		pr_err("Job Ring Device allocation failed\n");
> > +		kfree(buf);
> > +		return ret;
> > +	}
> > +
> > +	desc = kzalloc(CAAM_PRNG_DESC_LEN, GFP_KERNEL | GFP_DMA);
> > +	if (!desc) {
> > +		caam_jr_free(ctx.jrdev);
> > +		kfree(buf);
> > +		return -ENOMEM;
> Please fix the error handling to reuse the free code at the end of the function.
> 
> > +	}
> > +
> > +	dst_dma = dma_map_single(ctx.jrdev, buf, dlen, DMA_FROM_DEVICE);
> > +	if (dma_mapping_error(ctx.jrdev, dst_dma)) {
> > +		dev_err(ctx.jrdev, "Failed to map destination buffer memory\n");
> > +		ret = -ENOMEM;
> > +		goto out;
> > +	}
> > +
> > +	init_completion(&ctx.done);
> > +	ret = caam_jr_enqueue(ctx.jrdev,
> > +			      caam_init_prng_desc(desc, dst_dma, dlen),
> > +			      caam_prng_done, &ctx);
> > +
> > +	if (ret == -EINPROGRESS) {
> > +		wait_for_completion(&ctx.done);
> > +		ret = 0;
> > +	}
> > +
> > +	dma_unmap_single(ctx.jrdev, dst_dma, dlen, DMA_FROM_DEVICE);
> > +
> > +	memcpy(dst, buf, dlen);
> I am a bit worried wrt. performance, considering the memory allocations and
> the memcpy on the hotpath.
> 
> Previous version of CAAM PRNG driver was getting ~ 200 MB/s on LS and 50
> MB/s on i.MX8.
> 
> How does the current version compare?
> Given that there's no prefetch buffer and there are memory allocation, copy
> operations on the hotpath, I'd expect a hefty penalty.
> 
> > +out:
> > +	caam_jr_free(ctx.jrdev);
> > +	kfree(desc);
> > +	kfree(buf);
> > +	return ret;
> > +}
> > +
> > +static void caam_prng_exit(struct crypto_tfm *tfm) {}
> > +
> > +static int caam_prng_init(struct crypto_tfm *tfm) {
> > +	return 0;
> > +}
> > +
> > +static int caam_prng_seed(struct crypto_rng *tfm,
> > +			 const u8 *seed, unsigned int slen) {
> > +	struct caam_prng_ctx ctx;
> > +	dma_addr_t seed_dma;
> > +	u32 *desc;
> > +	u8 *buf;
> > +	int ret = 0;
> > +
> > +	if (seed == NULL) {
> > +		pr_err("Seed not provided\n");
> > +		return ret;
> > +	}
> > +
> > +	buf = kzalloc(slen, GFP_KERNEL);
> > +	if (!buf)
> > +		return -ENOMEM;
> > +
> > +	ctx.jrdev = caam_jr_alloc();
> > +	ret = PTR_ERR_OR_ZERO(ctx.jrdev);
> > +	if (ret) {
> > +		pr_err("Job Ring Device allocation failed\n");
> > +		kfree(buf);
> > +		return ret;
> > +	}
> > +
> > +	desc = kzalloc(CAAM_PRNG_DESC_LEN, GFP_KERNEL | GFP_DMA);
> > +	if (!desc) {
> > +		caam_jr_free(ctx.jrdev);
> > +		kfree(buf);
> > +		return -ENOMEM;
> Same here, error handling at the end of the function should be reused.
> 
> > +	}
> > +
> > +	memcpy(buf, seed, slen);
> > +
> > +	seed_dma = dma_map_single(ctx.jrdev, buf, slen, DMA_FROM_DEVICE);
> > +	if (dma_mapping_error(ctx.jrdev, seed_dma)) {
> > +		dev_err(ctx.jrdev, "Failed to map seed buffer memory\n");
> > +		ret = -ENOMEM;
> > +		goto out;
> > +	}
> > +
> > +	init_completion(&ctx.done);
> > +	ret = caam_jr_enqueue(ctx.jrdev,
> > +			      caam_init_reseed_desc(desc, seed_dma, slen),
> > +			      caam_prng_done, &ctx);
> > +
> > +	if (ret == -EINPROGRESS) {
> > +		wait_for_completion(&ctx.done);
> > +		ret = 0;
> > +	}
> > +
> > +	dma_unmap_single(ctx.jrdev, seed_dma, slen, DMA_FROM_DEVICE);
> > +
> > +out:
> > +	caam_jr_free(ctx.jrdev);
> > +	kfree(desc);
> > +	kfree(buf);
> > +	return ret;
> > +}
> > +
> > +static struct caam_prng_alg caam_prng_alg = {
> > +	.rng = {
> > +		.generate = caam_prng_generate,
> > +		.seed = caam_prng_seed,
> > +		.seedsize = 32,
> seedsize should be set to 0, HW does not need an externally-provided seed since
> it fetches it internally from TRNG.
> 
> > +int caam_prng_register(struct device *ctrldev) {
> > +	struct caam_drv_private *priv = dev_get_drvdata(ctrldev);
> > +	u32 rng_inst;
> > +	int ret = 0;
> > +
> > +	/* Check for available RNG blocks before registration */
> > +	if (priv->era < 10)
> > +		rng_inst = (rd_reg32(&priv->jr[0]->perfmon.cha_num_ls) &
> > +			    CHA_ID_LS_RNG_MASK) >> CHA_ID_LS_RNG_SHIFT;
> > +	else
> > +		rng_inst = rd_reg32(&priv->jr[0]->vreg.rng) &
> CHA_VER_NUM_MASK;
> > +
> > +	if (!rng_inst) {
> > +		dev_dbg(ctrldev, "RNG block is not available... skipping
> registering algorithm\n");
> > +		return ret;
> > +	}
> > +
> > +	ret = crypto_register_rng(&caam_prng_alg.rng);
> > +	if (ret) {
> > +		dev_err(ctrldev,
> > +			"couldn't register rng crypto alg: %d\n",
> > +			ret);
> > +		return ret;
> > +	}
> > +
> > +	caam_prng_alg.registered = true;
> > +
> > +	dev_info(ctrldev,
> > +		 "rng crypto API alg registered %s\n",
> > +caam_prng_alg.rng.base.cra_name);
> driver_name should be printed, it's more specific / unique.
> 
> > diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c index
> > 7f2b1101f567..11849362f912 100644
> > --- a/drivers/crypto/caam/jr.c
> > +++ b/drivers/crypto/caam/jr.c
> > @@ -39,6 +39,7 @@ static void register_algs(struct caam_drv_private_jr
> *jrpriv,
> >  	caam_algapi_hash_init(dev);
> >  	caam_pkc_init(dev);
> >  	jrpriv->hwrng = !caam_rng_init(dev);
> > +	caam_prng_register(dev);
> >  	caam_qi_algapi_init(dev);
> >
> >  algs_unlock:
> > @@ -56,6 +57,7 @@ static void unregister_algs(void)
> >
> >  	caam_pkc_exit();
> >  	caam_algapi_hash_exit();
> > +	caam_prng_unregister(NULL);
> Unregistering order should be the reverse order of registering.
> 
> Horia

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 0/1] crypto: caam/rng: Add support for PRNG
  2022-03-04 11:41 [PATCH] crypto: caam/rng: Add support for PRNG meenakshi.aggarwal
  2022-03-08 22:49 ` kernel test robot
  2022-03-16 18:01 ` [PATCH v2 0/1] " meenakshi.aggarwal
@ 2022-04-20  6:38 ` meenakshi.aggarwal
  2022-04-20  6:38   ` [PATCH v3 1/1] " meenakshi.aggarwal
  2022-04-29  8:45   ` [PATCH v4 0/1] " meenakshi.aggarwal
  2 siblings, 2 replies; 15+ messages in thread
From: meenakshi.aggarwal @ 2022-04-20  6:38 UTC (permalink / raw)
  To: Horia Geanta, Pankaj Gupta, Gaurav Jain, Varun Sethi, Herbert Xu,
	David S . Miller
  Cc: linux-crypto, linux-kernel, linux-imx, Meenakshi Aggarwal

From: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>

changes in v3:
	- rebase to latest master
	- incorporated review comments

Meenakshi Aggarwal (1):
  crypto: caam/rng: Add support for PRNG

 drivers/crypto/caam/Kconfig    |   9 ++
 drivers/crypto/caam/Makefile   |   1 +
 drivers/crypto/caam/caamprng.c | 260 +++++++++++++++++++++++++++++++++
 drivers/crypto/caam/desc.h     |   1 +
 drivers/crypto/caam/intern.h   |  15 ++
 drivers/crypto/caam/jr.c       |   3 +-
 6 files changed, 288 insertions(+), 1 deletion(-)
 create mode 100644 drivers/crypto/caam/caamprng.c


base-commit: 559089e0a93d44280ec3ab478830af319c56dbe3
-- 
2.25.1


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 1/1] crypto: caam/rng: Add support for PRNG
  2022-04-20  6:38 ` [PATCH v3 0/1] " meenakshi.aggarwal
@ 2022-04-20  6:38   ` meenakshi.aggarwal
  2022-04-27 11:48     ` Horia Geantă
  2022-04-29  8:45   ` [PATCH v4 0/1] " meenakshi.aggarwal
  1 sibling, 1 reply; 15+ messages in thread
From: meenakshi.aggarwal @ 2022-04-20  6:38 UTC (permalink / raw)
  To: Horia Geanta, Pankaj Gupta, Gaurav Jain, Varun Sethi, Herbert Xu,
	David S . Miller
  Cc: linux-crypto, linux-kernel, linux-imx, Meenakshi Aggarwal

From: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>

Add support for random number generation using PRNG
mode of CAAM and expose the interface through crypto API.

According to the RM, the HW implementation of the DRBG/PRNG
follows NIST SP 800-90A specification for DRBG_Hash SHA-256 function

Signed-off-by: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
---
 drivers/crypto/caam/Kconfig    |   9 ++
 drivers/crypto/caam/Makefile   |   1 +
 drivers/crypto/caam/caamprng.c | 260 +++++++++++++++++++++++++++++++++
 drivers/crypto/caam/desc.h     |   1 +
 drivers/crypto/caam/intern.h   |  15 ++
 drivers/crypto/caam/jr.c       |   3 +-
 6 files changed, 288 insertions(+), 1 deletion(-)
 create mode 100644 drivers/crypto/caam/caamprng.c

diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig
index 84ea7cba5ee5..d94250348b32 100644
--- a/drivers/crypto/caam/Kconfig
+++ b/drivers/crypto/caam/Kconfig
@@ -151,6 +151,15 @@ config CRYPTO_DEV_FSL_CAAM_RNG_API
 	  Selecting this will register the SEC4 hardware rng to
 	  the hw_random API for supplying the kernel entropy pool.
 
+
+config CRYPTO_DEV_FSL_CAAM_PRNG_API
+	bool "Register Pseudo random number generation implementation with Crypto API"
+	default y
+	select CRYPTO_RNG
+	help
+	  Selecting this will register the SEC hardware prng to
+	  the Crypto API.
+
 endif # CRYPTO_DEV_FSL_CAAM_JR
 
 endif # CRYPTO_DEV_FSL_CAAM
diff --git a/drivers/crypto/caam/Makefile b/drivers/crypto/caam/Makefile
index 3570286eb9ce..59961a0bbfe4 100644
--- a/drivers/crypto/caam/Makefile
+++ b/drivers/crypto/caam/Makefile
@@ -21,6 +21,7 @@ caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI) += caamalg_qi.o
 caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API) += caamhash.o
 caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o
 caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API) += caampkc.o pkc_desc.o
+caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_PRNG_API) += caamprng.o
 
 caam-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI) += qi.o
 ifneq ($(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI),)
diff --git a/drivers/crypto/caam/caamprng.c b/drivers/crypto/caam/caamprng.c
new file mode 100644
index 000000000000..a40f8d5f761f
--- /dev/null
+++ b/drivers/crypto/caam/caamprng.c
@@ -0,0 +1,260 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Driver to expose SEC4 PRNG via crypto RNG API
+ *
+ * Copyright 2022 NXP
+ *
+ */
+
+#include <linux/completion.h>
+#include <crypto/internal/rng.h>
+#include "compat.h"
+#include "regs.h"
+#include "intern.h"
+#include "desc_constr.h"
+#include "jr.h"
+#include "error.h"
+
+/*
+ * Length of used descriptors, see caam_init_desc()
+ */
+#define CAAM_PRNG_DESC_LEN (CAAM_CMD_SZ +				\
+			    CAAM_CMD_SZ +				\
+			    CAAM_CMD_SZ + CAAM_PTR_SZ_MAX)
+
+/* prng per-device context */
+struct caam_prng_ctx {
+	int err;
+	struct completion done;
+};
+
+struct caam_prng_alg {
+	struct rng_alg rng;
+	bool registered;
+};
+
+static void caam_prng_done(struct device *jrdev, u32 *desc, u32 err,
+			  void *context)
+{
+	struct caam_prng_ctx *jctx = context;
+
+	if (err >> JRSTA_SSRC_SHIFT)
+		jctx->err = caam_jr_strstatus(jrdev, err);
+	else
+		jctx->err = 0;
+
+	complete(&jctx->done);
+}
+
+static u32 *caam_init_reseed_desc(u32 *desc, dma_addr_t seed_dma, u32 len)
+{
+	init_job_desc(desc, 0);	/* + 1 cmd_sz */
+	/* Generate random bytes: + 1 cmd_sz */
+	append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
+			OP_ALG_AS_FINALIZE | OP_ALG_AI_ON);
+	/* Store bytes: + 1 cmd_sz + caam_ptr_sz  */
+	append_load(desc, seed_dma, len, CLASS_1 | LDST_SRCDST_BYTE_CONTEXT);
+
+	print_hex_dump_debug("prng reseed desc@: ", DUMP_PREFIX_ADDRESS,
+			     16, 4, desc, desc_bytes(desc), 1);
+
+	return desc;
+}
+
+static u32 *caam_init_prng_desc(u32 *desc, dma_addr_t dst_dma, u32 len)
+{
+	init_job_desc(desc, 0);	/* + 1 cmd_sz */
+	/* Generate random bytes: + 1 cmd_sz */
+	append_operation(desc, OP_ALG_ALGSEL_RNG | OP_TYPE_CLASS1_ALG);
+	/* Store bytes: + 1 cmd_sz + caam_ptr_sz  */
+	append_fifo_store(desc, dst_dma,
+			  len, FIFOST_TYPE_RNGSTORE);
+
+	print_hex_dump_debug("prng job desc@: ", DUMP_PREFIX_ADDRESS,
+			     16, 4, desc, desc_bytes(desc), 1);
+
+	return desc;
+}
+
+static int caam_prng_generate(struct crypto_rng *tfm,
+			     const u8 *src, unsigned int slen,
+			     u8 *dst, unsigned int dlen)
+{
+	struct caam_prng_ctx ctx;
+	struct device *jrdev;
+	dma_addr_t dst_dma;
+	u32 *desc;
+	u8 *buf;
+	int ret;
+
+	buf = kzalloc(dlen, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	jrdev = caam_jr_alloc();
+	ret = PTR_ERR_OR_ZERO(jrdev);
+	if (ret) {
+		pr_err("Job Ring Device allocation failed\n");
+		kfree(buf);
+		return ret;
+	}
+
+	desc = kzalloc(CAAM_PRNG_DESC_LEN, GFP_KERNEL | GFP_DMA);
+	if (!desc) {
+		ret = -ENOMEM;
+		goto out1;
+	}
+
+	dst_dma = dma_map_single(jrdev, buf, dlen, DMA_FROM_DEVICE);
+	if (dma_mapping_error(jrdev, dst_dma)) {
+		dev_err(jrdev, "Failed to map destination buffer memory\n");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	init_completion(&ctx.done);
+	ret = caam_jr_enqueue(jrdev,
+			      caam_init_prng_desc(desc, dst_dma, dlen),
+			      caam_prng_done, &ctx);
+
+	if (ret == -EINPROGRESS) {
+		wait_for_completion(&ctx.done);
+		ret = ctx.err;
+	}
+
+	dma_unmap_single(jrdev, dst_dma, dlen, DMA_FROM_DEVICE);
+
+	memcpy(dst, buf, dlen);
+out:
+	kfree(desc);
+out1:
+	caam_jr_free(jrdev);
+	kfree(buf);
+	return ret;
+}
+
+static void caam_prng_exit(struct crypto_tfm *tfm) {}
+
+static int caam_prng_init(struct crypto_tfm *tfm)
+{
+	return 0;
+}
+
+static int caam_prng_seed(struct crypto_rng *tfm,
+			 const u8 *seed, unsigned int slen)
+{
+	struct caam_prng_ctx ctx;
+	struct device *jrdev;
+	dma_addr_t seed_dma;
+	u32 *desc;
+	u8 *buf;
+	int ret = 0;
+
+	if (seed == NULL) {
+		pr_err("Seed not provided\n");
+		return ret;
+	}
+
+	buf = kzalloc(slen, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	jrdev = caam_jr_alloc();
+	ret = PTR_ERR_OR_ZERO(jrdev);
+	if (ret) {
+		pr_err("Job Ring Device allocation failed\n");
+		kfree(buf);
+		return ret;
+	}
+
+	desc = kzalloc(CAAM_PRNG_DESC_LEN, GFP_KERNEL | GFP_DMA);
+	if (!desc) {
+		ret = -ENOMEM;
+		goto out1;
+	}
+
+	memcpy(buf, seed, slen);
+
+	seed_dma = dma_map_single(jrdev, buf, slen, DMA_FROM_DEVICE);
+	if (dma_mapping_error(jrdev, seed_dma)) {
+		dev_err(jrdev, "Failed to map seed buffer memory\n");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	init_completion(&ctx.done);
+	ret = caam_jr_enqueue(jrdev,
+			      caam_init_reseed_desc(desc, seed_dma, slen),
+			      caam_prng_done, &ctx);
+
+	if (ret == -EINPROGRESS) {
+		wait_for_completion(&ctx.done);
+		ret = ctx.err;
+	}
+
+	dma_unmap_single(jrdev, seed_dma, slen, DMA_FROM_DEVICE);
+
+out:
+	kfree(desc);
+out1:
+	caam_jr_free(jrdev);
+	kfree(buf);
+	return ret;
+}
+
+static struct caam_prng_alg caam_prng_alg = {
+	.rng = {
+		.generate = caam_prng_generate,
+		.seed = caam_prng_seed,
+		.seedsize = 0,
+		.base = {
+			.cra_name = "stdrng",
+			.cra_driver_name = "prng-caam",
+			.cra_priority = 500,
+			.cra_ctxsize = sizeof(struct caam_prng_ctx),
+			.cra_module = THIS_MODULE,
+			.cra_init = caam_prng_init,
+			.cra_exit = caam_prng_exit,
+		},
+	}
+};
+
+void caam_prng_unregister(void *data)
+{
+	if (caam_prng_alg.registered)
+		crypto_unregister_rng(&caam_prng_alg.rng);
+}
+
+int caam_prng_register(struct device *ctrldev)
+{
+	struct caam_drv_private *priv = dev_get_drvdata(ctrldev);
+	u32 rng_inst;
+	int ret = 0;
+
+	/* Check for available RNG blocks before registration */
+	if (priv->era < 10)
+		rng_inst = (rd_reg32(&priv->jr[0]->perfmon.cha_num_ls) &
+			    CHA_ID_LS_RNG_MASK) >> CHA_ID_LS_RNG_SHIFT;
+	else
+		rng_inst = rd_reg32(&priv->jr[0]->vreg.rng) & CHA_VER_NUM_MASK;
+
+	if (!rng_inst) {
+		dev_dbg(ctrldev, "RNG block is not available... skipping registering algorithm\n");
+		return ret;
+	}
+
+	ret = crypto_register_rng(&caam_prng_alg.rng);
+	if (ret) {
+		dev_err(ctrldev,
+			"couldn't register rng crypto alg: %d\n",
+			ret);
+		return ret;
+	}
+
+	caam_prng_alg.registered = true;
+
+	dev_info(ctrldev,
+		 "rng crypto API alg registered %s\n", caam_prng_alg.rng.base.cra_driver_name);
+
+	return 0;
+}
diff --git a/drivers/crypto/caam/desc.h b/drivers/crypto/caam/desc.h
index e13470901586..33db8ed2b49e 100644
--- a/drivers/crypto/caam/desc.h
+++ b/drivers/crypto/caam/desc.h
@@ -1255,6 +1255,7 @@
 #define OP_ALG_ICV_ON		(1 << OP_ALG_ICV_SHIFT)
 
 #define OP_ALG_PR_ON		BIT(1)
+#define OP_ALG_AI_ON		BIT(11)
 
 #define OP_ALG_DIR_SHIFT	0
 #define OP_ALG_DIR_MASK		1
diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h
index 7d45b21bd55a..c2f51365df1b 100644
--- a/drivers/crypto/caam/intern.h
+++ b/drivers/crypto/caam/intern.h
@@ -185,6 +185,21 @@ static inline void caam_rng_exit(struct device *dev) {}
 
 #endif /* CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API */
 
+#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_PRNG_API
+
+int caam_prng_register(struct device *dev);
+void caam_prng_unregister(void *data);
+
+#else
+
+static inline int caam_prng_register(struct device *dev)
+{
+	return 0;
+}
+
+static inline void caam_prng_unregister(void *data) {}
+#endif /* CONFIG_CRYPTO_DEV_FSL_CAAM_PRNG_API */
+
 #ifdef CONFIG_CAAM_QI
 
 int caam_qi_algapi_init(struct device *dev);
diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c
index 7f2b1101f567..724fdec18bf9 100644
--- a/drivers/crypto/caam/jr.c
+++ b/drivers/crypto/caam/jr.c
@@ -39,6 +39,7 @@ static void register_algs(struct caam_drv_private_jr *jrpriv,
 	caam_algapi_hash_init(dev);
 	caam_pkc_init(dev);
 	jrpriv->hwrng = !caam_rng_init(dev);
+	caam_prng_register(dev);
 	caam_qi_algapi_init(dev);
 
 algs_unlock:
@@ -53,7 +54,7 @@ static void unregister_algs(void)
 		goto algs_unlock;
 
 	caam_qi_algapi_exit();
-
+	caam_prng_unregister(NULL);
 	caam_pkc_exit();
 	caam_algapi_hash_exit();
 	caam_algapi_exit();
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH v3 1/1] crypto: caam/rng: Add support for PRNG
  2022-04-20  6:38   ` [PATCH v3 1/1] " meenakshi.aggarwal
@ 2022-04-27 11:48     ` Horia Geantă
  0 siblings, 0 replies; 15+ messages in thread
From: Horia Geantă @ 2022-04-27 11:48 UTC (permalink / raw)
  To: Meenakshi Aggarwal, Pankaj Gupta, Gaurav Jain, Varun Sethi,
	Herbert Xu, David S . Miller
  Cc: linux-crypto, linux-kernel, dl-linux-imx

On 4/20/2022 9:38 AM, Meenakshi Aggarwal wrote:
> +static void caam_prng_done(struct device *jrdev, u32 *desc, u32 err,
> +			  void *context)
> +{
> +	struct caam_prng_ctx *jctx = context;
> +
> +	if (err >> JRSTA_SSRC_SHIFT)
> +		jctx->err = caam_jr_strstatus(jrdev, err);
The details of error handling are in error.c, let's keep this abstraction.

> +	else
> +		jctx->err = 0;
> +
> +	complete(&jctx->done);
> +}
> +
[...]
> +static int caam_prng_seed(struct crypto_rng *tfm,
> +			 const u8 *seed, unsigned int slen)
> +{
> +	struct caam_prng_ctx ctx;
> +	struct device *jrdev;
> +	dma_addr_t seed_dma;
> +	u32 *desc;
> +	u8 *buf;
> +	int ret = 0;
> +
> +	if (seed == NULL) {
> +		pr_err("Seed not provided\n");
> +		return ret;
> +	}
> +
> +	buf = kzalloc(slen, GFP_KERNEL);
> +	if (!buf)
> +		return -ENOMEM;
> +
> +	jrdev = caam_jr_alloc();
> +	ret = PTR_ERR_OR_ZERO(jrdev);
> +	if (ret) {
> +		pr_err("Job Ring Device allocation failed\n");
> +		kfree(buf);
> +		return ret;
> +	}
> +
> +	desc = kzalloc(CAAM_PRNG_DESC_LEN, GFP_KERNEL | GFP_DMA);
> +	if (!desc) {
> +		ret = -ENOMEM;
> +		goto out1;
> +	}
> +
> +	memcpy(buf, seed, slen);
> +
> +	seed_dma = dma_map_single(jrdev, buf, slen, DMA_FROM_DEVICE);
Now that seedsize is 0, the .seed callback is called with slen = 0.
Reseed descriptor should be updated too.

Horia

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v4 0/1] crypto: caam/rng: Add support for PRNG
  2022-04-20  6:38 ` [PATCH v3 0/1] " meenakshi.aggarwal
  2022-04-20  6:38   ` [PATCH v3 1/1] " meenakshi.aggarwal
@ 2022-04-29  8:45   ` meenakshi.aggarwal
  2022-04-29  8:45     ` [PATCH v4 1/1] " meenakshi.aggarwal
  2022-04-29 11:48     ` [PATCH v5 0/1] " meenakshi.aggarwal
  1 sibling, 2 replies; 15+ messages in thread
From: meenakshi.aggarwal @ 2022-04-29  8:45 UTC (permalink / raw)
  To: Horia Geanta, Pankaj Gupta, Gaurav Jain, Varun Sethi, Herbert Xu,
	David S . Miller
  Cc: linux-crypto, linux-kernel, linux-imx, Meenakshi Aggarwal

From: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>

changes in v4:
	- rebase to latest master
	- incorporated review comments

Meenakshi Aggarwal (1):
  crypto: caam/rng: Add support for PRNG

 drivers/crypto/caam/Kconfig    |   8 ++
 drivers/crypto/caam/Makefile   |   1 +
 drivers/crypto/caam/caamprng.c | 234 +++++++++++++++++++++++++++++++++
 drivers/crypto/caam/intern.h   |  15 +++
 drivers/crypto/caam/jr.c       |   3 +-
 5 files changed, 260 insertions(+), 1 deletion(-)
 create mode 100644 drivers/crypto/caam/caamprng.c


base-commit: 38d741cb70b30741c0e802cbed7bd9cf4fd15fa4
-- 
2.25.1


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v4 1/1] crypto: caam/rng: Add support for PRNG
  2022-04-29  8:45   ` [PATCH v4 0/1] " meenakshi.aggarwal
@ 2022-04-29  8:45     ` meenakshi.aggarwal
  2022-04-29 11:01       ` Horia Geantă
  2022-04-29 11:48     ` [PATCH v5 0/1] " meenakshi.aggarwal
  1 sibling, 1 reply; 15+ messages in thread
From: meenakshi.aggarwal @ 2022-04-29  8:45 UTC (permalink / raw)
  To: Horia Geanta, Pankaj Gupta, Gaurav Jain, Varun Sethi, Herbert Xu,
	David S . Miller
  Cc: linux-crypto, linux-kernel, linux-imx, Meenakshi Aggarwal

From: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>

Add support for random number generation using PRNG
mode of CAAM and expose the interface through crypto API.

According to the RM, the HW implementation of the DRBG follows
NIST SP 800-90A specification for DRBG_Hash SHA-256 function

Signed-off-by: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
---
 drivers/crypto/caam/Kconfig    |   8 ++
 drivers/crypto/caam/Makefile   |   1 +
 drivers/crypto/caam/caamprng.c | 234 +++++++++++++++++++++++++++++++++
 drivers/crypto/caam/intern.h   |  15 +++
 drivers/crypto/caam/jr.c       |   3 +-
 5 files changed, 260 insertions(+), 1 deletion(-)
 create mode 100644 drivers/crypto/caam/caamprng.c

diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig
index 84ea7cba5ee5..0aa52b612a01 100644
--- a/drivers/crypto/caam/Kconfig
+++ b/drivers/crypto/caam/Kconfig
@@ -151,6 +151,14 @@ config CRYPTO_DEV_FSL_CAAM_RNG_API
 	  Selecting this will register the SEC4 hardware rng to
 	  the hw_random API for supplying the kernel entropy pool.
 
+config CRYPTO_DEV_FSL_CAAM_PRNG_API
+	bool "Register Pseudo random number generation implementation with Crypto API"
+	default y
+	select CRYPTO_RNG
+	help
+	  Selecting this will register the SEC hardware prng to
+	  the Crypto API.
+
 endif # CRYPTO_DEV_FSL_CAAM_JR
 
 endif # CRYPTO_DEV_FSL_CAAM
diff --git a/drivers/crypto/caam/Makefile b/drivers/crypto/caam/Makefile
index 3570286eb9ce..4f9837a8a1ad 100644
--- a/drivers/crypto/caam/Makefile
+++ b/drivers/crypto/caam/Makefile
@@ -20,6 +20,7 @@ caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API) += caamalg.o
 caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI) += caamalg_qi.o
 caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API) += caamhash.o
 caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o
+caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_PRNG_API) += caamprng.o
 caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API) += caampkc.o pkc_desc.o
 
 caam-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI) += qi.o
diff --git a/drivers/crypto/caam/caamprng.c b/drivers/crypto/caam/caamprng.c
new file mode 100644
index 000000000000..728fd8e591d0
--- /dev/null
+++ b/drivers/crypto/caam/caamprng.c
@@ -0,0 +1,234 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Driver to expose SEC4 PRNG via crypto RNG API
+ *
+ * Copyright 2022 NXP
+ *
+ */
+
+#include <linux/completion.h>
+#include <crypto/internal/rng.h>
+#include "compat.h"
+#include "regs.h"
+#include "intern.h"
+#include "desc_constr.h"
+#include "jr.h"
+#include "error.h"
+
+/*
+ * Length of used descriptors, see caam_init_desc()
+ */
+#define CAAM_PRNG_DESC_LEN (CAAM_CMD_SZ +				\
+			    CAAM_CMD_SZ +				\
+			    CAAM_CMD_SZ + CAAM_PTR_SZ_MAX)
+
+/* prng per-device context */
+struct caam_prng_ctx {
+	int err;
+	struct completion done;
+};
+
+struct caam_prng_alg {
+	struct rng_alg rng;
+	bool registered;
+};
+
+static void caam_prng_done(struct device *jrdev, u32 *desc, u32 err,
+			  void *context)
+{
+	struct caam_prng_ctx *jctx = context;
+
+	jctx->err = err ? caam_jr_strstatus(jrdev, err) : 0;
+
+	complete(&jctx->done);
+}
+
+static u32 *caam_init_reseed_desc(u32 *desc)
+{
+	init_job_desc(desc, 0);	/* + 1 cmd_sz */
+	/* Generate random bytes: + 1 cmd_sz */
+	append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
+			OP_ALG_AS_FINALIZE);
+
+	print_hex_dump_debug("prng reseed desc@: ", DUMP_PREFIX_ADDRESS,
+			     16, 4, desc, desc_bytes(desc), 1);
+
+	return desc;
+}
+
+static u32 *caam_init_prng_desc(u32 *desc, dma_addr_t dst_dma, u32 len)
+{
+	init_job_desc(desc, 0);	/* + 1 cmd_sz */
+	/* Generate random bytes: + 1 cmd_sz */
+	append_operation(desc, OP_ALG_ALGSEL_RNG | OP_TYPE_CLASS1_ALG);
+	/* Store bytes: + 1 cmd_sz + caam_ptr_sz  */
+	append_fifo_store(desc, dst_dma,
+			  len, FIFOST_TYPE_RNGSTORE);
+
+	print_hex_dump_debug("prng job desc@: ", DUMP_PREFIX_ADDRESS,
+			     16, 4, desc, desc_bytes(desc), 1);
+
+	return desc;
+}
+
+static int caam_prng_generate(struct crypto_rng *tfm,
+			     const u8 *src, unsigned int slen,
+			     u8 *dst, unsigned int dlen)
+{
+	struct caam_prng_ctx ctx;
+	struct device *jrdev;
+	dma_addr_t dst_dma;
+	u32 *desc;
+	u8 *buf;
+	int ret;
+
+	buf = kzalloc(dlen, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	jrdev = caam_jr_alloc();
+	ret = PTR_ERR_OR_ZERO(jrdev);
+	if (ret) {
+		pr_err("Job Ring Device allocation failed\n");
+		kfree(buf);
+		return ret;
+	}
+
+	desc = kzalloc(CAAM_PRNG_DESC_LEN, GFP_KERNEL | GFP_DMA);
+	if (!desc) {
+		ret = -ENOMEM;
+		goto out1;
+	}
+
+	dst_dma = dma_map_single(jrdev, buf, dlen, DMA_FROM_DEVICE);
+	if (dma_mapping_error(jrdev, dst_dma)) {
+		dev_err(jrdev, "Failed to map destination buffer memory\n");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	init_completion(&ctx.done);
+	ret = caam_jr_enqueue(jrdev,
+			      caam_init_prng_desc(desc, dst_dma, dlen),
+			      caam_prng_done, &ctx);
+
+	if (ret == -EINPROGRESS) {
+		wait_for_completion(&ctx.done);
+		ret = ctx.err;
+	}
+
+	dma_unmap_single(jrdev, dst_dma, dlen, DMA_FROM_DEVICE);
+
+	memcpy(dst, buf, dlen);
+out:
+	kfree(desc);
+out1:
+	caam_jr_free(jrdev);
+	kfree(buf);
+	return ret;
+}
+
+static void caam_prng_exit(struct crypto_tfm *tfm) {}
+
+static int caam_prng_init(struct crypto_tfm *tfm)
+{
+	return 0;
+}
+
+static int caam_prng_seed(struct crypto_rng *tfm,
+			 const u8 *seed, unsigned int slen)
+{
+	struct caam_prng_ctx ctx;
+	struct device *jrdev;
+	u32 *desc;
+	int ret;
+
+	if (slen) {
+		pr_err("Seed length should be zero\n");
+		return -EINVAL;
+	}
+
+	jrdev = caam_jr_alloc();
+	ret = PTR_ERR_OR_ZERO(jrdev);
+	if (ret) {
+		pr_err("Job Ring Device allocation failed\n");
+		return ret;
+	}
+
+	desc = kzalloc(CAAM_PRNG_DESC_LEN, GFP_KERNEL | GFP_DMA);
+	if (!desc) {
+		caam_jr_free(jrdev);
+		return -ENOMEM;
+	}
+
+	init_completion(&ctx.done);
+	ret = caam_jr_enqueue(jrdev,
+			      caam_init_reseed_desc(desc),
+			      caam_prng_done, &ctx);
+
+	if (ret == -EINPROGRESS) {
+		wait_for_completion(&ctx.done);
+		ret = ctx.err;
+	}
+
+	kfree(desc);
+	caam_jr_free(jrdev);
+	return ret;
+}
+
+static struct caam_prng_alg caam_prng_alg = {
+	.rng = {
+		.generate = caam_prng_generate,
+		.seed = caam_prng_seed,
+		.seedsize = 0,
+		.base = {
+			.cra_name = "stdrng",
+			.cra_driver_name = "prng-caam",
+			.cra_priority = 500,
+			.cra_ctxsize = sizeof(struct caam_prng_ctx),
+			.cra_module = THIS_MODULE,
+			.cra_init = caam_prng_init,
+			.cra_exit = caam_prng_exit,
+		},
+	}
+};
+
+void caam_prng_unregister(void *data)
+{
+	if (caam_prng_alg.registered)
+		crypto_unregister_rng(&caam_prng_alg.rng);
+}
+
+int caam_prng_register(struct device *ctrldev)
+{
+	struct caam_drv_private *priv = dev_get_drvdata(ctrldev);
+	u32 rng_inst;
+	int ret = 0;
+
+	/* Check for available RNG blocks before registration */
+	if (priv->era < 10)
+		rng_inst = (rd_reg32(&priv->jr[0]->perfmon.cha_num_ls) &
+			    CHA_ID_LS_RNG_MASK) >> CHA_ID_LS_RNG_SHIFT;
+	else
+		rng_inst = rd_reg32(&priv->jr[0]->vreg.rng) & CHA_VER_NUM_MASK;
+
+	if (!rng_inst) {
+		dev_dbg(ctrldev, "RNG block is not available... skipping registering algorithm\n");
+		return ret;
+	}
+
+	ret = crypto_register_rng(&caam_prng_alg.rng);
+	if (ret) {
+		dev_err(ctrldev,
+			"couldn't register rng crypto alg: %d\n",
+			ret);
+		return ret;
+	}
+
+	caam_prng_alg.registered = true;
+
+	dev_info(ctrldev,
+		 "rng crypto API alg registered %s\n", caam_prng_alg.rng.base.cra_driver_name);
+
+	return 0;
+}
diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h
index 7d45b21bd55a..c2f51365df1b 100644
--- a/drivers/crypto/caam/intern.h
+++ b/drivers/crypto/caam/intern.h
@@ -185,6 +185,21 @@ static inline void caam_rng_exit(struct device *dev) {}
 
 #endif /* CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API */
 
+#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_PRNG_API
+
+int caam_prng_register(struct device *dev);
+void caam_prng_unregister(void *data);
+
+#else
+
+static inline int caam_prng_register(struct device *dev)
+{
+	return 0;
+}
+
+static inline void caam_prng_unregister(void *data) {}
+#endif /* CONFIG_CRYPTO_DEV_FSL_CAAM_PRNG_API */
+
 #ifdef CONFIG_CAAM_QI
 
 int caam_qi_algapi_init(struct device *dev);
diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c
index 7f2b1101f567..724fdec18bf9 100644
--- a/drivers/crypto/caam/jr.c
+++ b/drivers/crypto/caam/jr.c
@@ -39,6 +39,7 @@ static void register_algs(struct caam_drv_private_jr *jrpriv,
 	caam_algapi_hash_init(dev);
 	caam_pkc_init(dev);
 	jrpriv->hwrng = !caam_rng_init(dev);
+	caam_prng_register(dev);
 	caam_qi_algapi_init(dev);
 
 algs_unlock:
@@ -53,7 +54,7 @@ static void unregister_algs(void)
 		goto algs_unlock;
 
 	caam_qi_algapi_exit();
-
+	caam_prng_unregister(NULL);
 	caam_pkc_exit();
 	caam_algapi_hash_exit();
 	caam_algapi_exit();
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH v4 1/1] crypto: caam/rng: Add support for PRNG
  2022-04-29  8:45     ` [PATCH v4 1/1] " meenakshi.aggarwal
@ 2022-04-29 11:01       ` Horia Geantă
  0 siblings, 0 replies; 15+ messages in thread
From: Horia Geantă @ 2022-04-29 11:01 UTC (permalink / raw)
  To: Meenakshi Aggarwal, Pankaj Gupta, Gaurav Jain, Varun Sethi,
	Herbert Xu, David S . Miller
  Cc: linux-crypto, linux-kernel, dl-linux-imx

On 4/29/2022 11:45 AM, Meenakshi Aggarwal wrote:
> From: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
> 
> Add support for random number generation using PRNG
> mode of CAAM and expose the interface through crypto API.
> 
> According to the RM, the HW implementation of the DRBG follows
> NIST SP 800-90A specification for DRBG_Hash SHA-256 function
> 
> Signed-off-by: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>

There are a few nitpicks below, if you can address them great,
either way here's my
Reviewed-by: Horia Geantă <horia.geanta@nxp.com>

> + * Length of used descriptors, see caam_init_desc()
caam_init_desc() does not exist in this file.

> + */
> +#define CAAM_PRNG_DESC_LEN (CAAM_CMD_SZ +				\
> +			    CAAM_CMD_SZ +				\
> +			    CAAM_CMD_SZ + CAAM_PTR_SZ_MAX)
The reseed descriptor length is now smaller.
Memmory allocated by kmalloc() will probably be the same,
but code would be more readable.
If you want to use the same length for both descriptors,
I suggest renaming the define to CAAM_PRNG_MAX_DESC_LEN.

> +static u32 *caam_init_reseed_desc(u32 *desc)
> +{
> +	init_job_desc(desc, 0);	/* + 1 cmd_sz */
> +	/* Generate random bytes: + 1 cmd_sz */
This is a "reseed" operation, not "generate".

> +	append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
> +			OP_ALG_AS_FINALIZE);
> +
[...]
> +static int caam_prng_generate(struct crypto_rng *tfm,
> +			     const u8 *src, unsigned int slen,
> +			     u8 *dst, unsigned int dlen)
> +{
[...]
> +	ret = caam_jr_enqueue(jrdev,
> +			      caam_init_prng_desc(desc, dst_dma, dlen),
> +			      caam_prng_done, &ctx);
> +
> +	if (ret == -EINPROGRESS) {
> +		wait_for_completion(&ctx.done);
> +		ret = ctx.err;
> +	}
> +
> +	dma_unmap_single(jrdev, dst_dma, dlen, DMA_FROM_DEVICE);
> +
> +	memcpy(dst, buf, dlen);
memcpy() should be performed only when the HW executed the operation
successfully.

Thanks,
Horia

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v5 0/1] crypto: caam/rng: Add support for PRNG
  2022-04-29  8:45   ` [PATCH v4 0/1] " meenakshi.aggarwal
  2022-04-29  8:45     ` [PATCH v4 1/1] " meenakshi.aggarwal
@ 2022-04-29 11:48     ` meenakshi.aggarwal
  2022-04-29 11:48       ` [PATCH v5 1/1] " meenakshi.aggarwal
  1 sibling, 1 reply; 15+ messages in thread
From: meenakshi.aggarwal @ 2022-04-29 11:48 UTC (permalink / raw)
  To: Horia Geanta, Pankaj Gupta, Gaurav Jain, Varun Sethi, Herbert Xu,
	David S . Miller
  Cc: linux-crypto, linux-kernel, linux-imx, Meenakshi Aggarwal

From: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>

changes in v5:
	- incorporated review comments

Meenakshi Aggarwal (1):
  crypto: caam/rng: Add support for PRNG

 drivers/crypto/caam/Kconfig    |   8 ++
 drivers/crypto/caam/Makefile   |   1 +
 drivers/crypto/caam/caamprng.c | 235 +++++++++++++++++++++++++++++++++
 drivers/crypto/caam/intern.h   |  15 +++
 drivers/crypto/caam/jr.c       |   3 +-
 5 files changed, 261 insertions(+), 1 deletion(-)
 create mode 100644 drivers/crypto/caam/caamprng.c


base-commit: 38d741cb70b30741c0e802cbed7bd9cf4fd15fa4
-- 
2.25.1


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v5 1/1] crypto: caam/rng: Add support for PRNG
  2022-04-29 11:48     ` [PATCH v5 0/1] " meenakshi.aggarwal
@ 2022-04-29 11:48       ` meenakshi.aggarwal
  2022-05-06 10:22         ` Herbert Xu
  0 siblings, 1 reply; 15+ messages in thread
From: meenakshi.aggarwal @ 2022-04-29 11:48 UTC (permalink / raw)
  To: Horia Geanta, Pankaj Gupta, Gaurav Jain, Varun Sethi, Herbert Xu,
	David S . Miller
  Cc: linux-crypto, linux-kernel, linux-imx, Meenakshi Aggarwal

From: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>

Add support for random number generation using PRNG
mode of CAAM and expose the interface through crypto API.

According to the RM, the HW implementation of the DRBG follows
NIST SP 800-90A specification for DRBG_Hash SHA-256 function

Signed-off-by: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
Reviewed-by: Horia Geant <horia.geanta@nxp.com>
---
 drivers/crypto/caam/Kconfig    |   8 ++
 drivers/crypto/caam/Makefile   |   1 +
 drivers/crypto/caam/caamprng.c | 235 +++++++++++++++++++++++++++++++++
 drivers/crypto/caam/intern.h   |  15 +++
 drivers/crypto/caam/jr.c       |   3 +-
 5 files changed, 261 insertions(+), 1 deletion(-)
 create mode 100644 drivers/crypto/caam/caamprng.c

diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig
index 84ea7cba5ee5..0aa52b612a01 100644
--- a/drivers/crypto/caam/Kconfig
+++ b/drivers/crypto/caam/Kconfig
@@ -151,6 +151,14 @@ config CRYPTO_DEV_FSL_CAAM_RNG_API
 	  Selecting this will register the SEC4 hardware rng to
 	  the hw_random API for supplying the kernel entropy pool.
 
+config CRYPTO_DEV_FSL_CAAM_PRNG_API
+	bool "Register Pseudo random number generation implementation with Crypto API"
+	default y
+	select CRYPTO_RNG
+	help
+	  Selecting this will register the SEC hardware prng to
+	  the Crypto API.
+
 endif # CRYPTO_DEV_FSL_CAAM_JR
 
 endif # CRYPTO_DEV_FSL_CAAM
diff --git a/drivers/crypto/caam/Makefile b/drivers/crypto/caam/Makefile
index 3570286eb9ce..4f9837a8a1ad 100644
--- a/drivers/crypto/caam/Makefile
+++ b/drivers/crypto/caam/Makefile
@@ -20,6 +20,7 @@ caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API) += caamalg.o
 caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI) += caamalg_qi.o
 caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API) += caamhash.o
 caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o
+caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_PRNG_API) += caamprng.o
 caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API) += caampkc.o pkc_desc.o
 
 caam-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI) += qi.o
diff --git a/drivers/crypto/caam/caamprng.c b/drivers/crypto/caam/caamprng.c
new file mode 100644
index 000000000000..4839e66300a2
--- /dev/null
+++ b/drivers/crypto/caam/caamprng.c
@@ -0,0 +1,235 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Driver to expose SEC4 PRNG via crypto RNG API
+ *
+ * Copyright 2022 NXP
+ *
+ */
+
+#include <linux/completion.h>
+#include <crypto/internal/rng.h>
+#include "compat.h"
+#include "regs.h"
+#include "intern.h"
+#include "desc_constr.h"
+#include "jr.h"
+#include "error.h"
+
+/*
+ * Length of used descriptors, see caam_init_desc()
+ */
+#define CAAM_PRNG_MAX_DESC_LEN (CAAM_CMD_SZ +				\
+			    CAAM_CMD_SZ +				\
+			    CAAM_CMD_SZ + CAAM_PTR_SZ_MAX)
+
+/* prng per-device context */
+struct caam_prng_ctx {
+	int err;
+	struct completion done;
+};
+
+struct caam_prng_alg {
+	struct rng_alg rng;
+	bool registered;
+};
+
+static void caam_prng_done(struct device *jrdev, u32 *desc, u32 err,
+			  void *context)
+{
+	struct caam_prng_ctx *jctx = context;
+
+	jctx->err = err ? caam_jr_strstatus(jrdev, err) : 0;
+
+	complete(&jctx->done);
+}
+
+static u32 *caam_init_reseed_desc(u32 *desc)
+{
+	init_job_desc(desc, 0);	/* + 1 cmd_sz */
+	/* Generate random bytes: + 1 cmd_sz */
+	append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
+			OP_ALG_AS_FINALIZE);
+
+	print_hex_dump_debug("prng reseed desc@: ", DUMP_PREFIX_ADDRESS,
+			     16, 4, desc, desc_bytes(desc), 1);
+
+	return desc;
+}
+
+static u32 *caam_init_prng_desc(u32 *desc, dma_addr_t dst_dma, u32 len)
+{
+	init_job_desc(desc, 0);	/* + 1 cmd_sz */
+	/* Generate random bytes: + 1 cmd_sz */
+	append_operation(desc, OP_ALG_ALGSEL_RNG | OP_TYPE_CLASS1_ALG);
+	/* Store bytes: + 1 cmd_sz + caam_ptr_sz  */
+	append_fifo_store(desc, dst_dma,
+			  len, FIFOST_TYPE_RNGSTORE);
+
+	print_hex_dump_debug("prng job desc@: ", DUMP_PREFIX_ADDRESS,
+			     16, 4, desc, desc_bytes(desc), 1);
+
+	return desc;
+}
+
+static int caam_prng_generate(struct crypto_rng *tfm,
+			     const u8 *src, unsigned int slen,
+			     u8 *dst, unsigned int dlen)
+{
+	struct caam_prng_ctx ctx;
+	struct device *jrdev;
+	dma_addr_t dst_dma;
+	u32 *desc;
+	u8 *buf;
+	int ret;
+
+	buf = kzalloc(dlen, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	jrdev = caam_jr_alloc();
+	ret = PTR_ERR_OR_ZERO(jrdev);
+	if (ret) {
+		pr_err("Job Ring Device allocation failed\n");
+		kfree(buf);
+		return ret;
+	}
+
+	desc = kzalloc(CAAM_PRNG_MAX_DESC_LEN, GFP_KERNEL | GFP_DMA);
+	if (!desc) {
+		ret = -ENOMEM;
+		goto out1;
+	}
+
+	dst_dma = dma_map_single(jrdev, buf, dlen, DMA_FROM_DEVICE);
+	if (dma_mapping_error(jrdev, dst_dma)) {
+		dev_err(jrdev, "Failed to map destination buffer memory\n");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	init_completion(&ctx.done);
+	ret = caam_jr_enqueue(jrdev,
+			      caam_init_prng_desc(desc, dst_dma, dlen),
+			      caam_prng_done, &ctx);
+
+	if (ret == -EINPROGRESS) {
+		wait_for_completion(&ctx.done);
+		ret = ctx.err;
+	}
+
+	dma_unmap_single(jrdev, dst_dma, dlen, DMA_FROM_DEVICE);
+
+	if (!ret)
+		memcpy(dst, buf, dlen);
+out:
+	kfree(desc);
+out1:
+	caam_jr_free(jrdev);
+	kfree(buf);
+	return ret;
+}
+
+static void caam_prng_exit(struct crypto_tfm *tfm) {}
+
+static int caam_prng_init(struct crypto_tfm *tfm)
+{
+	return 0;
+}
+
+static int caam_prng_seed(struct crypto_rng *tfm,
+			 const u8 *seed, unsigned int slen)
+{
+	struct caam_prng_ctx ctx;
+	struct device *jrdev;
+	u32 *desc;
+	int ret;
+
+	if (slen) {
+		pr_err("Seed length should be zero\n");
+		return -EINVAL;
+	}
+
+	jrdev = caam_jr_alloc();
+	ret = PTR_ERR_OR_ZERO(jrdev);
+	if (ret) {
+		pr_err("Job Ring Device allocation failed\n");
+		return ret;
+	}
+
+	desc = kzalloc(CAAM_PRNG_MAX_DESC_LEN, GFP_KERNEL | GFP_DMA);
+	if (!desc) {
+		caam_jr_free(jrdev);
+		return -ENOMEM;
+	}
+
+	init_completion(&ctx.done);
+	ret = caam_jr_enqueue(jrdev,
+			      caam_init_reseed_desc(desc),
+			      caam_prng_done, &ctx);
+
+	if (ret == -EINPROGRESS) {
+		wait_for_completion(&ctx.done);
+		ret = ctx.err;
+	}
+
+	kfree(desc);
+	caam_jr_free(jrdev);
+	return ret;
+}
+
+static struct caam_prng_alg caam_prng_alg = {
+	.rng = {
+		.generate = caam_prng_generate,
+		.seed = caam_prng_seed,
+		.seedsize = 0,
+		.base = {
+			.cra_name = "stdrng",
+			.cra_driver_name = "prng-caam",
+			.cra_priority = 500,
+			.cra_ctxsize = sizeof(struct caam_prng_ctx),
+			.cra_module = THIS_MODULE,
+			.cra_init = caam_prng_init,
+			.cra_exit = caam_prng_exit,
+		},
+	}
+};
+
+void caam_prng_unregister(void *data)
+{
+	if (caam_prng_alg.registered)
+		crypto_unregister_rng(&caam_prng_alg.rng);
+}
+
+int caam_prng_register(struct device *ctrldev)
+{
+	struct caam_drv_private *priv = dev_get_drvdata(ctrldev);
+	u32 rng_inst;
+	int ret = 0;
+
+	/* Check for available RNG blocks before registration */
+	if (priv->era < 10)
+		rng_inst = (rd_reg32(&priv->jr[0]->perfmon.cha_num_ls) &
+			    CHA_ID_LS_RNG_MASK) >> CHA_ID_LS_RNG_SHIFT;
+	else
+		rng_inst = rd_reg32(&priv->jr[0]->vreg.rng) & CHA_VER_NUM_MASK;
+
+	if (!rng_inst) {
+		dev_dbg(ctrldev, "RNG block is not available... skipping registering algorithm\n");
+		return ret;
+	}
+
+	ret = crypto_register_rng(&caam_prng_alg.rng);
+	if (ret) {
+		dev_err(ctrldev,
+			"couldn't register rng crypto alg: %d\n",
+			ret);
+		return ret;
+	}
+
+	caam_prng_alg.registered = true;
+
+	dev_info(ctrldev,
+		 "rng crypto API alg registered %s\n", caam_prng_alg.rng.base.cra_driver_name);
+
+	return 0;
+}
diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h
index 7d45b21bd55a..c2f51365df1b 100644
--- a/drivers/crypto/caam/intern.h
+++ b/drivers/crypto/caam/intern.h
@@ -185,6 +185,21 @@ static inline void caam_rng_exit(struct device *dev) {}
 
 #endif /* CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API */
 
+#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_PRNG_API
+
+int caam_prng_register(struct device *dev);
+void caam_prng_unregister(void *data);
+
+#else
+
+static inline int caam_prng_register(struct device *dev)
+{
+	return 0;
+}
+
+static inline void caam_prng_unregister(void *data) {}
+#endif /* CONFIG_CRYPTO_DEV_FSL_CAAM_PRNG_API */
+
 #ifdef CONFIG_CAAM_QI
 
 int caam_qi_algapi_init(struct device *dev);
diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c
index 7f2b1101f567..724fdec18bf9 100644
--- a/drivers/crypto/caam/jr.c
+++ b/drivers/crypto/caam/jr.c
@@ -39,6 +39,7 @@ static void register_algs(struct caam_drv_private_jr *jrpriv,
 	caam_algapi_hash_init(dev);
 	caam_pkc_init(dev);
 	jrpriv->hwrng = !caam_rng_init(dev);
+	caam_prng_register(dev);
 	caam_qi_algapi_init(dev);
 
 algs_unlock:
@@ -53,7 +54,7 @@ static void unregister_algs(void)
 		goto algs_unlock;
 
 	caam_qi_algapi_exit();
-
+	caam_prng_unregister(NULL);
 	caam_pkc_exit();
 	caam_algapi_hash_exit();
 	caam_algapi_exit();
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH v5 1/1] crypto: caam/rng: Add support for PRNG
  2022-04-29 11:48       ` [PATCH v5 1/1] " meenakshi.aggarwal
@ 2022-05-06 10:22         ` Herbert Xu
  0 siblings, 0 replies; 15+ messages in thread
From: Herbert Xu @ 2022-05-06 10:22 UTC (permalink / raw)
  To: meenakshi.aggarwal
  Cc: Horia Geanta, Pankaj Gupta, Gaurav Jain, Varun Sethi,
	David S . Miller, linux-crypto, linux-kernel, linux-imx

On Fri, Apr 29, 2022 at 01:48:08PM +0200, meenakshi.aggarwal@nxp.com wrote:
> From: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
> 
> Add support for random number generation using PRNG
> mode of CAAM and expose the interface through crypto API.
> 
> According to the RM, the HW implementation of the DRBG follows
> NIST SP 800-90A specification for DRBG_Hash SHA-256 function
> 
> Signed-off-by: Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>
> Reviewed-by: Horia Geant <horia.geanta@nxp.com>
> ---
>  drivers/crypto/caam/Kconfig    |   8 ++
>  drivers/crypto/caam/Makefile   |   1 +
>  drivers/crypto/caam/caamprng.c | 235 +++++++++++++++++++++++++++++++++
>  drivers/crypto/caam/intern.h   |  15 +++
>  drivers/crypto/caam/jr.c       |   3 +-
>  5 files changed, 261 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/crypto/caam/caamprng.c

Patch applied.  Thanks.
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2022-05-06 10:22 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-04 11:41 [PATCH] crypto: caam/rng: Add support for PRNG meenakshi.aggarwal
2022-03-08 22:49 ` kernel test robot
2022-03-16 18:01 ` [PATCH v2 0/1] " meenakshi.aggarwal
2022-03-16 18:01   ` [PATCH v2 1/1] " meenakshi.aggarwal
2022-04-05 12:31     ` Horia Geantă
2022-04-20  5:57       ` Meenakshi Aggarwal
2022-04-20  6:38 ` [PATCH v3 0/1] " meenakshi.aggarwal
2022-04-20  6:38   ` [PATCH v3 1/1] " meenakshi.aggarwal
2022-04-27 11:48     ` Horia Geantă
2022-04-29  8:45   ` [PATCH v4 0/1] " meenakshi.aggarwal
2022-04-29  8:45     ` [PATCH v4 1/1] " meenakshi.aggarwal
2022-04-29 11:01       ` Horia Geantă
2022-04-29 11:48     ` [PATCH v5 0/1] " meenakshi.aggarwal
2022-04-29 11:48       ` [PATCH v5 1/1] " meenakshi.aggarwal
2022-05-06 10:22         ` Herbert Xu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).