From ca3acebf8f9d019ffb23106391d27d76cb1ce282 Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Tue, 18 Nov 2025 12:14:59 +0100 Subject: [PATCH] XOF: don't absorb/squeeze bytes one by one --- .../crypto_xof/shake128/ref/shake128_ref.c | 29 ++++++++++++++----- .../crypto_xof/shake256/ref/shake256_ref.c | 29 ++++++++++++++----- .../turboshake128/ref/turboshake128_ref.c | 29 ++++++++++++++----- .../turboshake256/ref/turboshake256_ref.c | 29 ++++++++++++++----- 4 files changed, 84 insertions(+), 32 deletions(-) diff --git a/src/libsodium/crypto_xof/shake128/ref/shake128_ref.c b/src/libsodium/crypto_xof/shake128/ref/shake128_ref.c index e6897db5..a6d9d1d9 100644 --- a/src/libsodium/crypto_xof/shake128/ref/shake128_ref.c +++ b/src/libsodium/crypto_xof/shake128/ref/shake128_ref.c @@ -27,20 +27,26 @@ shake128_ref_init(shake128_state_internal *state) int shake128_ref_update(shake128_state_internal *state, const unsigned char *in, size_t inlen) { - size_t i; + size_t consumed = 0; + size_t chunk_size; if (state->phase != SHAKE128_PHASE_ABSORBING) { state->phase = SHAKE128_PHASE_ABSORBING; state->offset = 0; } - for (i = 0; i < inlen; i++) { + while (consumed < inlen) { if (state->offset == SHAKE128_RATE) { crypto_core_keccak1600_permute_24(state->state); state->offset = 0; } - crypto_core_keccak1600_xor_bytes(state->state, &in[i], state->offset, 1); - state->offset++; + chunk_size = SHAKE128_RATE - state->offset; + if (chunk_size > inlen - consumed) { + chunk_size = inlen - consumed; + } + crypto_core_keccak1600_xor_bytes(state->state, &in[consumed], state->offset, chunk_size); + state->offset += chunk_size; + consumed += chunk_size; } return 0; @@ -73,19 +79,26 @@ shake128_finalize(shake128_state_internal *state) int shake128_ref_squeeze(shake128_state_internal *state, unsigned char *out, size_t outlen) { - size_t i; + size_t extracted = 0; + size_t chunk_size; if (state->phase == SHAKE128_PHASE_ABSORBING) { shake128_finalize(state); } - for (i = 0; i < outlen; i++) { + while (extracted < outlen) { if (state->offset == SHAKE128_RATE) { crypto_core_keccak1600_permute_24(state->state); state->offset = 0; } - crypto_core_keccak1600_extract_bytes(state->state, &out[i], state->offset, 1); - state->offset++; + chunk_size = SHAKE128_RATE - state->offset; + if (chunk_size > outlen - extracted) { + chunk_size = outlen - extracted; + } + crypto_core_keccak1600_extract_bytes(state->state, &out[extracted], state->offset, + chunk_size); + state->offset += chunk_size; + extracted += chunk_size; } return 0; diff --git a/src/libsodium/crypto_xof/shake256/ref/shake256_ref.c b/src/libsodium/crypto_xof/shake256/ref/shake256_ref.c index 6a5b8571..a3a8513d 100644 --- a/src/libsodium/crypto_xof/shake256/ref/shake256_ref.c +++ b/src/libsodium/crypto_xof/shake256/ref/shake256_ref.c @@ -27,20 +27,26 @@ shake256_ref_init(shake256_state_internal *state) int shake256_ref_update(shake256_state_internal *state, const unsigned char *in, size_t inlen) { - size_t i; + size_t consumed = 0; + size_t chunk_size; if (state->phase != SHAKE256_PHASE_ABSORBING) { state->phase = SHAKE256_PHASE_ABSORBING; state->offset = 0; } - for (i = 0; i < inlen; i++) { + while (consumed < inlen) { if (state->offset == SHAKE256_RATE) { crypto_core_keccak1600_permute_24(state->state); state->offset = 0; } - crypto_core_keccak1600_xor_bytes(state->state, &in[i], state->offset, 1); - state->offset++; + chunk_size = SHAKE256_RATE - state->offset; + if (chunk_size > inlen - consumed) { + chunk_size = inlen - consumed; + } + crypto_core_keccak1600_xor_bytes(state->state, &in[consumed], state->offset, chunk_size); + state->offset += chunk_size; + consumed += chunk_size; } return 0; @@ -73,19 +79,26 @@ shake256_finalize(shake256_state_internal *state) int shake256_ref_squeeze(shake256_state_internal *state, unsigned char *out, size_t outlen) { - size_t i; + size_t extracted = 0; + size_t chunk_size; if (state->phase == SHAKE256_PHASE_ABSORBING) { shake256_finalize(state); } - for (i = 0; i < outlen; i++) { + while (extracted < outlen) { if (state->offset == SHAKE256_RATE) { crypto_core_keccak1600_permute_24(state->state); state->offset = 0; } - crypto_core_keccak1600_extract_bytes(state->state, &out[i], state->offset, 1); - state->offset++; + chunk_size = SHAKE256_RATE - state->offset; + if (chunk_size > outlen - extracted) { + chunk_size = outlen - extracted; + } + crypto_core_keccak1600_extract_bytes(state->state, &out[extracted], state->offset, + chunk_size); + state->offset += chunk_size; + extracted += chunk_size; } return 0; diff --git a/src/libsodium/crypto_xof/turboshake128/ref/turboshake128_ref.c b/src/libsodium/crypto_xof/turboshake128/ref/turboshake128_ref.c index 6b624dca..fa5f4dc5 100644 --- a/src/libsodium/crypto_xof/turboshake128/ref/turboshake128_ref.c +++ b/src/libsodium/crypto_xof/turboshake128/ref/turboshake128_ref.c @@ -27,20 +27,26 @@ turboshake128_ref_init(turboshake128_state_internal *state) int turboshake128_ref_update(turboshake128_state_internal *state, const unsigned char *in, size_t inlen) { - size_t i; + size_t consumed = 0; + size_t chunk_size; if (state->phase != TURBOSHAKE128_PHASE_ABSORBING) { state->phase = TURBOSHAKE128_PHASE_ABSORBING; state->offset = 0; } - for (i = 0; i < inlen; i++) { + while (consumed < inlen) { if (state->offset == TURBOSHAKE128_RATE) { crypto_core_keccak1600_permute_12(state->state); state->offset = 0; } - crypto_core_keccak1600_xor_bytes(state->state, &in[i], state->offset, 1); - state->offset++; + chunk_size = TURBOSHAKE128_RATE - state->offset; + if (chunk_size > inlen - consumed) { + chunk_size = inlen - consumed; + } + crypto_core_keccak1600_xor_bytes(state->state, &in[consumed], state->offset, chunk_size); + state->offset += chunk_size; + consumed += chunk_size; } return 0; @@ -73,19 +79,26 @@ turboshake128_finalize(turboshake128_state_internal *state) int turboshake128_ref_squeeze(turboshake128_state_internal *state, unsigned char *out, size_t outlen) { - size_t i; + size_t extracted = 0; + size_t chunk_size; if (state->phase == TURBOSHAKE128_PHASE_ABSORBING) { turboshake128_finalize(state); } - for (i = 0; i < outlen; i++) { + while (extracted < outlen) { if (state->offset == TURBOSHAKE128_RATE) { crypto_core_keccak1600_permute_12(state->state); state->offset = 0; } - crypto_core_keccak1600_extract_bytes(state->state, &out[i], state->offset, 1); - state->offset++; + chunk_size = TURBOSHAKE128_RATE - state->offset; + if (chunk_size > outlen - extracted) { + chunk_size = outlen - extracted; + } + crypto_core_keccak1600_extract_bytes(state->state, &out[extracted], state->offset, + chunk_size); + state->offset += chunk_size; + extracted += chunk_size; } return 0; diff --git a/src/libsodium/crypto_xof/turboshake256/ref/turboshake256_ref.c b/src/libsodium/crypto_xof/turboshake256/ref/turboshake256_ref.c index 4f8699eb..b47c28e0 100644 --- a/src/libsodium/crypto_xof/turboshake256/ref/turboshake256_ref.c +++ b/src/libsodium/crypto_xof/turboshake256/ref/turboshake256_ref.c @@ -27,20 +27,26 @@ turboshake256_ref_init(turboshake256_state_internal *state) int turboshake256_ref_update(turboshake256_state_internal *state, const unsigned char *in, size_t inlen) { - size_t i; + size_t consumed = 0; + size_t chunk_size; if (state->phase != TURBOSHAKE256_PHASE_ABSORBING) { state->phase = TURBOSHAKE256_PHASE_ABSORBING; state->offset = 0; } - for (i = 0; i < inlen; i++) { + while (consumed < inlen) { if (state->offset == TURBOSHAKE256_RATE) { crypto_core_keccak1600_permute_12(state->state); state->offset = 0; } - crypto_core_keccak1600_xor_bytes(state->state, &in[i], state->offset, 1); - state->offset++; + chunk_size = TURBOSHAKE256_RATE - state->offset; + if (chunk_size > inlen - consumed) { + chunk_size = inlen - consumed; + } + crypto_core_keccak1600_xor_bytes(state->state, &in[consumed], state->offset, chunk_size); + state->offset += chunk_size; + consumed += chunk_size; } return 0; @@ -73,19 +79,26 @@ turboshake256_finalize(turboshake256_state_internal *state) int turboshake256_ref_squeeze(turboshake256_state_internal *state, unsigned char *out, size_t outlen) { - size_t i; + size_t extracted = 0; + size_t chunk_size; if (state->phase == TURBOSHAKE256_PHASE_ABSORBING) { turboshake256_finalize(state); } - for (i = 0; i < outlen; i++) { + while (extracted < outlen) { if (state->offset == TURBOSHAKE256_RATE) { crypto_core_keccak1600_permute_12(state->state); state->offset = 0; } - crypto_core_keccak1600_extract_bytes(state->state, &out[i], state->offset, 1); - state->offset++; + chunk_size = TURBOSHAKE256_RATE - state->offset; + if (chunk_size > outlen - extracted) { + chunk_size = outlen - extracted; + } + crypto_core_keccak1600_extract_bytes(state->state, &out[extracted], state->offset, + chunk_size); + state->offset += chunk_size; + extracted += chunk_size; } return 0;