diff --git a/BUILD.generated.bzl b/BUILD.generated.bzl index e6656f1ce..c2ced412b 100644 --- a/BUILD.generated.bzl +++ b/BUILD.generated.bzl @@ -458,6 +458,7 @@ crypto_sources = [ "src/crypto/rsa_extra/rsa_print.c", "src/crypto/sha/sha1.c", "src/crypto/sha/sha256.c", + "src/crypto/sha/sha512.c", "src/crypto/siphash/siphash.c", "src/crypto/slhdsa/fors.c", "src/crypto/slhdsa/merkle.c", diff --git a/CMakeLists.txt b/CMakeLists.txt index f6ee50458..c467259de 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -417,6 +417,7 @@ add_library( src/crypto/rsa_extra/rsa_print.c src/crypto/sha/sha1.c src/crypto/sha/sha256.c + src/crypto/sha/sha512.c src/crypto/siphash/siphash.c src/crypto/slhdsa/fors.c src/crypto/slhdsa/merkle.c diff --git a/sources.json b/sources.json index e5051e6de..0b4017a2c 100644 --- a/sources.json +++ b/sources.json @@ -160,6 +160,7 @@ "src/crypto/rsa_extra/rsa_print.c", "src/crypto/sha/sha1.c", "src/crypto/sha/sha256.c", + "src/crypto/sha/sha512.c", "src/crypto/siphash/siphash.c", "src/crypto/slhdsa/fors.c", "src/crypto/slhdsa/merkle.c", diff --git a/src/build.json b/src/build.json index e6829710b..f1e617311 100644 --- a/src/build.json +++ b/src/build.json @@ -305,6 +305,7 @@ "crypto/rsa_extra/rsa_print.c", "crypto/sha/sha1.c", "crypto/sha/sha256.c", + "crypto/sha/sha512.c", "crypto/siphash/siphash.c", "crypto/slhdsa/fors.c", "crypto/slhdsa/merkle.c", diff --git a/src/crypto/fipsmodule/bcm_interface.h b/src/crypto/fipsmodule/bcm_interface.h index 222a9db43..ba084f59a 100644 --- a/src/crypto/fipsmodule/bcm_interface.h +++ b/src/crypto/fipsmodule/bcm_interface.h @@ -137,7 +137,7 @@ bcm_infallible BCM_sha224_init(SHA256_CTX *sha); // BCM_sha224_update adds |len| bytes from |data| to |sha|. bcm_infallible BCM_sha224_update(SHA256_CTX *sha, const void *data, size_t len); -// BCM_sha224_Final adds the final padding to |sha| and writes the resulting +// BCM_sha224_final adds the final padding to |sha| and writes the resulting // digest to |out|, which must have at least |SHA224_DIGEST_LENGTH| bytes of // space. It aborts on programmer error. bcm_infallible BCM_sha224_final(uint8_t out[BCM_SHA224_DIGEST_LENGTH], @@ -175,6 +175,68 @@ bcm_infallible BCM_sha256_transform_blocks(uint32_t state[8], size_t num_blocks); +// SHA-384. + +// BCM_SHA384_DIGEST_LENGTH is the length of a SHA-384 digest. +#define BCM_SHA384_DIGEST_LENGTH 48 + +// BCM_sha384_init initialises |sha|. +bcm_infallible BCM_sha384_init(SHA512_CTX *sha); + +// BCM_sha384_update adds |len| bytes from |data| to |sha|. +bcm_infallible BCM_sha384_update(SHA512_CTX *sha, const void *data, size_t len); + +// BCM_sha384_final adds the final padding to |sha| and writes the resulting +// digest to |out|, which must have at least |BCM_sha384_DIGEST_LENGTH| bytes of +// space. It may abort on programmer error. +bcm_infallible BCM_sha384_final(uint8_t out[BCM_SHA384_DIGEST_LENGTH], + SHA512_CTX *sha); + + +// SHA-512. + +// BCM_SHA512_DIGEST_LENGTH is the length of a SHA-512 digest. +#define BCM_SHA512_DIGEST_LENGTH 64 + +// BCM_sha512_init initialises |sha|. +bcm_infallible BCM_sha512_init(SHA512_CTX *sha); + +// BCM_sha512_update adds |len| bytes from |data| to |sha|. +bcm_infallible BCM_sha512_update(SHA512_CTX *sha, const void *data, size_t len); + +// BCM_sha512_final adds the final padding to |sha| and writes the resulting +// digest to |out|, which must have at least |BCM_sha512_DIGEST_LENGTH| bytes of +// space. +bcm_infallible BCM_sha512_final(uint8_t out[BCM_SHA512_DIGEST_LENGTH], + SHA512_CTX *sha); + +// BCM_sha512_transform is a low-level function that performs a single, SHA-512 +// block transformation using the state from |sha| and |BCM_sha512_CBLOCK| bytes +// from |block|. +bcm_infallible BCM_sha512_transform(SHA512_CTX *sha, + const uint8_t block[BCM_SHA512_CBLOCK]); + + +// SHA-512-256 +// +// See https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf section 5.3.6 + +#define BCM_SHA512_256_DIGEST_LENGTH 32 + +// BCM_sha512_256_init initialises |sha|. +bcm_infallible BCM_sha512_256_init(SHA512_CTX *sha); + +// BCM_sha512_256_update adds |len| bytes from |data| to |sha|. +bcm_infallible BCM_sha512_256_update(SHA512_CTX *sha, const void *data, + size_t len); + +// BCM_sha512_256_final adds the final padding to |sha| and writes the resulting +// digest to |out|, which must have at least |BCM_sha512_256_DIGEST_LENGTH| +// bytes of space. It may abort on programmer error. +bcm_infallible BCM_sha512_256_final(uint8_t out[BCM_SHA512_256_DIGEST_LENGTH], + SHA512_CTX *sha); + + #if defined(__cplusplus) } // extern C #endif diff --git a/src/crypto/fipsmodule/digest/digests.c.inc b/src/crypto/fipsmodule/digest/digests.c.inc index 216af52f7..9ead2c65c 100644 --- a/src/crypto/fipsmodule/digest/digests.c.inc +++ b/src/crypto/fipsmodule/digest/digests.c.inc @@ -60,7 +60,6 @@ #include #include -#include #include "internal.h" #include "../delocate.h" @@ -146,20 +145,20 @@ DEFINE_METHOD_FUNCTION(EVP_MD, EVP_sha256) { static void sha384_init(EVP_MD_CTX *ctx) { - CHECK(SHA384_Init(ctx->md_data)); + BCM_sha384_init(ctx->md_data); } static void sha384_update(EVP_MD_CTX *ctx, const void *data, size_t count) { - CHECK(SHA384_Update(ctx->md_data, data, count)); + BCM_sha384_update(ctx->md_data, data, count); } static void sha384_final(EVP_MD_CTX *ctx, uint8_t *md) { - CHECK(SHA384_Final(md, ctx->md_data)); + BCM_sha384_final(md, ctx->md_data); } DEFINE_METHOD_FUNCTION(EVP_MD, EVP_sha384) { out->type = NID_sha384; - out->md_size = SHA384_DIGEST_LENGTH; + out->md_size = BCM_SHA384_DIGEST_LENGTH; out->flags = 0; out->init = sha384_init; out->update = sha384_update; @@ -170,20 +169,20 @@ DEFINE_METHOD_FUNCTION(EVP_MD, EVP_sha384) { static void sha512_init(EVP_MD_CTX *ctx) { - CHECK(SHA512_Init(ctx->md_data)); + BCM_sha512_init(ctx->md_data); } static void sha512_update(EVP_MD_CTX *ctx, const void *data, size_t count) { - CHECK(SHA512_Update(ctx->md_data, data, count)); + BCM_sha512_update(ctx->md_data, data, count); } static void sha512_final(EVP_MD_CTX *ctx, uint8_t *md) { - CHECK(SHA512_Final(md, ctx->md_data)); + BCM_sha512_final(md, ctx->md_data); } DEFINE_METHOD_FUNCTION(EVP_MD, EVP_sha512) { out->type = NID_sha512; - out->md_size = SHA512_DIGEST_LENGTH; + out->md_size = BCM_SHA512_DIGEST_LENGTH; out->flags = 0; out->init = sha512_init; out->update = sha512_update; @@ -194,20 +193,20 @@ DEFINE_METHOD_FUNCTION(EVP_MD, EVP_sha512) { static void sha512_256_init(EVP_MD_CTX *ctx) { - CHECK(SHA512_256_Init(ctx->md_data)); + BCM_sha512_256_init(ctx->md_data); } static void sha512_256_update(EVP_MD_CTX *ctx, const void *data, size_t count) { - CHECK(SHA512_256_Update(ctx->md_data, data, count)); + BCM_sha512_256_update(ctx->md_data, data, count); } static void sha512_256_final(EVP_MD_CTX *ctx, uint8_t *md) { - CHECK(SHA512_256_Final(md, ctx->md_data)); + BCM_sha512_256_final(md, ctx->md_data); } DEFINE_METHOD_FUNCTION(EVP_MD, EVP_sha512_256) { out->type = NID_sha512_256; - out->md_size = SHA512_256_DIGEST_LENGTH; + out->md_size = BCM_SHA512_256_DIGEST_LENGTH; out->flags = 0; out->init = sha512_256_init; out->update = sha512_256_update; diff --git a/src/crypto/fipsmodule/ecdh/ecdh.c.inc b/src/crypto/fipsmodule/ecdh/ecdh.c.inc index d16c3c106..86ba2583d 100644 --- a/src/crypto/fipsmodule/ecdh/ecdh.c.inc +++ b/src/crypto/fipsmodule/ecdh/ecdh.c.inc @@ -72,7 +72,6 @@ #include #include #include -#include #include "../../internal.h" #include "../ec/internal.h" @@ -106,24 +105,27 @@ int ECDH_compute_key_fips(uint8_t *out, size_t out_len, const EC_POINT *pub_key, FIPS_service_indicator_lock_state(); SHA256_CTX ctx; + SHA512_CTX ctx_512; switch (out_len) { case SHA224_DIGEST_LENGTH: BCM_sha224_init(&ctx); BCM_sha224_update(&ctx, buf, buflen); BCM_sha224_final(out, &ctx); - OPENSSL_cleanse(&ctx, sizeof(ctx)); break; case SHA256_DIGEST_LENGTH: BCM_sha256_init(&ctx); BCM_sha256_update(&ctx, buf, buflen); BCM_sha256_final(out, &ctx); - OPENSSL_cleanse(&ctx, sizeof(ctx)); break; case SHA384_DIGEST_LENGTH: - SHA384(buf, buflen, out); + BCM_sha384_init(&ctx_512); + BCM_sha384_update(&ctx_512, buf, buflen); + BCM_sha384_final(out, &ctx_512); break; case SHA512_DIGEST_LENGTH: - SHA512(buf, buflen, out); + BCM_sha512_init(&ctx_512); + BCM_sha512_update(&ctx_512, buf, buflen); + BCM_sha512_final(out, &ctx_512); break; default: OPENSSL_PUT_ERROR(ECDH, ECDH_R_UNKNOWN_DIGEST_LENGTH); diff --git a/src/crypto/fipsmodule/ecdsa/ecdsa.c.inc b/src/crypto/fipsmodule/ecdsa/ecdsa.c.inc index cba8972eb..f5508a153 100644 --- a/src/crypto/fipsmodule/ecdsa/ecdsa.c.inc +++ b/src/crypto/fipsmodule/ecdsa/ecdsa.c.inc @@ -58,7 +58,6 @@ #include #include #include -#include #include "../../internal.h" #include "../bn/internal.h" @@ -268,17 +267,17 @@ int ecdsa_sign_fixed(const uint8_t *digest, size_t digest_len, uint8_t *sig, // Pass a SHA512 hash of the private key and digest as additional data // into the RBG. This is a hardening measure against entropy failure. - static_assert(SHA512_DIGEST_LENGTH >= 32, + static_assert(BCM_SHA512_DIGEST_LENGTH >= 32, "additional_data is too large for SHA-512"); FIPS_service_indicator_lock_state(); SHA512_CTX sha; - uint8_t additional_data[SHA512_DIGEST_LENGTH]; - SHA512_Init(&sha); - SHA512_Update(&sha, priv_key->words, order->width * sizeof(BN_ULONG)); - SHA512_Update(&sha, digest, digest_len); - SHA512_Final(additional_data, &sha); + uint8_t additional_data[BCM_SHA512_DIGEST_LENGTH]; + BCM_sha512_init(&sha); + BCM_sha512_update(&sha, priv_key->words, order->width * sizeof(BN_ULONG)); + BCM_sha512_update(&sha, digest, digest_len); + BCM_sha512_final(additional_data, &sha); // Cap iterations so callers who supply invalid values as custom groups do not // infinite loop. This does not impact valid parameters (e.g. those covered by diff --git a/src/crypto/fipsmodule/rsa/padding.c.inc b/src/crypto/fipsmodule/rsa/padding.c.inc index e4c1c1c67..2deceb30b 100644 --- a/src/crypto/fipsmodule/rsa/padding.c.inc +++ b/src/crypto/fipsmodule/rsa/padding.c.inc @@ -63,7 +63,6 @@ #include #include #include -#include #include "internal.h" #include "../service_indicator/internal.h" diff --git a/src/crypto/fipsmodule/rsa/rsa.c.inc b/src/crypto/fipsmodule/rsa/rsa.c.inc index 8cb6c5d99..5f3800574 100644 --- a/src/crypto/fipsmodule/rsa/rsa.c.inc +++ b/src/crypto/fipsmodule/rsa/rsa.c.inc @@ -68,7 +68,6 @@ #include #include #include -#include #include #include "../bn/internal.h" @@ -501,14 +500,14 @@ static const struct pkcs1_sig_prefix kPKCS1SigPrefixes[] = { }, { NID_sha384, - SHA384_DIGEST_LENGTH, + BCM_SHA384_DIGEST_LENGTH, 19, {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30}, }, { NID_sha512, - SHA512_DIGEST_LENGTH, + BCM_SHA512_DIGEST_LENGTH, 19, {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40}, diff --git a/src/crypto/fipsmodule/sha/sha512.c.inc b/src/crypto/fipsmodule/sha/sha512.c.inc index f9f7be8f6..65a5265f8 100644 --- a/src/crypto/fipsmodule/sha/sha512.c.inc +++ b/src/crypto/fipsmodule/sha/sha512.c.inc @@ -54,13 +54,12 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ -#include - #include #include #include "../../internal.h" +#include "../bcm_interface.h" #include "../service_indicator/internal.h" #include "internal.h" @@ -71,9 +70,9 @@ // this writing, so there is no need for a common collector/padding // implementation yet. -static int sha512_final_impl(uint8_t *out, size_t md_len, SHA512_CTX *sha); +static void sha512_final_impl(uint8_t *out, size_t md_len, SHA512_CTX *sha); -int SHA384_Init(SHA512_CTX *sha) { +bcm_infallible BCM_sha384_init(SHA512_CTX *sha) { sha->h[0] = UINT64_C(0xcbbb9d5dc1059ed8); sha->h[1] = UINT64_C(0x629a292a367cd507); sha->h[2] = UINT64_C(0x9159015a3070dd17); @@ -86,12 +85,12 @@ int SHA384_Init(SHA512_CTX *sha) { sha->Nl = 0; sha->Nh = 0; sha->num = 0; - sha->md_len = SHA384_DIGEST_LENGTH; - return 1; + sha->md_len = BCM_SHA384_DIGEST_LENGTH; + return bcm_infallible_approved; } -int SHA512_Init(SHA512_CTX *sha) { +bcm_infallible BCM_sha512_init(SHA512_CTX *sha) { sha->h[0] = UINT64_C(0x6a09e667f3bcc908); sha->h[1] = UINT64_C(0xbb67ae8584caa73b); sha->h[2] = UINT64_C(0x3c6ef372fe94f82b); @@ -104,11 +103,11 @@ int SHA512_Init(SHA512_CTX *sha) { sha->Nl = 0; sha->Nh = 0; sha->num = 0; - sha->md_len = SHA512_DIGEST_LENGTH; - return 1; + sha->md_len = BCM_SHA512_DIGEST_LENGTH; + return bcm_infallible_approved; } -int SHA512_256_Init(SHA512_CTX *sha) { +bcm_infallible BCM_sha512_256_init(SHA512_CTX *sha) { sha->h[0] = UINT64_C(0x22312194fc2bf72c); sha->h[1] = UINT64_C(0x9f555fa3c84c64c2); sha->h[2] = UINT64_C(0x2393b86b6f53b151); @@ -121,38 +120,8 @@ int SHA512_256_Init(SHA512_CTX *sha) { sha->Nl = 0; sha->Nh = 0; sha->num = 0; - sha->md_len = SHA512_256_DIGEST_LENGTH; - return 1; -} - -uint8_t *SHA384(const uint8_t *data, size_t len, - uint8_t out[SHA384_DIGEST_LENGTH]) { - SHA512_CTX ctx; - SHA384_Init(&ctx); - SHA384_Update(&ctx, data, len); - SHA384_Final(out, &ctx); - OPENSSL_cleanse(&ctx, sizeof(ctx)); - return out; -} - -uint8_t *SHA512(const uint8_t *data, size_t len, - uint8_t out[SHA512_DIGEST_LENGTH]) { - SHA512_CTX ctx; - SHA512_Init(&ctx); - SHA512_Update(&ctx, data, len); - SHA512_Final(out, &ctx); - OPENSSL_cleanse(&ctx, sizeof(ctx)); - return out; -} - -uint8_t *SHA512_256(const uint8_t *data, size_t len, - uint8_t out[SHA512_256_DIGEST_LENGTH]) { - SHA512_CTX ctx; - SHA512_256_Init(&ctx); - SHA512_256_Update(&ctx, data, len); - SHA512_256_Final(out, &ctx); - OPENSSL_cleanse(&ctx, sizeof(ctx)); - return out; + sha->md_len = BCM_SHA512_256_DIGEST_LENGTH; + return bcm_infallible_approved; } #if !defined(SHA512_ASM) @@ -161,39 +130,48 @@ static void sha512_block_data_order(uint64_t state[8], const uint8_t *in, #endif -int SHA384_Final(uint8_t out[SHA384_DIGEST_LENGTH], SHA512_CTX *sha) { - // This function must be paired with |SHA384_Init|, which sets |sha->md_len| - // to |SHA384_DIGEST_LENGTH|. - assert(sha->md_len == SHA384_DIGEST_LENGTH); - return sha512_final_impl(out, SHA384_DIGEST_LENGTH, sha); +bcm_infallible BCM_sha384_final(uint8_t out[BCM_SHA384_DIGEST_LENGTH], + SHA512_CTX *sha) { + // This function must be paired with |BCM_sha384_init|, which sets + // |sha->md_len| to |BCM_SHA384_DIGEST_LENGTH|. + assert(sha->md_len == BCM_SHA384_DIGEST_LENGTH); + sha512_final_impl(out, BCM_SHA384_DIGEST_LENGTH, sha); + return bcm_infallible_approved; } -int SHA384_Update(SHA512_CTX *sha, const void *data, size_t len) { - return SHA512_Update(sha, data, len); +bcm_infallible BCM_sha384_update(SHA512_CTX *sha, const void *data, + size_t len) { + return BCM_sha512_update(sha, data, len); } -int SHA512_256_Update(SHA512_CTX *sha, const void *data, size_t len) { - return SHA512_Update(sha, data, len); +bcm_infallible BCM_sha512_256_update(SHA512_CTX *sha, const void *data, + size_t len) { + return BCM_sha512_update(sha, data, len); } -int SHA512_256_Final(uint8_t out[SHA512_256_DIGEST_LENGTH], SHA512_CTX *sha) { - // This function must be paired with |SHA512_256_Init|, which sets - // |sha->md_len| to |SHA512_256_DIGEST_LENGTH|. - assert(sha->md_len == SHA512_256_DIGEST_LENGTH); - return sha512_final_impl(out, SHA512_256_DIGEST_LENGTH, sha); +bcm_infallible BCM_sha512_256_final(uint8_t out[BCM_SHA512_256_DIGEST_LENGTH], + SHA512_CTX *sha) { + // This function must be paired with |BCM_sha512_256_init|, which sets + // |sha->md_len| to |BCM_SHA512_256_DIGEST_LENGTH|. + assert(sha->md_len == BCM_SHA512_256_DIGEST_LENGTH); + sha512_final_impl(out, BCM_SHA512_256_DIGEST_LENGTH, sha); + return bcm_infallible_approved; } -void SHA512_Transform(SHA512_CTX *c, const uint8_t block[SHA512_CBLOCK]) { +bcm_infallible BCM_sha512_transform(SHA512_CTX *c, + const uint8_t block[SHA512_CBLOCK]) { sha512_block_data_order(c->h, block, 1); + return bcm_infallible_approved; } -int SHA512_Update(SHA512_CTX *c, const void *in_data, size_t len) { +bcm_infallible BCM_sha512_update(SHA512_CTX *c, const void *in_data, + size_t len) { uint64_t l; uint8_t *p = c->p; const uint8_t *data = in_data; if (len == 0) { - return 1; + return bcm_infallible_approved; } l = (c->Nl + (((uint64_t)len) << 3)) & UINT64_C(0xffffffffffffffff); @@ -232,19 +210,21 @@ int SHA512_Update(SHA512_CTX *c, const void *in_data, size_t len) { c->num = (int)len; } - return 1; + return bcm_infallible_approved; } -int SHA512_Final(uint8_t out[SHA512_DIGEST_LENGTH], SHA512_CTX *sha) { - // Ideally we would assert |sha->md_len| is |SHA512_DIGEST_LENGTH| to match - // the size hint, but calling code often pairs |SHA384_Init| with - // |SHA512_Final| and expects |sha->md_len| to carry the size over. +bcm_infallible BCM_sha512_final(uint8_t out[BCM_SHA512_DIGEST_LENGTH], + SHA512_CTX *sha) { + // Ideally we would assert |sha->md_len| is |BCM_SHA512_DIGEST_LENGTH| to + // match the size hint, but calling code often pairs |BCM_sha384_init| with + // |BCM_sha512_final| and expects |sha->md_len| to carry the size over. // // TODO(davidben): Add an assert and fix code to match them up. - return sha512_final_impl(out, sha->md_len, sha); + sha512_final_impl(out, sha->md_len, sha); + return bcm_infallible_approved; } -static int sha512_final_impl(uint8_t *out, size_t md_len, SHA512_CTX *sha) { +static void sha512_final_impl(uint8_t *out, size_t md_len, SHA512_CTX *sha) { uint8_t *p = sha->p; size_t n = sha->num; @@ -262,12 +242,6 @@ static int sha512_final_impl(uint8_t *out, size_t md_len, SHA512_CTX *sha) { sha512_block_data_order(sha->h, p, 1); - if (out == NULL) { - // TODO(davidben): This NULL check is absent in other low-level hash 'final' - // functions and is one of the few places one can fail. - return 0; - } - assert(md_len % 8 == 0); const size_t out_words = md_len / 8; for (size_t i = 0; i < out_words; i++) { @@ -276,7 +250,6 @@ static int sha512_final_impl(uint8_t *out, size_t md_len, SHA512_CTX *sha) { } FIPS_service_indicator_update_state(); - return 1; } #if !defined(SHA512_ASM) @@ -423,7 +396,6 @@ static void sha512_block_data_order_nohw(uint64_t state[8], const uint8_t *in, int i; while (num--) { - a = state[0]; b = state[1]; c = state[2]; diff --git a/src/crypto/sha/sha512.c b/src/crypto/sha/sha512.c new file mode 100644 index 000000000..507320de9 --- /dev/null +++ b/src/crypto/sha/sha512.c @@ -0,0 +1,104 @@ +/* Copyright (c) 2024, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include + +#include "../fipsmodule/bcm_interface.h" + + +int SHA384_Init(SHA512_CTX *sha) { + BCM_sha384_init(sha); + return 1; +} + +int SHA384_Update(SHA512_CTX *sha, const void *data, size_t len) { + BCM_sha384_update(sha, data, len); + return 1; +} + +int SHA384_Final(uint8_t out[SHA384_DIGEST_LENGTH], SHA512_CTX *sha) { + BCM_sha384_final(out, sha); + return 1; +} + +uint8_t *SHA384(const uint8_t *data, size_t len, + uint8_t out[SHA384_DIGEST_LENGTH]) { + SHA512_CTX ctx; + BCM_sha384_init(&ctx); + BCM_sha384_update(&ctx, data, len); + BCM_sha384_final(out, &ctx); + OPENSSL_cleanse(&ctx, sizeof(ctx)); + return out; +} + +int SHA512_256_Init(SHA512_CTX *sha) { + BCM_sha512_256_init(sha); + return 1; +} + +int SHA512_256_Update(SHA512_CTX *sha, const void *data, size_t len) { + BCM_sha512_256_update(sha, data, len); + return 1; +} + +int SHA512_256_Final(uint8_t out[SHA512_256_DIGEST_LENGTH], SHA512_CTX *sha) { + BCM_sha512_256_final(out, sha); + return 1; +} + +uint8_t *SHA512_256(const uint8_t *data, size_t len, + uint8_t out[SHA512_256_DIGEST_LENGTH]) { + SHA512_CTX ctx; + BCM_sha512_256_init(&ctx); + BCM_sha512_256_update(&ctx, data, len); + BCM_sha512_256_final(out, &ctx); + OPENSSL_cleanse(&ctx, sizeof(ctx)); + return out; +} + +int SHA512_Init(SHA512_CTX *sha) { + BCM_sha512_init(sha); + return 1; +} + +int SHA512_Update(SHA512_CTX *sha, const void *data, size_t len) { + BCM_sha512_update(sha, data, len); + return 1; +} + +int SHA512_Final(uint8_t out[SHA512_DIGEST_LENGTH], SHA512_CTX *sha) { + // Historically this function retured failure if passed NULL, even + // though other final functions do not. + if (out == NULL) { + return 0; + } + BCM_sha512_final(out, sha); + return 1; +} + +uint8_t *SHA512(const uint8_t *data, size_t len, + uint8_t out[SHA512_DIGEST_LENGTH]) { + SHA512_CTX ctx; + BCM_sha512_init(&ctx); + BCM_sha512_update(&ctx, data, len); + BCM_sha512_final(out, &ctx); + OPENSSL_cleanse(&ctx, sizeof(ctx)); + return out; +} + +void SHA512_Transform(SHA512_CTX *sha, const uint8_t block[SHA512_CBLOCK]) { + BCM_sha512_transform(sha, block); +} diff --git a/src/gen/sources.bzl b/src/gen/sources.bzl index 1eef08959..1ca1a8bdf 100644 --- a/src/gen/sources.bzl +++ b/src/gen/sources.bzl @@ -400,6 +400,7 @@ crypto_sources = [ "crypto/rsa_extra/rsa_print.c", "crypto/sha/sha1.c", "crypto/sha/sha256.c", + "crypto/sha/sha512.c", "crypto/siphash/siphash.c", "crypto/slhdsa/fors.c", "crypto/slhdsa/merkle.c", diff --git a/src/gen/sources.cmake b/src/gen/sources.cmake index 933595939..94b619598 100644 --- a/src/gen/sources.cmake +++ b/src/gen/sources.cmake @@ -414,6 +414,7 @@ set( crypto/rsa_extra/rsa_print.c crypto/sha/sha1.c crypto/sha/sha256.c + crypto/sha/sha512.c crypto/siphash/siphash.c crypto/slhdsa/fors.c crypto/slhdsa/merkle.c diff --git a/src/gen/sources.gni b/src/gen/sources.gni index 36b50c8a7..131de078f 100644 --- a/src/gen/sources.gni +++ b/src/gen/sources.gni @@ -400,6 +400,7 @@ crypto_sources = [ "crypto/rsa_extra/rsa_print.c", "crypto/sha/sha1.c", "crypto/sha/sha256.c", + "crypto/sha/sha512.c", "crypto/siphash/siphash.c", "crypto/slhdsa/fors.c", "crypto/slhdsa/merkle.c", diff --git a/src/gen/sources.json b/src/gen/sources.json index 9587ab24b..f5879cd3e 100644 --- a/src/gen/sources.json +++ b/src/gen/sources.json @@ -384,6 +384,7 @@ "crypto/rsa_extra/rsa_print.c", "crypto/sha/sha1.c", "crypto/sha/sha256.c", + "crypto/sha/sha512.c", "crypto/siphash/siphash.c", "crypto/slhdsa/fors.c", "crypto/slhdsa/merkle.c", diff --git a/src/include/openssl/bcm_public.h b/src/include/openssl/bcm_public.h index 9bb0dbb77..ac594eaa8 100644 --- a/src/include/openssl/bcm_public.h +++ b/src/include/openssl/bcm_public.h @@ -64,6 +64,16 @@ struct sha256_state_st { unsigned num, md_len; }; +// BCM_SHA512_CBLOCK is the block size of SHA-512. +#define BCM_SHA512_CBLOCK 128 + +struct sha512_state_st { + uint64_t h[8]; + uint64_t Nl, Nh; + uint8_t p[BCM_SHA512_CBLOCK]; + unsigned num, md_len; +}; + #if defined(__cplusplus) } // extern C diff --git a/src/include/openssl/sha.h b/src/include/openssl/sha.h index bfaeb7896..d70f33cd9 100644 --- a/src/include/openssl/sha.h +++ b/src/include/openssl/sha.h @@ -240,14 +240,6 @@ OPENSSL_EXPORT uint8_t *SHA512(const uint8_t *data, size_t len, OPENSSL_EXPORT void SHA512_Transform(SHA512_CTX *sha, const uint8_t block[SHA512_CBLOCK]); -struct sha512_state_st { - uint64_t h[8]; - uint64_t Nl, Nh; - uint8_t p[128]; - unsigned num, md_len; -}; - - // SHA-512-256 // // See https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf section 5.3.6