[PATCH] sha256-avx2: fix reading beyond end of input buffer

Jussi Kivilinna jussi.kivilinna at iki.fi
Wed Feb 3 17:25:56 CET 2021


* cipher/sha256-avx2-bmi2-amd64.S
(_gcry_sha256_transform_amd64_avx2): Use 'last block' code path if
input length is only one block.
* tests/basic.c (check_one_md_final): Use dynamic allocated buffer
so that in future similar access errors get detected by
tests/basic + valgrind.
--

Reported-by: Guido Vranken <guidovranken at gmail.com>
Signed-off-by: Jussi Kivilinna <jussi.kivilinna at iki.fi>
---
 cipher/sha256-avx2-bmi2-amd64.S |  7 +++++++
 tests/basic.c                   | 20 +++++++++++++++-----
 2 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/cipher/sha256-avx2-bmi2-amd64.S b/cipher/sha256-avx2-bmi2-amd64.S
index faefba17..d130dd4a 100644
--- a/cipher/sha256-avx2-bmi2-amd64.S
+++ b/cipher/sha256-avx2-bmi2-amd64.S
@@ -285,6 +285,11 @@ _gcry_sha256_transform_amd64_avx2:
 	lea	NUM_BLKS, [NUM_BLKS + INP - 64] /*  pointer to last block */
 	mov	[rsp + _INP_END], NUM_BLKS
 
+	/* Check if only one block of input. Note: Loading initial digest
+	 * only uses 'mov' instruction and does not change condition
+	 * flags. */
+	cmp	NUM_BLKS, INP
+
 	/* ; load initial digest */
 	mov	a,[4*0 + CTX]
 	mov	b,[4*1 + CTX]
@@ -297,6 +302,8 @@ _gcry_sha256_transform_amd64_avx2:
 
 	mov	[rsp + _CTX], CTX
 
+	je	.Ldo_last_block
+
 .Loop0:
 	lea	TBL, [.LK256 ADD_RIP]
 
diff --git a/tests/basic.c b/tests/basic.c
index c54de78b..b4757d9c 100644
--- a/tests/basic.c
+++ b/tests/basic.c
@@ -10478,7 +10478,8 @@ check_one_md_multi (int algo, const char *data, int len, const char *expect)
 static void
 check_one_md_final(int algo, const char *expect, unsigned int expectlen)
 {
-  char inbuf[288 + 1];
+  const unsigned int max_inbuf_len = 288 + 1;
+  char *inbuf;
   char xorbuf[64];
   char digest[64];
   unsigned int mdlen;
@@ -10499,16 +10500,25 @@ check_one_md_final(int algo, const char *expect, unsigned int expectlen)
       return;
     }
 
-  for (i = 0; i < sizeof(inbuf); i++)
-    inbuf[i] = i;
-
   clutter_vector_registers();
   gcry_md_hash_buffer (algo, xorbuf, NULL, 0);
-  for (i = 1; i < sizeof(inbuf); i++)
+  for (i = 1; i < max_inbuf_len; i++)
     {
+      inbuf = xmalloc(i);
+      if (!inbuf)
+	{
+	  fail ("out-of-memory\n");
+	  return;
+	}
+
+      for (j = 0; j < i; j++)
+	inbuf[j] = j;
+
       gcry_md_hash_buffer (algo, digest, inbuf, i);
       for (j = 0; j < expectlen; j++)
 	xorbuf[j] ^= digest[j];
+
+      xfree (inbuf);
     }
 
   if (memcmp(expect, xorbuf, expectlen) != 0)
-- 
2.27.0




More information about the Gcrypt-devel mailing list