diff --git a/crypto/fipsmodule/digest/digests.c b/crypto/fipsmodule/digest/digests.c index 648278c6d0..88b45d2e5f 100644 --- a/crypto/fipsmodule/digest/digests.c +++ b/crypto/fipsmodule/digest/digests.c @@ -326,7 +326,7 @@ DEFINE_METHOD_FUNCTION(EVP_MD, EVP_sha512_256) { static void sha3_224_init(EVP_MD_CTX *ctx) { - CHECK(SHA3_Init(ctx->md_data, SHA3_PAD_CHAR, SHA3_224_DIGEST_BITLENGTH)); + CHECK(SHA3_Init(ctx->md_data, SHA3_224_DIGEST_BITLENGTH)); } static void sha3_224_update(EVP_MD_CTX *ctx, const void *data, size_t count) { @@ -351,7 +351,7 @@ DEFINE_METHOD_FUNCTION(EVP_MD, EVP_sha3_224) { static void sha3_256_init(EVP_MD_CTX *ctx) { - CHECK(SHA3_Init(ctx->md_data, SHA3_PAD_CHAR, SHA3_256_DIGEST_BITLENGTH)); + CHECK(SHA3_Init(ctx->md_data, SHA3_256_DIGEST_BITLENGTH)); } static void sha3_256_update(EVP_MD_CTX *ctx, const void *data, size_t count) { @@ -376,7 +376,7 @@ DEFINE_METHOD_FUNCTION(EVP_MD, EVP_sha3_256) { static void sha3_384_init(EVP_MD_CTX *ctx) { - CHECK(SHA3_Init(ctx->md_data, SHA3_PAD_CHAR, SHA3_384_DIGEST_BITLENGTH)); + CHECK(SHA3_Init(ctx->md_data, SHA3_384_DIGEST_BITLENGTH)); } static void sha3_384_update(EVP_MD_CTX *ctx, const void *data, size_t count) { @@ -401,7 +401,7 @@ DEFINE_METHOD_FUNCTION(EVP_MD, EVP_sha3_384) { static void sha3_512_init(EVP_MD_CTX *ctx) { - CHECK(SHA3_Init(ctx->md_data, SHA3_PAD_CHAR, SHA3_512_DIGEST_BITLENGTH)); + CHECK(SHA3_Init(ctx->md_data, SHA3_512_DIGEST_BITLENGTH)); } static void sha3_512_update(EVP_MD_CTX *ctx, const void *data, size_t count) { diff --git a/crypto/fipsmodule/sha/internal.h b/crypto/fipsmodule/sha/internal.h index 2a42d6aa8a..3a0a1c37ce 100644 --- a/crypto/fipsmodule/sha/internal.h +++ b/crypto/fipsmodule/sha/internal.h @@ -408,7 +408,7 @@ int SHAKE_Final(uint8_t *md, KECCAK1600_CTX *ctx, size_t len); void SHA3_Reset(KECCAK1600_CTX *ctx); // SHA3_Init initialises |ctx| fields and returns 1 on success and 0 on failure. -OPENSSL_EXPORT int SHA3_Init(KECCAK1600_CTX *ctx, uint8_t pad, size_t bitlen); +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. diff --git a/crypto/fipsmodule/sha/sha3.c b/crypto/fipsmodule/sha/sha3.c index c08f99e744..02c33cb238 100644 --- a/crypto/fipsmodule/sha/sha3.c +++ b/crypto/fipsmodule/sha/sha3.c @@ -14,7 +14,7 @@ uint8_t *SHA3_224(const uint8_t *data, size_t len, uint8_t out[SHA3_224_DIGEST_LENGTH]) { FIPS_service_indicator_lock_state(); KECCAK1600_CTX ctx; - int ok = (SHA3_Init(&ctx, SHA3_PAD_CHAR, SHA3_224_DIGEST_BITLENGTH) && + int ok = (SHA3_Init(&ctx, SHA3_224_DIGEST_BITLENGTH) && SHA3_Update(&ctx, data, len) && SHA3_Final(out, &ctx)); @@ -31,7 +31,7 @@ uint8_t *SHA3_256(const uint8_t *data, size_t len, uint8_t out[SHA3_256_DIGEST_LENGTH]) { FIPS_service_indicator_lock_state(); KECCAK1600_CTX ctx; - int ok = (SHA3_Init(&ctx, SHA3_PAD_CHAR, SHA3_256_DIGEST_BITLENGTH) && + int ok = (SHA3_Init(&ctx, SHA3_256_DIGEST_BITLENGTH) && SHA3_Update(&ctx, data, len) && SHA3_Final(out, &ctx)); @@ -48,7 +48,7 @@ uint8_t *SHA3_384(const uint8_t *data, size_t len, uint8_t out[SHA3_384_DIGEST_LENGTH]) { FIPS_service_indicator_lock_state(); KECCAK1600_CTX ctx; - int ok = (SHA3_Init(&ctx, SHA3_PAD_CHAR, SHA3_384_DIGEST_BITLENGTH) && + int ok = (SHA3_Init(&ctx, SHA3_384_DIGEST_BITLENGTH) && SHA3_Update(&ctx, data, len) && SHA3_Final(out, &ctx)); @@ -65,7 +65,7 @@ uint8_t *SHA3_512(const uint8_t *data, size_t len, uint8_t out[SHA3_512_DIGEST_LENGTH]) { FIPS_service_indicator_lock_state(); KECCAK1600_CTX ctx; - int ok = (SHA3_Init(&ctx, SHA3_PAD_CHAR, SHA3_512_DIGEST_BITLENGTH) && + int ok = (SHA3_Init(&ctx, SHA3_512_DIGEST_BITLENGTH) && SHA3_Update(&ctx, data, len) && SHA3_Final(out, &ctx)); @@ -109,49 +109,43 @@ uint8_t *SHAKE256(const uint8_t *data, const size_t in_len, uint8_t *out, size_t return out; } -int SHAKE_Init(KECCAK1600_CTX *ctx, size_t block_size) { - // The SHAKE block size depends on the security level of the algorithm only - // It is independent of the output size - ctx->block_size = block_size; - return SHA3_Init(ctx, SHAKE_PAD_CHAR, 0); +// FIPS202 APIs manage internal input/output buffer on top of Keccak1600 API layer +static void FIPS202_Reset(KECCAK1600_CTX *ctx) { + memset(ctx->A, 0, sizeof(ctx->A)); + ctx->buf_load = 0; + ctx->padded=0; } - -int SHAKE_Final(uint8_t *md, KECCAK1600_CTX *ctx, size_t len) { - ctx->md_size = len; - return SHA3_Final(md, ctx); +static int FIPS202_Init(KECCAK1600_CTX *ctx, uint8_t pad, size_t block_size, size_t bit_len) { + if (pad != SHA3_PAD_CHAR && + pad != SHAKE_PAD_CHAR) { + return 0; + } + + if (block_size <= sizeof(ctx->buf)) { + FIPS202_Reset(ctx); + ctx->block_size = block_size; + ctx->md_size = bit_len / 8; + ctx->pad = pad; + return 1; + } + 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, uint8_t pad, size_t bit_len) { - size_t block_size; - - // The block size is computed differently depending on which algorithm - // is calling |SHA3_Init|: - // - for SHA3 we compute it by calling SHA3_BLOCKSIZE(bit_len) - // because the block size depends on the digest bit-length, - // - for SHAKE we take the block size from the context. - // We use the given padding character to differentiate between SHA3 and SHAKE. - if (pad == SHA3_PAD_CHAR) { - block_size = SHA3_BLOCKSIZE(bit_len); - } else if (pad == SHAKE_PAD_CHAR) { - block_size = ctx->block_size; - } else { - return 0; - } - ctx->padded = 0; - - if (block_size <= sizeof(ctx->buf)) { - SHA3_Reset(ctx); - ctx->block_size = block_size; - ctx->md_size = bit_len / 8; - ctx->pad = pad; - return 1; +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; } @@ -230,3 +224,19 @@ int SHA3_Final(uint8_t *md, KECCAK1600_CTX *ctx) { 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) { + // |block_size| depends on the SHAKE security level + // The output length |bit_len| is initialized to 0 + return FIPS202_Init(ctx, SHAKE_PAD_CHAR, block_size, 0); + } + return 0; +} + +int SHAKE_Final(uint8_t *md, KECCAK1600_CTX *ctx, size_t len) { + ctx->md_size = len; + return SHA3_Final(md, ctx); +} \ No newline at end of file diff --git a/crypto/fipsmodule/sha/sha3_test.cc b/crypto/fipsmodule/sha/sha3_test.cc index 23cba17886..9e45ddf7d1 100644 --- a/crypto/fipsmodule/sha/sha3_test.cc +++ b/crypto/fipsmodule/sha/sha3_test.cc @@ -208,7 +208,7 @@ TEST(KeccakInternalTest, SqueezeOutputBufferOverflow) { const size_t out_lens[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, (1 << 5), (1 << 16) + 1}; for (auto out_len : out_lens) { - EXPECT_TRUE(SHA3_Init(&ctx, SHA3_PAD_CHAR, SHA3_384_DIGEST_BITLENGTH)); + EXPECT_TRUE(SHA3_Init(&ctx, SHA3_384_DIGEST_BITLENGTH)); out.resize(out_len + canary.size()); std::copy(canary.begin(), canary.end(), out.end() - canary.size()); Keccak1600_Squeeze(ctx.A, out.data(), out_len, ctx.block_size, 1);