diff --git a/crypto/digest_extra/digest_test.cc b/crypto/digest_extra/digest_test.cc index 910c7314..72e10b11 100644 --- a/crypto/digest_extra/digest_test.cc +++ b/crypto/digest_extra/digest_test.cc @@ -258,3 +258,20 @@ TEST(DigestTest, ASN1) { CBS_init(&cbs, kSHA256GarbageParam, sizeof(kSHA256GarbageParam)); EXPECT_FALSE(EVP_parse_digest_algorithm(&cbs)); } + +TEST(DigestTest, TransformBlocks) { + uint8_t blocks[SHA256_CBLOCK * 10]; + for (size_t i = 0; i < sizeof(blocks); i++) { + blocks[i] = i*3; + } + + SHA256_CTX ctx1; + SHA256_Init(&ctx1); + SHA256_Update(&ctx1, blocks, sizeof(blocks)); + + SHA256_CTX ctx2; + SHA256_Init(&ctx2); + SHA256_TransformBlocks(ctx2.h, blocks, sizeof(blocks) / SHA256_CBLOCK); + + EXPECT_TRUE(0 == OPENSSL_memcmp(ctx1.h, ctx2.h, sizeof(ctx1.h))); +} diff --git a/crypto/fipsmodule/sha/sha256.c b/crypto/fipsmodule/sha/sha256.c index 6d709a67..3e9bcbc1 100644 --- a/crypto/fipsmodule/sha/sha256.c +++ b/crypto/fipsmodule/sha/sha256.c @@ -316,6 +316,11 @@ static void sha256_block_data_order(uint32_t *state, const uint8_t *data, #endif // !SHA256_ASM +void SHA256_TransformBlocks(uint32_t state[8], const uint8_t *data, + size_t num_blocks) { + sha256_block_data_order(state, data, num_blocks); +} + #undef DATA_ORDER_IS_BIG_ENDIAN #undef HASH_CTX #undef HASH_CBLOCK diff --git a/include/openssl/sha.h b/include/openssl/sha.h index fc4644bf..306dc808 100644 --- a/include/openssl/sha.h +++ b/include/openssl/sha.h @@ -171,6 +171,14 @@ OPENSSL_EXPORT uint8_t *SHA256(const uint8_t *data, size_t len, uint8_t *out); // from |block|. OPENSSL_EXPORT void SHA256_Transform(SHA256_CTX *sha, const uint8_t *block); +// SHA256_TransformBlocks is a low-level function that takes |num_blocks| * +// |SHA256_CBLOCK| bytes of data and performs SHA-256 transforms on it to update +// |state|. You should not use this function unless you are implementing a +// derivative of SHA-256. +OPENSSL_EXPORT void SHA256_TransformBlocks(uint32_t state[8], + const uint8_t *data, + size_t num_blocks); + struct sha256_state_st { uint32_t h[8]; uint32_t Nl, Nh;