Skip to content

Commit 5106dfe

Browse files
intmcherbertx
authored andcommitted
crypto: qat - add AES-XTS support for QAT GEN4 devices
Add handling of AES-XTS specific to QAT GEN4 devices. Co-developed-by: Tomaszx Kowalik <[email protected]> Signed-off-by: Tomaszx Kowalik <[email protected]> Signed-off-by: Marco Chiappero <[email protected]> Reviewed-by: Giovanni Cabiddu <[email protected]> Signed-off-by: Giovanni Cabiddu <[email protected]> Signed-off-by: Herbert Xu <[email protected]>
1 parent 67916c9 commit 5106dfe

File tree

1 file changed

+89
-7
lines changed

1 file changed

+89
-7
lines changed

drivers/crypto/qat/qat_common/qat_algs.c

Lines changed: 89 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@
3333
ICP_QAT_HW_CIPHER_KEY_CONVERT, \
3434
ICP_QAT_HW_CIPHER_DECRYPT)
3535

36+
#define QAT_AES_HW_CONFIG_DEC_NO_CONV(alg, mode) \
37+
ICP_QAT_HW_CIPHER_CONFIG_BUILD(mode, alg, \
38+
ICP_QAT_HW_CIPHER_NO_CONVERT, \
39+
ICP_QAT_HW_CIPHER_DECRYPT)
40+
3641
#define HW_CAP_AES_V2(accel_dev) \
3742
(GET_HW_DATA(accel_dev)->accel_capabilities_mask & \
3843
ICP_ACCEL_CAPABILITIES_AES_V2)
@@ -95,6 +100,7 @@ struct qat_alg_skcipher_ctx {
95100
struct icp_qat_fw_la_bulk_req dec_fw_req;
96101
struct qat_crypto_instance *inst;
97102
struct crypto_skcipher *ftfm;
103+
struct crypto_cipher *tweak;
98104
bool fallback;
99105
int mode;
100106
};
@@ -428,7 +434,16 @@ static void qat_alg_skcipher_init_com(struct qat_alg_skcipher_ctx *ctx,
428434
cd_pars->u.s.content_desc_params_sz =
429435
sizeof(struct icp_qat_hw_cipher_algo_blk) >> 3;
430436

431-
if (aes_v2_capable && mode == ICP_QAT_HW_CIPHER_CTR_MODE) {
437+
if (aes_v2_capable && mode == ICP_QAT_HW_CIPHER_XTS_MODE) {
438+
ICP_QAT_FW_LA_SLICE_TYPE_SET(header->serv_specif_flags,
439+
ICP_QAT_FW_LA_USE_UCS_SLICE_TYPE);
440+
441+
/* Store both XTS keys in CD, only the first key is sent
442+
* to the HW, the second key is used for tweak calculation
443+
*/
444+
memcpy(cd->ucs_aes.key, key, keylen);
445+
keylen = keylen / 2;
446+
} else if (aes_v2_capable && mode == ICP_QAT_HW_CIPHER_CTR_MODE) {
432447
ICP_QAT_FW_LA_SLICE_TYPE_SET(header->serv_specif_flags,
433448
ICP_QAT_FW_LA_USE_UCS_SLICE_TYPE);
434449
keylen = round_up(keylen, 16);
@@ -458,23 +473,55 @@ static void qat_alg_skcipher_init_enc(struct qat_alg_skcipher_ctx *ctx,
458473
enc_cd->aes.cipher_config.val = QAT_AES_HW_CONFIG_ENC(alg, mode);
459474
}
460475

476+
static void qat_alg_xts_reverse_key(const u8 *key_forward, unsigned int keylen,
477+
u8 *key_reverse)
478+
{
479+
struct crypto_aes_ctx aes_expanded;
480+
int nrounds;
481+
u8 *key;
482+
483+
aes_expandkey(&aes_expanded, key_forward, keylen);
484+
if (keylen == AES_KEYSIZE_128) {
485+
nrounds = 10;
486+
key = (u8 *)aes_expanded.key_enc + (AES_BLOCK_SIZE * nrounds);
487+
memcpy(key_reverse, key, AES_BLOCK_SIZE);
488+
} else {
489+
/* AES_KEYSIZE_256 */
490+
nrounds = 14;
491+
key = (u8 *)aes_expanded.key_enc + (AES_BLOCK_SIZE * nrounds);
492+
memcpy(key_reverse, key, AES_BLOCK_SIZE);
493+
memcpy(key_reverse + AES_BLOCK_SIZE, key - AES_BLOCK_SIZE,
494+
AES_BLOCK_SIZE);
495+
}
496+
}
497+
461498
static void qat_alg_skcipher_init_dec(struct qat_alg_skcipher_ctx *ctx,
462499
int alg, const u8 *key,
463500
unsigned int keylen, int mode)
464501
{
465502
struct icp_qat_hw_cipher_algo_blk *dec_cd = ctx->dec_cd;
466503
struct icp_qat_fw_la_bulk_req *req = &ctx->dec_fw_req;
467504
struct icp_qat_fw_comn_req_hdr_cd_pars *cd_pars = &req->cd_pars;
505+
bool aes_v2_capable = HW_CAP_AES_V2(ctx->inst->accel_dev);
468506

469507
qat_alg_skcipher_init_com(ctx, req, dec_cd, key, keylen);
470508
cd_pars->u.s.content_desc_addr = ctx->dec_cd_paddr;
471509

472-
if (mode != ICP_QAT_HW_CIPHER_CTR_MODE)
510+
if (aes_v2_capable && mode == ICP_QAT_HW_CIPHER_XTS_MODE) {
511+
/* Key reversing not supported, set no convert */
512+
dec_cd->aes.cipher_config.val =
513+
QAT_AES_HW_CONFIG_DEC_NO_CONV(alg, mode);
514+
515+
/* In-place key reversal */
516+
qat_alg_xts_reverse_key(dec_cd->ucs_aes.key, keylen / 2,
517+
dec_cd->ucs_aes.key);
518+
} else if (mode != ICP_QAT_HW_CIPHER_CTR_MODE) {
473519
dec_cd->aes.cipher_config.val =
474520
QAT_AES_HW_CONFIG_DEC(alg, mode);
475-
else
521+
} else {
476522
dec_cd->aes.cipher_config.val =
477523
QAT_AES_HW_CONFIG_ENC(alg, mode);
524+
}
478525
}
479526

480527
static int qat_alg_validate_key(int key_len, int *alg, int mode)
@@ -1081,8 +1128,33 @@ static int qat_alg_skcipher_xts_setkey(struct crypto_skcipher *tfm,
10811128

10821129
ctx->fallback = false;
10831130

1084-
return qat_alg_skcipher_setkey(tfm, key, keylen,
1085-
ICP_QAT_HW_CIPHER_XTS_MODE);
1131+
ret = qat_alg_skcipher_setkey(tfm, key, keylen,
1132+
ICP_QAT_HW_CIPHER_XTS_MODE);
1133+
if (ret)
1134+
return ret;
1135+
1136+
if (HW_CAP_AES_V2(ctx->inst->accel_dev))
1137+
ret = crypto_cipher_setkey(ctx->tweak, key + (keylen / 2),
1138+
keylen / 2);
1139+
1140+
return ret;
1141+
}
1142+
1143+
static void qat_alg_set_req_iv(struct qat_crypto_request *qat_req)
1144+
{
1145+
struct icp_qat_fw_la_cipher_req_params *cipher_param;
1146+
struct qat_alg_skcipher_ctx *ctx = qat_req->skcipher_ctx;
1147+
bool aes_v2_capable = HW_CAP_AES_V2(ctx->inst->accel_dev);
1148+
u8 *iv = qat_req->skcipher_req->iv;
1149+
1150+
cipher_param = (void *)&qat_req->req.serv_specif_rqpars;
1151+
1152+
if (aes_v2_capable && ctx->mode == ICP_QAT_HW_CIPHER_XTS_MODE)
1153+
crypto_cipher_encrypt_one(ctx->tweak,
1154+
(u8 *)cipher_param->u.cipher_IV_array,
1155+
iv);
1156+
else
1157+
memcpy(cipher_param->u.cipher_IV_array, iv, AES_BLOCK_SIZE);
10861158
}
10871159

10881160
static int qat_alg_skcipher_encrypt(struct skcipher_request *req)
@@ -1114,7 +1186,8 @@ static int qat_alg_skcipher_encrypt(struct skcipher_request *req)
11141186
cipher_param = (void *)&qat_req->req.serv_specif_rqpars;
11151187
cipher_param->cipher_length = req->cryptlen;
11161188
cipher_param->cipher_offset = 0;
1117-
memcpy(cipher_param->u.cipher_IV_array, req->iv, AES_BLOCK_SIZE);
1189+
1190+
qat_alg_set_req_iv(qat_req);
11181191

11191192
do {
11201193
ret = adf_send_message(ctx->inst->sym_tx, (u32 *)msg);
@@ -1182,8 +1255,8 @@ static int qat_alg_skcipher_decrypt(struct skcipher_request *req)
11821255
cipher_param = (void *)&qat_req->req.serv_specif_rqpars;
11831256
cipher_param->cipher_length = req->cryptlen;
11841257
cipher_param->cipher_offset = 0;
1185-
memcpy(cipher_param->u.cipher_IV_array, req->iv, AES_BLOCK_SIZE);
11861258

1259+
qat_alg_set_req_iv(qat_req);
11871260
qat_alg_update_iv(qat_req);
11881261

11891262
do {
@@ -1293,6 +1366,12 @@ static int qat_alg_skcipher_init_xts_tfm(struct crypto_skcipher *tfm)
12931366
if (IS_ERR(ctx->ftfm))
12941367
return PTR_ERR(ctx->ftfm);
12951368

1369+
ctx->tweak = crypto_alloc_cipher("aes", 0, 0);
1370+
if (IS_ERR(ctx->tweak)) {
1371+
crypto_free_skcipher(ctx->ftfm);
1372+
return PTR_ERR(ctx->tweak);
1373+
}
1374+
12961375
reqsize = max(sizeof(struct qat_crypto_request),
12971376
sizeof(struct skcipher_request) +
12981377
crypto_skcipher_reqsize(ctx->ftfm));
@@ -1335,6 +1414,9 @@ static void qat_alg_skcipher_exit_xts_tfm(struct crypto_skcipher *tfm)
13351414
if (ctx->ftfm)
13361415
crypto_free_skcipher(ctx->ftfm);
13371416

1417+
if (ctx->tweak)
1418+
crypto_free_cipher(ctx->tweak);
1419+
13381420
qat_alg_skcipher_exit_tfm(tfm);
13391421
}
13401422

0 commit comments

Comments
 (0)