]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: Fix sha2 functions to not produce wrong results with >500MB input
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Fri, 6 Oct 2023 12:59:32 +0000 (15:59 +0300)
committerDovecot Automation <automation@dovecot.org>
Fri, 6 Oct 2023 15:57:54 +0000 (15:57 +0000)
src/lib/sha2.c
src/lib/sha2.h
src/lib/test-hash-method.c

index 93dddfbb397bbe424173ce778ab34b3b827efbd9..b6bef47684d92f6475d95e454599c0909860ce5f 100644 (file)
@@ -287,7 +287,7 @@ void sha256_result(struct sha256_ctx *ctx,
 {
        size_t block_nb;
        size_t pm_len;
-       size_t len_b;
+       uint64_t len_b;
        int i;
 
        block_nb = (1 + ((SHA256_BLOCK_SIZE - 9)
@@ -298,7 +298,7 @@ void sha256_result(struct sha256_ctx *ctx,
 
        memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
        ctx->block[ctx->len] = 0x80;
-       UNPACK32(len_b, ctx->block + pm_len - 4);
+       UNPACK64(len_b, ctx->block + pm_len - 8);
 
        sha256_transf(ctx, ctx->block, block_nb);
 
@@ -414,7 +414,7 @@ void sha384_result(struct sha384_ctx *ctx,
 {
        unsigned int block_nb;
        unsigned int pm_len;
-       size_t len_b;
+       uint64_t len_b;
        int i;
 
        block_nb = 1 + ((SHA384_BLOCK_SIZE - 17)
@@ -425,7 +425,7 @@ void sha384_result(struct sha384_ctx *ctx,
 
        memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
        ctx->block[ctx->len] = 0x80;
-       UNPACK32(len_b, ctx->block + pm_len - 4);
+       UNPACK64(len_b, ctx->block + pm_len - 8);
 
        sha384_transf(ctx, ctx->block, block_nb);
 
@@ -541,7 +541,7 @@ void sha512_result(struct sha512_ctx *ctx,
 {
        unsigned int block_nb;
        unsigned int pm_len;
-       size_t len_b;
+       uint64_t len_b;
        int i;
 
        block_nb = 1 + ((SHA512_BLOCK_SIZE - 17)
@@ -552,7 +552,7 @@ void sha512_result(struct sha512_ctx *ctx,
 
        memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
        ctx->block[ctx->len] = 0x80;
-       UNPACK32(len_b, ctx->block + pm_len - 4);
+       UNPACK64(len_b, ctx->block + pm_len - 8);
 
        sha512_transf(ctx, ctx->block, block_nb);
 
index 8c893eb3ad3e28e8238b2e3e5f72f89beace76a0..92bd2c74c68b851335b78c21236db4a1fee53d5c 100644 (file)
 #include "sha-common.h"
 
 struct sha256_ctx {
-       size_t tot_len;
+       uint64_t tot_len;
        size_t len;
        unsigned char block[2 * SHA256_BLOCK_SIZE];
        uint32_t h[8];
 };
 
 struct sha384_ctx {
-       size_t tot_len;
+       uint64_t tot_len;
        size_t len;
        unsigned char block[2 * SHA384_BLOCK_SIZE];
        uint64_t h[8];
 };
 
 struct sha512_ctx {
-       size_t tot_len;
+       uint64_t tot_len;
        size_t len;
        unsigned char block[2 * SHA512_BLOCK_SIZE];
        uint64_t h[8];
index 0fd41e0bb47744e2172a5a3ee5e540c5df2a7349..97db7c8bb6a1dbafbee4fea9b1145344bca58b68 100644 (file)
@@ -1,6 +1,7 @@
 /* Copyright (c) 2014-2018 Dovecot authors, see the included COPYING file */
 
 #include "test-lib.h"
+#include "hex-binary.h"
 #include "mmap-util.h"
 #include "hash-method.h"
 
@@ -453,8 +454,42 @@ static void test_hash_methods_fips() {
        test_end();
 }
 
+static void test_hash_methods_large(void)
+{
+       struct {
+               const char *method;
+               const char *hash;
+       } tests[] = {
+               { "sha256", "1ad0598b790b3acb38876105cc8938c3365f3215fbee3412ac3cd5e96a7dad01" },
+               { "sha384", "c187c084ffe516fea74b313340a540bc0bab306b1bdc564da21ecdc639e51f194460a0279c04aa40d65cec58698b10c0" },
+               { "sha512", "556247cfeab056903a3f42cf8496019d9ad90911ded9aa1ede3046b803623e5e2cd2adbd0620e666a927436d125984de9199d643ff21ad1c76e29b116c13ffb2" },
+       };
+       unsigned char data[1024];
+       unsigned int i;
+
+       test_begin("hash method (large inputs)");
+       for (i = 0; i < sizeof(data); i++)
+               data[i] = i & 0xFF;
+
+       for (i = 0; i < N_ELEMENTS(tests); i++) {
+               const struct hash_method *method =
+                       hash_method_lookup(tests[i].method);
+               unsigned char context[method->context_size];
+               unsigned char result[method->digest_size];
+
+               method->init(context);
+               for (unsigned int j = 0; j < 600000; j++)
+                       method->loop(context, data, sizeof(data));
+               method->result(context, result);
+               test_assert_strcmp_idx(binary_to_hex(result, method->digest_size),
+                                      tests[i].hash, i);
+       }
+       test_end();
+}
+
 void test_hash_method(void)
 {
        test_hash_method_boundary();
        test_hash_methods_fips();
+       test_hash_methods_large();
 }