144 lines
4.5 KiB
Diff
144 lines
4.5 KiB
Diff
From 4a66322e7be478c48b2ebcb2104fec114d37cd7b Mon Sep 17 00:00:00 2001
|
|
From: Wenkai Lin <linwenkai6@hisilicon.com>
|
|
Date: Fri, 11 Oct 2024 11:31:23 +0800
|
|
Subject: [PATCH 30/39] uadk/v1: fix for cipher update iv
|
|
|
|
The cipher iv is incorrectly updated, as a result, the uadk
|
|
fails to encrypt data. The CFB, OFB mode are modified
|
|
according to the algorithm protocol. BD2 does not support
|
|
the ofb mode, it works with cipher_ofb_data_handle, so it
|
|
still uses the old way to update iv.
|
|
|
|
Signed-off-by: Wenkai Lin <linwenkai6@hisilicon.com>
|
|
Signed-off-by: Qi Tao <taoqi10@huawei.com>
|
|
---
|
|
v1/drv/hisi_sec_udrv.c | 80 +++++++++++++++++++++++++++++++++---------
|
|
1 file changed, 63 insertions(+), 17 deletions(-)
|
|
|
|
diff --git a/v1/drv/hisi_sec_udrv.c b/v1/drv/hisi_sec_udrv.c
|
|
index ac6df5f..2c7ca20 100644
|
|
--- a/v1/drv/hisi_sec_udrv.c
|
|
+++ b/v1/drv/hisi_sec_udrv.c
|
|
@@ -253,30 +253,76 @@ static void update_iv_from_res(__u8 *dst, __u8 *src, size_t offset, __u16 bytes,
|
|
}
|
|
}
|
|
|
|
-static void update_iv(struct wcrypto_cipher_msg *msg)
|
|
+static int update_iv_ofb(struct wcrypto_cipher_msg *msg, size_t offset)
|
|
{
|
|
+ __u8 out[AES_BLOCK_SIZE] = {0};
|
|
+ __u8 in[AES_BLOCK_SIZE] = {0};
|
|
+ __u8 iv[AES_BLOCK_SIZE] = {0};
|
|
+ int ret;
|
|
+ __u8 i;
|
|
+
|
|
+ /* The iv_bytes is not greater than AES_BLOCK_SIZE. */
|
|
+ if (msg->data_fmt == WD_SGL_BUF) {
|
|
+ ret = wd_sgl_cp_to_pbuf((struct wd_sgl *)msg->out, offset,
|
|
+ (void *)out, msg->iv_bytes);
|
|
+ if (unlikely(ret))
|
|
+ return ret;
|
|
+ ret = wd_sgl_cp_to_pbuf((struct wd_sgl *)msg->in, offset,
|
|
+ (void *)in, msg->iv_bytes);
|
|
+ if (unlikely(ret))
|
|
+ return ret;
|
|
+ for (i = 0; i < msg->iv_bytes; i++)
|
|
+ iv[i] = in[i] ^ out[i];
|
|
+
|
|
+ return wd_sgl_cp_from_pbuf((struct wd_sgl *)msg->iv, 0,
|
|
+ (void *)iv, msg->iv_bytes);
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < msg->iv_bytes; i++)
|
|
+ msg->iv[i] = *((__u8 *)msg->in + offset + i) ^
|
|
+ *((__u8 *)msg->out + offset + i);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void update_iv(struct wcrypto_cipher_msg *msg, int bd_type)
|
|
+{
|
|
+ size_t offset;
|
|
+ int ret;
|
|
+
|
|
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,
|
|
- msg->out_bytes - msg->iv_bytes,
|
|
+ case WCRYPTO_CIPHER_CFB:
|
|
+ /* The out_bytes is equal to the in_bytes. */
|
|
+ if (msg->out_bytes < msg->iv_bytes)
|
|
+ break;
|
|
+
|
|
+ offset = msg->out_bytes - msg->iv_bytes;
|
|
+ if (msg->op_type == WCRYPTO_CIPHER_ENCRYPTION)
|
|
+ update_iv_from_res(msg->iv, msg->out, offset,
|
|
msg->iv_bytes, msg->data_fmt);
|
|
- if (msg->op_type == WCRYPTO_CIPHER_DECRYPTION &&
|
|
- msg->in_bytes >= msg->iv_bytes)
|
|
- update_iv_from_res(msg->iv, msg->in,
|
|
- msg->in_bytes - msg->iv_bytes,
|
|
+ else
|
|
+ update_iv_from_res(msg->iv, msg->in, offset,
|
|
msg->iv_bytes, msg->data_fmt);
|
|
break;
|
|
case WCRYPTO_CIPHER_OFB:
|
|
- case WCRYPTO_CIPHER_CFB:
|
|
- if (msg->out_bytes >= msg->iv_bytes)
|
|
- update_iv_from_res(msg->iv, msg->out,
|
|
- msg->out_bytes - msg->iv_bytes,
|
|
+ /* The out_bytes is equal to the in_bytes. */
|
|
+ if (msg->out_bytes < msg->iv_bytes)
|
|
+ break;
|
|
+
|
|
+ offset = msg->out_bytes - msg->iv_bytes;
|
|
+ /* BD2 does not support the ofb mode, it works with cipher_ofb_data_handle. */
|
|
+ if (bd_type == BD_TYPE2) {
|
|
+ update_iv_from_res(msg->iv, msg->out, offset,
|
|
msg->iv_bytes, msg->data_fmt);
|
|
+ } else if (bd_type == BD_TYPE3) {
|
|
+ ret = update_iv_ofb(msg, offset);
|
|
+ if (unlikely(ret))
|
|
+ WD_ERR("failed to update ofb iv!\n");
|
|
+ }
|
|
break;
|
|
case WCRYPTO_CIPHER_CTR:
|
|
ctr_iv_inc(msg->iv, msg->in_bytes >> CTR_MODE_LEN_SHIFT,
|
|
@@ -680,8 +726,8 @@ 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");
|
|
+ !msg->in_bytes || msg->in_bytes != msg->out_bytes)) {
|
|
+ WD_ERR("failed to check input cipher len(%u)!\n", msg->in_bytes);
|
|
return -WD_EINVAL;
|
|
}
|
|
|
|
@@ -1849,7 +1895,7 @@ static void parse_cipher_bd2(struct wd_queue *q, struct hisi_sec_sqe *sqe,
|
|
sqe->type2.c_ivin_addr_l, sqe->type2.c_ivin_addr_h,
|
|
cipher_msg->data_fmt);
|
|
|
|
- update_iv(cipher_msg);
|
|
+ update_iv(cipher_msg, BD_TYPE2);
|
|
|
|
if (cipher_msg->mode == WCRYPTO_CIPHER_OFB)
|
|
cipher_ofb_data_handle(cipher_msg);
|
|
@@ -1883,7 +1929,7 @@ static void parse_cipher_bd3(struct wd_queue *q, struct hisi_sec_bd3_sqe *sqe,
|
|
sqe->ipsec_scene.c_ivin_addr_h,
|
|
cipher_msg->data_fmt);
|
|
|
|
- update_iv(cipher_msg);
|
|
+ update_iv(cipher_msg, BD_TYPE3);
|
|
}
|
|
|
|
/*
|
|
--
|
|
2.25.1
|
|
|