+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.
buf += full_blocks;
len -= full_blocks;
memcpy (ctx->buffer, buf, len);
- ctx->buflen = len;
}
+ ctx->buflen = len;
return true;
}
"\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
"\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
"\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
"\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