From 87b4530b131e460052d76144ed4b628e85f33bf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Sat, 8 Aug 2026 18:58:12 +0200 Subject: [PATCH] keccak: Rework absorption of the final input bytes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the Keccak input processing loop, rework the code handling the last 0–7 bytes of input and the padding byte. The new code is not spectacularly better than the old one, but it fixes edge case where a compiler may decide to replace the old code with memcpy call. --- lib/evmone_precompiles/keccak.c | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/lib/evmone_precompiles/keccak.c b/lib/evmone_precompiles/keccak.c index 0e4f92657c..add0f877e1 100644 --- a/lib/evmone_precompiles/keccak.c +++ b/lib/evmone_precompiles/keccak.c @@ -323,16 +323,11 @@ static inline ALWAYS_INLINE void keccak( const size_t hash_size = bits / 8; const size_t block_size = (1600 - bits * 2) / 8; - size_t i; - uint64_t* state_iter; - uint64_t last_word = 0; - uint8_t* last_word_iter = (uint8_t*)&last_word; - uint64_t state[25] = {0}; while (size >= block_size) { - for (i = 0; i < (block_size / word_size); ++i) + for (size_t i = 0; i < (block_size / word_size); ++i) { state[i] ^= load_le(data); data += word_size; @@ -343,7 +338,7 @@ static inline ALWAYS_INLINE void keccak( size -= block_size; } - state_iter = state; + uint64_t* state_iter = state; while (size >= word_size) { @@ -353,21 +348,17 @@ static inline ALWAYS_INLINE void keccak( size -= word_size; } - while (size > 0) - { - *last_word_iter = *data; - ++last_word_iter; - ++data; - --size; - } - *last_word_iter = 0x01; - *state_iter ^= to_le64(last_word); + // Absorb last 0–7 bytes of input + the padding byte. + uint64_t last_word = (uint64_t)0x01 << (size * 8); + for (size_t i = 0; i < size; ++i) + last_word |= (uint64_t)data[i] << (i * 8); + *state_iter ^= last_word; - state[(block_size / word_size) - 1] ^= 0x8000000000000000; + state[(block_size / word_size) - 1] ^= 0x8000000000000000; // Last block bit flip. keccakf1600_best(state); - for (i = 0; i < (hash_size / word_size); ++i) + for (size_t i = 0; i < (hash_size / word_size); ++i) out[i] = to_le64(state[i]); }