Hello,

We realized that cfb8_decrypt doesn't update the IV correctly when the
input is shorter than AES block size.  The attached patches should fix
it.

Samba is also affected by this and there are similar fixes:
https://git.samba.org/?p=gd/nettle;a=commit;h=c9926d319a44858d9bde5c28e37f37ed4e3ad39a
https://git.samba.org/?p=gd/nettle;a=commit;h=a2aa783012ab874eebe79d6150027118fc823f52

Regards,
-- 
Daiki Ueno
>From 69fffd761a08e7915a0b544ccb3d5e680571fc18 Mon Sep 17 00:00:00 2001
From: Daiki Ueno <[email protected]>
Date: Mon, 30 Sep 2019 11:21:09 +0200
Subject: [PATCH 1/2] testsuite/cfb-test: check output IV

Signed-off-by: Daiki Ueno <[email protected]>
---
 testsuite/cfb-test.c  | 18 ++++++++++++------
 testsuite/testutils.c | 42 ++++++++++++++++++++++++++++++++++++++++--
 testsuite/testutils.h |  6 ++++--
 3 files changed, 56 insertions(+), 10 deletions(-)

diff --git a/testsuite/cfb-test.c b/testsuite/cfb-test.c
index dbb24e8a..7c42bec5 100644
--- a/testsuite/cfb-test.c
+++ b/testsuite/cfb-test.c
@@ -137,7 +137,8 @@ test_main(void)
 		        "ae2d"),
 		   SHEX("3b79424c9c0dd436bace9e0ed4586a4f"
 		        "32b9"),
-		   SHEX("000102030405060708090a0b0c0d0e0f"));
+		   SHEX("000102030405060708090a0b0c0d0e0f"),
+		   SHEX("424c9c0dd436bace9e0ed4586a4f32b9"));
 
   /* From NIST spec 800-38a on AES modes.
    *
@@ -152,7 +153,8 @@ test_main(void)
 		        "ae2d"),
 		   SHEX("cda2521ef0a905ca44cd057cbf0d47a0"
 			"678a"),
-		   SHEX("000102030405060708090a0b0c0d0e0f"));
+		   SHEX("000102030405060708090a0b0c0d0e0f"),
+		   SHEX("521ef0a905ca44cd057cbf0d47a0678a"));
 
   /* From NIST spec 800-38a on AES modes.
    *
@@ -167,7 +169,8 @@ test_main(void)
 		        "ae2d"),
 		   SHEX("dc1f1a8520a64db55fcc8ac554844e88"
 			"9700"),
-		   SHEX("000102030405060708090a0b0c0d0e0f"));
+		   SHEX("000102030405060708090a0b0c0d0e0f"),
+		   SHEX("1a8520a64db55fcc8ac554844e889700"));
 
   /* From NIST spec 800-38a on AES modes.
    *
@@ -192,7 +195,8 @@ test_main(void)
 		       "c8a64537a0b3a93fcde3cdad9f1ce58b"
 		       "26751f67a3cbb140b1808cf187a4f4df"
 		       "c04b05357c5d1c0eeac4c66f9ff7f2e6"),
-		  SHEX("000102030405060708090a0b0c0d0e0f"));
+		  SHEX("000102030405060708090a0b0c0d0e0f"),
+		  SHEX("c04b05357c5d1c0eeac4c66f9ff7f2e6"));
 
   /* F.3.15 CFB128-AES192.Encrypt */
 
@@ -215,7 +219,8 @@ test_main(void)
 		       "67ce7f7f81173621961a2b70171d3d7a"
 		       "2e1e8a1dd59b88b1c8e60fed1efac4c9"
 		       "c05f9f9ca9834fa042ae8fba584b09ff"),
-		  SHEX("000102030405060708090a0b0c0d0e0f"));
+		  SHEX("000102030405060708090a0b0c0d0e0f"),
+		  SHEX("c05f9f9ca9834fa042ae8fba584b09ff"));
 
   /* F.3.17 CFB128-AES256.Encrypt */
 
@@ -238,7 +243,8 @@ test_main(void)
 		       "39ffed143b28b1c832113c6331e5407b"
 		       "df10132415e54b92a13ed0a8267ae2f9"
 		       "75a385741ab9cef82031623d55b1e471"),
-		  SHEX("000102030405060708090a0b0c0d0e0f"));
+		  SHEX("000102030405060708090a0b0c0d0e0f"),
+		  SHEX("75a385741ab9cef82031623d55b1e471"));
 
   test_cfb_bulk();
   test_cfb8_bulk();
diff --git a/testsuite/testutils.c b/testsuite/testutils.c
index 2a19c0ac..6f6974f9 100644
--- a/testsuite/testutils.c
+++ b/testsuite/testutils.c
@@ -250,7 +250,8 @@ test_cipher_cfb(const struct nettle_cipher *cipher,
 		const struct tstring *key,
 		const struct tstring *cleartext,
 		const struct tstring *ciphertext,
-		const struct tstring *iiv)
+		const struct tstring *iiv,
+		const struct tstring *oiv)
 {
   void *ctx = xalloc(cipher->context_size);
   uint8_t *data, *data2;
@@ -284,6 +285,15 @@ test_cipher_cfb(const struct nettle_cipher *cipher,
       fprintf(stderr, "\n");
       FAIL();
     }
+  if (!MEMEQ(cipher->block_size, iv, oiv->data))
+    {
+      fprintf(stderr, "CFB encrypt returned wrong IV:\nOutput:");
+      print_hex(cipher->block_size, iv);
+      fprintf(stderr, "\nExpected:");
+      tstring_print_hex(oiv);
+      fprintf(stderr, "\n");
+      FAIL();
+    }
   cipher->set_encrypt_key(ctx, key->data);
   memcpy(iv, iiv->data, cipher->block_size);
 
@@ -302,6 +312,15 @@ test_cipher_cfb(const struct nettle_cipher *cipher,
       fprintf(stderr, "\n");
       FAIL();
     }
+  if (!MEMEQ(cipher->block_size, iv, oiv->data))
+    {
+      fprintf(stderr, "CFB decrypt returned wrong IV:\nOutput:");
+      print_hex(cipher->block_size, iv);
+      fprintf(stderr, "\nExpected:");
+      tstring_print_hex(oiv);
+      fprintf(stderr, "\n");
+      FAIL();
+    }
   cipher->set_encrypt_key(ctx, key->data);
   memcpy(iv, iiv->data, cipher->block_size);
   memcpy(data, cleartext->data, length);
@@ -428,7 +447,8 @@ test_cipher_cfb8(const struct nettle_cipher *cipher,
 		 const struct tstring *key,
 		 const struct tstring *cleartext,
 		 const struct tstring *ciphertext,
-		 const struct tstring *iiv)
+		 const struct tstring *iiv,
+		 const struct tstring *oiv)
 {
   void *ctx = xalloc(cipher->context_size);
   uint8_t *data, *data2;
@@ -462,6 +482,15 @@ test_cipher_cfb8(const struct nettle_cipher *cipher,
       fprintf(stderr, "\n");
       FAIL();
     }
+  if (!MEMEQ(cipher->block_size, iv, oiv->data))
+    {
+      fprintf(stderr, "CFB8 encrypt returned wrong IV:\nOutput:");
+      print_hex(cipher->block_size, iv);
+      fprintf(stderr, "\nExpected:");
+      tstring_print_hex(oiv);
+      fprintf(stderr, "\n");
+      FAIL();
+    }
   cipher->set_encrypt_key(ctx, key->data);
   memcpy(iv, iiv->data, cipher->block_size);
 
@@ -480,6 +509,15 @@ test_cipher_cfb8(const struct nettle_cipher *cipher,
       fprintf(stderr, "\n");
       FAIL();
     }
+  if (!MEMEQ(cipher->block_size, iv, oiv->data))
+    {
+      fprintf(stderr, "CFB8 decrypt returned wrong IV:\nOutput:");
+      print_hex(cipher->block_size, iv);
+      fprintf(stderr, "\nExpected:");
+      tstring_print_hex(oiv);
+      fprintf(stderr, "\n");
+      FAIL();
+    }
   cipher->set_encrypt_key(ctx, key->data);
   memcpy(iv, iiv->data, cipher->block_size);
   memcpy(data, cleartext->data, length);
diff --git a/testsuite/testutils.h b/testsuite/testutils.h
index f4ea38da..93db801b 100644
--- a/testsuite/testutils.h
+++ b/testsuite/testutils.h
@@ -127,14 +127,16 @@ test_cipher_cfb(const struct nettle_cipher *cipher,
 		const struct tstring *key,
 		const struct tstring *cleartext,
 		const struct tstring *ciphertext,
-		const struct tstring *iv);
+		const struct tstring *iiv,
+		const struct tstring *oiv);
 
 void
 test_cipher_cfb8(const struct nettle_cipher *cipher,
 		 const struct tstring *key,
 		 const struct tstring *cleartext,
 		 const struct tstring *ciphertext,
-		 const struct tstring *iv);
+		 const struct tstring *iiv,
+		 const struct tstring *oiv);
 
 void
 test_cipher_ctr(const struct nettle_cipher *cipher,
-- 
2.21.0

>From 1820f8524c0476069c53c893a08cc1e432092a5e Mon Sep 17 00:00:00 2001
From: Daiki Ueno <[email protected]>
Date: Fri, 27 Sep 2019 16:12:00 +0200
Subject: [PATCH 2/2] cfb8: don't truncate output IV if input is shorter than
 block size

Previously cfb8_decrypt didn't update the IV if the input is shorter
than the AES block size.  Reported by Stephan Mueller.

Signed-off-by: Daiki Ueno <[email protected]>
---
 cfb.c                | 10 ++++++----
 testsuite/cfb-test.c |  9 +++++++++
 2 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/cfb.c b/cfb.c
index 5429fc9c..b9da3159 100644
--- a/cfb.c
+++ b/cfb.c
@@ -226,10 +226,12 @@ cfb8_decrypt(const void *ctx, nettle_cipher_func *f,
       src += i;
       dst += i;
 
-      memcpy(buffer, buffer + block_size, block_size);
-      memcpy(buffer + block_size, src,
-	     length < block_size ? length : block_size);
-
+      if (i == block_size)
+	{
+	  memcpy(buffer, buffer + block_size, block_size);
+	  memcpy(buffer + block_size, src,
+		 length < block_size ? length : block_size);
+	}
     }
 
   memcpy(iv, buffer + i, block_size);
diff --git a/testsuite/cfb-test.c b/testsuite/cfb-test.c
index 7c42bec5..02bc63cc 100644
--- a/testsuite/cfb-test.c
+++ b/testsuite/cfb-test.c
@@ -140,6 +140,15 @@ test_main(void)
 		   SHEX("000102030405060708090a0b0c0d0e0f"),
 		   SHEX("424c9c0dd436bace9e0ed4586a4f32b9"));
 
+  /* Check if the intermediate IV is updated correctly with input
+   * shorter than AES block size. */
+  test_cipher_cfb8(&nettle_aes128,
+		   SHEX("2b7e151628aed2a6abf7158809cf4f3c"),
+		   SHEX("6bc1"),
+		   SHEX("3b79"),
+		   SHEX("000102030405060708090a0b0c0d0e0f"),
+		   SHEX("02030405060708090a0b0c0d0e0f3b79"));
+
   /* From NIST spec 800-38a on AES modes.
    *
    * F.3  CFB Example Vectors
-- 
2.21.0

_______________________________________________
nettle-bugs mailing list
[email protected]
http://lists.lysator.liu.se/mailman/listinfo/nettle-bugs

Reply via email to