* [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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.