From 722de8ed3d3626cd44744297d07d63c49f70f158 Mon Sep 17 00:00:00 2001 From: Samy Date: Fri, 28 Aug 2026 16:50:23 +0200 Subject: [PATCH] crypto: handle unaligned Groestl input --- src/crypto/groestl.c | 11 +++++++---- tests/unit_tests/crypto.cpp | 21 +++++++++++++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/crypto/groestl.c b/src/crypto/groestl.c index d5e2989a8..6f3cfb3ce 100644 --- a/src/crypto/groestl.c +++ b/src/crypto/groestl.c @@ -9,6 +9,7 @@ */ #include +#include #include "groestl.h" #include "groestl_tables.h" @@ -124,7 +125,7 @@ static void RND512Q(uint8_t *x, uint32_t *y, uint32_t r) { } /* compute compression function (short variants) */ -static void F512(uint32_t *h, const uint32_t *m) { +static void F512(uint32_t *h, const uint8_t *m) { int i; uint32_t Ptmp[2*COLS512]; uint32_t Qtmp[2*COLS512]; @@ -132,8 +133,10 @@ static void F512(uint32_t *h, const uint32_t *m) { uint32_t z[2*COLS512]; for (i = 0; i < 2*COLS512; i++) { - z[i] = m[i]; - Ptmp[i] = h[i]^m[i]; + uint32_t word; + memcpy(&word, m + i*sizeof(word), sizeof(word)); + z[i] = word; + Ptmp[i] = h[i]^word; } /* compute Q(m) */ @@ -175,7 +178,7 @@ static void Transform(hashState *ctx, /* digest message, one block at a time */ for (; msglen >= SIZE512; msglen -= SIZE512, input += SIZE512) { - F512(ctx->chaining,(uint32_t*)input); + F512(ctx->chaining, input); /* increment block counter */ ctx->block_counter1++; diff --git a/tests/unit_tests/crypto.cpp b/tests/unit_tests/crypto.cpp index e0e47130c..70a246522 100644 --- a/tests/unit_tests/crypto.cpp +++ b/tests/unit_tests/crypto.cpp @@ -27,6 +27,7 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include +#include #include #include #include @@ -102,6 +103,26 @@ TEST(Crypto, null_keys) ASSERT_EQ(memcmp(crypto::null_pkey.data, zero, 32), 0); } +TEST(Crypto, groestl_unaligned_input) +{ + constexpr std::size_t input_size = 128; + alignas(std::uint32_t) std::uint8_t aligned[input_size]; + alignas(std::uint32_t) std::uint8_t input[input_size + alignof(std::uint32_t)]; + char expected[crypto::HASH_SIZE]; + char actual[crypto::HASH_SIZE]; + + for (std::size_t i = 0; i < input_size; ++i) + aligned[i] = static_cast(i); + crypto::hash_extra_groestl(aligned, input_size, expected); + + for (std::size_t offset = 0; offset < alignof(std::uint32_t); ++offset) + { + std::memcpy(input + offset, aligned, input_size); + crypto::hash_extra_groestl(input + offset, input_size, actual); + EXPECT_EQ(0, std::memcmp(expected, actual, sizeof(expected))); + } +} + TEST(Crypto, verify_32) { // all bytes are treated the same, so we can brute force just one byte