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

122 lines
3.6 KiB
Diff

From d99d0e2683c6507304f72905b773623968c0962a Mon Sep 17 00:00:00 2001
From: Wenkai Lin <linwenkai6@hisilicon.com>
Date: Fri, 11 Oct 2024 11:29:45 +0800
Subject: [PATCH 29/39] uadk: fix for cipher update iv
The cipher iv is incorrectly updated, as a result, the uadk
fails to encrypt data. The CFB, OFB, and CTR mode are modified
according to the algorithm protocol.
Signed-off-by: Wenkai Lin <linwenkai6@hisilicon.com>
Signed-off-by: Qi Tao <taoqi10@huawei.com>
---
drv/hisi_sec.c | 40 ++++++++++++++++++++++++++++------------
wd_cipher.c | 6 ++++++
2 files changed, 34 insertions(+), 12 deletions(-)
diff --git a/drv/hisi_sec.c b/drv/hisi_sec.c
index 9d69831..bdde39f 100644
--- a/drv/hisi_sec.c
+++ b/drv/hisi_sec.c
@@ -733,11 +733,14 @@ static void ctr_iv_inc(__u8 *counter, __u32 len)
static void update_iv(struct wd_cipher_msg *msg)
{
+ __u8 i;
+
switch (msg->mode) {
case WD_CIPHER_CBC:
case WD_CIPHER_CBC_CS1:
case WD_CIPHER_CBC_CS2:
case WD_CIPHER_CBC_CS3:
+ case WD_CIPHER_CFB:
if (msg->op_type == WD_CIPHER_ENCRYPTION &&
msg->out_bytes >= msg->iv_bytes)
memcpy(msg->iv, msg->out + msg->out_bytes -
@@ -748,14 +751,15 @@ static void update_iv(struct wd_cipher_msg *msg)
msg->iv_bytes, msg->iv_bytes);
break;
case WD_CIPHER_OFB:
- case WD_CIPHER_CFB:
- if (msg->out_bytes >= msg->iv_bytes)
- memcpy(msg->iv, msg->out + msg->out_bytes -
- msg->iv_bytes, msg->iv_bytes);
+ if (msg->in_bytes < msg->iv_bytes)
+ break;
+ /* The iv_bytes has been checked and it is not greater than AES_BLOCK_SIZE. */
+ for (i = 0; i < msg->iv_bytes; i++)
+ msg->iv[i] = *((__u8 *)msg->in + msg->in_bytes - msg->iv_bytes + i) ^
+ *((__u8 *)msg->out + msg->out_bytes - msg->iv_bytes + i);
break;
case WD_CIPHER_CTR:
- ctr_iv_inc(msg->iv, msg->iv_bytes >>
- CTR_MODE_LEN_SHIFT);
+ ctr_iv_inc(msg->iv, msg->in_bytes >> CTR_MODE_LEN_SHIFT);
break;
default:
break;
@@ -764,8 +768,16 @@ static void update_iv(struct wd_cipher_msg *msg)
static void update_iv_sgl(struct wd_cipher_msg *msg)
{
+ __u8 out[AES_BLOCK_SIZE] = {0};
+ __u8 in[AES_BLOCK_SIZE] = {0};
+ __u8 i;
+
switch (msg->mode) {
case WD_CIPHER_CBC:
+ case WD_CIPHER_CBC_CS1:
+ case WD_CIPHER_CBC_CS2:
+ case WD_CIPHER_CBC_CS3:
+ case WD_CIPHER_CFB:
if (msg->op_type == WD_CIPHER_ENCRYPTION &&
msg->out_bytes >= msg->iv_bytes)
hisi_qm_sgl_copy(msg->iv, msg->out,
@@ -780,16 +792,20 @@ static void update_iv_sgl(struct wd_cipher_msg *msg)
break;
case WD_CIPHER_OFB:
- case WD_CIPHER_CFB:
- if (msg->out_bytes >= msg->iv_bytes)
- hisi_qm_sgl_copy(msg->iv, msg->out,
+ /* The iv_bytes has been checked and it is not greater than AES_BLOCK_SIZE. */
+ if (msg->in_bytes >= msg->iv_bytes) {
+ hisi_qm_sgl_copy(in, msg->in,
+ msg->in_bytes - msg->iv_bytes,
+ msg->iv_bytes, COPY_SGL_TO_PBUFF);
+ hisi_qm_sgl_copy(out, msg->out,
msg->out_bytes - msg->iv_bytes,
msg->iv_bytes, COPY_SGL_TO_PBUFF);
-
+ for (i = 0; i < msg->iv_bytes; i++)
+ msg->iv[i] = *(in + i) ^ *(out + i);
+ }
break;
case WD_CIPHER_CTR:
- ctr_iv_inc(msg->iv, msg->iv_bytes >>
- CTR_MODE_LEN_SHIFT);
+ ctr_iv_inc(msg->iv, msg->in_bytes >> CTR_MODE_LEN_SHIFT);
break;
default:
break;
diff --git a/wd_cipher.c b/wd_cipher.c
index ec6fb15..0e5de25 100644
--- a/wd_cipher.c
+++ b/wd_cipher.c
@@ -646,6 +646,12 @@ static int wd_cipher_check_params(handle_t h_sess,
return -WD_EINVAL;
}
+ if (unlikely(req->in_bytes != req->out_bytes)) {
+ WD_ERR("cipher set out_bytes is error, size = %u\n",
+ req->out_bytes);
+ return -WD_EINVAL;
+ }
+
ret = cipher_in_len_check(h_sess, req);
if (unlikely(ret))
return ret;
--
2.25.1