]> git.ipfire.org Git - thirdparty/gnulib.git/commitdiff
crypto/sha3: fix partial-buffer bug
authorPaul Eggert <eggert@cs.ucla.edu>
Sun, 22 Feb 2026 16:53:14 +0000 (08:53 -0800)
committerPaul Eggert <eggert@cs.ucla.edu>
Sun, 22 Feb 2026 16:55:01 +0000 (08:55 -0800)
* lib/sha3.c (sha3_process_bytes):
Update ctx->buflen to 0 if all bytes were processed.
* tests/test-sha3-224-buffer.c:
* tests/test-sha3-256-buffer.c:
* tests/test-sha3-384-buffer.c:
* tests/test-sha3-512-buffer.c:
(mismatch): New function.
(check): Check for the bug.

ChangeLog
lib/sha3.c
tests/test-sha3-224-buffer.c
tests/test-sha3-256-buffer.c
tests/test-sha3-384-buffer.c
tests/test-sha3-512-buffer.c

index 8eac7b6430f6247d501c13bdf5e05902d9fa8b1f..599452f58d13d788439d1aa1d435f545d930db3c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2026-02-22  Paul Eggert  <eggert@cs.ucla.edu>
+
+       crypto/sha3: fix partial-buffer bug
+       * lib/sha3.c (sha3_process_bytes):
+       Update ctx->buflen to 0 if all bytes were processed.
+       * tests/test-sha3-224-buffer.c:
+       * tests/test-sha3-256-buffer.c:
+       * tests/test-sha3-384-buffer.c:
+       * tests/test-sha3-512-buffer.c:
+       (mismatch): New function.
+       (check): Check for the bug.
+
 2026-02-22  Bruno Haible  <bruno@clisp.org>
 
        strnul-bench-tests: New module.
index 5ee23dc48e1b2865694e0b6c6664148228d1d775..352cea514ab9a3b40b0db3859c37e559f20ef613 100644 (file)
@@ -163,8 +163,8 @@ sha3_process_bytes (const void *buffer, size_t len, struct sha3_ctx *ctx)
       buf += full_blocks;
       len -= full_blocks;
       memcpy (ctx->buffer, buf, len);
-      ctx->buflen = len;
     }
+  ctx->buflen = len;
   return true;
 }
 
index 4df131252795fb6b67e66bf9b04b3032e69d4776..3b6dd22bf842a3a835ee1ff8c6895d9e7b5dc850 100644 (file)
@@ -44,23 +44,46 @@ static const struct test_case test_cases[] = {
     "\x85\x07\x0a\x51\xc1\x4c\xbf\x66\x5c\xbc" },
 };
 
+static int
+mismatch (char const expect[SHA3_224_DIGEST_SIZE],
+          char const buf[SHA3_224_DIGEST_SIZE])
+{
+  if (memcmp (expect, buf, SHA3_224_DIGEST_SIZE) == 0)
+    return 0;
+  printf ("expected:\n");
+  for (size_t i = 0; i < SHA3_224_DIGEST_SIZE; i++)
+    printf ("%02x ", expect[i] & 0xFFu);
+  printf ("\ncomputed:\n");
+  for (size_t i = 0; i < SHA3_224_DIGEST_SIZE; i++)
+    printf ("%02x ", buf[i] & 0xFFu);
+  printf ("\n");
+  return 1;
+}
+
 static int
 check (char const *message, size_t len, char const *expect)
 {
+  int failed = 0;
+
   char buf[SHA3_224_DIGEST_SIZE];
-  if (memcmp (sha3_224_buffer (message, len, buf),
-              expect, SHA3_224_DIGEST_SIZE) != 0)
+  failed |= mismatch (expect, sha3_224_buffer (message, len, buf));
+
+  while (SHA3_224_BLOCK_SIZE <= len)
     {
-      printf ("expected:\n");
-      for (size_t i = 0; i < SHA3_224_DIGEST_SIZE; i++)
-        printf ("%02x ", expect[i] & 0xFFu);
-      printf ("\ncomputed:\n");
-      for (size_t i = 0; i < SHA3_224_DIGEST_SIZE; i++)
-        printf ("%02x ", buf[i] & 0xFFu);
-      printf ("\n");
-      return 1;
+      struct sha3_ctx ctx;
+      sha3_224_init_ctx (&ctx);
+      int part = SHA3_224_BLOCK_SIZE / 3;
+      sha3_process_bytes (message, part, &ctx);
+      sha3_process_bytes (message + part, SHA3_224_BLOCK_SIZE - part, &ctx);
+      char buf2[SHA3_224_DIGEST_SIZE];
+      sha3_finish_ctx (&ctx, buf2);
+      failed |= mismatch (sha3_224_buffer (message, SHA3_224_BLOCK_SIZE, buf),
+                          buf2);
+      message += SHA3_224_BLOCK_SIZE;
+      len -= SHA3_224_BLOCK_SIZE;
     }
-  return 0;
+
+  return failed;
 }
 
 int
index 2f34c94fc38757de8bd0df9f60171d11444210ca..ee97c95c211f7327962f4e267428de113c776497 100644 (file)
@@ -45,23 +45,46 @@ static const struct test_case test_cases[] = {
     "\xa3\x2d\xc3\x6c\xb3\x25\x4e\x81\x2b\xe2\x7a\xad\x1d\x18" },
 };
 
+static int
+mismatch (char const expect[SHA3_256_DIGEST_SIZE],
+          char const buf[SHA3_256_DIGEST_SIZE])
+{
+  if (memcmp (expect, buf, SHA3_256_DIGEST_SIZE) == 0)
+    return 0;
+  printf ("expected:\n");
+  for (size_t i = 0; i < SHA3_256_DIGEST_SIZE; i++)
+    printf ("%02x ", expect[i] & 0xFFu);
+  printf ("\ncomputed:\n");
+  for (size_t i = 0; i < SHA3_256_DIGEST_SIZE; i++)
+    printf ("%02x ", buf[i] & 0xFFu);
+  printf ("\n");
+  return 1;
+}
+
 static int
 check (char const *message, size_t len, char const *expect)
 {
+  int failed = 0;
+
   char buf[SHA3_256_DIGEST_SIZE];
-  if (memcmp (sha3_256_buffer (message, len, buf),
-              expect, SHA3_256_DIGEST_SIZE) != 0)
+  failed |= mismatch (expect, sha3_256_buffer (message, len, buf));
+
+  while (SHA3_256_BLOCK_SIZE <= len)
     {
-      printf ("expected:\n");
-      for (size_t i = 0; i < SHA3_256_DIGEST_SIZE; i++)
-        printf ("%02x ", expect[i] & 0xFFu);
-      printf ("\ncomputed:\n");
-      for (size_t i = 0; i < SHA3_256_DIGEST_SIZE; i++)
-        printf ("%02x ", buf[i] & 0xFFu);
-      printf ("\n");
-      return 1;
+      struct sha3_ctx ctx;
+      sha3_256_init_ctx (&ctx);
+      int part = SHA3_256_BLOCK_SIZE / 3;
+      sha3_process_bytes (message, part, &ctx);
+      sha3_process_bytes (message + part, SHA3_256_BLOCK_SIZE - part, &ctx);
+      char buf2[SHA3_256_DIGEST_SIZE];
+      sha3_finish_ctx (&ctx, buf2);
+      failed |= mismatch (sha3_256_buffer (message, SHA3_256_BLOCK_SIZE, buf),
+                          buf2);
+      message += SHA3_256_BLOCK_SIZE;
+      len -= SHA3_256_BLOCK_SIZE;
     }
-  return 0;
+
+  return failed;
 }
 
 int
index 6523052fe8177ff579ffd62dcf9757d84e114aa4..7452b138f9f88bddd90144a264de02c9f7c60256 100644 (file)
@@ -49,23 +49,46 @@ static const struct test_case test_cases[] = {
     "\xb4\x3b\x38\x52\xb3\x37\x21\x61\x79\xaa\x7f\xc7" }
 };
 
+static int
+mismatch (char const expect[SHA3_384_DIGEST_SIZE],
+          char const buf[SHA3_384_DIGEST_SIZE])
+{
+  if (memcmp (expect, buf, SHA3_384_DIGEST_SIZE) == 0)
+    return 0;
+  printf ("expected:\n");
+  for (size_t i = 0; i < SHA3_384_DIGEST_SIZE; i++)
+    printf ("%02x ", expect[i] & 0xFFu);
+  printf ("\ncomputed:\n");
+  for (size_t i = 0; i < SHA3_384_DIGEST_SIZE; i++)
+    printf ("%02x ", buf[i] & 0xFFu);
+  printf ("\n");
+  return 1;
+}
+
 static int
 check (char const *message, size_t len, char const *expect)
 {
+  int failed = 0;
+
   char buf[SHA3_384_DIGEST_SIZE];
-  if (memcmp (sha3_384_buffer (message, len, buf),
-              expect, SHA3_384_DIGEST_SIZE) != 0)
+  failed |= mismatch (expect, sha3_384_buffer (message, len, buf));
+
+  while (SHA3_384_BLOCK_SIZE <= len)
     {
-      printf ("expected:\n");
-      for (size_t i = 0; i < SHA3_384_DIGEST_SIZE; i++)
-        printf ("%02x ", expect[i] & 0xFFu);
-      printf ("\ncomputed:\n");
-      for (size_t i = 0; i < SHA3_384_DIGEST_SIZE; i++)
-        printf ("%02x ", buf[i] & 0xFFu);
-      printf ("\n");
-      return 1;
+      struct sha3_ctx ctx;
+      sha3_384_init_ctx (&ctx);
+      int part = SHA3_384_BLOCK_SIZE / 3;
+      sha3_process_bytes (message, part, &ctx);
+      sha3_process_bytes (message + part, SHA3_384_BLOCK_SIZE - part, &ctx);
+      char buf2[SHA3_384_DIGEST_SIZE];
+      sha3_finish_ctx (&ctx, buf2);
+      failed |= mismatch (sha3_384_buffer (message, SHA3_384_BLOCK_SIZE, buf),
+                          buf2);
+      message += SHA3_384_BLOCK_SIZE;
+      len -= SHA3_384_BLOCK_SIZE;
     }
-  return 0;
+
+  return failed;
 }
 
 int
index 5897b89fe6bcbda2ce756c79052554b40617e2e5..303f75d61ebeb91cc1a75c71186e23fbb175d8eb 100644 (file)
@@ -53,23 +53,46 @@ static const struct test_case test_cases[] = {
     "\xf3\x82\x27\x0c\xb4\x55\xf2\x1d\xd1\x85" }
 };
 
+static int
+mismatch (char const expect[SHA3_512_DIGEST_SIZE],
+          char const buf[SHA3_512_DIGEST_SIZE])
+{
+  if (memcmp (expect, buf, SHA3_512_DIGEST_SIZE) == 0)
+    return 0;
+  printf ("expected:\n");
+  for (size_t i = 0; i < SHA3_512_DIGEST_SIZE; i++)
+    printf ("%02x ", expect[i] & 0xFFu);
+  printf ("\ncomputed:\n");
+  for (size_t i = 0; i < SHA3_512_DIGEST_SIZE; i++)
+    printf ("%02x ", buf[i] & 0xFFu);
+  printf ("\n");
+  return 1;
+}
+
 static int
 check (char const *message, size_t len, char const *expect)
 {
+  int failed = 0;
+
   char buf[SHA3_512_DIGEST_SIZE];
-  if (memcmp (sha3_512_buffer (message, len, buf),
-              expect, SHA3_512_DIGEST_SIZE) != 0)
+  failed |= mismatch (expect, sha3_512_buffer (message, len, buf));
+
+  while (SHA3_512_BLOCK_SIZE <= len)
     {
-      printf ("expected:\n");
-      for (size_t i = 0; i < SHA3_512_DIGEST_SIZE; i++)
-        printf ("%02x ", expect[i] & 0xFFu);
-      printf ("\ncomputed:\n");
-      for (size_t i = 0; i < SHA3_512_DIGEST_SIZE; i++)
-        printf ("%02x ", buf[i] & 0xFFu);
-      printf ("\n");
-      return 1;
+      struct sha3_ctx ctx;
+      sha3_512_init_ctx (&ctx);
+      int part = SHA3_512_BLOCK_SIZE / 3;
+      sha3_process_bytes (message, part, &ctx);
+      sha3_process_bytes (message + part, SHA3_512_BLOCK_SIZE - part, &ctx);
+      char buf2[SHA3_512_DIGEST_SIZE];
+      sha3_finish_ctx (&ctx, buf2);
+      failed |= mismatch (sha3_512_buffer (message, SHA3_512_BLOCK_SIZE, buf),
+                          buf2);
+      message += SHA3_512_BLOCK_SIZE;
+      len -= SHA3_512_BLOCK_SIZE;
     }
-  return 0;
+
+  return failed;
 }
 
 int