* 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 | 12 ++++++++++ lib/sha3.c | 2 +- tests/test-sha3-224-buffer.c | 45 +++++++++++++++++++++++++++--------- tests/test-sha3-256-buffer.c | 45 +++++++++++++++++++++++++++--------- tests/test-sha3-384-buffer.c | 45 +++++++++++++++++++++++++++--------- tests/test-sha3-512-buffer.c | 45 +++++++++++++++++++++++++++--------- 6 files changed, 149 insertions(+), 45 deletions(-)
diff --git a/ChangeLog b/ChangeLog index 8eac7b6430..599452f58d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2026-02-22 Paul Eggert <[email protected]> + + 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 <[email protected]> strnul-bench-tests: New module. diff --git a/lib/sha3.c b/lib/sha3.c index 5ee23dc48e..352cea514a 100644 --- a/lib/sha3.c +++ b/lib/sha3.c @@ -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; } diff --git a/tests/test-sha3-224-buffer.c b/tests/test-sha3-224-buffer.c index 4df1312527..3b6dd22bf8 100644 --- a/tests/test-sha3-224-buffer.c +++ b/tests/test-sha3-224-buffer.c @@ -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 diff --git a/tests/test-sha3-256-buffer.c b/tests/test-sha3-256-buffer.c index 2f34c94fc3..ee97c95c21 100644 --- a/tests/test-sha3-256-buffer.c +++ b/tests/test-sha3-256-buffer.c @@ -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 diff --git a/tests/test-sha3-384-buffer.c b/tests/test-sha3-384-buffer.c index 6523052fe8..7452b138f9 100644 --- a/tests/test-sha3-384-buffer.c +++ b/tests/test-sha3-384-buffer.c @@ -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 diff --git a/tests/test-sha3-512-buffer.c b/tests/test-sha3-512-buffer.c index 5897b89fe6..303f75d61e 100644 --- a/tests/test-sha3-512-buffer.c +++ b/tests/test-sha3-512-buffer.c @@ -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 -- 2.51.0
