]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
crypto: tegra - Transfer HASH init function to crypto engine
authorAkhil R <akhilrajeev@nvidia.com>
Mon, 24 Feb 2025 09:16:05 +0000 (14:46 +0530)
committerHerbert Xu <herbert@gondor.apana.org.au>
Sat, 8 Mar 2025 08:22:24 +0000 (16:22 +0800)
Ahash init() function was called asynchronous to the crypto engine queue.
This could corrupt the request context if there is any ongoing operation
for the same request. Queue the init function as well to the crypto
engine queue so that this scenario can be avoided.

Fixes: 0880bb3b00c8 ("crypto: tegra - Add Tegra Security Engine driver")
Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/tegra/tegra-se-aes.c
drivers/crypto/tegra/tegra-se-hash.c
drivers/crypto/tegra/tegra-se.h

index 5ca7996ecc6da283bc5fe97ea3b75d53c4acda5b..13d76de2bc81ca9ad4577da1ab38f070869daac0 100644 (file)
@@ -1459,6 +1459,34 @@ static void tegra_cmac_paste_result(struct tegra_se *se, struct tegra_cmac_reqct
                       se->base + se->hw->regs->result + (i * 4));
 }
 
+static int tegra_cmac_do_init(struct ahash_request *req)
+{
+       struct tegra_cmac_reqctx *rctx = ahash_request_ctx(req);
+       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+       struct tegra_cmac_ctx *ctx = crypto_ahash_ctx(tfm);
+       struct tegra_se *se = ctx->se;
+       int i;
+
+       rctx->total_len = 0;
+       rctx->datbuf.size = 0;
+       rctx->residue.size = 0;
+       rctx->task |= SHA_FIRST;
+       rctx->blk_size = crypto_ahash_blocksize(tfm);
+
+       rctx->residue.buf = dma_alloc_coherent(se->dev, rctx->blk_size * 2,
+                                              &rctx->residue.addr, GFP_KERNEL);
+       if (!rctx->residue.buf)
+               return -ENOMEM;
+
+       rctx->residue.size = 0;
+
+       /* Clear any previous result */
+       for (i = 0; i < CMAC_RESULT_REG_COUNT; i++)
+               writel(0, se->base + se->hw->regs->result + (i * 4));
+
+       return 0;
+}
+
 static int tegra_cmac_do_update(struct ahash_request *req)
 {
        struct tegra_cmac_reqctx *rctx = ahash_request_ctx(req);
@@ -1604,6 +1632,14 @@ static int tegra_cmac_do_one_req(struct crypto_engine *engine, void *areq)
        struct tegra_se *se = ctx->se;
        int ret = 0;
 
+       if (rctx->task & SHA_INIT) {
+               ret = tegra_cmac_do_init(req);
+               if (ret)
+                       goto out;
+
+               rctx->task &= ~SHA_INIT;
+       }
+
        if (rctx->task & SHA_UPDATE) {
                ret = tegra_cmac_do_update(req);
                if (ret)
@@ -1684,34 +1720,6 @@ static void tegra_cmac_cra_exit(struct crypto_tfm *tfm)
        tegra_key_invalidate(ctx->se, ctx->key_id, ctx->alg);
 }
 
-static int tegra_cmac_init(struct ahash_request *req)
-{
-       struct tegra_cmac_reqctx *rctx = ahash_request_ctx(req);
-       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
-       struct tegra_cmac_ctx *ctx = crypto_ahash_ctx(tfm);
-       struct tegra_se *se = ctx->se;
-       int i;
-
-       rctx->total_len = 0;
-       rctx->datbuf.size = 0;
-       rctx->residue.size = 0;
-       rctx->task = SHA_FIRST;
-       rctx->blk_size = crypto_ahash_blocksize(tfm);
-
-       rctx->residue.buf = dma_alloc_coherent(se->dev, rctx->blk_size * 2,
-                                              &rctx->residue.addr, GFP_KERNEL);
-       if (!rctx->residue.buf)
-               return -ENOMEM;
-
-       rctx->residue.size = 0;
-
-       /* Clear any previous result */
-       for (i = 0; i < CMAC_RESULT_REG_COUNT; i++)
-               writel(0, se->base + se->hw->regs->result + (i * 4));
-
-       return 0;
-}
-
 static int tegra_cmac_setkey(struct crypto_ahash *tfm, const u8 *key,
                             unsigned int keylen)
 {
@@ -1728,6 +1736,17 @@ static int tegra_cmac_setkey(struct crypto_ahash *tfm, const u8 *key,
        return tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id);
 }
 
+static int tegra_cmac_init(struct ahash_request *req)
+{
+       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+       struct tegra_cmac_ctx *ctx = crypto_ahash_ctx(tfm);
+       struct tegra_cmac_reqctx *rctx = ahash_request_ctx(req);
+
+       rctx->task = SHA_INIT;
+
+       return crypto_transfer_hash_request_to_engine(ctx->se->engine, req);
+}
+
 static int tegra_cmac_update(struct ahash_request *req)
 {
        struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
@@ -1766,13 +1785,9 @@ static int tegra_cmac_digest(struct ahash_request *req)
        struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
        struct tegra_cmac_ctx *ctx = crypto_ahash_ctx(tfm);
        struct tegra_cmac_reqctx *rctx = ahash_request_ctx(req);
-       int ret;
 
-       ret = tegra_cmac_init(req);
-       if (ret)
-               return ret;
+       rctx->task |= SHA_INIT | SHA_UPDATE | SHA_FINAL;
 
-       rctx->task |= SHA_UPDATE | SHA_FINAL;
        return crypto_transfer_hash_request_to_engine(ctx->se->engine, req);
 }
 
index 0ae5ce67bdd047164f1dfce644899340c9224ff3..07e4c7320ec8d913022c7a903ddc3f911fd5602c 100644 (file)
@@ -296,6 +296,44 @@ static void tegra_sha_paste_hash_result(struct tegra_se *se, struct tegra_sha_re
                       se->base + se->hw->regs->result + (i * 4));
 }
 
+static int tegra_sha_do_init(struct ahash_request *req)
+{
+       struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
+       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+       struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
+       struct tegra_se *se = ctx->se;
+
+       if (ctx->fallback)
+               return tegra_sha_fallback_init(req);
+
+       rctx->total_len = 0;
+       rctx->datbuf.size = 0;
+       rctx->residue.size = 0;
+       rctx->key_id = ctx->key_id;
+       rctx->task |= SHA_FIRST;
+       rctx->alg = ctx->alg;
+       rctx->blk_size = crypto_ahash_blocksize(tfm);
+       rctx->digest.size = crypto_ahash_digestsize(tfm);
+
+       rctx->digest.buf = dma_alloc_coherent(se->dev, rctx->digest.size,
+                                             &rctx->digest.addr, GFP_KERNEL);
+       if (!rctx->digest.buf)
+               goto digbuf_fail;
+
+       rctx->residue.buf = dma_alloc_coherent(se->dev, rctx->blk_size,
+                                              &rctx->residue.addr, GFP_KERNEL);
+       if (!rctx->residue.buf)
+               goto resbuf_fail;
+
+       return 0;
+
+resbuf_fail:
+       dma_free_coherent(se->dev, rctx->digest.size, rctx->digest.buf,
+                         rctx->digest.addr);
+digbuf_fail:
+       return -ENOMEM;
+}
+
 static int tegra_sha_do_update(struct ahash_request *req)
 {
        struct tegra_sha_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
@@ -435,6 +473,14 @@ static int tegra_sha_do_one_req(struct crypto_engine *engine, void *areq)
        struct tegra_se *se = ctx->se;
        int ret = 0;
 
+       if (rctx->task & SHA_INIT) {
+               ret = tegra_sha_do_init(req);
+               if (ret)
+                       goto out;
+
+               rctx->task &= ~SHA_INIT;
+       }
+
        if (rctx->task & SHA_UPDATE) {
                ret = tegra_sha_do_update(req);
                if (ret)
@@ -525,44 +571,6 @@ static void tegra_sha_cra_exit(struct crypto_tfm *tfm)
        tegra_key_invalidate(ctx->se, ctx->key_id, ctx->alg);
 }
 
-static int tegra_sha_init(struct ahash_request *req)
-{
-       struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
-       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
-       struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
-       struct tegra_se *se = ctx->se;
-
-       if (ctx->fallback)
-               return tegra_sha_fallback_init(req);
-
-       rctx->total_len = 0;
-       rctx->datbuf.size = 0;
-       rctx->residue.size = 0;
-       rctx->key_id = ctx->key_id;
-       rctx->task = SHA_FIRST;
-       rctx->alg = ctx->alg;
-       rctx->blk_size = crypto_ahash_blocksize(tfm);
-       rctx->digest.size = crypto_ahash_digestsize(tfm);
-
-       rctx->digest.buf = dma_alloc_coherent(se->dev, rctx->digest.size,
-                                             &rctx->digest.addr, GFP_KERNEL);
-       if (!rctx->digest.buf)
-               goto digbuf_fail;
-
-       rctx->residue.buf = dma_alloc_coherent(se->dev, rctx->blk_size,
-                                              &rctx->residue.addr, GFP_KERNEL);
-       if (!rctx->residue.buf)
-               goto resbuf_fail;
-
-       return 0;
-
-resbuf_fail:
-       dma_free_coherent(se->dev, rctx->digest.size, rctx->digest.buf,
-                         rctx->digest.addr);
-digbuf_fail:
-       return -ENOMEM;
-}
-
 static int tegra_hmac_fallback_setkey(struct tegra_sha_ctx *ctx, const u8 *key,
                                      unsigned int keylen)
 {
@@ -588,6 +596,17 @@ static int tegra_hmac_setkey(struct crypto_ahash *tfm, const u8 *key,
        return tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id);
 }
 
+static int tegra_sha_init(struct ahash_request *req)
+{
+       struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
+       struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+       struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
+
+       rctx->task = SHA_INIT;
+
+       return crypto_transfer_hash_request_to_engine(ctx->se->engine, req);
+}
+
 static int tegra_sha_update(struct ahash_request *req)
 {
        struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
@@ -635,16 +654,12 @@ static int tegra_sha_digest(struct ahash_request *req)
        struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
        struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
        struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
-       int ret;
 
        if (ctx->fallback)
                return tegra_sha_fallback_digest(req);
 
-       ret = tegra_sha_init(req);
-       if (ret)
-               return ret;
+       rctx->task |= SHA_INIT | SHA_UPDATE | SHA_FINAL;
 
-       rctx->task |= SHA_UPDATE | SHA_FINAL;
        return crypto_transfer_hash_request_to_engine(ctx->se->engine, req);
 }
 
index e196a90eedb92c077c72dc5acd6c359af364d42b..e1ec37bfb80a8cb034b2a5edf92727ea0d50fa14 100644 (file)
 #define SE_MAX_MEM_ALLOC                       SZ_4M
 
 #define SHA_FIRST      BIT(0)
-#define SHA_UPDATE     BIT(1)
-#define SHA_FINAL      BIT(2)
+#define SHA_INIT       BIT(1)
+#define SHA_UPDATE     BIT(2)
+#define SHA_FINAL      BIT(3)
 
 /* Security Engine operation modes */
 enum se_aes_alg {