SHAKE: in case update is called right after squeezing, permute

Calling update after squeezing is undocumented and non standard,
but if an application still decides to do it, permute the state
before absorbing so that it's still safe to do so.

We can easily do it since we keep track of the state.

Still return an error as this is not the expected usage of SHAKE,
and zeroing the state is another thing we could do.
This commit is contained in:
Frank Denis
2026-04-09 23:00:04 +02:00
parent a338eaaa02
commit 98e1f0dba7
4 changed files with 16 additions and 4 deletions
@@ -28,10 +28,13 @@ shake128_ref_update(shake128_state_internal *state, const unsigned char *in, siz
{
size_t consumed = 0;
size_t chunk_size;
int ret = 0;
if (state->phase != SHAKE128_PHASE_ABSORBING) {
crypto_core_keccak1600_permute_24(&state->state);
state->phase = SHAKE128_PHASE_ABSORBING;
state->offset = 0;
ret = -1;
}
while (consumed < inlen) {
@@ -48,7 +51,7 @@ shake128_ref_update(shake128_state_internal *state, const unsigned char *in, siz
consumed += chunk_size;
}
return 0;
return ret;
}
static void
@@ -28,10 +28,13 @@ shake256_ref_update(shake256_state_internal *state, const unsigned char *in, siz
{
size_t consumed = 0;
size_t chunk_size;
int ret = 0;
if (state->phase != SHAKE256_PHASE_ABSORBING) {
crypto_core_keccak1600_permute_24(&state->state);
state->phase = SHAKE256_PHASE_ABSORBING;
state->offset = 0;
ret = -1;
}
while (consumed < inlen) {
@@ -48,7 +51,7 @@ shake256_ref_update(shake256_state_internal *state, const unsigned char *in, siz
consumed += chunk_size;
}
return 0;
return ret;
}
static void
@@ -28,10 +28,13 @@ turboshake128_ref_update(turboshake128_state_internal *state, const unsigned cha
{
size_t consumed = 0;
size_t chunk_size;
int ret = 0;
if (state->phase != TURBOSHAKE128_PHASE_ABSORBING) {
crypto_core_keccak1600_permute_12(&state->state);
state->phase = TURBOSHAKE128_PHASE_ABSORBING;
state->offset = 0;
ret = -1;
}
while (consumed < inlen) {
@@ -48,7 +51,7 @@ turboshake128_ref_update(turboshake128_state_internal *state, const unsigned cha
consumed += chunk_size;
}
return 0;
return ret;
}
static void
@@ -28,10 +28,13 @@ turboshake256_ref_update(turboshake256_state_internal *state, const unsigned cha
{
size_t consumed = 0;
size_t chunk_size;
int ret = 0;
if (state->phase != TURBOSHAKE256_PHASE_ABSORBING) {
crypto_core_keccak1600_permute_12(&state->state);
state->phase = TURBOSHAKE256_PHASE_ABSORBING;
state->offset = 0;
ret = -1;
}
while (consumed < inlen) {
@@ -48,7 +51,7 @@ turboshake256_ref_update(turboshake256_state_internal *state, const unsigned cha
consumed += chunk_size;
}
return 0;
return ret;
}
static void