Support AES-CBC CTS(ciphertext stealing) mode in v1, including CBC-CS1, CBC-CS2, CBC-CS3.
Signed-off-by: Zhiqi Song songzhiqi1@huawei.com --- v1/drv/hisi_sec_udrv.c | 100 ++++++++++++++++++++++++++++++++++++++--- v1/drv/hisi_sec_udrv.h | 6 +++ v1/wd_cipher.c | 3 ++ v1/wd_cipher.h | 4 ++ 4 files changed, 106 insertions(+), 7 deletions(-)
diff --git a/v1/drv/hisi_sec_udrv.c b/v1/drv/hisi_sec_udrv.c index 4d5ede5..f9cd8c0 100644 --- a/v1/drv/hisi_sec_udrv.c +++ b/v1/drv/hisi_sec_udrv.c @@ -174,6 +174,18 @@ static int fill_cipher_bd2_mode(struct wcrypto_cipher_msg *msg, case WCRYPTO_CIPHER_XTS: sqe->type2.c_mode = C_MODE_XTS; break; + case WCRYPTO_CIPHER_CBC_CS1: + sqe->type2.c_mode = C_MODE_CBC_CS; + sqe->type2.c_width = C_WIDTH_CS1; + break; + case WCRYPTO_CIPHER_CBC_CS2: + sqe->type2.c_mode = C_MODE_CBC_CS; + sqe->type2.c_width = C_WIDTH_CS2; + break; + case WCRYPTO_CIPHER_CBC_CS3: + sqe->type2.c_mode = C_MODE_CBC_CS; + sqe->type2.c_width = C_WIDTH_CS3; + break; default: WD_ERR("Invalid cipher alg type!\n"); ret = -WD_EINVAL; @@ -248,6 +260,9 @@ static void update_iv(struct wcrypto_cipher_msg *msg) { switch (msg->mode) { case WCRYPTO_CIPHER_CBC: + case WCRYPTO_CIPHER_CBC_CS1: + case WCRYPTO_CIPHER_CBC_CS2: + case WCRYPTO_CIPHER_CBC_CS3: if (msg->op_type == WCRYPTO_CIPHER_ENCRYPTION && msg->out_bytes >= msg->iv_bytes) update_iv_from_res(msg->iv, msg->out, @@ -355,6 +370,18 @@ static int fill_cipher_bd1_mode(struct wcrypto_cipher_msg *msg, case WCRYPTO_CIPHER_XTS: sqe->type1.c_mode = C_MODE_XTS; break; + case WCRYPTO_CIPHER_CBC_CS1: + sqe->type1.c_mode = C_MODE_CBC_CS; + sqe->type1.c_width = C_WIDTH_CS1; + break; + case WCRYPTO_CIPHER_CBC_CS2: + sqe->type1.c_mode = C_MODE_CBC_CS; + sqe->type1.c_width = C_WIDTH_CS2; + break; + case WCRYPTO_CIPHER_CBC_CS3: + sqe->type1.c_mode = C_MODE_CBC_CS; + sqe->type1.c_width = C_WIDTH_CS3; + break; default: WD_ERR("Invalid cipher alg type for bd1\n"); return -WD_EINVAL; @@ -582,8 +609,32 @@ map_in_error: return ret; }
+static int aes_sm4_param_check(struct wcrypto_cipher_msg *msg) +{ + if (msg->alg == WCRYPTO_CIPHER_AES && + msg->in_bytes <= CBC_AES_BLOCK_SIZE && + (msg->mode == WCRYPTO_CIPHER_CBC_CS1 || + msg->mode == WCRYPTO_CIPHER_CBC_CS2 || + msg->mode == WCRYPTO_CIPHER_CBC_CS3)) { + WD_ERR("failed to check input bytes of AES CTS, size = %u\n", + msg->in_bytes); + return -WD_EINVAL; + } + + if ((msg->in_bytes & (CBC_AES_BLOCK_SIZE - 1)) && + (msg->mode == WCRYPTO_CIPHER_CBC || + msg->mode == WCRYPTO_CIPHER_ECB)) { + WD_ERR("input AES or SM4 cipher parameter is error!\n"); + return -WD_EINVAL; + } + + return WD_SUCCESS; +} + static int cipher_param_check(struct wcrypto_cipher_msg *msg) { + int ret; + if (unlikely(msg->in_bytes > MAX_CIPHER_LENGTH || !msg->in_bytes)) { WD_ERR("input cipher len is too large!\n"); @@ -611,10 +662,9 @@ static int cipher_param_check(struct wcrypto_cipher_msg *msg) }
if (msg->alg == WCRYPTO_CIPHER_AES || msg->alg == WCRYPTO_CIPHER_SM4) { - if (unlikely(msg->in_bytes & (CBC_AES_BLOCK_SIZE - 1))) { - WD_ERR("input AES or SM4 cipher parameter is error!\n"); - return -WD_EINVAL; - } + ret = aes_sm4_param_check(msg); + if (ret) + return ret; }
return WD_SUCCESS; @@ -788,6 +838,18 @@ static int fill_cipher_bd3_mode(struct wcrypto_cipher_msg *msg, case WCRYPTO_CIPHER_CFB: sqe->c_mode = C_MODE_CFB; break; + case WCRYPTO_CIPHER_CBC_CS1: + sqe->c_mode = C_MODE_CBC_CS; + sqe->c_width = C_WIDTH_CS1; + break; + case WCRYPTO_CIPHER_CBC_CS2: + sqe->c_mode = C_MODE_CBC_CS; + sqe->c_width = C_WIDTH_CS2; + break; + case WCRYPTO_CIPHER_CBC_CS3: + sqe->c_mode = C_MODE_CBC_CS; + sqe->c_width = C_WIDTH_CS3; + break; default: WD_ERR("Invalid cipher alg type!\n"); ret = -WD_EINVAL; @@ -838,7 +900,7 @@ static int fill_cipher_bd3(struct wd_queue *q, struct hisi_sec_bd3_sqe *sqe, return ret; }
-static int sm4_aes_mode_check(int mode) +static int sm4_mode_check(int mode) { switch (mode) { case WCRYPTO_CIPHER_ECB: @@ -855,6 +917,26 @@ static int sm4_aes_mode_check(int mode) } }
+static int aes_mode_check(int mode) +{ + switch (mode) { + case WCRYPTO_CIPHER_ECB: + case WCRYPTO_CIPHER_CBC: + case WCRYPTO_CIPHER_OFB: + case WCRYPTO_CIPHER_CFB: + case WCRYPTO_CIPHER_CTR: + case WCRYPTO_CIPHER_XTS: + case WCRYPTO_CIPHER_CCM: + case WCRYPTO_CIPHER_GCM: + case WCRYPTO_CIPHER_CBC_CS1: + case WCRYPTO_CIPHER_CBC_CS2: + case WCRYPTO_CIPHER_CBC_CS3: + return WD_SUCCESS; + default: + return -WD_EINVAL; + } +} + static int triple_des_mode_check(int mode) { switch (mode) { @@ -873,8 +955,10 @@ static int cipher_comb_param_check(struct wcrypto_cipher_msg *msg)
switch (msg->alg) { case WCRYPTO_CIPHER_SM4: + ret = sm4_mode_check(msg->mode); + break; case WCRYPTO_CIPHER_AES: - ret = sm4_aes_mode_check(msg->mode); + ret = aes_mode_check(msg->mode); break; case WCRYPTO_CIPHER_DES: case WCRYPTO_CIPHER_3DES: @@ -2125,8 +2209,10 @@ static int aead_comb_param_check(struct wcrypto_aead_msg *msg)
switch (msg->calg) { case WCRYPTO_CIPHER_SM4: + ret = sm4_mode_check(msg->cmode); + break; case WCRYPTO_CIPHER_AES: - ret = sm4_aes_mode_check(msg->cmode); + ret = aes_mode_check(msg->cmode); break; default: return -WD_EINVAL; diff --git a/v1/drv/hisi_sec_udrv.h b/v1/drv/hisi_sec_udrv.h index 9c0da47..054ab71 100644 --- a/v1/drv/hisi_sec_udrv.h +++ b/v1/drv/hisi_sec_udrv.h @@ -461,6 +461,12 @@ enum C_MODE { C_MODE_CBC_CS = 0x9 };
+enum SEC_C_WIDTH { + C_WIDTH_CS1 = 0x1, + C_WIDTH_CS2 = 0x2, + C_WIDTH_CS3 = 0x3, +}; + enum CKEY_LEN { CKEY_LEN_128_BIT = 0x0, CKEY_LEN_192_BIT = 0x1, diff --git a/v1/wd_cipher.c b/v1/wd_cipher.c index 3d7d140..a53cf8f 100644 --- a/v1/wd_cipher.c +++ b/v1/wd_cipher.c @@ -82,6 +82,9 @@ static __u32 get_iv_block_size(int alg, int mode)
switch (mode) { case WCRYPTO_CIPHER_CBC: + case WCRYPTO_CIPHER_CBC_CS1: + case WCRYPTO_CIPHER_CBC_CS2: + case WCRYPTO_CIPHER_CBC_CS3: case WCRYPTO_CIPHER_OFB: if (alg == WCRYPTO_CIPHER_3DES || alg == WCRYPTO_CIPHER_DES) diff --git a/v1/wd_cipher.h b/v1/wd_cipher.h index 591a590..dafd8a4 100644 --- a/v1/wd_cipher.h +++ b/v1/wd_cipher.h @@ -47,6 +47,10 @@ enum wcrypto_cipher_mode { WCRYPTO_CIPHER_CFB, WCRYPTO_CIPHER_CCM, WCRYPTO_CIPHER_GCM, + WCRYPTO_CIPHER_CBC_CS1, + WCRYPTO_CIPHER_CBC_CS2, + WCRYPTO_CIPHER_CBC_CS3, + WCRYPTO_CIPHER_MODE_MAX, };
/**
Support user self-defined data for calculation. This means user do not need to use reserved memory provided by uadk-v1 driver and make the data to be parsed and processed by the uadk-v1 driver. Through this new feature, users can configure the custom data according to 'struct wd_sec_udata', and pass it to the 'priv' member of 'struct wcrypto_cipher_op_data', enabling hardware deal with the user custom data directly.
Note that if users want to set key through custom data, the uadk-v1 api wcrypto_set_cipher_key(), which used to set the key, should not be used anymore. Users should set the key with 'struct wd_sec_udata' type and pass it to 'priv' member.
Signed-off-by: Zhiqi Song songzhiqi1@huawei.com --- v1/drv/hisi_sec_udrv.c | 152 ++++++++++++++++++++++++++++++++++------- v1/wd_cipher.c | 4 +- 2 files changed, 129 insertions(+), 27 deletions(-)
diff --git a/v1/drv/hisi_sec_udrv.c b/v1/drv/hisi_sec_udrv.c index f9cd8c0..7f95044 100644 --- a/v1/drv/hisi_sec_udrv.c +++ b/v1/drv/hisi_sec_udrv.c @@ -390,7 +390,7 @@ static int fill_cipher_bd1_mode(struct wcrypto_cipher_msg *msg, return WD_SUCCESS; }
-static void fill_cipher_bd1_udata(struct hisi_sec_sqe *sqe, +static void fill_cipher_bd1_dif(struct hisi_sec_sqe *sqe, struct wd_sec_udata *udata) { sqe->type1.gran_num = udata->gran_num; @@ -413,6 +413,27 @@ static void fill_cipher_bd1_udata(struct hisi_sec_sqe *sqe, sqe->type1.lba_h = udata->dif.lba >> QM_HADDR_SHIFT; }
+static void fill_cipher_bd1_udata_addr(struct wcrypto_cipher_msg *msg, + struct hisi_sec_sqe *sqe) +{ + uintptr_t phy; + + phy = (uintptr_t)msg->in; + sqe->type1.data_src_addr_l = (__u32)(phy & QM_L32BITS_MASK); + sqe->type1.data_src_addr_h = HI_U32(phy); + phy = (uintptr_t)msg->out; + sqe->type1.data_dst_addr_l = (__u32)(phy & QM_L32BITS_MASK); + sqe->type1.data_dst_addr_h = HI_U32(phy); + phy = (uintptr_t)msg->key; + sqe->type1.c_key_addr_l = (__u32)(phy & QM_L32BITS_MASK); + sqe->type1.c_key_addr_h = HI_U32(phy); + if (msg->iv_bytes) { + phy = (uintptr_t)msg->iv; + sqe->type1.c_ivin_addr_l = (__u32)(phy & QM_L32BITS_MASK); + sqe->type1.c_ivin_addr_h = HI_U32(phy); + } +} + static int map_addr(struct wd_queue *q, __u8 *key, __u16 len, __u32 *addr_l, __u32 *addr_h, __u8 data_fmt) { @@ -495,8 +516,8 @@ map_key_error: static int fill_cipher_bd1(struct wd_queue *q, struct hisi_sec_sqe *sqe, struct wcrypto_cipher_msg *msg, struct wcrypto_cipher_tag *tag) { - int ret; struct wd_sec_udata *udata = tag->priv; + int ret;
sqe->type = BD_TYPE1; sqe->scene = SCENE_STORAGE; @@ -514,11 +535,16 @@ static int fill_cipher_bd1(struct wd_queue *q, struct hisi_sec_sqe *sqe, if (ret != WD_SUCCESS) return ret;
- fill_cipher_bd1_udata(sqe, udata); - - ret = fill_cipher_bd1_addr(q, msg, sqe); - if (ret != WD_SUCCESS) - return ret; + if (udata) { + /* User self-defined data with DIF scence */ + fill_cipher_bd1_dif(sqe, udata); + fill_cipher_bd1_udata_addr(msg, sqe); + } else { + /* Reserved for non user self-defined data scence */ + ret = fill_cipher_bd1_addr(q, msg, sqe); + if (ret != WD_SUCCESS) + return ret; + }
sqe->type1.tag = tag->wcrypto_tag.ctx_id;
@@ -609,6 +635,27 @@ map_in_error: return ret; }
+static void fill_cipher_bd2_udata_addr(struct wcrypto_cipher_msg *msg, + struct hisi_sec_sqe *sqe) +{ + uintptr_t phy; + + 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->key; + sqe->type2.c_key_addr_l = (__u32)(phy & QM_L32BITS_MASK); + sqe->type2.c_key_addr_h = HI_U32(phy); + if (msg->iv_bytes) { + 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); + } +} + static int aes_sm4_param_check(struct wcrypto_cipher_msg *msg) { if (msg->alg == WCRYPTO_CIPHER_AES && @@ -700,9 +747,14 @@ static int fill_cipher_bd2(struct wd_queue *q, struct hisi_sec_sqe *sqe, return ret; }
- ret = fill_cipher_bd2_addr(q, msg, sqe); - if (ret != WD_SUCCESS) - return ret; + if (tag->priv) { + /* User self-defined data process */ + fill_cipher_bd2_udata_addr(msg, sqe); + } else { + ret = fill_cipher_bd2_addr(q, msg, sqe); + if (ret != WD_SUCCESS) + return ret; + }
if (tag) sqe->type2.tag = tag->wcrypto_tag.ctx_id; @@ -973,10 +1025,11 @@ static int cipher_comb_param_check(struct wcrypto_cipher_msg *msg)
int qm_fill_cipher_sqe(void *message, struct qm_queue_info *info, __u16 i) { - struct hisi_sec_sqe *sqe; struct wcrypto_cipher_msg *msg = message; - struct wd_queue *q = info->q; 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_sqe *sqe; uintptr_t temp; int ret;
@@ -989,10 +1042,13 @@ int qm_fill_cipher_sqe(void *message, struct qm_queue_info *info, __u16 i)
temp = (uintptr_t)info->sq_base + i * info->sqe_size; sqe = (struct hisi_sec_sqe *)temp; - memset(sqe, 0, sizeof(struct hisi_sec_sqe));
- if (tag->priv) + /* + * For user self-defined data with DIF scence, will fill BD1. + * Other scences will fill BD2 by default, including no DIF scence. + */ + if (udata && udata->gran_num != 0) ret = fill_cipher_bd1(q, sqe, msg, tag); else ret = fill_cipher_bd2(q, sqe, msg, tag); @@ -1010,10 +1066,12 @@ int qm_fill_cipher_sqe(void *message, struct qm_queue_info *info, __u16 i)
int qm_fill_cipher_bd3_sqe(void *message, struct qm_queue_info *info, __u16 i) { - struct hisi_sec_bd3_sqe *sqe3; struct wcrypto_cipher_msg *msg = message; - struct wd_queue *q = info->q; 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;
@@ -1025,18 +1083,35 @@ 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 - sec_dump_bd((unsigned char *)sqe3, SQE_BYTES_NUMS); + if (udata) + sec_dump_bd((unsigned char *)sqe, SQE_BYTES_NUMS); + else + sec_dump_bd((unsigned char *)sqe3, SQE_BYTES_NUMS); #endif
return ret; @@ -1588,6 +1663,7 @@ static void cipher_ofb_data_handle(struct wcrypto_cipher_msg *msg) static void parse_cipher_bd2(struct wd_queue *q, struct hisi_sec_sqe *sqe, struct wcrypto_cipher_msg *cipher_msg) { + struct wcrypto_cipher_tag *tag; __u64 dma_addr;
if (sqe->type2.done != SEC_HW_TASK_DONE || sqe->type2.error_type) { @@ -1597,6 +1673,11 @@ static void parse_cipher_bd2(struct wd_queue *q, struct hisi_sec_sqe *sqe, } 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->priv) + return; + dma_addr = DMA_ADDR(sqe->type2.data_src_addr_h, sqe->type2.data_src_addr_l); drv_iova_unmap(q, cipher_msg->in, (void *)(uintptr_t)dma_addr, @@ -1692,25 +1773,44 @@ int qm_parse_cipher_bd3_sqe(void *msg, const struct qm_queue_info *info, __u16 i, __u16 usr) { struct wcrypto_cipher_msg *cipher_msg = info->req_cache[i]; - struct hisi_sec_bd3_sqe *sqe = msg; + 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 (likely(sqe->type == BD_TYPE3)) { - if (unlikely(usr && sqe->tag_l != usr)) + switch (sqe3->type) { + case BD_TYPE3: + if (unlikely(usr && sqe3->tag_l != usr)) return 0; - parse_cipher_bd3(q, sqe, cipher_msg); - } else { + 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; }
#ifdef DEBUG_LOG - sec_dump_bd((unsigned char *)sqe, SQE_BYTES_NUMS); + if (sqe3->type == BD_TYPE3) + sec_dump_bd((unsigned char *)sqe3, SQE_BYTES_NUMS); + else + sec_dump_bd((unsigned char *)sqe, SQE_BYTES_NUMS); #endif
return 1; diff --git a/v1/wd_cipher.c b/v1/wd_cipher.c index a53cf8f..0ae4807 100644 --- a/v1/wd_cipher.c +++ b/v1/wd_cipher.c @@ -68,7 +68,7 @@ static void del_ctx_key(struct wcrypto_cipher_ctx *ctx) if (ctx->key) { if (ctx->setup.data_fmt == WD_FLAT_BUF) memset(ctx->key, 0, MAX_CIPHER_KEY_SIZE); - else if (ctx->setup.data_fmt == WD_SGL_BUF) + else if (ctx->setup.data_fmt == WD_SGL_BUF && ctx->key_bytes) wd_sgl_cp_from_pbuf(ctx->key, 0, tmp, MAX_CIPHER_KEY_SIZE); }
@@ -351,6 +351,8 @@ static int cipher_requests_init(struct wcrypto_cipher_msg **req, req[i]->in_bytes = op[i]->in_bytes; req[i]->out = op[i]->out; req[i]->out_bytes = op[i]->out_bytes; + + /* In user self-define data case, need update key from udata */ udata = op[i]->priv; if (udata && udata->key) { req[i]->key = udata->key;
Modify the jugement sequence in aes_sm4_len_check(), prioritize the conditions that must be met.
Signed-off-by: Zhiqi Song songzhiqi1@huawei.com --- drv/hisi_sec.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drv/hisi_sec.c b/drv/hisi_sec.c index bc4c248..3341b09 100644 --- a/drv/hisi_sec.c +++ b/drv/hisi_sec.c @@ -891,18 +891,18 @@ static void parse_cipher_bd2(struct hisi_qp *qp, struct hisi_sec_sqe *sqe,
static int aes_sm4_len_check(struct wd_cipher_msg *msg) { - if ((msg->mode == WD_CIPHER_CBC_CS1 || + if (msg->alg == WD_CIPHER_AES && + msg->in_bytes <= AES_BLOCK_SIZE && + (msg->mode == WD_CIPHER_CBC_CS1 || msg->mode == WD_CIPHER_CBC_CS2 || - msg->mode == WD_CIPHER_CBC_CS3) && - msg->alg == WD_CIPHER_AES && - msg->in_bytes <= AES_BLOCK_SIZE) { + msg->mode == WD_CIPHER_CBC_CS3)) { WD_ERR("failed to check input bytes of AES_CBC_CS_X, size = %u\n", msg->in_bytes); return -WD_EINVAL; }
- if ((msg->mode == WD_CIPHER_CBC || msg->mode == WD_CIPHER_ECB) && - msg->in_bytes & (AES_BLOCK_SIZE - 1)) { + if ((msg->in_bytes & (AES_BLOCK_SIZE - 1)) && + (msg->mode == WD_CIPHER_CBC || msg->mode == WD_CIPHER_ECB)) { WD_ERR("failed to check input bytes of AES or SM4, size = %u\n", msg->in_bytes); return -WD_EINVAL;