Skip to content

Commit ce065c4

Browse files
akhilr-nvgregkh
authored andcommitted
crypto: tegra - Transfer HASH init function to crypto engine
[ Upstream commit 97ee15e ] 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: 0880bb3 ("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> Stable-dep-of: 2aeec9a ("crypto: tegra - Disable softirqs before finalizing request") Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 23f03eb commit ce065c4

3 files changed

Lines changed: 109 additions & 78 deletions

File tree

drivers/crypto/tegra/tegra-se-aes.c

Lines changed: 48 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1460,6 +1460,34 @@ static void tegra_cmac_paste_result(struct tegra_se *se, struct tegra_cmac_reqct
14601460
se->base + se->hw->regs->result + (i * 4));
14611461
}
14621462

1463+
static int tegra_cmac_do_init(struct ahash_request *req)
1464+
{
1465+
struct tegra_cmac_reqctx *rctx = ahash_request_ctx(req);
1466+
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
1467+
struct tegra_cmac_ctx *ctx = crypto_ahash_ctx(tfm);
1468+
struct tegra_se *se = ctx->se;
1469+
int i;
1470+
1471+
rctx->total_len = 0;
1472+
rctx->datbuf.size = 0;
1473+
rctx->residue.size = 0;
1474+
rctx->task |= SHA_FIRST;
1475+
rctx->blk_size = crypto_ahash_blocksize(tfm);
1476+
1477+
rctx->residue.buf = dma_alloc_coherent(se->dev, rctx->blk_size * 2,
1478+
&rctx->residue.addr, GFP_KERNEL);
1479+
if (!rctx->residue.buf)
1480+
return -ENOMEM;
1481+
1482+
rctx->residue.size = 0;
1483+
1484+
/* Clear any previous result */
1485+
for (i = 0; i < CMAC_RESULT_REG_COUNT; i++)
1486+
writel(0, se->base + se->hw->regs->result + (i * 4));
1487+
1488+
return 0;
1489+
}
1490+
14631491
static int tegra_cmac_do_update(struct ahash_request *req)
14641492
{
14651493
struct tegra_cmac_reqctx *rctx = ahash_request_ctx(req);
@@ -1605,6 +1633,14 @@ static int tegra_cmac_do_one_req(struct crypto_engine *engine, void *areq)
16051633
struct tegra_se *se = ctx->se;
16061634
int ret = 0;
16071635

1636+
if (rctx->task & SHA_INIT) {
1637+
ret = tegra_cmac_do_init(req);
1638+
if (ret)
1639+
goto out;
1640+
1641+
rctx->task &= ~SHA_INIT;
1642+
}
1643+
16081644
if (rctx->task & SHA_UPDATE) {
16091645
ret = tegra_cmac_do_update(req);
16101646
if (ret)
@@ -1685,34 +1721,6 @@ static void tegra_cmac_cra_exit(struct crypto_tfm *tfm)
16851721
tegra_key_invalidate(ctx->se, ctx->key_id, ctx->alg);
16861722
}
16871723

1688-
static int tegra_cmac_init(struct ahash_request *req)
1689-
{
1690-
struct tegra_cmac_reqctx *rctx = ahash_request_ctx(req);
1691-
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
1692-
struct tegra_cmac_ctx *ctx = crypto_ahash_ctx(tfm);
1693-
struct tegra_se *se = ctx->se;
1694-
int i;
1695-
1696-
rctx->total_len = 0;
1697-
rctx->datbuf.size = 0;
1698-
rctx->residue.size = 0;
1699-
rctx->task = SHA_FIRST;
1700-
rctx->blk_size = crypto_ahash_blocksize(tfm);
1701-
1702-
rctx->residue.buf = dma_alloc_coherent(se->dev, rctx->blk_size * 2,
1703-
&rctx->residue.addr, GFP_KERNEL);
1704-
if (!rctx->residue.buf)
1705-
return -ENOMEM;
1706-
1707-
rctx->residue.size = 0;
1708-
1709-
/* Clear any previous result */
1710-
for (i = 0; i < CMAC_RESULT_REG_COUNT; i++)
1711-
writel(0, se->base + se->hw->regs->result + (i * 4));
1712-
1713-
return 0;
1714-
}
1715-
17161724
static int tegra_cmac_setkey(struct crypto_ahash *tfm, const u8 *key,
17171725
unsigned int keylen)
17181726
{
@@ -1729,6 +1737,17 @@ static int tegra_cmac_setkey(struct crypto_ahash *tfm, const u8 *key,
17291737
return tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id);
17301738
}
17311739

1740+
static int tegra_cmac_init(struct ahash_request *req)
1741+
{
1742+
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
1743+
struct tegra_cmac_ctx *ctx = crypto_ahash_ctx(tfm);
1744+
struct tegra_cmac_reqctx *rctx = ahash_request_ctx(req);
1745+
1746+
rctx->task = SHA_INIT;
1747+
1748+
return crypto_transfer_hash_request_to_engine(ctx->se->engine, req);
1749+
}
1750+
17321751
static int tegra_cmac_update(struct ahash_request *req)
17331752
{
17341753
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
@@ -1767,13 +1786,9 @@ static int tegra_cmac_digest(struct ahash_request *req)
17671786
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
17681787
struct tegra_cmac_ctx *ctx = crypto_ahash_ctx(tfm);
17691788
struct tegra_cmac_reqctx *rctx = ahash_request_ctx(req);
1770-
int ret;
17711789

1772-
ret = tegra_cmac_init(req);
1773-
if (ret)
1774-
return ret;
1790+
rctx->task |= SHA_INIT | SHA_UPDATE | SHA_FINAL;
17751791

1776-
rctx->task |= SHA_UPDATE | SHA_FINAL;
17771792
return crypto_transfer_hash_request_to_engine(ctx->se->engine, req);
17781793
}
17791794

drivers/crypto/tegra/tegra-se-hash.c

Lines changed: 58 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,44 @@ static void tegra_sha_paste_hash_result(struct tegra_se *se, struct tegra_sha_re
296296
se->base + se->hw->regs->result + (i * 4));
297297
}
298298

299+
static int tegra_sha_do_init(struct ahash_request *req)
300+
{
301+
struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
302+
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
303+
struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
304+
struct tegra_se *se = ctx->se;
305+
306+
if (ctx->fallback)
307+
return tegra_sha_fallback_init(req);
308+
309+
rctx->total_len = 0;
310+
rctx->datbuf.size = 0;
311+
rctx->residue.size = 0;
312+
rctx->key_id = ctx->key_id;
313+
rctx->task |= SHA_FIRST;
314+
rctx->alg = ctx->alg;
315+
rctx->blk_size = crypto_ahash_blocksize(tfm);
316+
rctx->digest.size = crypto_ahash_digestsize(tfm);
317+
318+
rctx->digest.buf = dma_alloc_coherent(se->dev, rctx->digest.size,
319+
&rctx->digest.addr, GFP_KERNEL);
320+
if (!rctx->digest.buf)
321+
goto digbuf_fail;
322+
323+
rctx->residue.buf = dma_alloc_coherent(se->dev, rctx->blk_size,
324+
&rctx->residue.addr, GFP_KERNEL);
325+
if (!rctx->residue.buf)
326+
goto resbuf_fail;
327+
328+
return 0;
329+
330+
resbuf_fail:
331+
dma_free_coherent(se->dev, rctx->digest.size, rctx->digest.buf,
332+
rctx->digest.addr);
333+
digbuf_fail:
334+
return -ENOMEM;
335+
}
336+
299337
static int tegra_sha_do_update(struct ahash_request *req)
300338
{
301339
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)
435473
struct tegra_se *se = ctx->se;
436474
int ret = 0;
437475

476+
if (rctx->task & SHA_INIT) {
477+
ret = tegra_sha_do_init(req);
478+
if (ret)
479+
goto out;
480+
481+
rctx->task &= ~SHA_INIT;
482+
}
483+
438484
if (rctx->task & SHA_UPDATE) {
439485
ret = tegra_sha_do_update(req);
440486
if (ret)
@@ -525,44 +571,6 @@ static void tegra_sha_cra_exit(struct crypto_tfm *tfm)
525571
tegra_key_invalidate(ctx->se, ctx->key_id, ctx->alg);
526572
}
527573

528-
static int tegra_sha_init(struct ahash_request *req)
529-
{
530-
struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
531-
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
532-
struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
533-
struct tegra_se *se = ctx->se;
534-
535-
if (ctx->fallback)
536-
return tegra_sha_fallback_init(req);
537-
538-
rctx->total_len = 0;
539-
rctx->datbuf.size = 0;
540-
rctx->residue.size = 0;
541-
rctx->key_id = ctx->key_id;
542-
rctx->task = SHA_FIRST;
543-
rctx->alg = ctx->alg;
544-
rctx->blk_size = crypto_ahash_blocksize(tfm);
545-
rctx->digest.size = crypto_ahash_digestsize(tfm);
546-
547-
rctx->digest.buf = dma_alloc_coherent(se->dev, rctx->digest.size,
548-
&rctx->digest.addr, GFP_KERNEL);
549-
if (!rctx->digest.buf)
550-
goto digbuf_fail;
551-
552-
rctx->residue.buf = dma_alloc_coherent(se->dev, rctx->blk_size,
553-
&rctx->residue.addr, GFP_KERNEL);
554-
if (!rctx->residue.buf)
555-
goto resbuf_fail;
556-
557-
return 0;
558-
559-
resbuf_fail:
560-
dma_free_coherent(se->dev, rctx->digest.size, rctx->digest.buf,
561-
rctx->digest.addr);
562-
digbuf_fail:
563-
return -ENOMEM;
564-
}
565-
566574
static int tegra_hmac_fallback_setkey(struct tegra_sha_ctx *ctx, const u8 *key,
567575
unsigned int keylen)
568576
{
@@ -593,6 +601,17 @@ static int tegra_hmac_setkey(struct crypto_ahash *tfm, const u8 *key,
593601
return 0;
594602
}
595603

604+
static int tegra_sha_init(struct ahash_request *req)
605+
{
606+
struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
607+
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
608+
struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
609+
610+
rctx->task = SHA_INIT;
611+
612+
return crypto_transfer_hash_request_to_engine(ctx->se->engine, req);
613+
}
614+
596615
static int tegra_sha_update(struct ahash_request *req)
597616
{
598617
struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
@@ -640,16 +659,12 @@ static int tegra_sha_digest(struct ahash_request *req)
640659
struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
641660
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
642661
struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
643-
int ret;
644662

645663
if (ctx->fallback)
646664
return tegra_sha_fallback_digest(req);
647665

648-
ret = tegra_sha_init(req);
649-
if (ret)
650-
return ret;
666+
rctx->task |= SHA_INIT | SHA_UPDATE | SHA_FINAL;
651667

652-
rctx->task |= SHA_UPDATE | SHA_FINAL;
653668
return crypto_transfer_hash_request_to_engine(ctx->se->engine, req);
654669
}
655670

drivers/crypto/tegra/tegra-se.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -342,8 +342,9 @@
342342
#define SE_MAX_MEM_ALLOC SZ_4M
343343

344344
#define SHA_FIRST BIT(0)
345-
#define SHA_UPDATE BIT(1)
346-
#define SHA_FINAL BIT(2)
345+
#define SHA_INIT BIT(1)
346+
#define SHA_UPDATE BIT(2)
347+
#define SHA_FINAL BIT(3)
347348

348349
/* Security Engine operation modes */
349350
enum se_aes_alg {

0 commit comments

Comments
 (0)