libwd/0030-uadk-v1-fix-for-cipher-update-iv.patch
2024-11-19 11:51:09 +08:00

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