2019-11-21 15:57:43

by Andrey Smirnov

[permalink] [raw]
Subject: [PATCH v4 0/6] enable CAAM's HWRNG as default

Everyone:

This series is a continuation of original [discussion]. I don't know
if what's in the series is enough to use CAAMs HWRNG system wide, but
I am hoping that with enough iterations and feedback it will be.

Changes since [v1]:

- Original hw_random replaced with the one using output of TRNG directly

- SEC4 DRNG IP block exposed via crypto API

- Small fix regarding use of GFP_DMA added to the series

Chagnes since [v2]:

- msleep in polling loop to avoid wasting CPU cycles

- caam_trng_read() bails out early if 'wait' is set to 'false'

- fixed typo in ZII's name

Changes since [v3]:

- DRNG's .cra_name is now "stdrng"

- collected Reviewd-by tag from Lucas

- typo fixes in commit messages of the series

Feedback is welcome!

Thanks,
Andrey Smirnov

[discussion] https://patchwork.kernel.org/patch/9850669/
[v1] https://lore.kernel.org/lkml/[email protected]
[v2] https://lore.kernel.org/lkml/[email protected]
[v3] https://lore.kernel.org/lkml/[email protected]

Andrey Smirnov (6):
crypto: caam - RNG4 TRNG errata
crypto: caam - enable prediction resistance in HRWNG
crypto: caam - allocate RNG instantiation descriptor with GFP_DMA
crypto: caam - move RNG presence check into a shared function
crypto: caam - replace DRNG with TRNG for use with hw_random
crypto: caam - expose SEC4 DRNG via crypto RNG API

drivers/crypto/caam/Kconfig | 15 +-
drivers/crypto/caam/Makefile | 3 +-
drivers/crypto/caam/caamrng.c | 358 ----------------------------------
drivers/crypto/caam/ctrl.c | 29 ++-
drivers/crypto/caam/desc.h | 2 +
drivers/crypto/caam/drng.c | 175 +++++++++++++++++
drivers/crypto/caam/intern.h | 32 ++-
drivers/crypto/caam/jr.c | 3 +-
drivers/crypto/caam/regs.h | 14 +-
drivers/crypto/caam/trng.c | 89 +++++++++
10 files changed, 338 insertions(+), 382 deletions(-)
delete mode 100644 drivers/crypto/caam/caamrng.c
create mode 100644 drivers/crypto/caam/drng.c
create mode 100644 drivers/crypto/caam/trng.c

--
2.21.0


2019-11-21 15:57:49

by Andrey Smirnov

[permalink] [raw]
Subject: [PATCH v4 2/6] crypto: caam - enable prediction resistance in HRWNG

Instantiate CAAM RNG with prediction resistance enabled to improve its
quality.

Signed-off-by: Andrey Smirnov <[email protected]>
Cc: Chris Healy <[email protected]>
Cc: Lucas Stach <[email protected]>
Cc: Horia Geantă <[email protected]>
Cc: Herbert Xu <[email protected]>
Cc: Iuliana Prodan <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
---
drivers/crypto/caam/caamrng.c | 3 ++-
drivers/crypto/caam/ctrl.c | 8 +++++---
drivers/crypto/caam/desc.h | 2 ++
drivers/crypto/caam/regs.h | 4 +++-
4 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/drivers/crypto/caam/caamrng.c b/drivers/crypto/caam/caamrng.c
index e8baacaabe07..6dde8ae3cd9b 100644
--- a/drivers/crypto/caam/caamrng.c
+++ b/drivers/crypto/caam/caamrng.c
@@ -202,7 +202,8 @@ static inline int rng_create_sh_desc(struct caam_rng_ctx *ctx)
init_sh_desc(desc, HDR_SHARE_SERIAL);

/* Generate random bytes */
- append_operation(desc, OP_ALG_ALGSEL_RNG | OP_TYPE_CLASS1_ALG);
+ append_operation(desc, OP_ALG_ALGSEL_RNG | OP_TYPE_CLASS1_ALG |
+ OP_ALG_PR_ON);

/* Store bytes */
append_seq_fifo_store(desc, RN_BUF_SIZE, FIFOST_TYPE_RNGSTORE);
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index df4db10e9fca..a1c879820286 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -36,7 +36,8 @@ static void build_instantiation_desc(u32 *desc, int handle, int do_sk)
init_job_desc(desc, 0);

op_flags = OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
- (handle << OP_ALG_AAI_SHIFT) | OP_ALG_AS_INIT;
+ (handle << OP_ALG_AAI_SHIFT) | OP_ALG_AS_INIT |
+ OP_ALG_PR_ON;

/* INIT RNG in non-test mode */
append_operation(desc, op_flags);
@@ -275,11 +276,12 @@ static int instantiate_rng(struct device *ctrldev, int state_handle_mask,
return -ENOMEM;

for (sh_idx = 0; sh_idx < RNG4_MAX_HANDLES; sh_idx++) {
+ const u32 rdsta_mask = (RDSTA_PR0 | RDSTA_IF0) << sh_idx;
/*
* If the corresponding bit is set, this state handle
* was initialized by somebody else, so it's left alone.
*/
- if ((1 << sh_idx) & state_handle_mask)
+ if (rdsta_mask & state_handle_mask)
continue;

/* Create the descriptor for instantiating RNG State Handle */
@@ -302,7 +304,7 @@ static int instantiate_rng(struct device *ctrldev, int state_handle_mask,

rdsta_val = rd_reg32(&ctrl->r4tst[0].rdsta) & RDSTA_IFMASK;
if ((status && status != JRSTA_SSRC_JUMP_HALT_CC) ||
- !(rdsta_val & (1 << sh_idx))) {
+ (rdsta_val & rdsta_mask) != rdsta_mask) {
ret = -EAGAIN;
break;
}
diff --git a/drivers/crypto/caam/desc.h b/drivers/crypto/caam/desc.h
index 4b6854bf896a..e796d3cb9be8 100644
--- a/drivers/crypto/caam/desc.h
+++ b/drivers/crypto/caam/desc.h
@@ -1254,6 +1254,8 @@
#define OP_ALG_ICV_OFF (0 << OP_ALG_ICV_SHIFT)
#define OP_ALG_ICV_ON (1 << OP_ALG_ICV_SHIFT)

+#define OP_ALG_PR_ON BIT(1)
+
#define OP_ALG_DIR_SHIFT 0
#define OP_ALG_DIR_MASK 1
#define OP_ALG_DECRYPT 0
diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h
index c191e8fd0fa7..fe1f8c1409fd 100644
--- a/drivers/crypto/caam/regs.h
+++ b/drivers/crypto/caam/regs.h
@@ -524,9 +524,11 @@ struct rng4tst {
u32 rsvd1[40];
#define RDSTA_SKVT 0x80000000
#define RDSTA_SKVN 0x40000000
+#define RDSTA_PR0 BIT(4)
+#define RDSTA_PR1 BIT(5)
#define RDSTA_IF0 0x00000001
#define RDSTA_IF1 0x00000002
-#define RDSTA_IFMASK (RDSTA_IF1 | RDSTA_IF0)
+#define RDSTA_IFMASK (RDSTA_PR1 | RDSTA_PR0 | RDSTA_IF1 | RDSTA_IF0)
u32 rdsta;
u32 rsvd2[15];
};
--
2.21.0

2019-11-21 15:57:52

by Andrey Smirnov

[permalink] [raw]
Subject: [PATCH v4 3/6] crypto: caam - allocate RNG instantiation descriptor with GFP_DMA

Be consistent with the rest of the codebase and use GFP_DMA when
allocating memory for a CAAM JR descriptor.

Signed-off-by: Andrey Smirnov <[email protected]>
Cc: Chris Healy <[email protected]>
Cc: Lucas Stach <[email protected]>
Cc: Horia Geantă <[email protected]>
Cc: Herbert Xu <[email protected]>
Cc: Iuliana Prodan <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
---
drivers/crypto/caam/ctrl.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index a1c879820286..8054ec29d35a 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -194,7 +194,7 @@ static int deinstantiate_rng(struct device *ctrldev, int state_handle_mask)
u32 *desc, status;
int sh_idx, ret = 0;

- desc = kmalloc(CAAM_CMD_SZ * 3, GFP_KERNEL);
+ desc = kmalloc(CAAM_CMD_SZ * 3, GFP_KERNEL | GFP_DMA);
if (!desc)
return -ENOMEM;

@@ -271,7 +271,7 @@ static int instantiate_rng(struct device *ctrldev, int state_handle_mask,
int ret = 0, sh_idx;

ctrl = (struct caam_ctrl __iomem *)ctrlpriv->ctrl;
- desc = kmalloc(CAAM_CMD_SZ * 7, GFP_KERNEL);
+ desc = kmalloc(CAAM_CMD_SZ * 7, GFP_KERNEL | GFP_DMA);
if (!desc)
return -ENOMEM;

--
2.21.0

2019-11-21 15:58:24

by Andrey Smirnov

[permalink] [raw]
Subject: [PATCH v4 6/6] crypto: caam - expose SEC4 DRNG via crypto RNG API

Expose SEC4 DRNG IP block using crypto RNG API so it could be used
both by kernel and userspace code.

Signed-off-by: Andrey Smirnov <[email protected]>
Cc: Chris Healy <[email protected]>
Cc: Lucas Stach <[email protected]>
Cc: Horia Geantă <[email protected]>
Cc: Herbert Xu <[email protected]>
Cc: Iuliana Prodan <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
---
drivers/crypto/caam/Kconfig | 8 ++
drivers/crypto/caam/Makefile | 1 +
drivers/crypto/caam/drng.c | 175 +++++++++++++++++++++++++++++++++++
drivers/crypto/caam/intern.h | 13 +++
drivers/crypto/caam/jr.c | 1 +
5 files changed, 198 insertions(+)
create mode 100644 drivers/crypto/caam/drng.c

diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig
index 22116a8e2ff3..11a8f9c02448 100644
--- a/drivers/crypto/caam/Kconfig
+++ b/drivers/crypto/caam/Kconfig
@@ -146,6 +146,14 @@ config CRYPTO_DEV_FSL_CAAM_PKC_API
Supported cryptographic primitives: encryption, decryption,
signature and verification.

+config CRYPTO_DEV_FSL_CAAM_DRNG_API
+ bool "Register caam device for hwrng API"
+ default y
+ select CRYPTO_RNG
+ help
+ Selecting this will register the SEC4 DRNG to
+ the crypto RNG 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 04884fc087f9..02b7ed8823ce 100644
--- a/drivers/crypto/caam/Makefile
+++ b/drivers/crypto/caam/Makefile
@@ -20,6 +20,7 @@ caam_jr-y := jr.o key_gen.o
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_DRNG_API) += drng.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/drng.c b/drivers/crypto/caam/drng.c
new file mode 100644
index 000000000000..9b2ff2fe7581
--- /dev/null
+++ b/drivers/crypto/caam/drng.c
@@ -0,0 +1,175 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Driver to expose SEC4 DRNG via crypto RNG API
+ *
+ * Copyright 2019 Zodiac Inflight Innovations
+ *
+ * Based on CAAM SEC4 hw_random driver
+ *
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2018-2019 NXP
+ *
+ * Based on caamalg.c crypto API driver.
+ *
+ */
+
+#include <linux/completion.h>
+#include <linux/atomic.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"
+
+#define CAAM_DRNG_MAX_FIFO_STORE_SIZE ((unsigned int)U16_MAX)
+
+/* rng per-device context */
+struct caam_drng_ctx {
+ struct device *jrdev;
+ struct completion done;
+};
+
+static void rng_done(struct device *jrdev, u32 *desc, u32 err, void *context)
+{
+ struct caam_drng_ctx *ctx = context;
+
+ if (err)
+ caam_jr_strstatus(jrdev, err);
+
+ complete(&ctx->done);
+}
+
+static int caam_drng_generate(struct crypto_rng *tfm,
+ const u8 *src, unsigned int slen,
+ u8 *dst, unsigned int dlen)
+{
+ struct caam_drng_ctx *ctx = crypto_rng_ctx(tfm);
+ struct device *jrdev = ctx->jrdev;
+ unsigned int residue = dlen;
+ dma_addr_t dst_dma, cur_dma;
+ u32 *desc;
+ int ret;
+
+ desc = kzalloc(5 * CAAM_CMD_SZ + CAAM_PTR_SZ_MAX,
+ GFP_KERNEL | GFP_DMA);
+ if (!desc)
+ return -ENOMEM;
+
+ cur_dma = dst_dma = dma_map_single(jrdev, dst, dlen, DMA_FROM_DEVICE);
+ if (dma_mapping_error(jrdev, dst_dma)) {
+ dev_err(jrdev, "unable to map destination memory\n");
+ ret = -ENOMEM;
+ goto free_mem;
+ }
+
+ do {
+ const unsigned int chunk = min(residue,
+ CAAM_DRNG_MAX_FIFO_STORE_SIZE);
+
+ init_job_desc(desc, 0); /* 1 word */
+ /* Generate random bytes */
+ append_operation(desc, OP_ALG_ALGSEL_RNG | OP_TYPE_CLASS1_ALG |
+ OP_ALG_PR_ON); /* 1 word */
+ /* Store bytes */
+ append_seq_out_ptr_intlen(desc, cur_dma, chunk, 0);
+ append_seq_fifo_store(desc, chunk, FIFOST_TYPE_RNGSTORE);
+
+ print_hex_dump_debug("rng job desc@: ", DUMP_PREFIX_ADDRESS,
+ 16, 4, desc, desc_bytes(desc), 1);
+
+ init_completion(&ctx->done);
+ ret = caam_jr_enqueue(jrdev, desc, rng_done, ctx);
+ if (ret)
+ break;
+
+ wait_for_completion(&ctx->done);
+
+ cur_dma += chunk;
+ residue -= chunk;
+ } while (residue);
+
+ dma_unmap_single(jrdev, dst_dma, dlen, DMA_FROM_DEVICE);
+free_mem:
+ kfree(desc);
+ return ret;
+}
+
+static int caam_drng_init(struct crypto_tfm *tfm)
+{
+ struct caam_drng_ctx *ctx = crypto_tfm_ctx(tfm);
+ int ret;
+
+ ctx->jrdev = caam_jr_alloc();
+ ret = PTR_ERR_OR_ZERO(ctx->jrdev);
+ if (ret) {
+ pr_err("Job Ring Device allocation for transform failed\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static void caam_drng_exit(struct crypto_tfm *tfm)
+{
+ struct caam_drng_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ caam_jr_free(ctx->jrdev);
+}
+
+static int caam_drng_seed(struct crypto_rng *tfm,
+ const u8 *seed, unsigned int slen)
+{
+ return 0;
+}
+
+static struct rng_alg caam_drng_alg = {
+ .generate = caam_drng_generate,
+ .seed = caam_drng_seed,
+ .seedsize = 0,
+ .base = {
+ .cra_name = "stdrng",
+ .cra_driver_name = "drng-caam",
+ .cra_priority = 300,
+ .cra_ctxsize = sizeof(struct caam_drng_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_init = caam_drng_init,
+ .cra_exit = caam_drng_exit,
+ },
+};
+
+static void caam_drng_unregister(void *data)
+{
+ crypto_unregister_rng(&caam_drng_alg);
+}
+
+int caam_drng_register(struct device *ctrldev)
+{
+ struct caam_drv_private *priv = dev_get_drvdata(ctrldev);
+
+ if (caam_has_rng(priv)) {
+ int ret;
+
+ ret = crypto_register_rng(&caam_drng_alg);
+ if (ret) {
+ dev_err(ctrldev,
+ "couldn't register rng crypto alg: %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = devm_add_action_or_reset(ctrldev, caam_drng_unregister,
+ NULL);
+ if (ret)
+ return ret;
+
+ dev_info(ctrldev,
+ "registering %s\n", caam_drng_alg.base.cra_name);
+ }
+
+ return 0;
+}
diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h
index 54bb04aa86bd..0c81eefd13a9 100644
--- a/drivers/crypto/caam/intern.h
+++ b/drivers/crypto/caam/intern.h
@@ -185,6 +185,19 @@ static inline int caam_trng_register(struct device *dev)

#endif /* CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API */

+#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_DRNG_API
+
+int caam_drng_register(struct device *dev);
+
+#else
+
+static inline int caam_drng_register(struct device *dev)
+{
+ return 0;
+}
+
+#endif /* CONFIG_CRYPTO_DEV_FSL_CAAM_DRNG_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 c745b7044fe6..e68ba0606e3f 100644
--- a/drivers/crypto/caam/jr.c
+++ b/drivers/crypto/caam/jr.c
@@ -38,6 +38,7 @@ static void register_algs(struct device *dev)
caam_algapi_hash_init(dev);
caam_pkc_init(dev);
caam_qi_algapi_init(dev);
+ caam_drng_register(dev);

algs_unlock:
mutex_unlock(&algs_lock);
--
2.21.0

2019-11-21 16:00:01

by Andrey Smirnov

[permalink] [raw]
Subject: [PATCH v4 1/6] crypto: caam - RNG4 TRNG errata

The TRNG as used in RNG4, used in CAAM has a documentation issue. The
effect is that it is possible that the entropy used to instantiate the
DRBG may be old entropy, rather than newly generated entropy. There is
proper programming guidance, but it is not in the documentation.

Signed-off-by: Aymen Sghaier <[email protected]>
Signed-off-by: Vipul Kumar <[email protected]>
[[email protected] ported to upstream kernel]
Signed-off-by: Andrey Smirnov <[email protected]>
Cc: Chris Healy <[email protected]>
Cc: Lucas Stach <[email protected]>
Cc: Horia Geantă <[email protected]>
Cc: Herbert Xu <[email protected]>
Cc: Iuliana Prodan <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
---
drivers/crypto/caam/ctrl.c | 11 ++++++++---
drivers/crypto/caam/regs.h | 3 ++-
2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index d7c3c3805693..df4db10e9fca 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -338,8 +338,12 @@ static void kick_trng(struct platform_device *pdev, int ent_delay)
ctrl = (struct caam_ctrl __iomem *)ctrlpriv->ctrl;
r4tst = &ctrl->r4tst[0];

- /* put RNG4 into program mode */
- clrsetbits_32(&r4tst->rtmctl, 0, RTMCTL_PRGM);
+ /*
+ * Setting both RTMCTL:PRGM and RTMCTL:TRNG_ACC causes TRNG to
+ * properly invalidate the entropy in the entropy register and
+ * force re-generation.
+ */
+ clrsetbits_32(&r4tst->rtmctl, 0, RTMCTL_PRGM | RTMCTL_ACC);

/*
* Performance-wise, it does not make sense to
@@ -369,7 +373,8 @@ static void kick_trng(struct platform_device *pdev, int ent_delay)
* select raw sampling in both entropy shifter
* and statistical checker; ; put RNG4 into run mode
*/
- clrsetbits_32(&r4tst->rtmctl, RTMCTL_PRGM, RTMCTL_SAMP_MODE_RAW_ES_SC);
+ clrsetbits_32(&r4tst->rtmctl, RTMCTL_PRGM | RTMCTL_ACC,
+ RTMCTL_SAMP_MODE_RAW_ES_SC);
}

static int caam_get_era_from_hw(struct caam_ctrl __iomem *ctrl)
diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h
index 05127b70527d..c191e8fd0fa7 100644
--- a/drivers/crypto/caam/regs.h
+++ b/drivers/crypto/caam/regs.h
@@ -487,7 +487,8 @@ struct rngtst {

/* RNG4 TRNG test registers */
struct rng4tst {
-#define RTMCTL_PRGM 0x00010000 /* 1 -> program mode, 0 -> run mode */
+#define RTMCTL_ACC BIT(5) /* TRNG access mode */
+#define RTMCTL_PRGM BIT(16) /* 1 -> program mode, 0 -> run mode */
#define RTMCTL_SAMP_MODE_VON_NEUMANN_ES_SC 0 /* use von Neumann data in
both entropy shifter and
statistical checker */
--
2.21.0