Skip to content

Commit 97ee15e

Browse files
Akhil Rherbertx
authored andcommitted
crypto: tegra - Transfer HASH init function to crypto engine
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 <[email protected]> Signed-off-by: Herbert Xu <[email protected]>
1 parent dcf8b7e commit 97ee15e

File tree

3 files changed

+109
-78
lines changed

3 files changed

+109
-78
lines changed

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

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

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

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

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

1739+
static int tegra_cmac_init(struct ahash_request *req)
1740+
{
1741+
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
1742+
struct tegra_cmac_ctx *ctx = crypto_ahash_ctx(tfm);
1743+
struct tegra_cmac_reqctx *rctx = ahash_request_ctx(req);
1744+
1745+
rctx->task = SHA_INIT;
1746+
1747+
return crypto_transfer_hash_request_to_engine(ctx->se->engine, req);
1748+
}
1749+
17311750
static int tegra_cmac_update(struct ahash_request *req)
17321751
{
17331752
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
@@ -1766,13 +1785,9 @@ static int tegra_cmac_digest(struct ahash_request *req)
17661785
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
17671786
struct tegra_cmac_ctx *ctx = crypto_ahash_ctx(tfm);
17681787
struct tegra_cmac_reqctx *rctx = ahash_request_ctx(req);
1769-
int ret;
17701788

1771-
ret = tegra_cmac_init(req);
1772-
if (ret)
1773-
return ret;
1789+
rctx->task |= SHA_INIT | SHA_UPDATE | SHA_FINAL;
17741790

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

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
{
@@ -588,6 +596,17 @@ static int tegra_hmac_setkey(struct crypto_ahash *tfm, const u8 *key,
588596
return tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id);
589597
}
590598

599+
static int tegra_sha_init(struct ahash_request *req)
600+
{
601+
struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
602+
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
603+
struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
604+
605+
rctx->task = SHA_INIT;
606+
607+
return crypto_transfer_hash_request_to_engine(ctx->se->engine, req);
608+
}
609+
591610
static int tegra_sha_update(struct ahash_request *req)
592611
{
593612
struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
@@ -635,16 +654,12 @@ static int tegra_sha_digest(struct ahash_request *req)
635654
struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
636655
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
637656
struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
638-
int ret;
639657

640658
if (ctx->fallback)
641659
return tegra_sha_fallback_digest(req);
642660

643-
ret = tegra_sha_init(req);
644-
if (ret)
645-
return ret;
661+
rctx->task |= SHA_INIT | SHA_UPDATE | SHA_FINAL;
646662

647-
rctx->task |= SHA_UPDATE | SHA_FINAL;
648663
return crypto_transfer_hash_request_to_engine(ctx->se->engine, req);
649664
}
650665

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)