Commit 15b5e911 authored by Giovanni Cabiddu's avatar Giovanni Cabiddu Committed by Herbert Xu

crypto: qat - update iv after encryption or decryption operations

Allocate a contiguous buffer and instruct the qat hardware to return the
iv at the end of an encryption or decryption operation.
The iv is copied to the array provided by the user in the callback
function.

This problem was found with by the crypto self test.
Reviewed-by: default avatarConor Mcloughlin <conor.mcloughlin@intel.com>
Tested-by: default avatarSergey Portnoy <sergey.portnoy@intel.com>
Signed-off-by: default avatarGiovanni Cabiddu <giovanni.cabiddu@intel.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent c044b62c
...@@ -255,7 +255,24 @@ static int qat_alg_do_precomputes(struct icp_qat_hw_auth_algo_blk *hash, ...@@ -255,7 +255,24 @@ static int qat_alg_do_precomputes(struct icp_qat_hw_auth_algo_blk *hash,
return 0; return 0;
} }
static void qat_alg_init_common_hdr(struct icp_qat_fw_comn_req_hdr *header) static void qat_alg_init_hdr_iv_updt(struct icp_qat_fw_comn_req_hdr *header)
{
ICP_QAT_FW_LA_CIPH_IV_FLD_FLAG_SET(header->serv_specif_flags,
ICP_QAT_FW_CIPH_IV_64BIT_PTR);
ICP_QAT_FW_LA_UPDATE_STATE_SET(header->serv_specif_flags,
ICP_QAT_FW_LA_UPDATE_STATE);
}
static void qat_alg_init_hdr_no_iv_updt(struct icp_qat_fw_comn_req_hdr *header)
{
ICP_QAT_FW_LA_CIPH_IV_FLD_FLAG_SET(header->serv_specif_flags,
ICP_QAT_FW_CIPH_IV_16BYTE_DATA);
ICP_QAT_FW_LA_UPDATE_STATE_SET(header->serv_specif_flags,
ICP_QAT_FW_LA_NO_UPDATE_STATE);
}
static void qat_alg_init_common_hdr(struct icp_qat_fw_comn_req_hdr *header,
int aead)
{ {
header->hdr_flags = header->hdr_flags =
ICP_QAT_FW_COMN_HDR_FLAGS_BUILD(ICP_QAT_FW_COMN_REQ_FLAG_SET); ICP_QAT_FW_COMN_HDR_FLAGS_BUILD(ICP_QAT_FW_COMN_REQ_FLAG_SET);
...@@ -265,12 +282,12 @@ static void qat_alg_init_common_hdr(struct icp_qat_fw_comn_req_hdr *header) ...@@ -265,12 +282,12 @@ static void qat_alg_init_common_hdr(struct icp_qat_fw_comn_req_hdr *header)
QAT_COMN_PTR_TYPE_SGL); QAT_COMN_PTR_TYPE_SGL);
ICP_QAT_FW_LA_PARTIAL_SET(header->serv_specif_flags, ICP_QAT_FW_LA_PARTIAL_SET(header->serv_specif_flags,
ICP_QAT_FW_LA_PARTIAL_NONE); ICP_QAT_FW_LA_PARTIAL_NONE);
ICP_QAT_FW_LA_CIPH_IV_FLD_FLAG_SET(header->serv_specif_flags, if (aead)
ICP_QAT_FW_CIPH_IV_16BYTE_DATA); qat_alg_init_hdr_no_iv_updt(header);
else
qat_alg_init_hdr_iv_updt(header);
ICP_QAT_FW_LA_PROTO_SET(header->serv_specif_flags, ICP_QAT_FW_LA_PROTO_SET(header->serv_specif_flags,
ICP_QAT_FW_LA_NO_PROTO); ICP_QAT_FW_LA_NO_PROTO);
ICP_QAT_FW_LA_UPDATE_STATE_SET(header->serv_specif_flags,
ICP_QAT_FW_LA_NO_UPDATE_STATE);
} }
static int qat_alg_aead_init_enc_session(struct crypto_aead *aead_tfm, static int qat_alg_aead_init_enc_session(struct crypto_aead *aead_tfm,
...@@ -305,7 +322,7 @@ static int qat_alg_aead_init_enc_session(struct crypto_aead *aead_tfm, ...@@ -305,7 +322,7 @@ static int qat_alg_aead_init_enc_session(struct crypto_aead *aead_tfm,
return -EFAULT; return -EFAULT;
/* Request setup */ /* Request setup */
qat_alg_init_common_hdr(header); qat_alg_init_common_hdr(header, 1);
header->service_cmd_id = ICP_QAT_FW_LA_CMD_CIPHER_HASH; header->service_cmd_id = ICP_QAT_FW_LA_CMD_CIPHER_HASH;
ICP_QAT_FW_LA_DIGEST_IN_BUFFER_SET(header->serv_specif_flags, ICP_QAT_FW_LA_DIGEST_IN_BUFFER_SET(header->serv_specif_flags,
ICP_QAT_FW_LA_DIGEST_IN_BUFFER); ICP_QAT_FW_LA_DIGEST_IN_BUFFER);
...@@ -392,7 +409,7 @@ static int qat_alg_aead_init_dec_session(struct crypto_aead *aead_tfm, ...@@ -392,7 +409,7 @@ static int qat_alg_aead_init_dec_session(struct crypto_aead *aead_tfm,
return -EFAULT; return -EFAULT;
/* Request setup */ /* Request setup */
qat_alg_init_common_hdr(header); qat_alg_init_common_hdr(header, 1);
header->service_cmd_id = ICP_QAT_FW_LA_CMD_HASH_CIPHER; header->service_cmd_id = ICP_QAT_FW_LA_CMD_HASH_CIPHER;
ICP_QAT_FW_LA_DIGEST_IN_BUFFER_SET(header->serv_specif_flags, ICP_QAT_FW_LA_DIGEST_IN_BUFFER_SET(header->serv_specif_flags,
ICP_QAT_FW_LA_DIGEST_IN_BUFFER); ICP_QAT_FW_LA_DIGEST_IN_BUFFER);
...@@ -456,7 +473,7 @@ static void qat_alg_ablkcipher_init_com(struct qat_alg_ablkcipher_ctx *ctx, ...@@ -456,7 +473,7 @@ static void qat_alg_ablkcipher_init_com(struct qat_alg_ablkcipher_ctx *ctx,
struct icp_qat_fw_cipher_cd_ctrl_hdr *cd_ctrl = (void *)&req->cd_ctrl; struct icp_qat_fw_cipher_cd_ctrl_hdr *cd_ctrl = (void *)&req->cd_ctrl;
memcpy(cd->aes.key, key, keylen); memcpy(cd->aes.key, key, keylen);
qat_alg_init_common_hdr(header); qat_alg_init_common_hdr(header, 0);
header->service_cmd_id = ICP_QAT_FW_LA_CMD_CIPHER; header->service_cmd_id = ICP_QAT_FW_LA_CMD_CIPHER;
cd_pars->u.s.content_desc_params_sz = cd_pars->u.s.content_desc_params_sz =
sizeof(struct icp_qat_hw_cipher_algo_blk) >> 3; sizeof(struct icp_qat_hw_cipher_algo_blk) >> 3;
...@@ -803,11 +820,17 @@ static void qat_ablkcipher_alg_callback(struct icp_qat_fw_la_resp *qat_resp, ...@@ -803,11 +820,17 @@ static void qat_ablkcipher_alg_callback(struct icp_qat_fw_la_resp *qat_resp,
struct qat_crypto_instance *inst = ctx->inst; struct qat_crypto_instance *inst = ctx->inst;
struct ablkcipher_request *areq = qat_req->ablkcipher_req; struct ablkcipher_request *areq = qat_req->ablkcipher_req;
uint8_t stat_filed = qat_resp->comn_resp.comn_status; uint8_t stat_filed = qat_resp->comn_resp.comn_status;
struct device *dev = &GET_DEV(ctx->inst->accel_dev);
int res = 0, qat_res = ICP_QAT_FW_COMN_RESP_CRYPTO_STAT_GET(stat_filed); int res = 0, qat_res = ICP_QAT_FW_COMN_RESP_CRYPTO_STAT_GET(stat_filed);
qat_alg_free_bufl(inst, qat_req); qat_alg_free_bufl(inst, qat_req);
if (unlikely(qat_res != ICP_QAT_FW_COMN_STATUS_FLAG_OK)) if (unlikely(qat_res != ICP_QAT_FW_COMN_STATUS_FLAG_OK))
res = -EINVAL; res = -EINVAL;
memcpy(areq->info, qat_req->iv, AES_BLOCK_SIZE);
dma_free_coherent(dev, AES_BLOCK_SIZE, qat_req->iv,
qat_req->iv_paddr);
areq->base.complete(&areq->base, res); areq->base.complete(&areq->base, res);
} }
...@@ -989,11 +1012,20 @@ static int qat_alg_ablkcipher_encrypt(struct ablkcipher_request *req) ...@@ -989,11 +1012,20 @@ static int qat_alg_ablkcipher_encrypt(struct ablkcipher_request *req)
struct qat_crypto_request *qat_req = ablkcipher_request_ctx(req); struct qat_crypto_request *qat_req = ablkcipher_request_ctx(req);
struct icp_qat_fw_la_cipher_req_params *cipher_param; struct icp_qat_fw_la_cipher_req_params *cipher_param;
struct icp_qat_fw_la_bulk_req *msg; struct icp_qat_fw_la_bulk_req *msg;
struct device *dev = &GET_DEV(ctx->inst->accel_dev);
int ret, ctr = 0; int ret, ctr = 0;
qat_req->iv = dma_alloc_coherent(dev, AES_BLOCK_SIZE,
&qat_req->iv_paddr, GFP_ATOMIC);
if (!qat_req->iv)
return -ENOMEM;
ret = qat_alg_sgl_to_bufl(ctx->inst, req->src, req->dst, qat_req); ret = qat_alg_sgl_to_bufl(ctx->inst, req->src, req->dst, qat_req);
if (unlikely(ret)) if (unlikely(ret)) {
dma_free_coherent(dev, AES_BLOCK_SIZE, qat_req->iv,
qat_req->iv_paddr);
return ret; return ret;
}
msg = &qat_req->req; msg = &qat_req->req;
*msg = ctx->enc_fw_req; *msg = ctx->enc_fw_req;
...@@ -1006,13 +1038,16 @@ static int qat_alg_ablkcipher_encrypt(struct ablkcipher_request *req) ...@@ -1006,13 +1038,16 @@ static int qat_alg_ablkcipher_encrypt(struct ablkcipher_request *req)
cipher_param = (void *)&qat_req->req.serv_specif_rqpars; cipher_param = (void *)&qat_req->req.serv_specif_rqpars;
cipher_param->cipher_length = req->nbytes; cipher_param->cipher_length = req->nbytes;
cipher_param->cipher_offset = 0; cipher_param->cipher_offset = 0;
memcpy(cipher_param->u.cipher_IV_array, req->info, AES_BLOCK_SIZE); cipher_param->u.s.cipher_IV_ptr = qat_req->iv_paddr;
memcpy(qat_req->iv, req->info, AES_BLOCK_SIZE);
do { do {
ret = adf_send_message(ctx->inst->sym_tx, (uint32_t *)msg); ret = adf_send_message(ctx->inst->sym_tx, (uint32_t *)msg);
} while (ret == -EAGAIN && ctr++ < 10); } while (ret == -EAGAIN && ctr++ < 10);
if (ret == -EAGAIN) { if (ret == -EAGAIN) {
qat_alg_free_bufl(ctx->inst, qat_req); qat_alg_free_bufl(ctx->inst, qat_req);
dma_free_coherent(dev, AES_BLOCK_SIZE, qat_req->iv,
qat_req->iv_paddr);
return -EBUSY; return -EBUSY;
} }
return -EINPROGRESS; return -EINPROGRESS;
...@@ -1026,11 +1061,20 @@ static int qat_alg_ablkcipher_decrypt(struct ablkcipher_request *req) ...@@ -1026,11 +1061,20 @@ static int qat_alg_ablkcipher_decrypt(struct ablkcipher_request *req)
struct qat_crypto_request *qat_req = ablkcipher_request_ctx(req); struct qat_crypto_request *qat_req = ablkcipher_request_ctx(req);
struct icp_qat_fw_la_cipher_req_params *cipher_param; struct icp_qat_fw_la_cipher_req_params *cipher_param;
struct icp_qat_fw_la_bulk_req *msg; struct icp_qat_fw_la_bulk_req *msg;
struct device *dev = &GET_DEV(ctx->inst->accel_dev);
int ret, ctr = 0; int ret, ctr = 0;
qat_req->iv = dma_alloc_coherent(dev, AES_BLOCK_SIZE,
&qat_req->iv_paddr, GFP_ATOMIC);
if (!qat_req->iv)
return -ENOMEM;
ret = qat_alg_sgl_to_bufl(ctx->inst, req->src, req->dst, qat_req); ret = qat_alg_sgl_to_bufl(ctx->inst, req->src, req->dst, qat_req);
if (unlikely(ret)) if (unlikely(ret)) {
dma_free_coherent(dev, AES_BLOCK_SIZE, qat_req->iv,
qat_req->iv_paddr);
return ret; return ret;
}
msg = &qat_req->req; msg = &qat_req->req;
*msg = ctx->dec_fw_req; *msg = ctx->dec_fw_req;
...@@ -1043,13 +1087,16 @@ static int qat_alg_ablkcipher_decrypt(struct ablkcipher_request *req) ...@@ -1043,13 +1087,16 @@ static int qat_alg_ablkcipher_decrypt(struct ablkcipher_request *req)
cipher_param = (void *)&qat_req->req.serv_specif_rqpars; cipher_param = (void *)&qat_req->req.serv_specif_rqpars;
cipher_param->cipher_length = req->nbytes; cipher_param->cipher_length = req->nbytes;
cipher_param->cipher_offset = 0; cipher_param->cipher_offset = 0;
memcpy(cipher_param->u.cipher_IV_array, req->info, AES_BLOCK_SIZE); cipher_param->u.s.cipher_IV_ptr = qat_req->iv_paddr;
memcpy(qat_req->iv, req->info, AES_BLOCK_SIZE);
do { do {
ret = adf_send_message(ctx->inst->sym_tx, (uint32_t *)msg); ret = adf_send_message(ctx->inst->sym_tx, (uint32_t *)msg);
} while (ret == -EAGAIN && ctr++ < 10); } while (ret == -EAGAIN && ctr++ < 10);
if (ret == -EAGAIN) { if (ret == -EAGAIN) {
qat_alg_free_bufl(ctx->inst, qat_req); qat_alg_free_bufl(ctx->inst, qat_req);
dma_free_coherent(dev, AES_BLOCK_SIZE, qat_req->iv,
qat_req->iv_paddr);
return -EBUSY; return -EBUSY;
} }
return -EINPROGRESS; return -EINPROGRESS;
......
...@@ -88,6 +88,8 @@ struct qat_crypto_request { ...@@ -88,6 +88,8 @@ struct qat_crypto_request {
struct qat_crypto_request_buffs buf; struct qat_crypto_request_buffs buf;
void (*cb)(struct icp_qat_fw_la_resp *resp, void (*cb)(struct icp_qat_fw_la_resp *resp,
struct qat_crypto_request *req); struct qat_crypto_request *req);
void *iv;
dma_addr_t iv_paddr;
}; };
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment