316 lines
9.6 KiB
Diff
316 lines
9.6 KiB
Diff
From 5d971d27ddfadea7a7f68749decc94a5ffbe6ae3 Mon Sep 17 00:00:00 2001
|
||
From: Wenkai Lin <linwenkai6@hisilicon.com>
|
||
Date: Tue, 8 Aug 2023 21:22:22 +0800
|
||
Subject: [PATCH 13/26] uadk: support aead to parse user private data
|
||
|
||
In aead storage scene, the address filled by users are DMA address,
|
||
which are transferred to the WD through the opdata priv field.
|
||
The WD only needs to parse the address and fill them in the hardware BD,
|
||
the IOVA map is not required for address translation.
|
||
|
||
Signed-off-by: Wenkai Lin <linwenkai6@hisilicon.com>
|
||
---
|
||
v1/drv/hisi_sec_udrv.c | 142 ++++++++++++++++++++++++++++++++++++-----
|
||
v1/wd_aead.c | 10 +--
|
||
v1/wd_util.h | 13 ++++
|
||
3 files changed, 142 insertions(+), 23 deletions(-)
|
||
|
||
diff --git a/v1/drv/hisi_sec_udrv.c b/v1/drv/hisi_sec_udrv.c
|
||
index f42022b..32bded4 100644
|
||
--- a/v1/drv/hisi_sec_udrv.c
|
||
+++ b/v1/drv/hisi_sec_udrv.c
|
||
@@ -64,6 +64,11 @@ static int g_hmac_a_alg[WCRYPTO_MAX_DIGEST_TYPE] = {
|
||
A_ALG_HMAC_SHA512, A_ALG_HMAC_SHA512_224, A_ALG_HMAC_SHA512_256
|
||
};
|
||
|
||
+static void parse_aead_bd2(struct wd_queue *q, struct hisi_sec_sqe *sqe,
|
||
+ struct wcrypto_aead_msg *msg);
|
||
+static int fill_aead_bd_udata(struct wd_queue *q, struct hisi_sec_sqe *sqe,
|
||
+ struct wcrypto_aead_msg *msg, struct wcrypto_aead_tag *tag);
|
||
+
|
||
#ifdef DEBUG_LOG
|
||
static void sec_dump_bd(unsigned char *bd, unsigned int len)
|
||
{
|
||
@@ -2224,6 +2229,7 @@ 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;
|
||
|
||
@@ -2235,13 +2241,17 @@ 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;
|
||
- 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 (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);
|
||
+ }
|
||
if (ret != WD_SUCCESS)
|
||
return ret;
|
||
|
||
@@ -2313,6 +2323,7 @@ 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)) {
|
||
@@ -2324,6 +2335,10 @@ int qm_parse_aead_bd3_sqe(void *msg, const struct qm_queue_info *info,
|
||
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;
|
||
@@ -2664,7 +2679,45 @@ static int aead_param_len_check(struct wcrypto_aead_msg *msg)
|
||
return 0;
|
||
}
|
||
|
||
-static int fill_aead_bd2(struct wd_queue *q, struct hisi_sec_sqe *sqe,
|
||
+static int fill_aead_bd2_udata_inner(struct wcrypto_aead_msg *msg,
|
||
+ struct hisi_sec_sqe *sqe, struct wd_aead_udata *udata)
|
||
+{
|
||
+ uintptr_t phy;
|
||
+
|
||
+ sqe->type2.auth_src_offset = udata->src_offset;
|
||
+ sqe->type2.cipher_src_offset = udata->src_offset + msg->assoc_bytes;
|
||
+ /* for bd2 udata scene, address do not need to be mapped. */
|
||
+ phy = (uintptr_t)msg->in;
|
||
+ sqe->type2.data_src_addr_l = (__u32)(phy & QM_L32BITS_MASK);
|
||
+ sqe->type2.data_src_addr_h = HI_U32(phy);
|
||
+ phy = (uintptr_t)msg->out;
|
||
+ sqe->type2.data_dst_addr_l = (__u32)(phy & QM_L32BITS_MASK);
|
||
+ sqe->type2.data_dst_addr_h = HI_U32(phy);
|
||
+ phy = (uintptr_t)msg->iv;
|
||
+ sqe->type2.c_ivin_addr_l = (__u32)(phy & QM_L32BITS_MASK);
|
||
+ sqe->type2.c_ivin_addr_h = HI_U32(phy);
|
||
+
|
||
+ phy = (uintptr_t)udata->ckey;
|
||
+ sqe->type2.c_key_addr_l = (__u32)(phy & QM_L32BITS_MASK);
|
||
+ sqe->type2.c_key_addr_h = HI_U32(phy);
|
||
+ phy = (uintptr_t)udata->mac;
|
||
+ sqe->type2.mac_addr_l = (__u32)(phy & QM_L32BITS_MASK);
|
||
+ sqe->type2.mac_addr_h = HI_U32(phy);
|
||
+ if (msg->cmode == WCRYPTO_CIPHER_CCM || msg->cmode == WCRYPTO_CIPHER_GCM) {
|
||
+ if (udata->aiv) {
|
||
+ phy = (uintptr_t)udata->aiv;
|
||
+ sqe->type2.a_ivin_addr_l = (__u32)(phy & QM_L32BITS_MASK);
|
||
+ sqe->type2.a_ivin_addr_h = HI_U32(phy);
|
||
+ } else {
|
||
+ WD_ERR("Invalid aiv addr in CCM/GCM mode!\n");
|
||
+ return -WD_EINVAL;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return WD_SUCCESS;
|
||
+}
|
||
+
|
||
+static int fill_aead_bd2_common(struct wd_queue *q, struct hisi_sec_sqe *sqe,
|
||
struct wcrypto_aead_msg *msg, struct wcrypto_aead_tag *tag)
|
||
{
|
||
int ret;
|
||
@@ -2686,26 +2739,77 @@ static int fill_aead_bd2(struct wd_queue *q, struct hisi_sec_sqe *sqe,
|
||
|
||
ret = fill_aead_bd2_alg(msg, sqe);
|
||
if (ret != WD_SUCCESS) {
|
||
- WD_ERR("fill_cipher_bd2_alg fail!\n");
|
||
+ WD_ERR("fill_aead_bd2_alg fail!\n");
|
||
return ret;
|
||
}
|
||
|
||
ret = fill_aead_bd2_mode(msg, sqe);
|
||
if (ret != WD_SUCCESS) {
|
||
- WD_ERR("fill_cipher_bd2_mode fail!\n");
|
||
+ WD_ERR("fill_aead_bd2_mode fail!\n");
|
||
return ret;
|
||
}
|
||
|
||
- ret = fill_aead_bd2_addr(q, msg, sqe);
|
||
- if (ret != WD_SUCCESS)
|
||
- return ret;
|
||
-
|
||
if (tag)
|
||
sqe->type2.tag = tag->wcrypto_tag.ctx_id;
|
||
|
||
return ret;
|
||
}
|
||
|
||
+static int fill_aead_bd2(struct wd_queue *q, struct hisi_sec_sqe *sqe,
|
||
+ struct wcrypto_aead_msg *msg, struct wcrypto_aead_tag *tag)
|
||
+{
|
||
+ int ret;
|
||
+
|
||
+ ret = fill_aead_bd2_common(q, sqe, msg, tag);
|
||
+ if (ret != WD_SUCCESS)
|
||
+ return ret;
|
||
+
|
||
+ 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)
|
||
+{
|
||
+ int ret;
|
||
+
|
||
+ ret = fill_aead_bd2_common(q, sqe, msg, tag);
|
||
+ if (ret != WD_SUCCESS)
|
||
+ return ret;
|
||
+
|
||
+ return fill_aead_bd2_udata_inner(msg, sqe, (struct wd_aead_udata *)tag->priv);
|
||
+}
|
||
+
|
||
+static int fill_aead_bd_udata(struct wd_queue *q, struct hisi_sec_sqe *sqe,
|
||
+ struct wcrypto_aead_msg *msg, struct wcrypto_aead_tag *tag)
|
||
+{
|
||
+ struct wd_aead_udata *udata = tag->priv;
|
||
+ int ret;
|
||
+
|
||
+ ret = init_msg_with_udata(msg, udata);
|
||
+ if (ret != WD_SUCCESS)
|
||
+ return ret;
|
||
+
|
||
+ return fill_aead_bd2_udata(q, sqe, msg, tag);
|
||
+}
|
||
+
|
||
int qm_fill_aead_sqe(void *message, struct qm_queue_info *info, __u16 i)
|
||
{
|
||
struct wcrypto_aead_msg *msg = message;
|
||
@@ -2727,7 +2831,10 @@ int qm_fill_aead_sqe(void *message, struct qm_queue_info *info, __u16 i)
|
||
|
||
memset(sqe, 0, sizeof(struct hisi_sec_sqe));
|
||
|
||
- ret = fill_aead_bd2(q, sqe, msg, tag);
|
||
+ if (tag->priv)
|
||
+ ret = fill_aead_bd_udata(q, sqe, msg, tag);
|
||
+ else
|
||
+ ret = fill_aead_bd2(q, sqe, msg, tag);
|
||
if (ret != WD_SUCCESS)
|
||
return ret;
|
||
|
||
@@ -2743,6 +2850,7 @@ int qm_fill_aead_sqe(void *message, struct qm_queue_info *info, __u16 i)
|
||
static void parse_aead_bd2(struct wd_queue *q, struct hisi_sec_sqe *sqe,
|
||
struct wcrypto_aead_msg *msg)
|
||
{
|
||
+ struct wcrypto_aead_tag *tag;
|
||
__u8 mac[64] = { 0 };
|
||
__u64 dma_addr;
|
||
int ret;
|
||
@@ -2756,6 +2864,10 @@ static void parse_aead_bd2(struct wd_queue *q, struct hisi_sec_sqe *sqe,
|
||
msg->result = WD_SUCCESS;
|
||
}
|
||
|
||
+ tag = (void *)(uintptr_t)msg->usr_data;
|
||
+ if (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
|
||
diff --git a/v1/wd_aead.c b/v1/wd_aead.c
|
||
index 7abb8a0..f81f327 100644
|
||
--- a/v1/wd_aead.c
|
||
+++ b/v1/wd_aead.c
|
||
@@ -79,14 +79,14 @@ static void del_ctx_key(struct wcrypto_aead_ctx *ctx)
|
||
* want to clear the SGL buffer, we can only use 'wd_sgl_cp_from_pbuf'
|
||
* whose 'pbuf' is all zero.
|
||
*/
|
||
- if (ctx->ckey) {
|
||
+ if (ctx->ckey && ctx->ckey_bytes) {
|
||
if (ctx->setup.data_fmt == WD_FLAT_BUF)
|
||
memset(ctx->ckey, 0, MAX_CIPHER_KEY_SIZE);
|
||
else if (ctx->setup.data_fmt == WD_SGL_BUF)
|
||
wd_sgl_cp_from_pbuf(ctx->ckey, 0, tmp, MAX_CIPHER_KEY_SIZE);
|
||
}
|
||
|
||
- if (ctx->akey) {
|
||
+ if (ctx->akey && ctx->akey_bytes) {
|
||
if (ctx->setup.data_fmt == WD_FLAT_BUF)
|
||
memset(ctx->akey, 0, MAX_AEAD_KEY_SIZE);
|
||
else if (ctx->setup.data_fmt == WD_SGL_BUF)
|
||
@@ -445,7 +445,6 @@ static int aead_requests_init(struct wcrypto_aead_msg **req,
|
||
struct wcrypto_aead_op_data **op,
|
||
struct wcrypto_aead_ctx *ctx, __u32 num)
|
||
{
|
||
- struct wd_sec_udata *udata;
|
||
int ret;
|
||
__u32 i;
|
||
|
||
@@ -471,11 +470,6 @@ static int aead_requests_init(struct wcrypto_aead_msg **req,
|
||
req[i]->out_bytes = op[i]->out_bytes;
|
||
req[i]->assoc_bytes = op[i]->assoc_size;
|
||
req[i]->auth_bytes = ctx->auth_size;
|
||
- udata = op[i]->priv;
|
||
- if (udata && udata->key) {
|
||
- req[i]->ckey = udata->key;
|
||
- req[i]->ckey_bytes = udata->key_bytes;
|
||
- }
|
||
|
||
req[i]->aiv = ctx->setup.br.alloc(ctx->setup.br.usr,
|
||
MAX_AEAD_KEY_SIZE);
|
||
diff --git a/v1/wd_util.h b/v1/wd_util.h
|
||
index fc4586c..617af3b 100644
|
||
--- a/v1/wd_util.h
|
||
+++ b/v1/wd_util.h
|
||
@@ -175,6 +175,19 @@ struct wd_sec_udata {
|
||
__u8 *key;
|
||
};
|
||
|
||
+struct wd_aead_udata {
|
||
+ __u32 src_offset;
|
||
+ __u32 dst_offset;
|
||
+ __u16 ckey_bytes;
|
||
+ __u16 akey_bytes;
|
||
+ __u16 aiv_bytes;
|
||
+ __u16 mac_bytes;
|
||
+ __u8 *ckey;
|
||
+ __u8 *akey;
|
||
+ __u8 *aiv;
|
||
+ __u8 *mac;
|
||
+};
|
||
+
|
||
/* Digest tag format of Warpdrive */
|
||
struct wcrypto_digest_tag {
|
||
struct wcrypto_cb_tag wcrypto_tag;
|
||
--
|
||
2.25.1
|
||
|