Skip to content

Commit 9a0ed69

Browse files
akhilr-nvgregkh
authored andcommitted
crypto: tegra - Reserve keyslots to allocate dynamically
[ Upstream commit b157e7a ] The HW supports only storing 15 keys at a time. This limits the number of tfms that can work without failutes. Reserve keyslots to solve this and use the reserved ones during the encryption/decryption operation. This allow users to have the capability of hardware protected keys and faster operations if there are limited number of tfms while not halting the operation if there are more tfms. 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 ce065c4 commit 9a0ed69

3 files changed

Lines changed: 164 additions & 22 deletions

File tree

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

Lines changed: 118 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ struct tegra_aes_ctx {
2828
u32 ivsize;
2929
u32 key1_id;
3030
u32 key2_id;
31+
u32 keylen;
32+
u8 key1[AES_MAX_KEY_SIZE];
33+
u8 key2[AES_MAX_KEY_SIZE];
3134
};
3235

3336
struct tegra_aes_reqctx {
@@ -43,8 +46,9 @@ struct tegra_aead_ctx {
4346
struct tegra_se *se;
4447
unsigned int authsize;
4548
u32 alg;
46-
u32 keylen;
4749
u32 key_id;
50+
u32 keylen;
51+
u8 key[AES_MAX_KEY_SIZE];
4852
};
4953

5054
struct tegra_aead_reqctx {
@@ -56,8 +60,8 @@ struct tegra_aead_reqctx {
5660
unsigned int cryptlen;
5761
unsigned int authsize;
5862
bool encrypt;
59-
u32 config;
6063
u32 crypto_config;
64+
u32 config;
6165
u32 key_id;
6266
u32 iv[4];
6367
u8 authdata[16];
@@ -67,6 +71,8 @@ struct tegra_cmac_ctx {
6771
struct tegra_se *se;
6872
unsigned int alg;
6973
u32 key_id;
74+
u32 keylen;
75+
u8 key[AES_MAX_KEY_SIZE];
7076
struct crypto_shash *fallback_tfm;
7177
};
7278

@@ -260,11 +266,13 @@ static int tegra_aes_do_one_req(struct crypto_engine *engine, void *areq)
260266
struct tegra_aes_ctx *ctx = crypto_skcipher_ctx(crypto_skcipher_reqtfm(req));
261267
struct tegra_aes_reqctx *rctx = skcipher_request_ctx(req);
262268
struct tegra_se *se = ctx->se;
263-
unsigned int cmdlen;
269+
unsigned int cmdlen, key1_id, key2_id;
264270
int ret;
265271

266272
rctx->iv = (ctx->alg == SE_ALG_ECB) ? NULL : (u32 *)req->iv;
267273
rctx->len = req->cryptlen;
274+
key1_id = ctx->key1_id;
275+
key2_id = ctx->key2_id;
268276

269277
/* Pad input to AES Block size */
270278
if (ctx->alg != SE_ALG_XTS) {
@@ -282,6 +290,29 @@ static int tegra_aes_do_one_req(struct crypto_engine *engine, void *areq)
282290

283291
scatterwalk_map_and_copy(rctx->datbuf.buf, req->src, 0, req->cryptlen, 0);
284292

293+
rctx->config = tegra234_aes_cfg(ctx->alg, rctx->encrypt);
294+
rctx->crypto_config = tegra234_aes_crypto_cfg(ctx->alg, rctx->encrypt);
295+
296+
if (!key1_id) {
297+
ret = tegra_key_submit_reserved_aes(ctx->se, ctx->key1,
298+
ctx->keylen, ctx->alg, &key1_id);
299+
if (ret)
300+
goto out;
301+
}
302+
303+
rctx->crypto_config |= SE_AES_KEY_INDEX(key1_id);
304+
305+
if (ctx->alg == SE_ALG_XTS) {
306+
if (!key2_id) {
307+
ret = tegra_key_submit_reserved_xts(ctx->se, ctx->key2,
308+
ctx->keylen, ctx->alg, &key2_id);
309+
if (ret)
310+
goto out;
311+
}
312+
313+
rctx->crypto_config |= SE_AES_KEY2_INDEX(key2_id);
314+
}
315+
285316
/* Prepare the command and submit for execution */
286317
cmdlen = tegra_aes_prep_cmd(ctx, rctx);
287318
ret = tegra_se_host1x_submit(se, se->cmdbuf, cmdlen);
@@ -290,10 +321,17 @@ static int tegra_aes_do_one_req(struct crypto_engine *engine, void *areq)
290321
tegra_aes_update_iv(req, ctx);
291322
scatterwalk_map_and_copy(rctx->datbuf.buf, req->dst, 0, req->cryptlen, 1);
292323

324+
out:
293325
/* Free the buffer */
294326
dma_free_coherent(ctx->se->dev, rctx->datbuf.size,
295327
rctx->datbuf.buf, rctx->datbuf.addr);
296328

329+
if (tegra_key_is_reserved(key1_id))
330+
tegra_key_invalidate_reserved(ctx->se, key1_id, ctx->alg);
331+
332+
if (tegra_key_is_reserved(key2_id))
333+
tegra_key_invalidate_reserved(ctx->se, key2_id, ctx->alg);
334+
297335
out_finalize:
298336
crypto_finalize_skcipher_request(se->engine, req, ret);
299337

@@ -316,6 +354,7 @@ static int tegra_aes_cra_init(struct crypto_skcipher *tfm)
316354
ctx->se = se_alg->se_dev;
317355
ctx->key1_id = 0;
318356
ctx->key2_id = 0;
357+
ctx->keylen = 0;
319358

320359
algname = crypto_tfm_alg_name(&tfm->base);
321360
ret = se_algname_to_algid(algname);
@@ -344,13 +383,20 @@ static int tegra_aes_setkey(struct crypto_skcipher *tfm,
344383
const u8 *key, u32 keylen)
345384
{
346385
struct tegra_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
386+
int ret;
347387

348388
if (aes_check_keylen(keylen)) {
349389
dev_dbg(ctx->se->dev, "invalid key length (%d)\n", keylen);
350390
return -EINVAL;
351391
}
352392

353-
return tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key1_id);
393+
ret = tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key1_id);
394+
if (ret) {
395+
ctx->keylen = keylen;
396+
memcpy(ctx->key1, key, keylen);
397+
}
398+
399+
return 0;
354400
}
355401

356402
static int tegra_xts_setkey(struct crypto_skcipher *tfm,
@@ -368,11 +414,17 @@ static int tegra_xts_setkey(struct crypto_skcipher *tfm,
368414

369415
ret = tegra_key_submit(ctx->se, key, len,
370416
ctx->alg, &ctx->key1_id);
371-
if (ret)
372-
return ret;
417+
if (ret) {
418+
ctx->keylen = len;
419+
memcpy(ctx->key1, key, len);
420+
}
373421

374-
return tegra_key_submit(ctx->se, key + len, len,
422+
ret = tegra_key_submit(ctx->se, key + len, len,
375423
ctx->alg, &ctx->key2_id);
424+
if (ret) {
425+
ctx->keylen = len;
426+
memcpy(ctx->key2, key + len, len);
427+
}
376428

377429
return 0;
378430
}
@@ -447,12 +499,6 @@ static int tegra_aes_crypt(struct skcipher_request *req, bool encrypt)
447499
return 0;
448500

449501
rctx->encrypt = encrypt;
450-
rctx->config = tegra234_aes_cfg(ctx->alg, encrypt);
451-
rctx->crypto_config = tegra234_aes_crypto_cfg(ctx->alg, encrypt);
452-
rctx->crypto_config |= SE_AES_KEY_INDEX(ctx->key1_id);
453-
454-
if (ctx->key2_id)
455-
rctx->crypto_config |= SE_AES_KEY2_INDEX(ctx->key2_id);
456502

457503
return crypto_transfer_skcipher_request_to_engine(ctx->se->engine, req);
458504
}
@@ -719,7 +765,7 @@ static int tegra_gcm_do_gmac(struct tegra_aead_ctx *ctx, struct tegra_aead_reqct
719765

720766
rctx->config = tegra234_aes_cfg(SE_ALG_GMAC, rctx->encrypt);
721767
rctx->crypto_config = tegra234_aes_crypto_cfg(SE_ALG_GMAC, rctx->encrypt) |
722-
SE_AES_KEY_INDEX(ctx->key_id);
768+
SE_AES_KEY_INDEX(rctx->key_id);
723769

724770
cmdlen = tegra_gmac_prep_cmd(ctx, rctx);
725771

@@ -736,7 +782,7 @@ static int tegra_gcm_do_crypt(struct tegra_aead_ctx *ctx, struct tegra_aead_reqc
736782

737783
rctx->config = tegra234_aes_cfg(SE_ALG_GCM, rctx->encrypt);
738784
rctx->crypto_config = tegra234_aes_crypto_cfg(SE_ALG_GCM, rctx->encrypt) |
739-
SE_AES_KEY_INDEX(ctx->key_id);
785+
SE_AES_KEY_INDEX(rctx->key_id);
740786

741787
/* Prepare command and submit */
742788
cmdlen = tegra_gcm_crypt_prep_cmd(ctx, rctx);
@@ -759,7 +805,7 @@ static int tegra_gcm_do_final(struct tegra_aead_ctx *ctx, struct tegra_aead_reqc
759805

760806
rctx->config = tegra234_aes_cfg(SE_ALG_GCM_FINAL, rctx->encrypt);
761807
rctx->crypto_config = tegra234_aes_crypto_cfg(SE_ALG_GCM_FINAL, rctx->encrypt) |
762-
SE_AES_KEY_INDEX(ctx->key_id);
808+
SE_AES_KEY_INDEX(rctx->key_id);
763809

764810
/* Prepare command and submit */
765811
cmdlen = tegra_gcm_prep_final_cmd(se, cpuvaddr, rctx);
@@ -890,7 +936,7 @@ static int tegra_ccm_do_cbcmac(struct tegra_aead_ctx *ctx, struct tegra_aead_req
890936
rctx->config = tegra234_aes_cfg(SE_ALG_CBC_MAC, rctx->encrypt);
891937
rctx->crypto_config = tegra234_aes_crypto_cfg(SE_ALG_CBC_MAC,
892938
rctx->encrypt) |
893-
SE_AES_KEY_INDEX(ctx->key_id);
939+
SE_AES_KEY_INDEX(rctx->key_id);
894940

895941
/* Prepare command and submit */
896942
cmdlen = tegra_cbcmac_prep_cmd(ctx, rctx);
@@ -1077,7 +1123,7 @@ static int tegra_ccm_do_ctr(struct tegra_aead_ctx *ctx, struct tegra_aead_reqctx
10771123

10781124
rctx->config = tegra234_aes_cfg(SE_ALG_CTR, rctx->encrypt);
10791125
rctx->crypto_config = tegra234_aes_crypto_cfg(SE_ALG_CTR, rctx->encrypt) |
1080-
SE_AES_KEY_INDEX(ctx->key_id);
1126+
SE_AES_KEY_INDEX(rctx->key_id);
10811127

10821128
/* Copy authdata in the top of buffer for encryption/decryption */
10831129
if (rctx->encrypt)
@@ -1158,6 +1204,8 @@ static int tegra_ccm_do_one_req(struct crypto_engine *engine, void *areq)
11581204
if (ret)
11591205
goto out_finalize;
11601206

1207+
rctx->key_id = ctx->key_id;
1208+
11611209
/* Allocate buffers required */
11621210
rctx->inbuf.size = rctx->assoclen + rctx->authsize + rctx->cryptlen + 100;
11631211
rctx->inbuf.buf = dma_alloc_coherent(ctx->se->dev, rctx->inbuf.size,
@@ -1173,6 +1221,13 @@ static int tegra_ccm_do_one_req(struct crypto_engine *engine, void *areq)
11731221
goto out_free_inbuf;
11741222
}
11751223

1224+
if (!ctx->key_id) {
1225+
ret = tegra_key_submit_reserved_aes(ctx->se, ctx->key,
1226+
ctx->keylen, ctx->alg, &rctx->key_id);
1227+
if (ret)
1228+
goto out;
1229+
}
1230+
11761231
if (rctx->encrypt) {
11771232
/* CBC MAC Operation */
11781233
ret = tegra_ccm_compute_auth(ctx, rctx);
@@ -1203,6 +1258,9 @@ static int tegra_ccm_do_one_req(struct crypto_engine *engine, void *areq)
12031258
dma_free_coherent(ctx->se->dev, rctx->outbuf.size,
12041259
rctx->inbuf.buf, rctx->inbuf.addr);
12051260

1261+
if (tegra_key_is_reserved(rctx->key_id))
1262+
tegra_key_invalidate_reserved(ctx->se, rctx->key_id, ctx->alg);
1263+
12061264
out_finalize:
12071265
crypto_finalize_aead_request(ctx->se->engine, req, ret);
12081266

@@ -1230,6 +1288,8 @@ static int tegra_gcm_do_one_req(struct crypto_engine *engine, void *areq)
12301288
memcpy(rctx->iv, req->iv, GCM_AES_IV_SIZE);
12311289
rctx->iv[3] = (1 << 24);
12321290

1291+
rctx->key_id = ctx->key_id;
1292+
12331293
/* Allocate buffers required */
12341294
rctx->inbuf.size = rctx->assoclen + rctx->authsize + rctx->cryptlen;
12351295
rctx->inbuf.buf = dma_alloc_coherent(ctx->se->dev, rctx->inbuf.size,
@@ -1247,6 +1307,13 @@ static int tegra_gcm_do_one_req(struct crypto_engine *engine, void *areq)
12471307
goto out_free_inbuf;
12481308
}
12491309

1310+
if (!ctx->key_id) {
1311+
ret = tegra_key_submit_reserved_aes(ctx->se, ctx->key,
1312+
ctx->keylen, ctx->alg, &rctx->key_id);
1313+
if (ret)
1314+
goto out;
1315+
}
1316+
12501317
/* If there is associated data perform GMAC operation */
12511318
if (rctx->assoclen) {
12521319
ret = tegra_gcm_do_gmac(ctx, rctx);
@@ -1277,6 +1344,9 @@ static int tegra_gcm_do_one_req(struct crypto_engine *engine, void *areq)
12771344
dma_free_coherent(ctx->se->dev, rctx->inbuf.size,
12781345
rctx->inbuf.buf, rctx->inbuf.addr);
12791346

1347+
if (tegra_key_is_reserved(rctx->key_id))
1348+
tegra_key_invalidate_reserved(ctx->se, rctx->key_id, ctx->alg);
1349+
12801350
out_finalize:
12811351
crypto_finalize_aead_request(ctx->se->engine, req, ret);
12821352

@@ -1299,6 +1369,7 @@ static int tegra_aead_cra_init(struct crypto_aead *tfm)
12991369

13001370
ctx->se = se_alg->se_dev;
13011371
ctx->key_id = 0;
1372+
ctx->keylen = 0;
13021373

13031374
ret = se_algname_to_algid(algname);
13041375
if (ret < 0) {
@@ -1380,13 +1451,20 @@ static int tegra_aead_setkey(struct crypto_aead *tfm,
13801451
const u8 *key, u32 keylen)
13811452
{
13821453
struct tegra_aead_ctx *ctx = crypto_aead_ctx(tfm);
1454+
int ret;
13831455

13841456
if (aes_check_keylen(keylen)) {
13851457
dev_dbg(ctx->se->dev, "invalid key length (%d)\n", keylen);
13861458
return -EINVAL;
13871459
}
13881460

1389-
return tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id);
1461+
ret = tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id);
1462+
if (ret) {
1463+
ctx->keylen = keylen;
1464+
memcpy(ctx->key, key, keylen);
1465+
}
1466+
1467+
return 0;
13901468
}
13911469

13921470
static unsigned int tegra_cmac_prep_cmd(struct tegra_cmac_ctx *ctx,
@@ -1471,6 +1549,7 @@ static int tegra_cmac_do_init(struct ahash_request *req)
14711549
rctx->total_len = 0;
14721550
rctx->datbuf.size = 0;
14731551
rctx->residue.size = 0;
1552+
rctx->key_id = ctx->key_id;
14741553
rctx->task |= SHA_FIRST;
14751554
rctx->blk_size = crypto_ahash_blocksize(tfm);
14761555

@@ -1515,7 +1594,7 @@ static int tegra_cmac_do_update(struct ahash_request *req)
15151594
rctx->datbuf.size = (req->nbytes + rctx->residue.size) - nresidue;
15161595
rctx->total_len += rctx->datbuf.size;
15171596
rctx->config = tegra234_aes_cfg(SE_ALG_CMAC, 0);
1518-
rctx->crypto_config = SE_AES_KEY_INDEX(ctx->key_id);
1597+
rctx->crypto_config = SE_AES_KEY_INDEX(rctx->key_id);
15191598

15201599
/*
15211600
* Keep one block and residue bytes in residue and
@@ -1641,6 +1720,13 @@ static int tegra_cmac_do_one_req(struct crypto_engine *engine, void *areq)
16411720
rctx->task &= ~SHA_INIT;
16421721
}
16431722

1723+
if (!ctx->key_id) {
1724+
ret = tegra_key_submit_reserved_aes(ctx->se, ctx->key,
1725+
ctx->keylen, ctx->alg, &rctx->key_id);
1726+
if (ret)
1727+
goto out;
1728+
}
1729+
16441730
if (rctx->task & SHA_UPDATE) {
16451731
ret = tegra_cmac_do_update(req);
16461732
if (ret)
@@ -1657,6 +1743,9 @@ static int tegra_cmac_do_one_req(struct crypto_engine *engine, void *areq)
16571743
rctx->task &= ~SHA_FINAL;
16581744
}
16591745
out:
1746+
if (tegra_key_is_reserved(rctx->key_id))
1747+
tegra_key_invalidate_reserved(ctx->se, rctx->key_id, ctx->alg);
1748+
16601749
crypto_finalize_hash_request(se->engine, req, ret);
16611750

16621751
return 0;
@@ -1697,6 +1786,7 @@ static int tegra_cmac_cra_init(struct crypto_tfm *tfm)
16971786

16981787
ctx->se = se_alg->se_dev;
16991788
ctx->key_id = 0;
1789+
ctx->keylen = 0;
17001790

17011791
ret = se_algname_to_algid(algname);
17021792
if (ret < 0) {
@@ -1725,6 +1815,7 @@ static int tegra_cmac_setkey(struct crypto_ahash *tfm, const u8 *key,
17251815
unsigned int keylen)
17261816
{
17271817
struct tegra_cmac_ctx *ctx = crypto_ahash_ctx(tfm);
1818+
int ret;
17281819

17291820
if (aes_check_keylen(keylen)) {
17301821
dev_dbg(ctx->se->dev, "invalid key length (%d)\n", keylen);
@@ -1734,7 +1825,13 @@ static int tegra_cmac_setkey(struct crypto_ahash *tfm, const u8 *key,
17341825
if (ctx->fallback_tfm)
17351826
crypto_shash_setkey(ctx->fallback_tfm, key, keylen);
17361827

1737-
return tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id);
1828+
ret = tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id);
1829+
if (ret) {
1830+
ctx->keylen = keylen;
1831+
memcpy(ctx->key, key, keylen);
1832+
}
1833+
1834+
return 0;
17381835
}
17391836

17401837
static int tegra_cmac_init(struct ahash_request *req)

0 commit comments

Comments
 (0)