From: Wenkai Lin <linwenkai6(a)hisilicon.com>
The SEC module has duplicated BD3 fill/parse paths across cipher,
digest, and aead, a stream mode scene misconfiguration for common
digests, and silently swallowed computation errors in the CE driver.
The following three issues are addressed:
Unify the BD3 fill/parse paths for cipher, digest, and aead on V3+
hardware. Previously each algorithm duplicated udata handling, scene
selection, and DIF detection in the qm_fill/qm_parse entry points.
Route everything through fill_xxx_bd3/parse_xxx_bd3, add DIF and
udata address helpers, select scene (STORAGE/IPSEC/STREAM) by
is_storage, and guard unmap in error paths. BD1/BD2 paths are
retained for V2 hardware.
The common digest (such as SHA/SM3) that is not GMAC supports
streaming hash processing, but SCENE_STREAM was only described for
CTR/GCM streaming encryption in the FS, and the hash function for
streaming mode in FS014/FS017 was ignored. Use SCENE_STREAM for
common digests; GMAC uses SCENE_IPSEC independently.
In sm3_ce_drv_send and isa_ce_cipher_send, the return value of the
software digest/cipher computation is silently overwritten by the
subsequent wd_get_sqe_from_queue call. If the computation fails, the
error is swallowed and the function may return success. Add an early
return on error before calling wd_get_sqe_from_queue.
Signed-off-by: Wenkai Lin <linwenkai6(a)hisilicon.com>
---
drv/isa_ce_sm3.c | 2 +
drv/isa_ce_sm4.c | 2 +
v1/drv/hisi_sec_udrv.c | 465 ++++++++++++++++++++++++++---------------
3 files changed, 298 insertions(+), 171 deletions(-)
diff --git a/drv/isa_ce_sm3.c b/drv/isa_ce_sm3.c
index b41f6c5..117b95e 100644
--- a/drv/isa_ce_sm3.c
+++ b/drv/isa_ce_sm3.c
@@ -374,6 +374,8 @@ static int sm3_ce_drv_send(handle_t ctx, void *digest_msg)
WD_ERR("invalid digest mode!\n");
ret = -WD_EINVAL;
}
+ if (ret)
+ return ret;
ret = wd_get_sqe_from_queue(sfctx, msg->tag);
if (ret)
diff --git a/drv/isa_ce_sm4.c b/drv/isa_ce_sm4.c
index 863b99e..7547c00 100644
--- a/drv/isa_ce_sm4.c
+++ b/drv/isa_ce_sm4.c
@@ -399,6 +399,8 @@ static int isa_ce_cipher_send(handle_t ctx, void *wd_msg)
ret = sm4_xts_encrypt(msg, &rkey);
else
ret = sm4_xts_decrypt(msg, &rkey);
+ if (ret)
+ return ret;
break;
default:
WD_ERR("The current block cipher mode is not supported!\n");
diff --git a/v1/drv/hisi_sec_udrv.c b/v1/drv/hisi_sec_udrv.c
index cf4bcd9..6ad6c57 100644
--- a/v1/drv/hisi_sec_udrv.c
+++ b/v1/drv/hisi_sec_udrv.c
@@ -823,11 +823,6 @@ static int fill_cipher_bd3_alg(struct wcrypto_cipher_msg *msg,
struct hisi_sec_bd3_sqe *sqe)
{
int ret = WD_SUCCESS;
-
- ret = cipher_param_check(msg);
- if (unlikely(ret))
- return ret;
-
__u8 c_key_len = 0;
switch (msg->alg) {
@@ -971,19 +966,72 @@ static int fill_cipher_bd3_mode(struct wcrypto_cipher_msg *msg,
return ret;
}
+static void fill_cipher_bd3_dif(struct hisi_sec_bd3_sqe *sqe,
+ struct wd_sec_udata *udata)
+{
+ sqe->skip_data.gran_num = udata->gran_num;
+ sqe->skip_data.src_skip_data_len = udata->src_offset;
+ sqe->skip_data.dst_skip_data_len = udata->dst_offset;
+
+ sqe->storage_scene.gen_ver_val = udata->dif.ver;
+ sqe->storage_scene.gen_app_val = udata->dif.app;
+ sqe->storage_scene.gen_page_pad_ctrl = udata->dif.ctrl.gen.page_layout_gen_type;
+ sqe->storage_scene.gen_grd_ctrl = udata->dif.ctrl.gen.grd_gen_type;
+ sqe->storage_scene.gen_ver_ctrl = udata->dif.ctrl.gen.ver_gen_type;
+ sqe->storage_scene.gen_app_ctrl = udata->dif.ctrl.gen.app_gen_type;
+ sqe->storage_scene.gen_ref_ctrl = udata->dif.ctrl.gen.ref_gen_type;
+ sqe->storage_scene.page_pad_type = udata->dif.ctrl.gen.page_layout_pad_type;
+ sqe->storage_scene.block_size = udata->block_size;
+ sqe->storage_scene.private_info = udata->dif.priv_info;
+ sqe->storage_scene.chk_grd_ctrl = udata->dif.ctrl.verify.grd_verify_type;
+ sqe->storage_scene.chk_ref_ctrl = udata->dif.ctrl.verify.ref_verify_type;
+ sqe->storage_scene.lba_l = udata->dif.lba & QM_L32BITS_MASK;
+ sqe->storage_scene.lba_h = udata->dif.lba >> QM_HADDR_SHIFT;
+}
+
+static void fill_cipher_bd3_udata_addr(struct wcrypto_cipher_msg *msg,
+ struct hisi_sec_bd3_sqe *sqe, __u8 is_storage)
+{
+ uintptr_t phy;
+
+ phy = (uintptr_t)msg->in;
+ sqe->data_src_addr_l = (__u32)(phy & QM_L32BITS_MASK);
+ sqe->data_src_addr_h = HI_U32(phy);
+ phy = (uintptr_t)msg->out;
+ sqe->data_dst_addr_l = (__u32)(phy & QM_L32BITS_MASK);
+ sqe->data_dst_addr_h = HI_U32(phy);
+ phy = (uintptr_t)msg->key;
+ sqe->c_key_addr_l = (__u32)(phy & QM_L32BITS_MASK);
+ sqe->c_key_addr_h = HI_U32(phy);
+ if (msg->iv_bytes) {
+ phy = (uintptr_t)msg->iv;
+ if (is_storage) {
+ sqe->skip_data.c_iv_a_key_l = (__u32)(phy & QM_L32BITS_MASK);
+ sqe->skip_data.c_iv_a_key_h = HI_U32(phy);
+ } else {
+ sqe->ipsec_scene.c_ivin_addr_l = (__u32)(phy & QM_L32BITS_MASK);
+ sqe->ipsec_scene.c_ivin_addr_h = HI_U32(phy);
+ }
+ }
+}
+
static int fill_cipher_bd3(struct wd_queue *q, struct hisi_sec_bd3_sqe *sqe,
struct wcrypto_cipher_msg *msg, struct wcrypto_cipher_tag *tag)
{
+ struct wd_sec_udata *udata = tag ? tag->priv : NULL;
+ __u8 is_storage = udata && udata->gran_num != 0;
int ret;
+ if (!is_storage) {
+ ret = cipher_param_check(msg);
+ if (unlikely(ret))
+ return ret;
+ }
+
sqe->type = BD_TYPE3;
- sqe->scene = SCENE_IPSEC;
+ sqe->scene = is_storage ? SCENE_STORAGE : SCENE_IPSEC;
sqe->de = DATA_DST_ADDR_ENABLE;
- if (msg->in_bytes > MAX_CIPHER_LENGTH) {
- WD_ERR("input data is too large.\n");
- return -WD_EINVAL;
- }
sqe->c_len = msg->in_bytes;
fill_bd3_addr_type(msg->data_fmt, sqe);
@@ -1000,10 +1048,19 @@ static int fill_cipher_bd3(struct wd_queue *q, struct hisi_sec_bd3_sqe *sqe,
return ret;
}
- ret = fill_cipher_bd3_area(q, msg, sqe);
- if (ret != WD_SUCCESS) {
- WD_ERR("fail to fill_cipher_bd3_addr.\n");
- return ret;
+ if (is_storage && msg->mode == WCRYPTO_CIPHER_XTS)
+ sqe->ci_gen = CI_GEN_BY_LBA;
+
+ if (udata) {
+ fill_cipher_bd3_udata_addr(msg, sqe, is_storage);
+ if (is_storage)
+ fill_cipher_bd3_dif(sqe, udata);
+ } else {
+ ret = fill_cipher_bd3_area(q, msg, sqe);
+ if (ret != WD_SUCCESS) {
+ WD_ERR("fail to fill_cipher_bd3_addr.\n");
+ return ret;
+ }
}
if (tag)
@@ -1129,10 +1186,8 @@ int qm_fill_cipher_bd3_sqe(void *message, struct qm_queue_info *info, __u16 i)
{
struct wcrypto_cipher_msg *msg = message;
struct wcrypto_cipher_tag *tag = (void *)(uintptr_t)msg->usr_data;
- struct wd_sec_udata *udata = tag->priv;
struct wd_queue *q = info->q;
struct hisi_sec_bd3_sqe *sqe3;
- struct hisi_sec_sqe *sqe;
uintptr_t temp;
int ret;
@@ -1144,35 +1199,17 @@ int qm_fill_cipher_bd3_sqe(void *message, struct qm_queue_info *info, __u16 i)
}
temp = (uintptr_t)info->sq_base + i * info->sqe_size;
+ sqe3 = (struct hisi_sec_bd3_sqe *)temp;
+ memset(sqe3, 0, sizeof(struct hisi_sec_bd3_sqe));
- /*
- * For user self-defined data with DIF scence, will fill BD1.
- * For user self-defined data without DIF scence, will fill BD2.
- * For non user self-defined data scence, will fill BD3.
- */
- if (udata) {
- sqe = (struct hisi_sec_sqe *)temp;
- memset(sqe, 0, sizeof(struct hisi_sec_sqe));
- if (udata->gran_num != 0)
- ret = fill_cipher_bd1(q, sqe, msg, tag);
- else
- ret = fill_cipher_bd2(q, sqe, msg, tag);
- } else {
- sqe3 = (struct hisi_sec_bd3_sqe *)temp;
- memset(sqe3, 0, sizeof(struct hisi_sec_bd3_sqe));
- ret = fill_cipher_bd3(q, sqe3, msg, tag);
- }
-
+ ret = fill_cipher_bd3(q, sqe3, msg, tag);
if (ret != WD_SUCCESS)
return ret;
info->req_cache[i] = msg;
#ifdef DEBUG_LOG
- if (udata)
- sec_dump_bd((unsigned char *)sqe, SQE_BYTES_NUMS);
- else
- sec_dump_bd((unsigned char *)sqe3, SQE_BYTES_NUMS);
+ sec_dump_bd((unsigned char *)sqe3, SQE_BYTES_NUMS);
#endif
return ret;
@@ -1707,24 +1744,45 @@ static int digest_param_check_v3(struct wcrypto_digest_msg *msg)
return WD_SUCCESS;
}
-static int fill_digest_bd3(struct wd_queue *q, struct hisi_sec_bd3_sqe *sqe,
- struct wcrypto_digest_msg *msg, struct wcrypto_digest_tag *tag)
+static void fill_digest_bd3_udata_addr(struct wcrypto_digest_msg *msg,
+ struct hisi_sec_bd3_sqe *sqe)
{
uintptr_t phy;
- int ret;
- ret = digest_param_check_v3(msg);
- if (unlikely(ret))
- return ret;
+ phy = (uintptr_t)msg->in;
+ sqe->data_src_addr_l = (__u32)(phy & QM_L32BITS_MASK);
+ sqe->data_src_addr_h = HI_U32(phy);
+ phy = (uintptr_t)msg->out;
+ sqe->mac_addr_l = (__u32)(phy & QM_L32BITS_MASK);
+ sqe->mac_addr_h = HI_U32(phy);
- sqe->type = BD_TYPE3;
- if (msg->alg == WCRYPTO_AES_GMAC)
- sqe->scene = SCENE_IPSEC;
- else
- sqe->scene = SCENE_STREAM;
+ if (msg->mode == WCRYPTO_DIGEST_HMAC) {
+ sqe->a_key_len = msg->key_bytes / SEC_SQE_LEN_RATE;
+ phy = (uintptr_t)msg->key;
+ sqe->auth_key_iv.a_key_addr_l = (__u32)(phy & QM_L32BITS_MASK);
+ sqe->auth_key_iv.a_key_addr_h = HI_U32(phy);
+ }
+}
+
+static void fill_digest_bd3_dif(struct hisi_sec_bd3_sqe *sqe,
+ struct wd_sec_udata *udata)
+{
+ sqe->skip_data.gran_num = udata->gran_num;
+ sqe->skip_data.src_skip_data_len = udata->src_offset;
+ sqe->storage_scene.block_size = udata->block_size;
+ sqe->storage_scene.private_info = udata->dif.priv_info;
+ sqe->storage_scene.chk_grd_ctrl = udata->dif.ctrl.verify.grd_verify_type;
+ sqe->storage_scene.chk_ref_ctrl = udata->dif.ctrl.verify.ref_verify_type;
+ sqe->storage_scene.lba_l = udata->dif.lba & QM_L32BITS_MASK;
+ sqe->storage_scene.lba_h = udata->dif.lba >> QM_HADDR_SHIFT;
+}
+
+static int fill_digest_bd3_map(struct wd_queue *q, struct hisi_sec_bd3_sqe *sqe,
+ struct wcrypto_digest_msg *msg)
+{
+ uintptr_t phy;
+ int ret;
- sqe->auth = AUTH_MAC_CALCULATE;
- sqe->a_len = msg->in_bytes;
phy = (uintptr_t)drv_iova_map(q, msg->in, msg->in_bytes);
if (unlikely(!phy)) {
WD_ERR("Get message in dma address fail!\n");
@@ -1740,33 +1798,84 @@ static int fill_digest_bd3(struct wd_queue *q, struct hisi_sec_bd3_sqe *sqe,
WD_ERR("Get digest bd3 message out dma address fail!\n");
goto map_out_error;
}
+
+ ret = set_hmac_mode_v3(msg, sqe, q);
+ if (unlikely(ret))
+ goto unmap_out;
+
+ return WD_SUCCESS;
+
+unmap_out:
+ unmap_addr(q, msg->out, msg->out_bytes, sqe->mac_addr_l,
+ sqe->mac_addr_h, msg->data_fmt);
+map_out_error:
+ phy = DMA_ADDR(sqe->data_src_addr_h, sqe->data_src_addr_l);
+ drv_iova_unmap(q, msg->in, (void *)(uintptr_t)phy, msg->in_bytes);
+ return ret;
+}
+
+static int fill_digest_bd3(struct wd_queue *q, struct hisi_sec_bd3_sqe *sqe,
+ struct wcrypto_digest_msg *msg, struct wcrypto_digest_tag *tag)
+{
+ struct wd_sec_udata *udata = tag ? tag->priv : NULL;
+ __u8 is_storage = udata && udata->gran_num != 0;
+ uintptr_t phy;
+ int ret;
+
+ ret = digest_param_check_v3(msg);
+ if (unlikely(ret))
+ return ret;
+
+ sqe->type = BD_TYPE3;
+
+ /*
+ * GMAC is an IPSEC-specific auth algo (RFC4543); other digests use
+ * stream scene for long-data hash processing.
+ */
+ if (is_storage)
+ sqe->scene = SCENE_STORAGE;
+ else if (msg->alg == WCRYPTO_AES_GMAC)
+ sqe->scene = SCENE_IPSEC;
+ else
+ sqe->scene = SCENE_STREAM;
+
+ sqe->auth = AUTH_MAC_CALCULATE;
+ sqe->a_len = msg->in_bytes;
+
+ if (udata) {
+ fill_digest_bd3_udata_addr(msg, sqe);
+ if (is_storage)
+ fill_digest_bd3_dif(sqe, udata);
+ } else {
+ ret = fill_digest_bd3_map(q, sqe, msg);
+ if (unlikely(ret))
+ return ret;
+ }
+
sqe->mac_len = msg->out_bytes / WORD_BYTES;
ret = fill_digest_bd3_alg(msg, sqe);
if (ret != WD_SUCCESS) {
WD_ERR("fill_digest_bd3_alg fail!\n");
- goto map_alg_error;
+ goto unmap;
}
ret = qm_fill_digest_long_bd3(msg, sqe);
if (ret)
- goto map_alg_error;
-
- ret = set_hmac_mode_v3(msg, sqe, q);
- if (ret)
- goto map_alg_error;
+ goto unmap;
if (tag)
sqe->tag_l = tag->wcrypto_tag.ctx_id;
return ret;
-map_alg_error:
- unmap_addr(q, msg->out, msg->out_bytes, sqe->mac_addr_l,
- sqe->mac_addr_h, msg->data_fmt);
-map_out_error:
- phy = DMA_ADDR(sqe->data_src_addr_h, sqe->data_src_addr_l);
- drv_iova_unmap(q, msg->in, (void *)(uintptr_t)phy, msg->in_bytes);
+unmap:
+ if (!udata) {
+ unmap_addr(q, msg->out, msg->out_bytes, sqe->mac_addr_l,
+ sqe->mac_addr_h, msg->data_fmt);
+ phy = DMA_ADDR(sqe->data_src_addr_h, sqe->data_src_addr_l);
+ drv_iova_unmap(q, msg->in, (void *)(uintptr_t)phy, msg->in_bytes);
+ }
return ret;
}
@@ -1776,23 +1885,15 @@ int qm_fill_digest_bd3_sqe(void *message, struct qm_queue_info *info, __u16 i)
struct wcrypto_digest_tag *tag = (void *)(uintptr_t)msg->usr_data;
struct wd_queue *q = info->q;
struct hisi_sec_bd3_sqe *sqe;
- struct hisi_sec_sqe *sqe2;
uintptr_t temp;
int ret;
temp = (uintptr_t)info->sq_base + i * info->sqe_size;
+ sqe = (struct hisi_sec_bd3_sqe *)temp;
+ memset(sqe, 0, sizeof(struct hisi_sec_bd3_sqe));
+ fill_bd3_addr_type(msg->data_fmt, sqe);
- if (tag->priv) {
- sqe2 = (struct hisi_sec_sqe *)temp;
- memset(sqe2, 0, sizeof(struct hisi_sec_sqe));
- fill_bd_addr_type(msg->data_fmt, sqe2);
- ret = fill_digest_bd_udata(q, sqe2, msg, tag);
- } else {
- sqe = (struct hisi_sec_bd3_sqe *)temp;
- memset(sqe, 0, sizeof(struct hisi_sec_bd3_sqe));
- fill_bd3_addr_type(msg->data_fmt, sqe);
- ret = fill_digest_bd3(q, sqe, msg, tag);
- }
+ ret = fill_digest_bd3(q, sqe, msg, tag);
if (ret != WD_SUCCESS)
return ret;
@@ -1890,7 +1991,7 @@ static void parse_cipher_bd2(struct wd_queue *q, struct hisi_sec_sqe *sqe,
/* In user self-define data case, may not need addr map, just return */
tag = (void *)(uintptr_t)cipher_msg->usr_data;
- if (tag->priv)
+ if (tag && tag->priv)
return;
dma_addr = DMA_ADDR(sqe->type2.data_src_addr_h,
@@ -1919,16 +2020,24 @@ static void parse_cipher_bd2(struct wd_queue *q, struct hisi_sec_sqe *sqe,
static void parse_cipher_bd3(struct wd_queue *q, struct hisi_sec_bd3_sqe *sqe,
struct wcrypto_cipher_msg *cipher_msg)
{
+ struct wcrypto_cipher_tag *tag;
__u64 dma_addr;
if (sqe->done != SEC_HW_TASK_DONE || sqe->error_type) {
WD_ERR("Fail to parse SEC BD3 %s, done=0x%x, etype=0x%x\n", "cipher",
(__u32)sqe->done, (__u32)sqe->error_type);
cipher_msg->result = WD_IN_EPARA;
+ } else if (sqe->dc == DIF_VERIFY_FAIL) {
+ cipher_msg->result = WD_VERIFY_ERR;
} else {
cipher_msg->result = WD_SUCCESS;
}
+ /* In user self-define data case, may not need addr map, just return */
+ tag = (void *)(uintptr_t)cipher_msg->usr_data;
+ if (tag && tag->priv)
+ return;
+
dma_addr = DMA_ADDR(sqe->data_src_addr_h, sqe->data_src_addr_l);
drv_iova_unmap(q, cipher_msg->in, (void *)(uintptr_t)dma_addr,
cipher_msg->in_bytes);
@@ -1990,36 +2099,15 @@ int qm_parse_cipher_bd3_sqe(void *msg, const struct qm_queue_info *info,
struct wcrypto_cipher_msg *cipher_msg = info->req_cache[i];
struct hisi_sec_bd3_sqe *sqe3 = msg;
struct wd_queue *q = info->q;
- struct hisi_sec_sqe *sqe;
if (unlikely(!cipher_msg)) {
WD_ERR("info->req_cache is null at index:%hu\n", i);
return 0;
}
+ if (unlikely(usr && sqe3->tag_l != usr))
+ return 0;
- switch (sqe3->type) {
- case BD_TYPE3:
- if (unlikely(usr && sqe3->tag_l != usr))
- return 0;
- parse_cipher_bd3(q, sqe3, cipher_msg);
- break;
- case BD_TYPE2:
- sqe = (struct hisi_sec_sqe *)sqe3;
- if (usr && sqe->type2.tag != usr)
- return 0;
- parse_cipher_bd2(q, sqe, cipher_msg);
- break;
- case BD_TYPE1:
- sqe = (struct hisi_sec_sqe *)sqe3;
- if (usr && sqe->type1.tag != usr)
- return 0;
- parse_cipher_bd1(q, sqe, cipher_msg);
- break;
- default:
- WD_ERR("SEC BD Type error\n");
- cipher_msg->result = WD_IN_EPARA;
- break;
- }
+ parse_cipher_bd3(q, sqe3, cipher_msg);
#ifdef DEBUG_LOG
sec_dump_bd((unsigned char *)msg, SQE_BYTES_NUMS);
@@ -2068,7 +2156,7 @@ static void parse_digest_bd2(struct wd_queue *q, struct hisi_sec_sqe *sqe,
digest_msg->result = WD_SUCCESS;
tag = (void *)(uintptr_t)digest_msg->usr_data;
- if (tag->priv)
+ if (tag && tag->priv)
return;
dma_addr = DMA_ADDR(sqe->type2.data_src_addr_h,
@@ -2674,16 +2762,80 @@ out:
return ret;
}
+static int fill_aead_bd3_udata_addr(struct wcrypto_aead_msg *msg,
+ struct hisi_sec_bd3_sqe *sqe, struct wd_aead_udata *udata)
+{
+ uintptr_t phy;
+
+ sqe->auth_src_offset = udata->src_offset;
+ sqe->cipher_src_offset = udata->src_offset + msg->assoc_bytes;
+
+ phy = (uintptr_t)msg->in;
+ sqe->data_src_addr_l = (__u32)(phy & QM_L32BITS_MASK);
+ sqe->data_src_addr_h = HI_U32(phy);
+ phy = (uintptr_t)msg->out;
+ sqe->data_dst_addr_l = (__u32)(phy & QM_L32BITS_MASK);
+ sqe->data_dst_addr_h = HI_U32(phy);
+ phy = (uintptr_t)msg->iv;
+ sqe->ipsec_scene.c_ivin_addr_l = (__u32)(phy & QM_L32BITS_MASK);
+ sqe->ipsec_scene.c_ivin_addr_h = HI_U32(phy);
+
+ phy = (uintptr_t)udata->ckey;
+ sqe->c_key_addr_l = (__u32)(phy & QM_L32BITS_MASK);
+ sqe->c_key_addr_h = HI_U32(phy);
+ phy = (uintptr_t)udata->mac;
+ sqe->mac_addr_l = (__u32)(phy & QM_L32BITS_MASK);
+ sqe->mac_addr_h = HI_U32(phy);
+ if (msg->cmode == WCRYPTO_CIPHER_CCM || msg->cmode == WCRYPTO_CIPHER_GCM) {
+ if (unlikely(!udata->aiv)) {
+ WD_ERR("invalid aead udata: aiv is NULL!\n");
+ return -WD_EINVAL;
+ }
+ phy = (uintptr_t)udata->aiv;
+ sqe->auth_key_iv.a_ivin_addr_l = (__u32)(phy & QM_L32BITS_MASK);
+ sqe->auth_key_iv.a_ivin_addr_h = HI_U32(phy);
+ }
+
+ return WD_SUCCESS;
+}
+
+static int init_msg_with_udata(struct wcrypto_aead_msg *req, struct wd_aead_udata *udata)
+{
+ if (!udata->ckey || !udata->mac) {
+ WD_ERR("invalid udata para!\n");
+ return -WD_EINVAL;
+ }
+
+ if (req->cmode == WCRYPTO_CIPHER_CCM || req->cmode == WCRYPTO_CIPHER_GCM) {
+ req->ckey_bytes = udata->ckey_bytes;
+ req->auth_bytes = udata->mac_bytes;
+ } else {
+ WD_ERR("invalid cmode para!\n");
+ return -WD_EINVAL;
+ }
+
+ return WD_SUCCESS;
+}
+
static int fill_aead_bd3(struct wd_queue *q, struct hisi_sec_bd3_sqe *sqe,
struct wcrypto_aead_msg *msg, struct wcrypto_aead_tag *tag)
{
+ struct wd_aead_udata *udata = tag ? tag->priv : NULL;
int ret;
+ if (udata) {
+ ret = init_msg_with_udata(msg, udata);
+ if (ret != WD_SUCCESS)
+ return ret;
+ }
+
sqe->type = BD_TYPE3;
sqe->scene = SCENE_IPSEC;
sqe->de = DATA_DST_ADDR_ENABLE;
sqe->c_len = msg->in_bytes;
- sqe->cipher_src_offset = msg->assoc_bytes;
+ sqe->cipher_src_offset = udata ? udata->src_offset + msg->assoc_bytes
+ : msg->assoc_bytes;
+ sqe->auth_src_offset = udata ? udata->src_offset : 0;
sqe->a_len = msg->in_bytes + msg->assoc_bytes;
ret = fill_aead_bd3_alg(msg, sqe);
@@ -2698,15 +2850,21 @@ static int fill_aead_bd3(struct wd_queue *q, struct hisi_sec_bd3_sqe *sqe,
return ret;
}
- ret = fill_aead_bd3_addr(q, msg, sqe);
- if (ret != WD_SUCCESS) {
- WD_ERR("fail to fill_aead_bd3_addr!\n");
- return ret;
- }
+ if (udata) {
+ ret = fill_aead_bd3_udata_addr(msg, sqe, udata);
+ if (unlikely(ret))
+ return ret;
+ } else {
+ ret = fill_aead_bd3_addr(q, msg, sqe);
+ if (ret != WD_SUCCESS) {
+ WD_ERR("fail to fill_aead_bd3_addr!\n");
+ return ret;
+ }
- ret = fill_aead_stream_bd3(q, msg, sqe);
- if (unlikely(ret))
- return ret;
+ ret = fill_aead_stream_bd3(q, msg, sqe);
+ if (unlikely(ret))
+ return ret;
+ }
if (tag)
sqe->tag_l = tag->wcrypto_tag.ctx_id;
@@ -2777,7 +2935,6 @@ int qm_fill_aead_bd3_sqe(void *message, struct qm_queue_info *info, __u16 i)
struct wcrypto_aead_tag *tag = (void *)(uintptr_t)msg->usr_data;
struct wd_queue *q = info->q;
struct hisi_sec_bd3_sqe *sqe;
- struct hisi_sec_sqe *sqe2;
uintptr_t temp;
int ret;
@@ -2789,17 +2946,11 @@ int qm_fill_aead_bd3_sqe(void *message, struct qm_queue_info *info, __u16 i)
}
temp = (uintptr_t)info->sq_base + i * info->sqe_size;
- if (tag->priv) {
- sqe2 = (struct hisi_sec_sqe *)temp;
- memset(sqe2, 0, sizeof(struct hisi_sec_sqe));
- fill_bd_addr_type(msg->data_fmt, sqe2);
- ret = fill_aead_bd_udata(q, sqe2, msg, tag);
- } else {
- sqe = (struct hisi_sec_bd3_sqe *)temp;
- memset(sqe, 0, sizeof(struct hisi_sec_bd3_sqe));
- fill_bd3_addr_type(msg->data_fmt, sqe);
- ret = fill_aead_bd3(q, sqe, msg, tag);
- }
+ sqe = (struct hisi_sec_bd3_sqe *)temp;
+ memset(sqe, 0, sizeof(struct hisi_sec_bd3_sqe));
+ fill_bd3_addr_type(msg->data_fmt, sqe);
+
+ ret = fill_aead_bd3(q, sqe, msg, tag);
if (ret != WD_SUCCESS)
return ret;
@@ -2815,6 +2966,7 @@ int qm_fill_aead_bd3_sqe(void *message, struct qm_queue_info *info, __u16 i)
static void parse_aead_bd3(struct wd_queue *q, struct hisi_sec_bd3_sqe *sqe3,
struct wcrypto_aead_msg *msg)
{
+ struct wcrypto_aead_tag *tag;
__u8 mac[AEAD_IV_MAX_BYTES] = { 0 };
__u64 dma_addr;
int ret;
@@ -2828,6 +2980,11 @@ static void parse_aead_bd3(struct wd_queue *q, struct hisi_sec_bd3_sqe *sqe3,
msg->result = WD_SUCCESS;
}
+ /* In user self-define data case, may not need addr map, just return */
+ tag = (void *)(uintptr_t)msg->usr_data;
+ if (tag && tag->priv)
+ return;
+
/*
* We obtain a memory from IV SGL as a temporary address space for MAC,
* After the encryption is completed, copy the data from this temporary
@@ -2883,26 +3040,16 @@ int qm_parse_aead_bd3_sqe(void *msg, const struct qm_queue_info *info,
{
struct wcrypto_aead_msg *aead_msg = info->req_cache[i];
struct hisi_sec_bd3_sqe *sqe = msg;
- struct hisi_sec_sqe *sqe2 = msg;
struct wd_queue *q = info->q;
if (unlikely(!aead_msg)) {
WD_ERR("info->req_cache is null at index:%hu\n", i);
return 0;
}
+ if (unlikely(usr && sqe->tag_l != usr))
+ return 0;
- if (sqe->type == BD_TYPE3) {
- if (usr && sqe->tag_l != usr)
- return 0;
- parse_aead_bd3(q, sqe, aead_msg);
- } else if (sqe->type == BD_TYPE2) {
- if (usr && sqe2->type2.tag != usr)
- return 0;
- parse_aead_bd2(q, sqe2, aead_msg);
- } else {
- WD_ERR("SEC BD Type error\n");
- aead_msg->result = WD_IN_EPARA;
- }
+ parse_aead_bd3(q, sqe, aead_msg);
#ifdef DEBUG_LOG
sec_dump_bd((unsigned char *)msg, SQE_BYTES_NUMS);
@@ -2914,16 +3061,24 @@ int qm_parse_aead_bd3_sqe(void *msg, const struct qm_queue_info *info,
static void parse_digest_bd3(struct wd_queue *q, struct hisi_sec_bd3_sqe *sqe,
struct wcrypto_digest_msg *digest_msg)
{
+ struct wcrypto_digest_tag *tag;
__u64 dma_addr;
if (sqe->done != SEC_HW_TASK_DONE || sqe->error_type) {
WD_ERR("SEC BD3 %s fail!done=0x%x, etype=0x%x\n", "digest",
(__u32)sqe->done, (__u32)sqe->error_type);
digest_msg->result = WD_IN_EPARA;
+ } else if (sqe->dc == DIF_VERIFY_FAIL) {
+ digest_msg->result = WD_VERIFY_ERR;
} else {
digest_msg->result = WD_SUCCESS;
}
+ /* In user self-define data case, may not need addr map, just return */
+ tag = (void *)(uintptr_t)digest_msg->usr_data;
+ if (tag && tag->priv)
+ return;
+
dma_addr = DMA_ADDR(sqe->data_src_addr_h, sqe->data_src_addr_l);
drv_iova_unmap(q, digest_msg->in, (void *)(uintptr_t)dma_addr,
digest_msg->in_bytes);
@@ -2946,30 +3101,16 @@ int qm_parse_digest_bd3_sqe(void *msg, const struct qm_queue_info *info,
{
struct wcrypto_digest_msg *digest_msg = info->req_cache[i];
struct hisi_sec_bd3_sqe *sqe = msg;
- struct hisi_sec_sqe *sqe2 = msg;
struct wd_queue *q = info->q;
if (unlikely(!digest_msg)) {
WD_ERR("info->req_cache is null at index:%hu\n", i);
return 0;
}
+ if (unlikely(usr && sqe->tag_l != usr))
+ return 0;
- if (sqe->type == BD_TYPE3) {
- if (usr && sqe->tag_l != usr)
- return 0;
- parse_digest_bd3(q, sqe, digest_msg);
- } else if (sqe->type == BD_TYPE2) {
- if (usr && sqe2->type2.tag != usr)
- return 0;
- parse_digest_bd2(q, sqe2, digest_msg);
- } else if (sqe->type == BD_TYPE1) {
- if (usr && sqe2->type1.tag != usr)
- return 0;
- parse_digest_bd1(q, sqe2, digest_msg);
- } else {
- WD_ERR("SEC Digest BD Type error\n");
- digest_msg->result = WD_IN_EPARA;
- }
+ parse_digest_bd3(q, sqe, digest_msg);
#ifdef DEBUG_LOG
sec_dump_bd((unsigned char *)msg, SQE_BYTES_NUMS);
@@ -3332,24 +3473,6 @@ static int fill_aead_bd2(struct wd_queue *q, struct hisi_sec_sqe *sqe,
return fill_aead_bd2_addr(q, msg, sqe);
}
-static int init_msg_with_udata(struct wcrypto_aead_msg *req, struct wd_aead_udata *udata)
-{
- if (!udata->ckey || !udata->mac) {
- WD_ERR("invalid udata para!\n");
- return -WD_EINVAL;
- }
-
- if (req->cmode == WCRYPTO_CIPHER_CCM || req->cmode == WCRYPTO_CIPHER_GCM) {
- req->ckey_bytes = udata->ckey_bytes;
- req->auth_bytes = udata->mac_bytes;
- } else {
- WD_ERR("invalid cmode para!\n");
- return -WD_EINVAL;
- }
-
- return WD_SUCCESS;
-}
-
static int fill_aead_bd2_udata(struct wd_queue *q, struct hisi_sec_sqe *sqe,
struct wcrypto_aead_msg *msg, struct wcrypto_aead_tag *tag)
{
@@ -3433,7 +3556,7 @@ static void parse_aead_bd2(struct wd_queue *q, struct hisi_sec_sqe *sqe,
}
tag = (void *)(uintptr_t)msg->usr_data;
- if (tag->priv)
+ if (tag && tag->priv)
return;
/*
--
2.28.0.windows.1