2021-09-24 09:29:22

by yekai (A)

[permalink] [raw]
Subject: [PATCH v2 0/6] crypto: hisilicon - supports hash algorithm for SEC engine

The driver adds hash algorithms,
sm3, md5, sha1, sha256, sha512.
Add fallback tfm supporting. Modify the driver
as needed. The fuzzing test has been passed.

changes v1->v2:
1. Modify the process of export and import. Using the ahash_req as
hash state. By copying the content of structure sec_ahash_req to
avoid dereferencing random pointers from import path. User can
export the hash state and then import the hash state, and it
still work.
2. Add sm3/md5 generic selection

Kai Ye (6):
crypto: hisilicon/sec - add ping-pong buffer for ahash
crypto: hisilicon/sec - add ahash alg features for Kunpeng920
crypto: hisilicon/sec - support the larger packets for digest mode
crypto: hisilicon/sec - ahash adapt to Kunpeng930 SQE
crypto: hisilicon/sec - add fallback tfm supporting for ahash
crypto: hisilicon/sec - add sm3/md5 generic selection for ahash

drivers/crypto/hisilicon/Kconfig | 2 +
drivers/crypto/hisilicon/sec2/sec.h | 52 +-
drivers/crypto/hisilicon/sec2/sec_crypto.c | 1323 +++++++++++++++++++-
drivers/crypto/hisilicon/sec2/sec_crypto.h | 9 +
4 files changed, 1369 insertions(+), 17 deletions(-)

--
2.33.0


2021-09-24 09:29:22

by yekai (A)

[permalink] [raw]
Subject: [PATCH v2 5/6] crypto: hisilicon/sec - add fallback tfm supporting for ahash

1. The Kunpeng920 hardware not supports 0 packet size for digest mode.
2. The hardware only supports 4-byte alignment key inputing.
Due to the above hardware limitations, So the driver needs
to setting the soft fallback hash tfm for user.

Signed-off-by: Kai Ye <[email protected]>
---
drivers/crypto/hisilicon/sec2/sec.h | 2 +
drivers/crypto/hisilicon/sec2/sec_crypto.c | 106 +++++++++++++++++++++
2 files changed, 108 insertions(+)

diff --git a/drivers/crypto/hisilicon/sec2/sec.h b/drivers/crypto/hisilicon/sec2/sec.h
index 2713a08e7053..da4e14734747 100644
--- a/drivers/crypto/hisilicon/sec2/sec.h
+++ b/drivers/crypto/hisilicon/sec2/sec.h
@@ -129,6 +129,8 @@ struct sec_auth_ctx {
*/
char metamac_idx[SEC_MAX_STREAMS];
struct crypto_shash *hash_tfm;
+ /* Alloc soft hash tfm for not support parameter */
+ struct crypto_shash *fallback_ahash_tfm;
struct shash_desc *desc;
struct crypto_aead *fallback_aead_tfm;
};
diff --git a/drivers/crypto/hisilicon/sec2/sec_crypto.c b/drivers/crypto/hisilicon/sec2/sec_crypto.c
index f52862ab0f96..52839223e8f5 100644
--- a/drivers/crypto/hisilicon/sec2/sec_crypto.c
+++ b/drivers/crypto/hisilicon/sec2/sec_crypto.c
@@ -1224,6 +1224,18 @@ static int sec_ahash_set_key(struct crypto_ahash *tfm, const u8 *key,
struct crypto_shash *shash_tfm = a_ctx->hash_tfm;
int blocksize, ret, digestsize;

+ a_ctx->fallback = false;
+ ret = crypto_shash_setkey(a_ctx->fallback_ahash_tfm, key, keylen);
+ if (ret) {
+ pr_err("hisi_sec2: fallback shash set key error!\n");
+ return ret;
+ }
+
+ if (keylen & WORD_ALIGNMENT_MASK) {
+ a_ctx->fallback = true;
+ return 0;
+ }
+
blocksize = crypto_shash_blocksize(shash_tfm);
digestsize = crypto_shash_digestsize(shash_tfm);
if (keylen > blocksize) {
@@ -2575,6 +2587,8 @@ static int sec_ahash_req_init(struct ahash_request *req)
int sid;

sreq->ctx = ctx;
+ if (unlikely(a_ctx->fallback))
+ return crypto_shash_init(a_ctx->desc);

tfm_alg_name = tfm->base.__crt_alg->cra_name;
a_ctx->mac_len = crypto_ahash_digestsize(tfm);
@@ -2746,6 +2760,27 @@ static int sec_ahash_process(struct ahash_request *req)
return ctx->req_op->process(ctx, sreq);
}

+static int sec_shash_update(struct ahash_request *req, struct sec_auth_ctx *ctx)
+{
+ int nents = sg_nents(req->src);
+ int total_sgl_len = 0;
+ struct scatterlist *sg;
+ int ret, i;
+
+ for_each_sg(req->src, sg, nents, i) {
+ ret = crypto_shash_update(ctx->desc, sg_virt(sg), sg->length);
+ if (ret) {
+ pr_err("ahash use fallback ahash is error!\n");
+ return ret;
+ }
+ total_sgl_len += sg->length;
+ if (total_sgl_len == req->nbytes)
+ break;
+ }
+
+ return 0;
+}
+
static int sec_ahash_update(struct ahash_request *req)
{
struct sec_req *sreq = ahash_request_ctx(req);
@@ -2757,6 +2792,9 @@ static int sec_ahash_update(struct ahash_request *req)
u32 data_len;
u8 idx;

+ if (unlikely(a_ctx->fallback))
+ return sec_shash_update(req, a_ctx);
+
if (unlikely(req->nbytes > SEC_HW_MAX_LEN)) {
dev_err_ratelimited(ctx->dev, "too long input for updating!\n");
return -EINVAL;
@@ -2800,6 +2838,9 @@ static int sec_ahash_final(struct ahash_request *req)
u32 sid = sareq->sid;
u8 idx;

+ if (unlikely(a_ctx->fallback))
+ return crypto_shash_final(a_ctx->desc, req->result);
+
sareq->op = SEC_SHA_FINAL;
if (sareq->is_stream_mode) {
idx = ctx->pingpong_idx[sid];
@@ -2826,6 +2867,20 @@ static int sec_ahash_finup(struct ahash_request *req)
int i = 0;
int ret;

+ if (unlikely(a_ctx->fallback)) {
+ for_each_sg(req->src, sg, nents, i) {
+ if (i + 1 == sg_nents(req->src))
+ return crypto_shash_finup(a_ctx->desc, sg_virt(sg),
+ sg->length, req->result);
+
+ ret = crypto_shash_update(a_ctx->desc, sg_virt(sg), sg->length);
+ if (ret) {
+ pr_err("ahash use fallback ahash is error!\n");
+ return ret;
+ }
+ }
+ }
+
if (sareq->op == SEC_SHA_UPDATE) {
if (unlikely(req->nbytes > SEC_HW_MAX_LEN)) {
dev_err_ratelimited(ctx->dev, "too long input for update+finup!\n");
@@ -2940,6 +2995,23 @@ static int sec_ahash_digest(struct ahash_request *req)
if (req->nbytes > SEC_HW_MAX_LEN)
return sec_ahash_larger_digest(req);

+ /* Kunpeng 920, digest mode not support input 0 size */
+ if (unlikely(ctx->type_supported == SEC_BD_TYPE2 && !req->nbytes))
+ return crypto_shash_digest(a_ctx->desc, sg_virt(req->src), 0,
+ req->result);
+
+ if (unlikely(a_ctx->fallback)) {
+ for_each_sg(req->src, sg, nents, i) {
+ ret = crypto_shash_update(a_ctx->desc, sg_virt(sg),
+ sg->length);
+ if (ret) {
+ pr_err("ahash use fallback ahash is error!\n");
+ return ret;
+ }
+ }
+
+ return crypto_shash_final(a_ctx->desc, req->result);
+ }
sareq->op = SEC_SHA_DIGEST;

return sec_ahash_finup(req);
@@ -2978,6 +3050,40 @@ static int sec_ahash_import(struct ahash_request *req, const void *in)
return 0;
}

+static void sec_release_fallback_shash(struct crypto_shash *tfm,
+ struct shash_desc *desc)
+{
+ crypto_free_shash(tfm);
+ kfree(desc);
+}
+
+static int sec_alloc_fallback_shash(const char *driver,
+ struct crypto_shash **tfm_ret,
+ struct shash_desc **desc_ret)
+{
+ struct crypto_shash *tfm;
+ struct shash_desc *desc;
+ int ret;
+
+ tfm = crypto_alloc_shash(driver, 0, CRYPTO_ALG_NEED_FALLBACK);
+ if (IS_ERR(tfm)) {
+ pr_err("ahash driver alloc hmac shash error!\n");
+ ret = PTR_ERR(tfm);
+ return ret;
+ }
+ desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(tfm), GFP_KERNEL);
+ if (!desc) {
+ crypto_free_shash(tfm);
+ return -ENOMEM;
+ }
+ desc->tfm = tfm;
+
+ *tfm_ret = tfm;
+ *desc_ret = desc;
+
+ return 0;
+}
+
static void sec_ahash_tfm_uninit(struct crypto_tfm *tfm)
{
struct sec_ctx *ctx = crypto_tfm_ctx(tfm);
--
2.33.0