2023-07-06 07:44:12

by Thomas Bourgoin

[permalink] [raw]
Subject: [PATCH 0/7] Support of HASH on STM32MP13

From: Thomas Bourgoin <[email protected]>

The STM32MP13 platform introduces a new version of the IP HASH.
This version of the IP support SHA1, SHA2, SHA3 algorithms and HMAC.
This serie also add some fixes when using the DMA to feed data to the IP.

1. Add new YAML compatible st,stm32mp13-hash.

2. Update driver to support SHA2, SHA3 algorithms for the compatible
st,stm32mp13-hash.

3. Argument bufcnt is unused in function stm32_hash_write_ctrl. Removes it
to simplify the declaration of the function.

4-7. DMA fixes

Lionel Debieve (1):
dt-bindings: crypto: add new compatible for stm32-hash

Thomas Bourgoin (6):
crypto: stm32 - add new algorithms support
crypto: stm32 - remove bufcnt in stm32_hash_write_ctrl.
crypto: stm32 - fix loop iterating through scatterlist for DMA
crypto: stm32 - check request size and scatterlist size when using
DMA.
crypto: stm32 - fix MDMAT condition
crypto: stm32 - remove flag HASH_FLAGS_DMA_READY

.../bindings/crypto/st,stm32-hash.yaml | 1 +
drivers/crypto/stm32/Kconfig | 2 +
drivers/crypto/stm32/stm32-hash.c | 710 ++++++++++++++----
3 files changed, 566 insertions(+), 147 deletions(-)

--
2.25.1



2023-07-06 07:44:22

by Thomas Bourgoin

[permalink] [raw]
Subject: [PATCH 3/7] crypto: stm32 - remove bufcnt in stm32_hash_write_ctrl.

From: Thomas Bourgoin <[email protected]>

Commit "crypto: stm32 - Fix empty message processing" remove the use of
the argument bufcnt in stm32_hash_write_ctrl.
Hence, we can remove it from the function prototype and simplify the
function declaration.

Signed-off-by: Thomas Bourgoin <[email protected]>
---
drivers/crypto/stm32/stm32-hash.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/crypto/stm32/stm32-hash.c b/drivers/crypto/stm32/stm32-hash.c
index ded718196ac9..420df501360d 100644
--- a/drivers/crypto/stm32/stm32-hash.c
+++ b/drivers/crypto/stm32/stm32-hash.c
@@ -286,7 +286,7 @@ static int stm32_hash_write_key(struct stm32_hash_dev *hdev)
return 0;
}

-static void stm32_hash_write_ctrl(struct stm32_hash_dev *hdev, int bufcnt)
+static void stm32_hash_write_ctrl(struct stm32_hash_dev *hdev)
{
struct stm32_hash_request_ctx *rctx = ahash_request_ctx(hdev->req);
struct crypto_ahash *tfm = crypto_ahash_reqtfm(hdev->req);
@@ -395,7 +395,7 @@ static int stm32_hash_xmit_cpu(struct stm32_hash_dev *hdev,

hdev->flags |= HASH_FLAGS_CPU;

- stm32_hash_write_ctrl(hdev, length);
+ stm32_hash_write_ctrl(hdev);

if (stm32_hash_wait_busy(hdev))
return -ETIMEDOUT;
@@ -669,7 +669,7 @@ static int stm32_hash_dma_send(struct stm32_hash_dev *hdev)
if (rctx->nents < 0)
return -EINVAL;

- stm32_hash_write_ctrl(hdev, rctx->total);
+ stm32_hash_write_ctrl(hdev);

if (hdev->flags & HASH_FLAGS_HMAC) {
err = stm32_hash_hmac_dma_send(hdev);
--
2.25.1


2023-07-06 07:44:27

by Thomas Bourgoin

[permalink] [raw]
Subject: [PATCH 1/7] dt-bindings: crypto: add new compatible for stm32-hash

From: Lionel Debieve <[email protected]>

Add a new compatible for stm32mp13 support.

Signed-off-by: Lionel Debieve <[email protected]>
---
Documentation/devicetree/bindings/crypto/st,stm32-hash.yaml | 1 +
1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/crypto/st,stm32-hash.yaml b/Documentation/devicetree/bindings/crypto/st,stm32-hash.yaml
index b767ec72a999..ac480765cde0 100644
--- a/Documentation/devicetree/bindings/crypto/st,stm32-hash.yaml
+++ b/Documentation/devicetree/bindings/crypto/st,stm32-hash.yaml
@@ -20,6 +20,7 @@ properties:
- stericsson,ux500-hash
- st,stm32f456-hash
- st,stm32f756-hash
+ - st,stm32mp13-hash

reg:
maxItems: 1
--
2.25.1


2023-07-06 07:45:47

by Thomas Bourgoin

[permalink] [raw]
Subject: [PATCH 2/7] crypto: stm32 - add new algorithms support

From: Thomas Bourgoin <[email protected]>

Add the all SHA-2 (up to 512) and SHA-3 algorithm support.
Update compatible table to add stm32mp13.

Signed-off-by: Thomas Bourgoin <[email protected]>
---
drivers/crypto/stm32/Kconfig | 2 +
drivers/crypto/stm32/stm32-hash.c | 666 ++++++++++++++++++++++++------
2 files changed, 543 insertions(+), 125 deletions(-)

diff --git a/drivers/crypto/stm32/Kconfig b/drivers/crypto/stm32/Kconfig
index 4fc581e9e595..49dfd161e9b9 100644
--- a/drivers/crypto/stm32/Kconfig
+++ b/drivers/crypto/stm32/Kconfig
@@ -16,6 +16,8 @@ config CRYPTO_DEV_STM32_HASH
select CRYPTO_MD5
select CRYPTO_SHA1
select CRYPTO_SHA256
+ select CRYPTO_SHA512
+ select CRYPTO_SHA3
select CRYPTO_ENGINE
help
This enables support for the HASH hw accelerator which can be found
diff --git a/drivers/crypto/stm32/stm32-hash.c b/drivers/crypto/stm32/stm32-hash.c
index f0df32382719..ded718196ac9 100644
--- a/drivers/crypto/stm32/stm32-hash.c
+++ b/drivers/crypto/stm32/stm32-hash.c
@@ -26,6 +26,7 @@
#include <crypto/scatterwalk.h>
#include <crypto/sha1.h>
#include <crypto/sha2.h>
+#include <crypto/sha3.h>
#include <crypto/internal/hash.h>

#define HASH_CR 0x00
@@ -45,19 +46,11 @@
#define HASH_CR_DMAE BIT(3)
#define HASH_CR_DATATYPE_POS 4
#define HASH_CR_MODE BIT(6)
+#define HASH_CR_ALGO_POS 7
#define HASH_CR_MDMAT BIT(13)
#define HASH_CR_DMAA BIT(14)
#define HASH_CR_LKEY BIT(16)

-#define HASH_CR_ALGO_SHA1 0x0
-#define HASH_CR_ALGO_MD5 0x80
-#define HASH_CR_ALGO_SHA224 0x40000
-#define HASH_CR_ALGO_SHA256 0x40080
-
-#define HASH_CR_UX500_EMPTYMSG BIT(20)
-#define HASH_CR_UX500_ALGO_SHA1 BIT(7)
-#define HASH_CR_UX500_ALGO_SHA256 0x0
-
/* Interrupt */
#define HASH_DINIE BIT(0)
#define HASH_DCIE BIT(1)
@@ -66,9 +59,6 @@
#define HASH_MASK_CALC_COMPLETION BIT(0)
#define HASH_MASK_DATA_INPUT BIT(1)

-/* Context swap register */
-#define HASH_CSR_REGISTER_NUMBER 54
-
/* Status Flags */
#define HASH_SR_DATA_INPUT_READY BIT(0)
#define HASH_SR_OUTPUT_READY BIT(1)
@@ -79,6 +69,18 @@
#define HASH_STR_NBLW_MASK GENMASK(4, 0)
#define HASH_STR_DCAL BIT(8)

+/* HWCFGR Register */
+#define HASH_HWCFG_DMA_MASK GENMASK(3, 0)
+
+/* Context swap register */
+#define HASH_CSR_NB_SHA256_HMAC 54
+#define HASH_CSR_NB_SHA256 22
+#define HASH_CSR_NB_SHA512_HMAC 103
+#define HASH_CSR_NB_SHA512 91
+#define HASH_CSR_NB_SHA3_HMAC 88
+#define HASH_CSR_NB_SHA3 72
+#define HASH_CSR_NB_MAX HASH_CSR_NB_SHA512_HMAC
+
#define HASH_FLAGS_INIT BIT(0)
#define HASH_FLAGS_OUTPUT_READY BIT(1)
#define HASH_FLAGS_CPU BIT(2)
@@ -87,20 +89,20 @@
#define HASH_FLAGS_HMAC_INIT BIT(5)
#define HASH_FLAGS_HMAC_FINAL BIT(6)
#define HASH_FLAGS_HMAC_KEY BIT(7)
-
+#define HASH_FLAGS_SHA3_MODE BIT(8)
#define HASH_FLAGS_FINAL BIT(15)
#define HASH_FLAGS_FINUP BIT(16)
-#define HASH_FLAGS_ALGO_MASK GENMASK(21, 18)
-#define HASH_FLAGS_MD5 BIT(18)
-#define HASH_FLAGS_SHA1 BIT(19)
-#define HASH_FLAGS_SHA224 BIT(20)
-#define HASH_FLAGS_SHA256 BIT(21)
+#define HASH_FLAGS_ALGO_MASK GENMASK(20, 17)
+#define HASH_FLAGS_ALGO_SHIFT 17
+#define HASH_FLAGS_ERRORS BIT(21)
#define HASH_FLAGS_EMPTY BIT(22)
#define HASH_FLAGS_HMAC BIT(23)

#define HASH_OP_UPDATE 1
#define HASH_OP_FINAL 2

+#define HASH_BURST_LEVEL 4
+
enum stm32_hash_data_format {
HASH_DATA_32_BITS = 0x0,
HASH_DATA_16_BITS = 0x1,
@@ -108,11 +110,26 @@ enum stm32_hash_data_format {
HASH_DATA_1_BIT = 0x3
};

-#define HASH_BUFLEN 256
-#define HASH_LONG_KEY 64
-#define HASH_MAX_KEY_SIZE (SHA256_BLOCK_SIZE * 8)
-#define HASH_QUEUE_LENGTH 16
-#define HASH_DMA_THRESHOLD 50
+#define HASH_BUFLEN (SHA3_224_BLOCK_SIZE + 4)
+#define HASH_MAX_KEY_SIZE (SHA512_BLOCK_SIZE * 8)
+
+enum stm32_hash_algo {
+ HASH_SHA1 = 0,
+ HASH_MD5 = 1,
+ HASH_SHA224 = 2,
+ HASH_SHA256 = 3,
+ HASH_SHA3_224 = 4,
+ HASH_SHA3_256 = 5,
+ HASH_SHA3_384 = 6,
+ HASH_SHA3_512 = 7,
+ HASH_SHA384 = 12,
+ HASH_SHA512 = 15,
+};
+
+enum ux500_hash_algo {
+ HASH_SHA256_UX500 = 0,
+ HASH_SHA1_UX500 = 1,
+};

#define HASH_AUTOSUSPEND_DELAY 50

@@ -130,19 +147,19 @@ struct stm32_hash_state {
u32 flags;

u16 bufcnt;
- u16 buflen;
+ u16 blocklen;

u8 buffer[HASH_BUFLEN] __aligned(4);

/* hash state */
- u32 hw_context[3 + HASH_CSR_REGISTER_NUMBER];
+ u32 hw_context[3 + HASH_CSR_NB_MAX];
};

struct stm32_hash_request_ctx {
struct stm32_hash_dev *hdev;
unsigned long op;

- u8 digest[SHA256_DIGEST_SIZE] __aligned(sizeof(u32));
+ u8 digest[SHA512_DIGEST_SIZE] __aligned(sizeof(u32));
size_t digcnt;

/* DMA */
@@ -166,12 +183,13 @@ struct stm32_hash_algs_info {
};

struct stm32_hash_pdata {
- struct stm32_hash_algs_info *algs_info;
- size_t algs_info_size;
- bool has_sr;
- bool has_mdmat;
- bool broken_emptymsg;
- bool ux500;
+ const int alg_shift;
+ const struct stm32_hash_algs_info *algs_info;
+ size_t algs_info_size;
+ bool has_sr;
+ bool has_mdmat;
+ bool broken_emptymsg;
+ bool ux500;
};

struct stm32_hash_dev {
@@ -182,7 +200,6 @@ struct stm32_hash_dev {
void __iomem *io_base;
phys_addr_t phys_base;
u32 dma_mode;
- u32 dma_maxburst;
bool polled;

struct ahash_request *req;
@@ -275,31 +292,19 @@ static void stm32_hash_write_ctrl(struct stm32_hash_dev *hdev, int bufcnt)
struct crypto_ahash *tfm = crypto_ahash_reqtfm(hdev->req);
struct stm32_hash_ctx *ctx = crypto_ahash_ctx(tfm);
struct stm32_hash_state *state = &rctx->state;
+ u32 alg = (state->flags & HASH_FLAGS_ALGO_MASK) >> HASH_FLAGS_ALGO_SHIFT;

u32 reg = HASH_CR_INIT;

if (!(hdev->flags & HASH_FLAGS_INIT)) {
- switch (state->flags & HASH_FLAGS_ALGO_MASK) {
- case HASH_FLAGS_MD5:
- reg |= HASH_CR_ALGO_MD5;
- break;
- case HASH_FLAGS_SHA1:
- if (hdev->pdata->ux500)
- reg |= HASH_CR_UX500_ALGO_SHA1;
- else
- reg |= HASH_CR_ALGO_SHA1;
- break;
- case HASH_FLAGS_SHA224:
- reg |= HASH_CR_ALGO_SHA224;
- break;
- case HASH_FLAGS_SHA256:
- if (hdev->pdata->ux500)
- reg |= HASH_CR_UX500_ALGO_SHA256;
+ if (hdev->pdata->ux500) {
+ reg |= ((alg & BIT(0)) << HASH_CR_ALGO_POS);
+ } else {
+ if (hdev->pdata->alg_shift == HASH_CR_ALGO_POS)
+ reg |= ((alg & BIT(1)) << 17) |
+ ((alg & BIT(0)) << HASH_CR_ALGO_POS);
else
- reg |= HASH_CR_ALGO_SHA256;
- break;
- default:
- reg |= HASH_CR_ALGO_MD5;
+ reg |= alg << hdev->pdata->alg_shift;
}

reg |= (rctx->data_type << HASH_CR_DATATYPE_POS);
@@ -307,7 +312,7 @@ static void stm32_hash_write_ctrl(struct stm32_hash_dev *hdev, int bufcnt)
if (state->flags & HASH_FLAGS_HMAC) {
hdev->flags |= HASH_FLAGS_HMAC;
reg |= HASH_CR_MODE;
- if (ctx->keylen > HASH_LONG_KEY)
+ if (ctx->keylen > crypto_ahash_blocksize(tfm))
reg |= HASH_CR_LKEY;
}

@@ -318,6 +323,12 @@ static void stm32_hash_write_ctrl(struct stm32_hash_dev *hdev, int bufcnt)

hdev->flags |= HASH_FLAGS_INIT;

+ /*
+ * After first block + 1 words are fill up,
+ * we only need to fill 1 block to start partial computation
+ */
+ rctx->state.blocklen -= sizeof(u32);
+
dev_dbg(hdev->dev, "Write Control %x\n", reg);
}
}
@@ -327,9 +338,9 @@ static void stm32_hash_append_sg(struct stm32_hash_request_ctx *rctx)
struct stm32_hash_state *state = &rctx->state;
size_t count;

- while ((state->bufcnt < state->buflen) && rctx->total) {
+ while ((state->bufcnt < state->blocklen) && rctx->total) {
count = min(rctx->sg->length - rctx->offset, rctx->total);
- count = min_t(size_t, count, state->buflen - state->bufcnt);
+ count = min_t(size_t, count, state->blocklen - state->bufcnt);

if (count <= 0) {
if ((rctx->sg->length == 0) && !sg_is_last(rctx->sg)) {
@@ -419,20 +430,59 @@ static int stm32_hash_xmit_cpu(struct stm32_hash_dev *hdev,
return 0;
}

+static int hash_swap_reg(struct stm32_hash_request_ctx *rctx)
+{
+ struct stm32_hash_state *state = &rctx->state;
+
+ switch ((state->flags & HASH_FLAGS_ALGO_MASK) >>
+ HASH_FLAGS_ALGO_SHIFT) {
+ case HASH_MD5:
+ case HASH_SHA1:
+ case HASH_SHA224:
+ case HASH_SHA256:
+ if (state->flags & HASH_FLAGS_HMAC)
+ return HASH_CSR_NB_SHA256_HMAC;
+ else
+ return HASH_CSR_NB_SHA256;
+ break;
+
+ case HASH_SHA384:
+ case HASH_SHA512:
+ if (state->flags & HASH_FLAGS_HMAC)
+ return HASH_CSR_NB_SHA512_HMAC;
+ else
+ return HASH_CSR_NB_SHA512;
+ break;
+
+ case HASH_SHA3_224:
+ case HASH_SHA3_256:
+ case HASH_SHA3_384:
+ case HASH_SHA3_512:
+ if (state->flags & HASH_FLAGS_HMAC)
+ return HASH_CSR_NB_SHA3_HMAC;
+ else
+ return HASH_CSR_NB_SHA3;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+}
+
static int stm32_hash_update_cpu(struct stm32_hash_dev *hdev)
{
struct stm32_hash_request_ctx *rctx = ahash_request_ctx(hdev->req);
struct stm32_hash_state *state = &rctx->state;
u32 *preg = state->hw_context;
int bufcnt, err = 0, final;
- int i;
+ int i, swap_reg;

dev_dbg(hdev->dev, "%s flags %x\n", __func__, state->flags);

final = state->flags & HASH_FLAGS_FINAL;

- while ((rctx->total >= state->buflen) ||
- (state->bufcnt + rctx->total >= state->buflen)) {
+ while ((rctx->total >= state->blocklen) ||
+ (state->bufcnt + rctx->total >= state->blocklen)) {
stm32_hash_append_sg(rctx);
bufcnt = state->bufcnt;
state->bufcnt = 0;
@@ -455,11 +505,13 @@ static int stm32_hash_update_cpu(struct stm32_hash_dev *hdev)
if (stm32_hash_wait_busy(hdev))
return -ETIMEDOUT;

+ swap_reg = hash_swap_reg(rctx);
+
if (!hdev->pdata->ux500)
*preg++ = stm32_hash_read(hdev, HASH_IMR);
*preg++ = stm32_hash_read(hdev, HASH_STR);
*preg++ = stm32_hash_read(hdev, HASH_CR);
- for (i = 0; i < HASH_CSR_REGISTER_NUMBER; i++)
+ for (i = 0; i < swap_reg; i++)
*preg++ = stm32_hash_read(hdev, HASH_CSR(i));

state->flags |= HASH_FLAGS_INIT;
@@ -544,7 +596,7 @@ static int stm32_hash_hmac_dma_send(struct stm32_hash_dev *hdev)
struct stm32_hash_ctx *ctx = crypto_ahash_ctx(tfm);
int err;

- if (ctx->keylen < HASH_DMA_THRESHOLD || (hdev->dma_mode == 1)) {
+ if (ctx->keylen < rctx->state.blocklen || hdev->dma_mode == 1) {
err = stm32_hash_write_key(hdev);
if (stm32_hash_wait_busy(hdev))
return -ETIMEDOUT;
@@ -579,8 +631,8 @@ static int stm32_hash_dma_init(struct stm32_hash_dev *hdev)
dma_conf.direction = DMA_MEM_TO_DEV;
dma_conf.dst_addr = hdev->phys_base + HASH_DIN;
dma_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
- dma_conf.src_maxburst = hdev->dma_maxburst;
- dma_conf.dst_maxburst = hdev->dma_maxburst;
+ dma_conf.src_maxburst = HASH_BURST_LEVEL;
+ dma_conf.dst_maxburst = HASH_BURST_LEVEL;
dma_conf.device_fc = false;

chan = dma_request_chan(hdev->dev, "in");
@@ -614,7 +666,6 @@ static int stm32_hash_dma_send(struct stm32_hash_dev *hdev)
rctx->total = hdev->req->nbytes;

rctx->nents = sg_nents(rctx->sg);
-
if (rctx->nents < 0)
return -EINVAL;

@@ -718,11 +769,12 @@ static struct stm32_hash_dev *stm32_hash_find_dev(struct stm32_hash_ctx *ctx)
static bool stm32_hash_dma_aligned_data(struct ahash_request *req)
{
struct scatterlist *sg;
+ struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req);
struct stm32_hash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx);
int i;

- if (req->nbytes <= HASH_DMA_THRESHOLD)
+ if (!hdev->dma_lch || req->nbytes <= rctx->state.blocklen)
return false;

if (sg_nents(req->src) > 1) {
@@ -748,31 +800,64 @@ static int stm32_hash_init(struct ahash_request *req)
struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req);
struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx);
struct stm32_hash_state *state = &rctx->state;
+ bool sha3_mode = ctx->flags & HASH_FLAGS_SHA3_MODE;

rctx->hdev = hdev;

state->flags = HASH_FLAGS_CPU;

+ if (sha3_mode)
+ state->flags |= HASH_FLAGS_SHA3_MODE;
+
rctx->digcnt = crypto_ahash_digestsize(tfm);
switch (rctx->digcnt) {
case MD5_DIGEST_SIZE:
- state->flags |= HASH_FLAGS_MD5;
+ state->flags |= HASH_MD5 << HASH_FLAGS_ALGO_SHIFT;
break;
case SHA1_DIGEST_SIZE:
- state->flags |= HASH_FLAGS_SHA1;
+ if (hdev->pdata->ux500)
+ state->flags |= HASH_SHA1_UX500 << HASH_FLAGS_ALGO_SHIFT;
+ else
+ state->flags |= HASH_SHA1 << HASH_FLAGS_ALGO_SHIFT;
break;
case SHA224_DIGEST_SIZE:
- state->flags |= HASH_FLAGS_SHA224;
+ if (sha3_mode)
+ state->flags |= HASH_SHA3_224 << HASH_FLAGS_ALGO_SHIFT;
+ else
+ state->flags |= HASH_SHA224 << HASH_FLAGS_ALGO_SHIFT;
break;
case SHA256_DIGEST_SIZE:
- state->flags |= HASH_FLAGS_SHA256;
+ if (sha3_mode) {
+ state->flags |= HASH_SHA3_256 << HASH_FLAGS_ALGO_SHIFT;
+ } else {
+ if (hdev->pdata->ux500)
+ state->flags |= HASH_SHA256_UX500 << HASH_FLAGS_ALGO_SHIFT;
+ else
+ state->flags |= HASH_SHA256 << HASH_FLAGS_ALGO_SHIFT;
+ }
+ break;
+ case SHA384_DIGEST_SIZE:
+ if (sha3_mode)
+ state->flags |= HASH_SHA3_384 << HASH_FLAGS_ALGO_SHIFT;
+ else
+ state->flags |= HASH_SHA384 << HASH_FLAGS_ALGO_SHIFT;
+ break;
+ case SHA512_DIGEST_SIZE:
+ if (sha3_mode)
+ state->flags |= HASH_SHA3_512 << HASH_FLAGS_ALGO_SHIFT;
+ else
+ state->flags |= HASH_SHA512 << HASH_FLAGS_ALGO_SHIFT;
break;
default:
return -EINVAL;
}

rctx->state.bufcnt = 0;
- rctx->state.buflen = HASH_BUFLEN;
+ rctx->state.blocklen = crypto_ahash_blocksize(tfm) + sizeof(u32);
+ if (rctx->state.blocklen > HASH_BUFLEN) {
+ dev_err(hdev->dev, "Error, block too large");
+ return -EINVAL;
+ }
rctx->total = 0;
rctx->offset = 0;
rctx->data_type = HASH_DATA_8_BITS;
@@ -842,6 +927,7 @@ static void stm32_hash_emptymsg_fallback(struct ahash_request *req)

static void stm32_hash_copy_hash(struct ahash_request *req)
{
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req);
struct stm32_hash_state *state = &rctx->state;
struct stm32_hash_dev *hdev = rctx->hdev;
@@ -851,22 +937,7 @@ static void stm32_hash_copy_hash(struct ahash_request *req)
if (hdev->pdata->broken_emptymsg && (state->flags & HASH_FLAGS_EMPTY))
return stm32_hash_emptymsg_fallback(req);

- switch (state->flags & HASH_FLAGS_ALGO_MASK) {
- case HASH_FLAGS_MD5:
- hashsize = MD5_DIGEST_SIZE;
- break;
- case HASH_FLAGS_SHA1:
- hashsize = SHA1_DIGEST_SIZE;
- break;
- case HASH_FLAGS_SHA224:
- hashsize = SHA224_DIGEST_SIZE;
- break;
- case HASH_FLAGS_SHA256:
- hashsize = SHA256_DIGEST_SIZE;
- break;
- default:
- return;
- }
+ hashsize = crypto_ahash_digestsize(tfm);

for (i = 0; i < hashsize / sizeof(u32); i++) {
if (hdev->pdata->ux500)
@@ -881,6 +952,11 @@ static void stm32_hash_copy_hash(struct ahash_request *req)
static int stm32_hash_finish(struct ahash_request *req)
{
struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req);
+ u32 reg;
+
+ reg = stm32_hash_read(rctx->hdev, HASH_SR);
+ reg &= ~HASH_SR_OUTPUT_READY;
+ stm32_hash_write(rctx->hdev, HASH_SR, reg);

if (!req->result)
return -EINVAL;
@@ -920,6 +996,7 @@ static int stm32_hash_one_request(struct crypto_engine *engine, void *areq)
struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req);
struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx);
struct stm32_hash_state *state = &rctx->state;
+ int swap_reg;
int err = 0;

if (!hdev)
@@ -932,6 +1009,7 @@ static int stm32_hash_one_request(struct crypto_engine *engine, void *areq)

hdev->req = req;
hdev->flags = 0;
+ swap_reg = hash_swap_reg(rctx);

if (state->flags & HASH_FLAGS_INIT) {
u32 *preg = rctx->state.hw_context;
@@ -945,7 +1023,7 @@ static int stm32_hash_one_request(struct crypto_engine *engine, void *areq)
reg = *preg++ | HASH_CR_INIT;
stm32_hash_write(hdev, HASH_CR, reg);

- for (i = 0; i < HASH_CSR_REGISTER_NUMBER; i++)
+ for (i = 0; i < swap_reg; i++)
stm32_hash_write(hdev, HASH_CSR(i), *preg++);

hdev->flags |= HASH_FLAGS_INIT;
@@ -1000,7 +1078,7 @@ static int stm32_hash_update(struct ahash_request *req)
rctx->sg = req->src;
rctx->offset = 0;

- if ((state->bufcnt + rctx->total < state->buflen)) {
+ if ((state->bufcnt + rctx->total < state->blocklen)) {
stm32_hash_append_sg(rctx);
return 0;
}
@@ -1102,8 +1180,7 @@ static int stm32_hash_init_fallback(struct crypto_tfm *tfm)
return 0;
}

-static int stm32_hash_cra_init_algs(struct crypto_tfm *tfm,
- const char *algs_hmac_name)
+static int stm32_hash_cra_init_algs(struct crypto_tfm *tfm, u32 algs_flags)
{
struct stm32_hash_ctx *ctx = crypto_tfm_ctx(tfm);

@@ -1112,8 +1189,8 @@ static int stm32_hash_cra_init_algs(struct crypto_tfm *tfm,

ctx->keylen = 0;

- if (algs_hmac_name)
- ctx->flags |= HASH_FLAGS_HMAC;
+ if (algs_flags)
+ ctx->flags |= algs_flags;

ctx->enginectx.op.do_one_request = stm32_hash_one_request;

@@ -1122,28 +1199,25 @@ static int stm32_hash_cra_init_algs(struct crypto_tfm *tfm,

static int stm32_hash_cra_init(struct crypto_tfm *tfm)
{
- return stm32_hash_cra_init_algs(tfm, NULL);
+ return stm32_hash_cra_init_algs(tfm, 0);
}

-static int stm32_hash_cra_md5_init(struct crypto_tfm *tfm)
+static int stm32_hash_cra_hmac_init(struct crypto_tfm *tfm)
{
- return stm32_hash_cra_init_algs(tfm, "md5");
+ return stm32_hash_cra_init_algs(tfm, HASH_FLAGS_HMAC);
}

-static int stm32_hash_cra_sha1_init(struct crypto_tfm *tfm)
+static int stm32_hash_cra_sha3_init(struct crypto_tfm *tfm)
{
- return stm32_hash_cra_init_algs(tfm, "sha1");
+ return stm32_hash_cra_init_algs(tfm, HASH_FLAGS_SHA3_MODE);
}

-static int stm32_hash_cra_sha224_init(struct crypto_tfm *tfm)
+static int stm32_hash_cra_sha3_hmac_init(struct crypto_tfm *tfm)
{
- return stm32_hash_cra_init_algs(tfm, "sha224");
+ return stm32_hash_cra_init_algs(tfm, HASH_FLAGS_SHA3_MODE |
+ HASH_FLAGS_HMAC);
}

-static int stm32_hash_cra_sha256_init(struct crypto_tfm *tfm)
-{
- return stm32_hash_cra_init_algs(tfm, "sha256");
-}

static void stm32_hash_cra_exit(struct crypto_tfm *tfm)
{
@@ -1185,8 +1259,6 @@ static irqreturn_t stm32_hash_irq_handler(int irq, void *dev_id)

reg = stm32_hash_read(hdev, HASH_SR);
if (reg & HASH_SR_OUTPUT_READY) {
- reg &= ~HASH_SR_OUTPUT_READY;
- stm32_hash_write(hdev, HASH_SR, reg);
hdev->flags |= HASH_FLAGS_OUTPUT_READY;
/* Disable IT*/
stm32_hash_write(hdev, HASH_IMR, 0);
@@ -1244,12 +1316,12 @@ static struct ahash_alg algs_md5[] = {
.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct stm32_hash_ctx),
.cra_alignmask = 3,
- .cra_init = stm32_hash_cra_md5_init,
+ .cra_init = stm32_hash_cra_hmac_init,
.cra_exit = stm32_hash_cra_exit,
.cra_module = THIS_MODULE,
}
}
- },
+ }
};

static struct ahash_alg algs_sha1[] = {
@@ -1300,7 +1372,7 @@ static struct ahash_alg algs_sha1[] = {
.cra_blocksize = SHA1_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct stm32_hash_ctx),
.cra_alignmask = 3,
- .cra_init = stm32_hash_cra_sha1_init,
+ .cra_init = stm32_hash_cra_hmac_init,
.cra_exit = stm32_hash_cra_exit,
.cra_module = THIS_MODULE,
}
@@ -1356,7 +1428,7 @@ static struct ahash_alg algs_sha224[] = {
.cra_blocksize = SHA224_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct stm32_hash_ctx),
.cra_alignmask = 3,
- .cra_init = stm32_hash_cra_sha224_init,
+ .cra_init = stm32_hash_cra_hmac_init,
.cra_exit = stm32_hash_cra_exit,
.cra_module = THIS_MODULE,
}
@@ -1412,12 +1484,336 @@ static struct ahash_alg algs_sha256[] = {
.cra_blocksize = SHA256_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct stm32_hash_ctx),
.cra_alignmask = 3,
- .cra_init = stm32_hash_cra_sha256_init,
+ .cra_init = stm32_hash_cra_hmac_init,
+ .cra_exit = stm32_hash_cra_exit,
+ .cra_module = THIS_MODULE,
+ }
+ }
+ },
+};
+
+static struct ahash_alg algs_sha384_sha512[] = {
+ {
+ .init = stm32_hash_init,
+ .update = stm32_hash_update,
+ .final = stm32_hash_final,
+ .finup = stm32_hash_finup,
+ .digest = stm32_hash_digest,
+ .export = stm32_hash_export,
+ .import = stm32_hash_import,
+ .halg = {
+ .digestsize = SHA384_DIGEST_SIZE,
+ .statesize = sizeof(struct stm32_hash_state),
+ .base = {
+ .cra_name = "sha384",
+ .cra_driver_name = "stm32-sha384",
+ .cra_priority = 200,
+ .cra_flags = CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_KERN_DRIVER_ONLY,
+ .cra_blocksize = SHA384_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct stm32_hash_ctx),
+ .cra_alignmask = 3,
+ .cra_init = stm32_hash_cra_init,
+ .cra_exit = stm32_hash_cra_exit,
+ .cra_module = THIS_MODULE,
+ }
+ }
+ },
+ {
+ .init = stm32_hash_init,
+ .update = stm32_hash_update,
+ .final = stm32_hash_final,
+ .finup = stm32_hash_finup,
+ .digest = stm32_hash_digest,
+ .setkey = stm32_hash_setkey,
+ .export = stm32_hash_export,
+ .import = stm32_hash_import,
+ .halg = {
+ .digestsize = SHA384_DIGEST_SIZE,
+ .statesize = sizeof(struct stm32_hash_state),
+ .base = {
+ .cra_name = "hmac(sha384)",
+ .cra_driver_name = "stm32-hmac-sha384",
+ .cra_priority = 200,
+ .cra_flags = CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_KERN_DRIVER_ONLY,
+ .cra_blocksize = SHA384_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct stm32_hash_ctx),
+ .cra_alignmask = 3,
+ .cra_init = stm32_hash_cra_hmac_init,
+ .cra_exit = stm32_hash_cra_exit,
+ .cra_module = THIS_MODULE,
+ }
+ }
+ },
+ {
+ .init = stm32_hash_init,
+ .update = stm32_hash_update,
+ .final = stm32_hash_final,
+ .finup = stm32_hash_finup,
+ .digest = stm32_hash_digest,
+ .export = stm32_hash_export,
+ .import = stm32_hash_import,
+ .halg = {
+ .digestsize = SHA512_DIGEST_SIZE,
+ .statesize = sizeof(struct stm32_hash_state),
+ .base = {
+ .cra_name = "sha512",
+ .cra_driver_name = "stm32-sha512",
+ .cra_priority = 200,
+ .cra_flags = CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_KERN_DRIVER_ONLY,
+ .cra_blocksize = SHA512_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct stm32_hash_ctx),
+ .cra_alignmask = 3,
+ .cra_init = stm32_hash_cra_init,
+ .cra_exit = stm32_hash_cra_exit,
+ .cra_module = THIS_MODULE,
+ }
+ }
+ },
+ {
+ .init = stm32_hash_init,
+ .update = stm32_hash_update,
+ .final = stm32_hash_final,
+ .finup = stm32_hash_finup,
+ .digest = stm32_hash_digest,
+ .export = stm32_hash_export,
+ .import = stm32_hash_import,
+ .setkey = stm32_hash_setkey,
+ .halg = {
+ .digestsize = SHA512_DIGEST_SIZE,
+ .statesize = sizeof(struct stm32_hash_state),
+ .base = {
+ .cra_name = "hmac(sha512)",
+ .cra_driver_name = "stm32-hmac-sha512",
+ .cra_priority = 200,
+ .cra_flags = CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_KERN_DRIVER_ONLY,
+ .cra_blocksize = SHA512_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct stm32_hash_ctx),
+ .cra_alignmask = 3,
+ .cra_init = stm32_hash_cra_hmac_init,
+ .cra_exit = stm32_hash_cra_exit,
+ .cra_module = THIS_MODULE,
+ }
+ }
+ },
+};
+
+static struct ahash_alg algs_sha3[] = {
+ {
+ .init = stm32_hash_init,
+ .update = stm32_hash_update,
+ .final = stm32_hash_final,
+ .finup = stm32_hash_finup,
+ .digest = stm32_hash_digest,
+ .export = stm32_hash_export,
+ .import = stm32_hash_import,
+ .halg = {
+ .digestsize = SHA3_224_DIGEST_SIZE,
+ .statesize = sizeof(struct stm32_hash_state),
+ .base = {
+ .cra_name = "sha3-224",
+ .cra_driver_name = "stm32-sha3-224",
+ .cra_priority = 200,
+ .cra_flags = CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_KERN_DRIVER_ONLY,
+ .cra_blocksize = SHA3_224_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct stm32_hash_ctx),
+ .cra_alignmask = 3,
+ .cra_init = stm32_hash_cra_sha3_init,
.cra_exit = stm32_hash_cra_exit,
.cra_module = THIS_MODULE,
}
}
},
+ {
+ .init = stm32_hash_init,
+ .update = stm32_hash_update,
+ .final = stm32_hash_final,
+ .finup = stm32_hash_finup,
+ .digest = stm32_hash_digest,
+ .export = stm32_hash_export,
+ .import = stm32_hash_import,
+ .setkey = stm32_hash_setkey,
+ .halg = {
+ .digestsize = SHA3_224_DIGEST_SIZE,
+ .statesize = sizeof(struct stm32_hash_state),
+ .base = {
+ .cra_name = "hmac(sha3-224)",
+ .cra_driver_name = "stm32-hmac-sha3-224",
+ .cra_priority = 200,
+ .cra_flags = CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_KERN_DRIVER_ONLY,
+ .cra_blocksize = SHA3_224_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct stm32_hash_ctx),
+ .cra_alignmask = 3,
+ .cra_init = stm32_hash_cra_sha3_hmac_init,
+ .cra_exit = stm32_hash_cra_exit,
+ .cra_module = THIS_MODULE,
+ }
+ }
+ },
+ {
+ .init = stm32_hash_init,
+ .update = stm32_hash_update,
+ .final = stm32_hash_final,
+ .finup = stm32_hash_finup,
+ .digest = stm32_hash_digest,
+ .export = stm32_hash_export,
+ .import = stm32_hash_import,
+ .halg = {
+ .digestsize = SHA3_256_DIGEST_SIZE,
+ .statesize = sizeof(struct stm32_hash_state),
+ .base = {
+ .cra_name = "sha3-256",
+ .cra_driver_name = "stm32-sha3-256",
+ .cra_priority = 200,
+ .cra_flags = CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_KERN_DRIVER_ONLY,
+ .cra_blocksize = SHA3_256_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct stm32_hash_ctx),
+ .cra_alignmask = 3,
+ .cra_init = stm32_hash_cra_sha3_init,
+ .cra_exit = stm32_hash_cra_exit,
+ .cra_module = THIS_MODULE,
+ }
+ }
+ },
+ {
+ .init = stm32_hash_init,
+ .update = stm32_hash_update,
+ .final = stm32_hash_final,
+ .finup = stm32_hash_finup,
+ .digest = stm32_hash_digest,
+ .export = stm32_hash_export,
+ .import = stm32_hash_import,
+ .setkey = stm32_hash_setkey,
+ .halg = {
+ .digestsize = SHA3_256_DIGEST_SIZE,
+ .statesize = sizeof(struct stm32_hash_state),
+ .base = {
+ .cra_name = "hmac(sha3-256)",
+ .cra_driver_name = "stm32-hmac-sha3-256",
+ .cra_priority = 200,
+ .cra_flags = CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_KERN_DRIVER_ONLY,
+ .cra_blocksize = SHA3_256_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct stm32_hash_ctx),
+ .cra_alignmask = 3,
+ .cra_init = stm32_hash_cra_sha3_hmac_init,
+ .cra_exit = stm32_hash_cra_exit,
+ .cra_module = THIS_MODULE,
+ }
+ }
+ },
+ {
+ .init = stm32_hash_init,
+ .update = stm32_hash_update,
+ .final = stm32_hash_final,
+ .finup = stm32_hash_finup,
+ .digest = stm32_hash_digest,
+ .export = stm32_hash_export,
+ .import = stm32_hash_import,
+ .halg = {
+ .digestsize = SHA3_384_DIGEST_SIZE,
+ .statesize = sizeof(struct stm32_hash_state),
+ .base = {
+ .cra_name = "sha3-384",
+ .cra_driver_name = "stm32-sha3-384",
+ .cra_priority = 200,
+ .cra_flags = CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_KERN_DRIVER_ONLY,
+ .cra_blocksize = SHA3_384_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct stm32_hash_ctx),
+ .cra_alignmask = 3,
+ .cra_init = stm32_hash_cra_sha3_init,
+ .cra_exit = stm32_hash_cra_exit,
+ .cra_module = THIS_MODULE,
+ }
+ }
+ },
+ {
+ .init = stm32_hash_init,
+ .update = stm32_hash_update,
+ .final = stm32_hash_final,
+ .finup = stm32_hash_finup,
+ .digest = stm32_hash_digest,
+ .export = stm32_hash_export,
+ .import = stm32_hash_import,
+ .setkey = stm32_hash_setkey,
+ .halg = {
+ .digestsize = SHA3_384_DIGEST_SIZE,
+ .statesize = sizeof(struct stm32_hash_state),
+ .base = {
+ .cra_name = "hmac(sha3-384)",
+ .cra_driver_name = "stm32-hmac-sha3-384",
+ .cra_priority = 200,
+ .cra_flags = CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_KERN_DRIVER_ONLY,
+ .cra_blocksize = SHA3_384_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct stm32_hash_ctx),
+ .cra_alignmask = 3,
+ .cra_init = stm32_hash_cra_sha3_hmac_init,
+ .cra_exit = stm32_hash_cra_exit,
+ .cra_module = THIS_MODULE,
+ }
+ }
+ },
+ {
+ .init = stm32_hash_init,
+ .update = stm32_hash_update,
+ .final = stm32_hash_final,
+ .finup = stm32_hash_finup,
+ .digest = stm32_hash_digest,
+ .export = stm32_hash_export,
+ .import = stm32_hash_import,
+ .halg = {
+ .digestsize = SHA3_512_DIGEST_SIZE,
+ .statesize = sizeof(struct stm32_hash_state),
+ .base = {
+ .cra_name = "sha3-512",
+ .cra_driver_name = "stm32-sha3-512",
+ .cra_priority = 200,
+ .cra_flags = CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_KERN_DRIVER_ONLY,
+ .cra_blocksize = SHA3_512_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct stm32_hash_ctx),
+ .cra_alignmask = 3,
+ .cra_init = stm32_hash_cra_sha3_init,
+ .cra_exit = stm32_hash_cra_exit,
+ .cra_module = THIS_MODULE,
+ }
+ }
+ },
+ {
+ .init = stm32_hash_init,
+ .update = stm32_hash_update,
+ .final = stm32_hash_final,
+ .finup = stm32_hash_finup,
+ .digest = stm32_hash_digest,
+ .export = stm32_hash_export,
+ .import = stm32_hash_import,
+ .setkey = stm32_hash_setkey,
+ .halg = {
+ .digestsize = SHA3_512_DIGEST_SIZE,
+ .statesize = sizeof(struct stm32_hash_state),
+ .base = {
+ .cra_name = "hmac(sha3-512)",
+ .cra_driver_name = "stm32-hmac-sha3-512",
+ .cra_priority = 200,
+ .cra_flags = CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_KERN_DRIVER_ONLY,
+ .cra_blocksize = SHA3_512_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct stm32_hash_ctx),
+ .cra_alignmask = 3,
+ .cra_init = stm32_hash_cra_sha3_hmac_init,
+ .cra_exit = stm32_hash_cra_exit,
+ .cra_module = THIS_MODULE,
+ }
+ }
+ }
};

static int stm32_hash_register_algs(struct stm32_hash_dev *hdev)
@@ -1471,6 +1867,7 @@ static struct stm32_hash_algs_info stm32_hash_algs_info_ux500[] = {
};

static const struct stm32_hash_pdata stm32_hash_pdata_ux500 = {
+ .alg_shift = 7,
.algs_info = stm32_hash_algs_info_ux500,
.algs_info_size = ARRAY_SIZE(stm32_hash_algs_info_ux500),
.broken_emptymsg = true,
@@ -1489,6 +1886,7 @@ static struct stm32_hash_algs_info stm32_hash_algs_info_stm32f4[] = {
};

static const struct stm32_hash_pdata stm32_hash_pdata_stm32f4 = {
+ .alg_shift = 7,
.algs_info = stm32_hash_algs_info_stm32f4,
.algs_info_size = ARRAY_SIZE(stm32_hash_algs_info_stm32f4),
.has_sr = true,
@@ -1515,25 +1913,49 @@ static struct stm32_hash_algs_info stm32_hash_algs_info_stm32f7[] = {
};

static const struct stm32_hash_pdata stm32_hash_pdata_stm32f7 = {
+ .alg_shift = 7,
.algs_info = stm32_hash_algs_info_stm32f7,
.algs_info_size = ARRAY_SIZE(stm32_hash_algs_info_stm32f7),
.has_sr = true,
.has_mdmat = true,
};

-static const struct of_device_id stm32_hash_of_match[] = {
+static struct stm32_hash_algs_info stm32_hash_algs_info_stm32mp13[] = {
+ {
+ .algs_list = algs_sha1,
+ .size = ARRAY_SIZE(algs_sha1),
+ },
+ {
+ .algs_list = algs_sha224,
+ .size = ARRAY_SIZE(algs_sha224),
+ },
{
- .compatible = "stericsson,ux500-hash",
- .data = &stm32_hash_pdata_ux500,
+ .algs_list = algs_sha256,
+ .size = ARRAY_SIZE(algs_sha256),
},
{
- .compatible = "st,stm32f456-hash",
- .data = &stm32_hash_pdata_stm32f4,
+ .algs_list = algs_sha384_sha512,
+ .size = ARRAY_SIZE(algs_sha384_sha512),
},
{
- .compatible = "st,stm32f756-hash",
- .data = &stm32_hash_pdata_stm32f7,
+ .algs_list = algs_sha3,
+ .size = ARRAY_SIZE(algs_sha3),
},
+};
+
+static const struct stm32_hash_pdata stm32_hash_pdata_stm32mp13 = {
+ .alg_shift = 17,
+ .algs_info = stm32_hash_algs_info_stm32mp13,
+ .algs_info_size = ARRAY_SIZE(stm32_hash_algs_info_stm32mp13),
+ .has_sr = true,
+ .has_mdmat = true,
+};
+
+static const struct of_device_id stm32_hash_of_match[] = {
+ { .compatible = "stericsson,ux500-hash", .data = &stm32_hash_pdata_ux500 },
+ { .compatible = "st,stm32f456-hash", .data = &stm32_hash_pdata_stm32f4 },
+ { .compatible = "st,stm32f756-hash", .data = &stm32_hash_pdata_stm32f7 },
+ { .compatible = "st,stm32mp13-hash", .data = &stm32_hash_pdata_stm32mp13 },
{},
};

@@ -1548,12 +1970,6 @@ static int stm32_hash_get_of_match(struct stm32_hash_dev *hdev,
return -EINVAL;
}

- if (of_property_read_u32(dev->of_node, "dma-maxburst",
- &hdev->dma_maxburst)) {
- dev_info(dev, "dma-maxburst not specified, using 0\n");
- hdev->dma_maxburst = 0;
- }
-
return 0;
}

@@ -1663,7 +2079,7 @@ static int stm32_hash_probe(struct platform_device *pdev)
/* FIXME: implement DMA mode for Ux500 */
hdev->dma_mode = 0;
else
- hdev->dma_mode = stm32_hash_read(hdev, HASH_HWCFGR);
+ hdev->dma_mode = stm32_hash_read(hdev, HASH_HWCFGR) & HASH_HWCFG_DMA_MASK;

/* Register algos */
ret = stm32_hash_register_algs(hdev);
@@ -1772,6 +2188,6 @@ static struct platform_driver stm32_hash_driver = {

module_platform_driver(stm32_hash_driver);

-MODULE_DESCRIPTION("STM32 SHA1/224/256 & MD5 (HMAC) hw accelerator driver");
+MODULE_DESCRIPTION("STM32 SHA1/SHA2/SHA3 & MD5 (HMAC) hw accelerator driver");
MODULE_AUTHOR("Lionel Debieve <[email protected]>");
MODULE_LICENSE("GPL v2");
--
2.25.1


2023-07-06 07:51:56

by Thomas Bourgoin

[permalink] [raw]
Subject: [PATCH 7/7] crypto: stm32 - remove flag HASH_FLAGS_DMA_READY

From: Thomas Bourgoin <[email protected]>

Remove flag HASH_FLAGS_DMA_READY as it can put the driver in a deadlock
state.
If the DMA automatically set the DCAL bit, the interrupt indicating the
end of a computation can be raised before the DMA complete sequence.

Signed-off-by: Thomas Bourgoin <[email protected]>
---
drivers/crypto/stm32/stm32-hash.c | 21 ++++++++-------------
1 file changed, 8 insertions(+), 13 deletions(-)

diff --git a/drivers/crypto/stm32/stm32-hash.c b/drivers/crypto/stm32/stm32-hash.c
index 0b5e580efbba..a50d73c18d5c 100644
--- a/drivers/crypto/stm32/stm32-hash.c
+++ b/drivers/crypto/stm32/stm32-hash.c
@@ -84,12 +84,11 @@
#define HASH_FLAGS_INIT BIT(0)
#define HASH_FLAGS_OUTPUT_READY BIT(1)
#define HASH_FLAGS_CPU BIT(2)
-#define HASH_FLAGS_DMA_READY BIT(3)
-#define HASH_FLAGS_DMA_ACTIVE BIT(4)
-#define HASH_FLAGS_HMAC_INIT BIT(5)
-#define HASH_FLAGS_HMAC_FINAL BIT(6)
-#define HASH_FLAGS_HMAC_KEY BIT(7)
-#define HASH_FLAGS_SHA3_MODE BIT(8)
+#define HASH_FLAGS_DMA_ACTIVE BIT(3)
+#define HASH_FLAGS_HMAC_INIT BIT(4)
+#define HASH_FLAGS_HMAC_FINAL BIT(5)
+#define HASH_FLAGS_HMAC_KEY BIT(6)
+#define HASH_FLAGS_SHA3_MODE BIT(7)
#define HASH_FLAGS_FINAL BIT(15)
#define HASH_FLAGS_FINUP BIT(16)
#define HASH_FLAGS_ALGO_MASK GENMASK(20, 17)
@@ -585,8 +584,6 @@ static void stm32_hash_dma_callback(void *param)
struct stm32_hash_dev *hdev = param;

complete(&hdev->dma_completion);
-
- hdev->flags |= HASH_FLAGS_DMA_READY;
}

static int stm32_hash_hmac_dma_send(struct stm32_hash_dev *hdev)
@@ -1241,11 +1238,9 @@ static irqreturn_t stm32_hash_irq_thread(int irq, void *dev_id)
hdev->flags &= ~HASH_FLAGS_OUTPUT_READY;
goto finish;
}
- } else if (HASH_FLAGS_DMA_READY & hdev->flags) {
- if (HASH_FLAGS_DMA_ACTIVE & hdev->flags) {
- hdev->flags &= ~HASH_FLAGS_DMA_ACTIVE;
- goto finish;
- }
+ } else if (HASH_FLAGS_DMA_ACTIVE & hdev->flags) {
+ hdev->flags &= ~HASH_FLAGS_DMA_ACTIVE;
+ goto finish;
}

return IRQ_HANDLED;
--
2.25.1


2023-07-06 07:57:05

by Thomas Bourgoin

[permalink] [raw]
Subject: [PATCH 4/7] crypto: stm32 - fix loop iterating through scatterlist for DMA

From: Thomas Bourgoin <[email protected]>

We were reading the length of the scatterlist sg after copying value of
tsg inside.
So we are using the size of the previous scatterlist and for the first
one we are using an unitialised value.
Fix this by copying tsg in sg[0] before reading the size.

Signed-off-by: Thomas Bourgoin <[email protected]>
---
drivers/crypto/stm32/stm32-hash.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/crypto/stm32/stm32-hash.c b/drivers/crypto/stm32/stm32-hash.c
index 420df501360d..bc2651ef5208 100644
--- a/drivers/crypto/stm32/stm32-hash.c
+++ b/drivers/crypto/stm32/stm32-hash.c
@@ -678,9 +678,9 @@ static int stm32_hash_dma_send(struct stm32_hash_dev *hdev)
}

for_each_sg(rctx->sg, tsg, rctx->nents, i) {
+ sg[0] = *tsg;
len = sg->length;

- sg[0] = *tsg;
if (sg_is_last(sg)) {
if (hdev->dma_mode == 1) {
len = (ALIGN(sg->length, 16) - 16);
--
2.25.1


2023-07-06 07:57:46

by Thomas Bourgoin

[permalink] [raw]
Subject: [PATCH 6/7] crypto: stm32 - fix MDMAT condition

From: Thomas Bourgoin <[email protected]>

If IP has MDMAT support, set or reset the bit MDMAT in Control Register.

Fixes: b56403a25af7 ("crypto: stm32/hash - Support Ux500 hash")
Signed-off-by: Thomas Bourgoin <[email protected]>
---
drivers/crypto/stm32/stm32-hash.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/crypto/stm32/stm32-hash.c b/drivers/crypto/stm32/stm32-hash.c
index ee68e38b6e28..0b5e580efbba 100644
--- a/drivers/crypto/stm32/stm32-hash.c
+++ b/drivers/crypto/stm32/stm32-hash.c
@@ -544,7 +544,7 @@ static int stm32_hash_xmit_dma(struct stm32_hash_dev *hdev,

reg = stm32_hash_read(hdev, HASH_CR);

- if (!hdev->pdata->has_mdmat) {
+ if (hdev->pdata->has_mdmat) {
if (mdma)
reg |= HASH_CR_MDMAT;
else
--
2.25.1


2023-07-06 08:00:58

by Thomas Bourgoin

[permalink] [raw]
Subject: [PATCH 5/7] crypto: stm32 - check request size and scatterlist size when using DMA.

From: Thomas Bourgoin <[email protected]>

When we are sending the data to HASH with the DMA, we send all the data
provided in the scatterlists of the request.
But in some cases (ex : tcrypt performances tests), we should only send
req->nbytes
When iterating through the scatterlist we verify if it is the last
scatterlist or if the number of bytes sent plus the data of the current
scatterlist is superior of the total number of bytes to hash.

Signed-off-by: Thomas Bourgoin <[email protected]>
---
drivers/crypto/stm32/stm32-hash.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/drivers/crypto/stm32/stm32-hash.c b/drivers/crypto/stm32/stm32-hash.c
index bc2651ef5208..ee68e38b6e28 100644
--- a/drivers/crypto/stm32/stm32-hash.c
+++ b/drivers/crypto/stm32/stm32-hash.c
@@ -659,8 +659,9 @@ static int stm32_hash_dma_send(struct stm32_hash_dev *hdev)
struct stm32_hash_request_ctx *rctx = ahash_request_ctx(hdev->req);
u32 *buffer = (void *)rctx->state.buffer;
struct scatterlist sg[1], *tsg;
- int err = 0, len = 0, reg, ncp = 0;
- unsigned int i;
+ int err = 0, reg, ncp = 0;
+ unsigned int i, len = 0, bufcnt = 0;
+ bool is_last = false;

rctx->sg = hdev->req->src;
rctx->total = hdev->req->nbytes;
@@ -681,7 +682,9 @@ static int stm32_hash_dma_send(struct stm32_hash_dev *hdev)
sg[0] = *tsg;
len = sg->length;

- if (sg_is_last(sg)) {
+ if (sg_is_last(sg) || (bufcnt + sg[0].length) >= rctx->total) {
+ sg->length = rctx->total - bufcnt;
+ is_last = true;
if (hdev->dma_mode == 1) {
len = (ALIGN(sg->length, 16) - 16);

@@ -707,13 +710,15 @@ static int stm32_hash_dma_send(struct stm32_hash_dev *hdev)
return -ENOMEM;
}

- err = stm32_hash_xmit_dma(hdev, sg, len,
- !sg_is_last(sg));
+ err = stm32_hash_xmit_dma(hdev, sg, len, !is_last);

+ bufcnt += sg[0].length;
dma_unmap_sg(hdev->dev, sg, 1, DMA_TO_DEVICE);

if (err == -ENOMEM)
return err;
+ if (is_last)
+ break;
}

if (hdev->dma_mode == 1) {
--
2.25.1


2023-07-06 15:52:31

by Krzysztof Kozlowski

[permalink] [raw]
Subject: Re: [PATCH 1/7] dt-bindings: crypto: add new compatible for stm32-hash

On 06/07/2023 09:37, Thomas BOURGOIN wrote:
> From: Lionel Debieve <[email protected]>
>
> Add a new compatible for stm32mp13 support.
>
> Signed-off-by: Lionel Debieve <[email protected]>

Your SoB is missing.

Best regards,
Krzysztof


2023-07-06 21:46:18

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH 6/7] crypto: stm32 - fix MDMAT condition

On Thu, Jul 6, 2023 at 9:39 AM Thomas BOURGOIN
<[email protected]> wrote:

> From: Thomas Bourgoin <[email protected]>
>
> If IP has MDMAT support, set or reset the bit MDMAT in Control Register.
>
> Fixes: b56403a25af7 ("crypto: stm32/hash - Support Ux500 hash")
> Signed-off-by: Thomas Bourgoin <[email protected]>

Oops probably my fault.
Reviewed-by: Linus Walleij <[email protected]>

This should probably be applied for fixes/stable.

Yours,
Linus Walleij

2023-07-06 22:21:53

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH 2/7] crypto: stm32 - add new algorithms support

Hi Thomas,

thanks for your patch! I overall like the looks of
the end result.

On Thu, Jul 6, 2023 at 9:38 AM Thomas BOURGOIN
<[email protected]> wrote:

> From: Thomas Bourgoin <[email protected]>
>
> Add the all SHA-2 (up to 512) and SHA-3 algorithm support.
> Update compatible table to add stm32mp13.
>
> Signed-off-by: Thomas Bourgoin <[email protected]>

I testes to apply this and boot the Skomer (U8500, Samsung
GT-S7710) This patch regresses the ux500 hash like this:

[ 3.612426] stm32-hash a03c2000.hash: allocated hmac(sha256) fallback
[ 4.236755] stm32-hash a03c2000.hash: allocated sha256 fallback
[ 4.269287] alg: ahash: stm32-sha256 test failed (wrong result) on
test vector 4, cfg="init+update+final aligned buffer"
[ 4.280273] alg: self-tests for sha256 using stm32-sha256 failed (rc=-22)
[ 4.280273] ------------[ cut here ]------------
[ 4.291748] WARNING: CPU: 0 PID: 100 at crypto/testmgr.c:5936
alg_test.part.0+0x4d0/0x4e0
[ 4.299987] alg: self-tests for sha256 using stm32-sha256 failed (rc=-22)
[ 4.299987] Modules linked in:
[ 4.309906] CPU: 0 PID: 100 Comm: cryptomgr_test Not tainted
6.4.0-rc1-00014-g3c85f4ad9472 #274
[ 4.318603] Hardware name: ST-Ericsson Ux5x0 platform (Device Tree Support)
[ 4.325561] unwind_backtrace from show_stack+0x10/0x14
[ 4.330810] show_stack from dump_stack_lvl+0x40/0x4c
[ 4.335876] dump_stack_lvl from __warn+0x94/0xc0
[ 4.340606] __warn from warn_slowpath_fmt+0x118/0x164
[ 4.345733] warn_slowpath_fmt from alg_test.part.0+0x4d0/0x4e0
[ 4.351684] alg_test.part.0 from cryptomgr_test+0x18/0x38
[ 4.357177] cryptomgr_test from kthread+0xd0/0xd4
[ 4.361968] kthread from ret_from_fork+0x14/0x2c
[ 4.366668] Exception stack(0xf0df5fb0 to 0xf0df5ff8)
[ 4.371734] 5fa0: 00000000
00000000 00000000 00000000
[ 4.379913] 5fc0: 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000
[ 4.388061] 5fe0: 00000000 00000000 00000000 00000000 00000013 00000000
[ 4.394744] ---[ end trace 0000000000000000 ]---
[ 4.669372] stm32-hash a03c2000.hash: allocated hmac(sha1) fallback
[ 5.131622] stm32-hash a03c2000.hash: allocated sha1 fallback
[ 5.156005] alg: ahash: stm32-sha1 test failed (wrong result) on
test vector 3, cfg="init+update+final aligned buffer"
[ 5.166778] alg: self-tests for sha1 using stm32-sha1 failed (rc=-22)
[ 5.166778] ------------[ cut here ]------------
[ 5.177947] WARNING: CPU: 0 PID: 115 at crypto/testmgr.c:5936
alg_test.part.0+0x4d0/0x4e0
[ 5.186187] alg: self-tests for sha1 using stm32-sha1 failed (rc=-22)
[ 5.186187] Modules linked in:
[ 5.195739] CPU: 0 PID: 115 Comm: cryptomgr_test Tainted: G
W 6.4.0-rc1-00014-g3c85f4ad9472 #274
[ 5.205902] Hardware name: ST-Ericsson Ux5x0 platform (Device Tree Support)
[ 5.212860] unwind_backtrace from show_stack+0x10/0x14
[ 5.218109] show_stack from dump_stack_lvl+0x40/0x4c
[ 5.223175] dump_stack_lvl from __warn+0x94/0xc0
[ 5.227874] __warn from warn_slowpath_fmt+0x118/0x164
[ 5.233032] warn_slowpath_fmt from alg_test.part.0+0x4d0/0x4e0
[ 5.238952] alg_test.part.0 from cryptomgr_test+0x18/0x38
[ 5.244445] cryptomgr_test from kthread+0xd0/0xd4
[ 5.249267] kthread from ret_from_fork+0x14/0x2c
[ 5.253967] Exception stack(0xf0f21fb0 to 0xf0f21ff8)
[ 5.259002] 1fa0: 00000000
00000000 00000000 00000000
[ 5.267181] 1fc0: 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000
[ 5.275360] 1fe0: 00000000 00000000 00000000 00000000 00000013 00000000
[ 5.282012] ---[ end trace 0000000000000000 ]---

This worked before the patch (verified).

> drivers/crypto/stm32/Kconfig | 2 +
> drivers/crypto/stm32/stm32-hash.c | 666 ++++++++++++++++++++++++------

The patch is a bit big so it is hard to see the problem, do you
think you can break it into increments?

Yours,
Linus Walleij

2023-07-12 08:04:04

by Thomas Bourgoin

[permalink] [raw]
Subject: Re: [PATCH 2/7] crypto: stm32 - add new algorithms support

Hi Linus,

Did you run your test only with the patch adding the support for
STM32MP13 or did you try the whole patch set ?

The error is on the test vector number 4, which is an HASH of 64 bytes
which is exactly the size of a blcok for SHA1.

Did you try to run the test for SHA256 ? (I guess you will see the same
error on test vector 4)

I have two hypothesis :
- it could be related to the padding of the data. (I don't think, the
patch does not modify these lines)
- it could come from the way the first block of data is handle. To
start the first pre computation, we have to write 1 block + 1 word. The
test only write one block so maybe the issue is here.

On 7/6/23 09:37, Thomas BOURGOIN wrote:
> + /*
> + * After first block + 1 words are fill up,
> + * we only need to fill 1 block to start partial computation
> + */
> + rctx->state.blocklen -= sizeof(u32);
> +

I found a typo in the number of CSR to save/restore for the SHA1 and
SHA256 algorithm. It should be 38 instead of 22.
Tell me if it fixes the regression.

It could be possible to divide the patch in 2 (one patch rework
preparing MP13 and one patch with the new algorithm) but for the
upstream I do not know if it is relevant to have 2 patches instead of one.

Best regards,

Thomas

---
drivers/crypto/stm32/stm32-hash.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/crypto/stm32/stm32-hash.c
b/drivers/crypto/stm32/stm32-hash.c
index a50d73c18d5c..88a186c3dd78 100644
--- a/drivers/crypto/stm32/stm32-hash.c
+++ b/drivers/crypto/stm32/stm32-hash.c
@@ -74,7 +74,7 @@

/* Context swap register */
#define HASH_CSR_NB_SHA256_HMAC 54
-#define HASH_CSR_NB_SHA256 22
+#define HASH_CSR_NB_SHA256 38
#define HASH_CSR_NB_SHA512_HMAC 103
#define HASH_CSR_NB_SHA512 91
#define HASH_CSR_NB_SHA3_HMAC 88
--
2.25.1



2023-07-12 23:03:25

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH 2/7] crypto: stm32 - add new algorithms support

On Wed, Jul 12, 2023 at 9:58 AM Thomas BOURGOIN
<[email protected]> wrote:

> Did you run your test only with the patch adding the support for
> STM32MP13 or did you try the whole patch set ?

Both, actually.

> The error is on the test vector number 4, which is an HASH of 64 bytes
> which is exactly the size of a blcok for SHA1.
>
> Did you try to run the test for SHA256 ? (I guess you will see the same
> error on test vector 4)

Yes... I posted a log with both SHA256 and SHA1.

> I found a typo in the number of CSR to save/restore for the SHA1 and
> SHA256 algorithm. It should be 38 instead of 22.
> Tell me if it fixes the regression.

Yes this fixes the bug and the tests pass fine :)
I wonder why SHA1 was affected? Same codepath?

> It could be possible to divide the patch in 2 (one patch rework
> preparing MP13 and one patch with the new algorithm) but for the
> upstream I do not know if it is relevant to have 2 patches instead of one.

The major point of splitting patches to "one technical step" is to be
able to do fine-grained git bisect to find bugs such as this one :D
But admittedly the defintion of "techical step" is a bit fuzzy.

Yours,
Linus Walleij

2023-07-13 08:09:09

by Thomas Bourgoin

[permalink] [raw]
Subject: Re: [PATCH 2/7] crypto: stm32 - add new algorithms support

Hi Linus,

On 7/13/23 00:56, Linus Walleij wrote:
> Yes this fixes the bug and the tests pass fine ????

Great news

> I wonder why SHA1 was affected? Same codepath?

Yes the number of CSR to save is the same for SHA256 and SHA1. You can
look at the 'Context swapping' chapter (47.3.3) in the reference manual
for UX500. There is a note at the end telling that you do not have to
save all 54 register if you do HASH operation, only 38 are necessary :
> If the context swap does not involve HMAC operations, registers
cs_rk0 to cs_rk7 and
> cs_rh0 to cs_rh7 can be ignored
Best regards,

Thomas