diff --git a/crypto/fipsmodule/digest/digests.c b/crypto/fipsmodule/digest/digests.c index 88b45d2e5f..d869723685 100644 --- a/crypto/fipsmodule/digest/digests.c +++ b/crypto/fipsmodule/digest/digests.c @@ -430,7 +430,7 @@ static void shake128_init(EVP_MD_CTX *ctx) { } static void shake128_update(EVP_MD_CTX *ctx, const void *data, size_t count) { - CHECK(SHA3_Update(ctx->md_data, data, count)); + CHECK(SHAKE_Absorb(ctx->md_data, data, count)); } static void shake128_final(EVP_MD_CTX *ctx, uint8_t *md, size_t len) { @@ -455,7 +455,7 @@ static void shake256_init(EVP_MD_CTX *ctx) { } static void shake256_update(EVP_MD_CTX *ctx, const void *data, size_t count) { - CHECK(SHA3_Update(ctx->md_data, data, count)); + CHECK(SHAKE_Absorb(ctx->md_data, data, count)); } static void shake256_finalXOF(EVP_MD_CTX *ctx, uint8_t *md, size_t len) { diff --git a/crypto/fipsmodule/ml_kem/ml_kem_ref/symmetric-shake.c b/crypto/fipsmodule/ml_kem/ml_kem_ref/symmetric-shake.c index d31d7136fd..72bf98c2f2 100644 --- a/crypto/fipsmodule/ml_kem/ml_kem_ref/symmetric-shake.c +++ b/crypto/fipsmodule/ml_kem/ml_kem_ref/symmetric-shake.c @@ -29,8 +29,8 @@ void kyber_shake128_absorb(KECCAK1600_CTX *ctx, // SHAKE_Init always returns 1 when called with correct block size value SHAKE_Init(ctx, SHAKE128_BLOCKSIZE); - // SHA3_Update always returns 1 on first call of sizeof(extseed) (34 bytes) - SHA3_Update(ctx, extseed, sizeof(extseed)); + // SHAKE_Absorb always returns 1 on first call of sizeof(extseed) (34 bytes) + SHAKE_Absorb(ctx, extseed, sizeof(extseed)); } /************************************************* @@ -48,8 +48,9 @@ void kyber_shake128_absorb(KECCAK1600_CTX *ctx, void kyber_shake128_squeeze(KECCAK1600_CTX *ctx, uint8_t *out, int nblocks) { // Return code checks can be omitted - // SHAKE_Final always returns 1 - SHAKE_Final(out, ctx, nblocks * SHAKE128_BLOCKSIZE); + // SHAKE_Squeeze always returns 1 when |ctx->state| flag is different + // from |KECCAK1600_STATE_FINAL| + SHAKE_Squeeze(out, ctx, nblocks * SHAKE128_BLOCKSIZE); } /************************************************* @@ -94,12 +95,13 @@ void kyber_shake256_rkprf(ml_kem_params *params, uint8_t out[KYBER_SSBYTES], con // SHAKE_Init always returns 1 when called with correct block size value SHAKE_Init(&ctx, SHAKE256_BLOCKSIZE); - // SHA3_Update always returns 1 on first call of KYBER_SYMBYTES (32 bytes) - SHA3_Update(&ctx, key, KYBER_SYMBYTES); + // SHAKE_Absorb always returns 1 on first call of KYBER_SYMBYTES (32 bytes) + SHAKE_Absorb(&ctx, key, KYBER_SYMBYTES); - // SHA3_Update always returns 1 processing all data blocks that don't need pad - SHA3_Update(&ctx, input, params->ciphertext_bytes); + // SHAKE_Absorb always returns 1 processing all data blocks that don't need pad + SHAKE_Absorb(&ctx, input, params->ciphertext_bytes); - // SHAKE_Final always returns 1 + // SHAKE_Final always returns 1 when |ctx->state| flag is set to + // |KECCAK1600_STATE_ABSORB| (no previous calls to SHAKE_Final) SHAKE_Final(out, &ctx, KYBER_SSBYTES); } diff --git a/crypto/fipsmodule/sha/internal.h b/crypto/fipsmodule/sha/internal.h index 3a0a1c37ce..7ec335be32 100644 --- a/crypto/fipsmodule/sha/internal.h +++ b/crypto/fipsmodule/sha/internal.h @@ -71,6 +71,14 @@ extern "C" { // SHAKE128 has the maximum block size among the SHA3/SHAKE algorithms. #define SHA3_MAX_BLOCKSIZE SHAKE128_BLOCKSIZE +// Define state flag values for Keccak-based functions +#define KECCAK1600_STATE_ABSORB 0 +#define KECCAK1600_STATE_SQUEEZE 1 +// KECCAK1600_STATE_FINAL restricts the incremental calls to SHAKE_Final . +// KECCAK1600_STATE_FINAL can be called once. SHAKE_Squeeze cannot be called after SHAKE_Final. +// SHAKE_Squeeze should be called for streaming XOF output. +#define KECCAK1600_STATE_FINAL 2 + typedef struct keccak_st KECCAK1600_CTX; // The data buffer should have at least the maximum number of @@ -82,7 +90,7 @@ struct keccak_st { size_t buf_load; // used bytes in below buffer uint8_t buf[SHA3_MAX_BLOCKSIZE]; // should have at least the max data block size bytes uint8_t pad; // padding character - uint8_t padded; // denotes if padding has been performed + uint8_t state; // denotes the keccak phase (absorb, squeeze, final) }; // Define SHA{n}[_{variant}]_ASM if sha{n}_block_data_order[_{variant}] is @@ -396,32 +404,43 @@ OPENSSL_EXPORT uint8_t *SHAKE128(const uint8_t *data, const size_t in_len, OPENSSL_EXPORT uint8_t *SHAKE256(const uint8_t *data, const size_t in_len, uint8_t *out, size_t out_len); -// SHAKE_Init initializes |ctx| with specified |block_size|, returns 1 on -// success and 0 on failure. Calls SHA3_Init under the hood. -int SHAKE_Init(KECCAK1600_CTX *ctx, size_t block_size); - -// SHAKE_Final writes |len| bytes of finalized digest to |md|, returns 1 on -// success and 0 on failure. Calls SHA3_Final under the hood. -int SHAKE_Final(uint8_t *md, KECCAK1600_CTX *ctx, size_t len); - -// SHA3_Reset zeros the bitstate and the amount of processed input. -void SHA3_Reset(KECCAK1600_CTX *ctx); - -// SHA3_Init initialises |ctx| fields and returns 1 on success and 0 on failure. +// SHA3_Init initialises |ctx| fields through |FIPS202_Init| and +// returns 1 on success and 0 on failure. OPENSSL_EXPORT int SHA3_Init(KECCAK1600_CTX *ctx, size_t bitlen); -// SHA3_Update processes all data blocks that don't need pad through -// |Keccak1600_Absorb| and returns 1 and 0 on failure. + // SHA3_Update check |ctx| pointer and |len| value, calls |FIPS202_Update| + // and returns 1 on success and 0 on failure. int SHA3_Update(KECCAK1600_CTX *ctx, const void *data, size_t len); -// SHA3_Final pads the last data block and processes it through |Keccak1600_Absorb|. -// It processes the data through |Keccak1600_Squeeze| and returns 1 and 0 on failure. +// SHA3_Final pads the last data block and absorbs it through |FIPS202_Finalize|. +// It processes the data through |Keccak1600_Squeeze| and returns 1 on success +// and 0 on failure. int SHA3_Final(uint8_t *md, KECCAK1600_CTX *ctx); -// Keccak1600_Absorb processes the largest multiple of |r| out of |len| bytes and -// returns the remaining number of bytes. +// SHAKE_Init initialises |ctx| fields through |FIPS202_Init| and +// returns 1 on success and 0 on failure. +int SHAKE_Init(KECCAK1600_CTX *ctx, size_t block_size); + +// SHAKE_Absorb checks |ctx| pointer and |len| values. It updates and absorbs +// input blocks via |FIPS202_Update|. +int SHAKE_Absorb(KECCAK1600_CTX *ctx, const void *data, + size_t len); + +// SHAKE_Squeeze pads the last data block and absorbs it through +// |FIPS202_Finalize| on first call. It writes |len| bytes of incremental +// XOF output to |md| and returns 1 on success and 0 on failure. It can be +// called multiple times. +int SHAKE_Squeeze(uint8_t *md, KECCAK1600_CTX *ctx, size_t len); + +// SHAKE_Final writes |len| bytes of finalized extendible output to |md|, returns 1 on +// success and 0 on failure. It should be called once to finalize absorb and +// squeeze phases. Incremental XOF output should be generated via |SHAKE_Squeeze|. +int SHAKE_Final(uint8_t *md, KECCAK1600_CTX *ctx, size_t len); + +// Keccak1600_Absorb processes the largest multiple of |r| (block size) out of +// |len| bytes and returns the remaining number of bytes. size_t Keccak1600_Absorb(uint64_t A[KECCAK1600_ROWS][KECCAK1600_ROWS], - const uint8_t *data, size_t len, size_t r); + const uint8_t *data, size_t len, size_t r); // Keccak1600_Squeeze generates |out| value of |len| bytes (per call). It can be called // multiple times when used as eXtendable Output Function. |padded| indicates diff --git a/crypto/fipsmodule/sha/sha3.c b/crypto/fipsmodule/sha/sha3.c index 708d554a6d..8b03fcf227 100644 --- a/crypto/fipsmodule/sha/sha3.c +++ b/crypto/fipsmodule/sha/sha3.c @@ -82,7 +82,7 @@ uint8_t *SHAKE128(const uint8_t *data, const size_t in_len, uint8_t *out, size_t FIPS_service_indicator_lock_state(); KECCAK1600_CTX ctx; int ok = (SHAKE_Init(&ctx, SHAKE128_BLOCKSIZE) && - SHA3_Update(&ctx, data, in_len) && + SHAKE_Absorb(&ctx, data, in_len) && SHAKE_Final(out, &ctx, out_len)); OPENSSL_cleanse(&ctx, sizeof(ctx)); @@ -98,7 +98,7 @@ uint8_t *SHAKE256(const uint8_t *data, const size_t in_len, uint8_t *out, size_t FIPS_service_indicator_lock_state(); KECCAK1600_CTX ctx; int ok = (SHAKE_Init(&ctx, SHAKE256_BLOCKSIZE) && - SHA3_Update(&ctx, data, in_len) && + SHAKE_Absorb(&ctx, data, in_len) && SHAKE_Final(out, &ctx, out_len)); OPENSSL_cleanse(&ctx, sizeof(ctx)); FIPS_service_indicator_unlock_state(); @@ -113,7 +113,7 @@ uint8_t *SHAKE256(const uint8_t *data, const size_t in_len, uint8_t *out, size_t static void FIPS202_Reset(KECCAK1600_CTX *ctx) { memset(ctx->A, 0, sizeof(ctx->A)); ctx->buf_load = 0; - ctx->padded=0; + ctx->state = KECCAK1600_STATE_ABSORB; } static int FIPS202_Init(KECCAK1600_CTX *ctx, uint8_t pad, size_t block_size, size_t bit_len) { @@ -132,33 +132,17 @@ static int FIPS202_Init(KECCAK1600_CTX *ctx, uint8_t pad, size_t block_size, siz return 0; } -// SHA3 APIs implement SHA3 functionalities on top of FIPS202 API layer -void SHA3_Reset(KECCAK1600_CTX *ctx) { - memset(ctx->A, 0, sizeof(ctx->A)); - ctx->buf_load = 0; - ctx->padded = 0; -} - -int SHA3_Init(KECCAK1600_CTX *ctx, size_t bit_len) { - if (bit_len == SHA3_224_DIGEST_BITLENGTH || - bit_len == SHA3_256_DIGEST_BITLENGTH || - bit_len == SHA3_384_DIGEST_BITLENGTH || - bit_len == SHA3_512_DIGEST_BITLENGTH) { - // |block_size| depends on the SHA3 |bit_len| output (digest) length - return FIPS202_Init(ctx, SHA3_PAD_CHAR, SHA3_BLOCKSIZE(bit_len), bit_len); - } - return 0; -} - -int SHA3_Update(KECCAK1600_CTX *ctx, const void *data, size_t len) { +static int FIPS202_Update(KECCAK1600_CTX *ctx, const void *data, size_t len) { uint8_t *data_ptr_copy = (uint8_t *) data; size_t block_size = ctx->block_size; size_t num, rem; - if (len == 0) { - return 1; + if (ctx->state == KECCAK1600_STATE_SQUEEZE || + ctx->state == KECCAK1600_STATE_FINAL ) { + return 0; } + // Case |len| equals 0 is checked in SHA3/SHAKE higher level APIs // Process intermediate buffer. num = ctx->buf_load; if (num != 0) { @@ -169,9 +153,9 @@ int SHA3_Update(KECCAK1600_CTX *ctx, const void *data, size_t len) { return 1; } - // There is enough data to fill or overflow the intermediate - // buffer. So we append |rem| bytes and process the block, - // leaving the rest for later processing. + // There is enough data to fill or overflow the intermediate + // buffer. So we append |rem| bytes and process the block, + // leaving the rest for later processing. memcpy(ctx->buf + num, data_ptr_copy, rem); data_ptr_copy += rem, len -= rem; if (Keccak1600_Absorb(ctx->A, ctx->buf, block_size, block_size) != 0 ) { @@ -196,36 +180,73 @@ int SHA3_Update(KECCAK1600_CTX *ctx, const void *data, size_t len) { return 1; } -int SHA3_Final(uint8_t *md, KECCAK1600_CTX *ctx) { +// FIPS202_Finalize processes padding and absorb of last input block +// This function should be called once to finalize absorb and initiate squeeze phase +static int FIPS202_Finalize(uint8_t *md, KECCAK1600_CTX *ctx) { size_t block_size = ctx->block_size; size_t num = ctx->buf_load; - if (ctx->md_size == 0) { + if (ctx->state == KECCAK1600_STATE_SQUEEZE || + ctx->state == KECCAK1600_STATE_FINAL ) { + return 0; + } + + // Pad the data with 10*1. Note that |num| can be |block_size - 1| + // in which case both byte operations below are performed on + // the same byte. + memset(ctx->buf + num, 0, block_size - num); + ctx->buf[num] = ctx->pad; + ctx->buf[block_size - 1] |= 0x80; + + if (Keccak1600_Absorb(ctx->A, ctx->buf, block_size, block_size) != 0) { + return 0; + } + + return 1; +} + +// SHA3 APIs implement SHA3 functionalities on top of FIPS202 API layer +int SHA3_Init(KECCAK1600_CTX *ctx, size_t bit_len) { + if (bit_len == SHA3_224_DIGEST_BITLENGTH || + bit_len == SHA3_256_DIGEST_BITLENGTH || + bit_len == SHA3_384_DIGEST_BITLENGTH || + bit_len == SHA3_512_DIGEST_BITLENGTH) { + // |block_size| depends on the SHA3 |bit_len| output (digest) length + return FIPS202_Init(ctx, SHA3_PAD_CHAR, SHA3_BLOCKSIZE(bit_len), bit_len); + } + return 0; +} + +int SHA3_Update(KECCAK1600_CTX *ctx, const void *data, size_t len) { + if (ctx == NULL) { + return 0; + } + + if (len == 0) { return 1; } - if (ctx->padded == 0) { - // Pad the data with 10*1. Note that |num| can be |block_size - 1| - // in which case both byte operations below are performed on - // the same byte. - memset(ctx->buf + num, 0, block_size - num); - ctx->buf[num] = ctx->pad; - ctx->buf[block_size - 1] |= 0x80; + return FIPS202_Update(ctx, data, len); +} - if (Keccak1600_Absorb(ctx->A, ctx->buf, block_size, block_size) != 0) { - return 0; - } +// SHA3_Final should be called once to process final digest value +// |ctx->state| flag does not need to be updated +int SHA3_Final(uint8_t *md, KECCAK1600_CTX *ctx) { + if (ctx->md_size == 0) { + return 1; } - Keccak1600_Squeeze(ctx->A, md, ctx->md_size, block_size, ctx->padded); - ctx->padded = 1; + if (FIPS202_Finalize(md, ctx) == 0) { + return 0; + } + Keccak1600_Squeeze(ctx->A, md, ctx->md_size, ctx->block_size, ctx->state); + ctx->state = KECCAK1600_STATE_FINAL; + FIPS_service_indicator_update_state(); - return 1; } -// SHAKE APIs implement SHAKE functionalities on top of FIPS202 API layer int SHAKE_Init(KECCAK1600_CTX *ctx, size_t block_size) { if (block_size == SHAKE128_BLOCKSIZE || block_size == SHAKE256_BLOCKSIZE) { @@ -236,7 +257,62 @@ int SHAKE_Init(KECCAK1600_CTX *ctx, size_t block_size) { return 0; } +int SHAKE_Absorb(KECCAK1600_CTX *ctx, const void *data, size_t len) { + if (ctx == NULL) { + return 0; + } + + if (len == 0) { + return 1; + } + + return FIPS202_Update(ctx, data, len); +} + +// SHAKE_Final is a single-shot API and can be called once to finalize absorb and squeeze phases +// |ctx->state| restricts consecutive calls to FIPS202_Finalize +// Function SHAKE_Squeeze should be used for incremental XOF output int SHAKE_Final(uint8_t *md, KECCAK1600_CTX *ctx, size_t len) { ctx->md_size = len; - return SHA3_Final(md, ctx); + if (ctx->md_size == 0) { + return 1; + } + + if (FIPS202_Finalize(md, ctx) == 0) { + return 0; + } + + Keccak1600_Squeeze(ctx->A, md, ctx->md_size, ctx->block_size, ctx->state); + ctx->state = KECCAK1600_STATE_FINAL; + + FIPS_service_indicator_update_state(); + + return 1; +} + +// SHAKE_Squeeze can be called multiple times +// SHAKE_Squeeze should be called for incremental XOF output +int SHAKE_Squeeze(uint8_t *md, KECCAK1600_CTX *ctx, size_t len) { + ctx->md_size = len; + + if (ctx->md_size == 0) { + return 1; + } + + if (ctx->state == KECCAK1600_STATE_FINAL) { + return 0; + } + + if (ctx->state == KECCAK1600_STATE_ABSORB) { + // Skip FIPS202_Finalize if the input has been padded and the last block has been processed + if (FIPS202_Finalize(md, ctx) == 0) { + return 0; + } + } + + Keccak1600_Squeeze(ctx->A, md, len, ctx->block_size, ctx->state); + ctx->state = KECCAK1600_STATE_SQUEEZE; + + //FIPS_service_indicator_update_state(); + return 1; } diff --git a/crypto/fipsmodule/sha/sha3_test.cc b/crypto/fipsmodule/sha/sha3_test.cc index 9e45ddf7d1..310a5af9c3 100644 --- a/crypto/fipsmodule/sha/sha3_test.cc +++ b/crypto/fipsmodule/sha/sha3_test.cc @@ -165,7 +165,6 @@ TEST(SHA3Test, NISTTestVectors) { }); } - TEST(SHA3Test, NISTTestVectors_SingleShot) { FileTestGTest("crypto/fipsmodule/sha/testvectors/SHA3_224ShortMsg.txt", [](FileTest *t) { diff --git a/crypto/ml_dsa/ml_dsa_ref/poly.c b/crypto/ml_dsa/ml_dsa_ref/poly.c index 42809f98e3..72d81d2e8d 100644 --- a/crypto/ml_dsa/ml_dsa_ref/poly.c +++ b/crypto/ml_dsa/ml_dsa_ref/poly.c @@ -316,9 +316,9 @@ void ml_dsa_poly_uniform(ml_dsa_poly *a, t[1] = nonce >> 8; SHAKE_Init(&state, SHAKE128_BLOCKSIZE); - SHA3_Update(&state, seed, ML_DSA_SEEDBYTES); - SHA3_Update(&state, t, 2); - SHAKE_Final(buf, &state, POLY_UNIFORM_NBLOCKS * SHAKE128_BLOCKSIZE); + SHAKE_Absorb(&state, seed, ML_DSA_SEEDBYTES); + SHAKE_Absorb(&state, t, 2); + SHAKE_Squeeze(buf, &state, POLY_UNIFORM_NBLOCKS * SHAKE128_BLOCKSIZE); ctr = ml_dsa_rej_uniform(a->coeffs, ML_DSA_N, buf, buflen); @@ -327,7 +327,7 @@ void ml_dsa_poly_uniform(ml_dsa_poly *a, for(i = 0; i < off; ++i) buf[i] = buf[buflen - off + i]; - SHAKE_Final(buf + off, &state, POLY_UNIFORM_NBLOCKS * SHAKE128_BLOCKSIZE); + SHAKE_Squeeze(buf + off, &state, POLY_UNIFORM_NBLOCKS * SHAKE128_BLOCKSIZE); buflen = SHAKE128_BLOCKSIZE + off; ctr += ml_dsa_rej_uniform(a->coeffs + ctr, ML_DSA_N - ctr, buf, buflen); } @@ -418,16 +418,17 @@ void ml_dsa_poly_uniform_eta(ml_dsa_params *params, t[1] = nonce >> 8; SHAKE_Init(&state, SHAKE256_BLOCKSIZE); - SHA3_Update(&state, seed, ML_DSA_CRHBYTES); - SHA3_Update(&state, t, 2); - SHAKE_Final(buf, &state, ML_DSA_POLY_UNIFORM_ETA_NBLOCKS_MAX * SHAKE256_BLOCKSIZE); + SHAKE_Absorb(&state, seed, ML_DSA_CRHBYTES); + SHAKE_Absorb(&state, t, 2); + SHAKE_Squeeze(buf, &state, ML_DSA_POLY_UNIFORM_ETA_NBLOCKS_MAX * SHAKE256_BLOCKSIZE); ctr = rej_eta(params, a->coeffs, ML_DSA_N, buf, buflen); while(ctr < ML_DSA_N) { - SHAKE_Final(buf, &state, SHAKE256_BLOCKSIZE); + SHAKE_Squeeze(buf, &state, SHAKE256_BLOCKSIZE); ctr += rej_eta(params, a->coeffs + ctr, ML_DSA_N - ctr, buf, SHAKE256_BLOCKSIZE); } + /* FIPS 204. Section 3.6.3 Destruction of intermediate values. */ OPENSSL_cleanse(buf, sizeof(buf)); OPENSSL_cleanse(&state, sizeof(state)); @@ -459,9 +460,8 @@ void ml_dsa_poly_uniform_gamma1(ml_dsa_params *params, t[1] = nonce >> 8; SHAKE_Init(&state, SHAKE256_BLOCKSIZE); - SHA3_Update(&state, seed, ML_DSA_CRHBYTES); - SHA3_Update(&state, t, 2); - + SHAKE_Absorb(&state, seed, ML_DSA_CRHBYTES); + SHAKE_Absorb(&state, t, 2); SHAKE_Final(buf, &state, POLY_UNIFORM_GAMMA1_NBLOCKS * SHAKE256_BLOCKSIZE); ml_dsa_polyz_unpack(params, a, buf); /* FIPS 204. Section 3.6.3 Destruction of intermediate values. */ @@ -487,8 +487,8 @@ void ml_dsa_poly_challenge(ml_dsa_params *params, ml_dsa_poly *c, const uint8_t KECCAK1600_CTX state; SHAKE_Init(&state, SHAKE256_BLOCKSIZE); - SHA3_Update(&state, seed, params->c_tilde_bytes); - SHAKE_Final(buf, &state, SHAKE256_BLOCKSIZE); + SHAKE_Absorb(&state, seed, params->c_tilde_bytes); + SHAKE_Squeeze(buf, &state, SHAKE256_BLOCKSIZE); signs = 0; for(i = 0; i < 8; ++i) { @@ -502,7 +502,7 @@ void ml_dsa_poly_challenge(ml_dsa_params *params, ml_dsa_poly *c, const uint8_t for(i = ML_DSA_N-params->tau; i < ML_DSA_N; ++i) { do { if(pos >= SHAKE256_BLOCKSIZE) { - SHAKE_Final(buf, &state, SHAKE256_BLOCKSIZE); + SHAKE_Squeeze(buf, &state, SHAKE256_BLOCKSIZE); pos = 0; } diff --git a/crypto/ml_dsa/ml_dsa_ref/sign.c b/crypto/ml_dsa/ml_dsa_ref/sign.c index 64f4110656..0573eb1b01 100644 --- a/crypto/ml_dsa/ml_dsa_ref/sign.c +++ b/crypto/ml_dsa/ml_dsa_ref/sign.c @@ -171,9 +171,9 @@ int ml_dsa_sign_internal(ml_dsa_params *params, /* FIPS 204: line 7 Compute rhoprime = CRH(key, rnd, mu) */ SHAKE_Init(&state, SHAKE256_BLOCKSIZE); - SHA3_Update(&state, key, ML_DSA_SEEDBYTES); - SHA3_Update(&state, rnd, ML_DSA_RNDBYTES); - SHA3_Update(&state, mu, ML_DSA_CRHBYTES); + SHAKE_Absorb(&state, key, ML_DSA_SEEDBYTES); + SHAKE_Absorb(&state, rnd, ML_DSA_RNDBYTES); + SHAKE_Absorb(&state, mu, ML_DSA_CRHBYTES); SHAKE_Final(rhoprime, &state, ML_DSA_CRHBYTES); /* FIPS 204: line 5 Expand matrix and transform vectors */ @@ -199,8 +199,8 @@ int ml_dsa_sign_internal(ml_dsa_params *params, ml_dsa_polyveck_pack_w1(params, sig, &w1); SHAKE_Init(&state, SHAKE256_BLOCKSIZE); - SHA3_Update(&state, mu, ML_DSA_CRHBYTES); - SHA3_Update(&state, sig, params->k * params->poly_w1_packed_bytes); + SHAKE_Absorb(&state, mu, ML_DSA_CRHBYTES); + SHAKE_Absorb(&state, sig, params->k * params->poly_w1_packed_bytes); SHAKE_Final(sig, &state, params->c_tilde_bytes); ml_dsa_poly_challenge(params, &cp, sig); ml_dsa_poly_ntt(&cp); @@ -471,9 +471,10 @@ int ml_dsa_verify_internal(ml_dsa_params *params, /* FIPS 204: line 12 Call random oracle and verify challenge */ SHAKE_Init(&state, SHAKE256_BLOCKSIZE); - SHA3_Update(&state, mu, ML_DSA_CRHBYTES); - SHA3_Update(&state, buf, params->k * params->poly_w1_packed_bytes); + SHAKE_Absorb(&state, mu, ML_DSA_CRHBYTES); + SHAKE_Absorb(&state, buf, params->k * params->poly_w1_packed_bytes); SHAKE_Final(c2, &state, params->c_tilde_bytes); + for(i = 0; i < params->c_tilde_bytes; ++i) { if(c[i] != c2[i]) { return -1;