Extract SHA1 from bcm This makes sha1 be internal to bcm other than the shared (public) SHA_CTX structure and lengths. Change-Id: Ib30e0e54a988e6c74a171ecf1fb400e70a9187b0 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/70567 Commit-Queue: Bob Beck <bbe@google.com> Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/build.json b/build.json index f3ac354..5f973d8 100644 --- a/build.json +++ b/build.json
@@ -302,6 +302,7 @@ "crypto/rsa_extra/rsa_asn1.c", "crypto/rsa_extra/rsa_crypt.c", "crypto/rsa_extra/rsa_print.c", + "crypto/sha/sha1.c", "crypto/siphash/siphash.c", "crypto/spx/spx_address.c", "crypto/spx/spx_fors.c", @@ -399,6 +400,7 @@ "include/openssl/asn1t.h", "include/openssl/base.h", "include/openssl/base64.h", + "include/openssl/bcm_public.h", "include/openssl/bio.h", "include/openssl/blake2.h", "include/openssl/blowfish.h",
diff --git a/crypto/fipsmodule/bcm_interface.h b/crypto/fipsmodule/bcm_interface.h index 9687b79..8c07281 100644 --- a/crypto/fipsmodule/bcm_interface.h +++ b/crypto/fipsmodule/bcm_interface.h
@@ -15,6 +15,8 @@ #ifndef OPENSSL_HEADER_CRYPTO_BCM_INTERFACE_H #define OPENSSL_HEADER_CRYPTO_BCM_INTERFACE_H +#include <openssl/bcm_public.h> + // This header will eventually become the interface between BCM and the // rest of libcrypto. More cleanly separating the two is still a work in // progress (see https://crbug.com/boringssl/722) so, at the moment, we @@ -51,6 +53,9 @@ return status == bcm_status_approved || status == bcm_status_not_approved; } + +// Random number generator. + #if defined(BORINGSSL_FIPS) // We overread from /dev/urandom or RDRAND by a factor of 10 and XOR to whiten. @@ -64,7 +69,7 @@ // module. The |want_additional_input| parameter is true iff the entropy was // obtained from a source other than the system, e.g. directly from the CPU. bcm_infallible BCM_rand_load_entropy(const uint8_t *entropy, size_t entropy_len, - int want_additional_input); + int want_additional_input); // BCM_rand_bytes is the same as the public |RAND_bytes| function, other // than returning a bcm_infallible status indicator. @@ -82,6 +87,44 @@ uint8_t *out, size_t out_len, const uint8_t user_additional_data[32]); +// SHA-1 + +// BCM_SHA_DIGEST_LENGTH is the length of a SHA-1 digest. +#define BCM_SHA_DIGEST_LENGTH 20 + +// BCM_sha1_init initialises |sha|. +bcm_infallible BCM_sha1_init(SHA_CTX *sha); + +// BCM_SHA1_transform is a low-level function that performs a single, SHA-1 +// block transformation using the state from |sha| and |SHA_CBLOCK| bytes from +// |block|. +bcm_infallible BCM_sha1_transform(SHA_CTX *c, const uint8_t data[BCM_SHA_CBLOCK]); + +// BCM_sha1_update adds |len| bytes from |data| to |sha|. +bcm_infallible BCM_sha1_update(SHA_CTX *c, const void *data, size_t len); + +// BCM_sha1_final adds the final padding to |sha| and writes the resulting +// digest to |out|, which must have at least |SHA_DIGEST_LENGTH| bytes of space. +bcm_infallible BCM_sha1_final(uint8_t out[BCM_SHA_DIGEST_LENGTH], SHA_CTX *c); + + +// BCM_fips_186_2_prf derives |out_len| bytes from |xkey| using the PRF +// defined in FIPS 186-2, Appendix 3.1, with change notice 1 applied. The b +// parameter is 160 and seed, XKEY, is also 160 bits. The optional XSEED user +// input is all zeros. +// +// The PRF generates a sequence of 320-bit numbers. Each number is encoded as a +// 40-byte string in big-endian and then concatenated to form |out|. If +// |out_len| is not a multiple of 40, the result is truncated. This matches the +// construction used in Section 7 of RFC 4186 and Section 7 of RFC 4187. +// +// This PRF is based on SHA-1, a weak hash function, and should not be used +// in new protocols. It is provided for compatibility with some legacy EAP +// methods. +bcm_infallible BCM_fips_186_2_prf(uint8_t *out, size_t out_len, + const uint8_t xkey[BCM_SHA_DIGEST_LENGTH]); + + #if defined(__cplusplus) } // extern C #endif
diff --git a/crypto/fipsmodule/digest/digests.c.inc b/crypto/fipsmodule/digest/digests.c.inc index effcbf5..4773a23 100644 --- a/crypto/fipsmodule/digest/digests.c.inc +++ b/crypto/fipsmodule/digest/digests.c.inc
@@ -74,20 +74,20 @@ static void sha1_init(EVP_MD_CTX *ctx) { - CHECK(SHA1_Init(ctx->md_data)); + BCM_sha1_init(ctx->md_data); } static void sha1_update(EVP_MD_CTX *ctx, const void *data, size_t count) { - CHECK(SHA1_Update(ctx->md_data, data, count)); + BCM_sha1_update(ctx->md_data, data, count); } static void sha1_final(EVP_MD_CTX *ctx, uint8_t *md) { - CHECK(SHA1_Final(md, ctx->md_data)); + BCM_sha1_final(md, ctx->md_data); } DEFINE_METHOD_FUNCTION(EVP_MD, EVP_sha1) { out->type = NID_sha1; - out->md_size = SHA_DIGEST_LENGTH; + out->md_size = BCM_SHA_DIGEST_LENGTH; out->flags = 0; out->init = sha1_init; out->update = sha1_update;
diff --git a/crypto/fipsmodule/rsa/rsa.c.inc b/crypto/fipsmodule/rsa/rsa.c.inc index b524e77..9b97655 100644 --- a/crypto/fipsmodule/rsa/rsa.c.inc +++ b/crypto/fipsmodule/rsa/rsa.c.inc
@@ -480,7 +480,7 @@ }, { NID_sha1, - SHA_DIGEST_LENGTH, + BCM_SHA_DIGEST_LENGTH, 15, {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14},
diff --git a/crypto/fipsmodule/sha/sha1.c.inc b/crypto/fipsmodule/sha/sha1.c.inc index 70353a6..53117a5 100644 --- a/crypto/fipsmodule/sha/sha1.c.inc +++ b/crypto/fipsmodule/sha/sha1.c.inc
@@ -54,35 +54,25 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ -#include <openssl/sha.h> - #include <string.h> #include <openssl/mem.h> +#include "../bcm_interface.h" #include "../../internal.h" #include "../digest/md32_common.h" #include "../service_indicator/internal.h" #include "internal.h" -int SHA1_Init(SHA_CTX *sha) { +bcm_infallible BCM_sha1_init(SHA_CTX *sha) { OPENSSL_memset(sha, 0, sizeof(SHA_CTX)); sha->h[0] = 0x67452301UL; sha->h[1] = 0xefcdab89UL; sha->h[2] = 0x98badcfeUL; sha->h[3] = 0x10325476UL; sha->h[4] = 0xc3d2e1f0UL; - return 1; -} - -uint8_t *SHA1(const uint8_t *data, size_t len, uint8_t out[SHA_DIGEST_LENGTH]) { - SHA_CTX ctx; - SHA1_Init(&ctx); - SHA1_Update(&ctx, data, len); - SHA1_Final(out, &ctx); - OPENSSL_cleanse(&ctx, sizeof(ctx)); - return out; + return bcm_infallible_approved; } #if !defined(SHA1_ASM) @@ -90,14 +80,15 @@ size_t num); #endif -void SHA1_Transform(SHA_CTX *c, const uint8_t data[SHA_CBLOCK]) { +bcm_infallible BCM_sha1_transform(SHA_CTX *c, const uint8_t data[SHA_CBLOCK]) { sha1_block_data_order(c->h, data, 1); + return bcm_infallible_approved; } -int SHA1_Update(SHA_CTX *c, const void *data, size_t len) { +bcm_infallible BCM_sha1_update(SHA_CTX *c, const void *data, size_t len) { crypto_md32_update(&sha1_block_data_order, c->h, c->data, SHA_CBLOCK, &c->num, &c->Nh, &c->Nl, data, len); - return 1; + return bcm_infallible_approved; } static void sha1_output_state(uint8_t out[SHA_DIGEST_LENGTH], @@ -109,16 +100,16 @@ CRYPTO_store_u32_be(out + 16, ctx->h[4]); } -int SHA1_Final(uint8_t out[SHA_DIGEST_LENGTH], SHA_CTX *c) { +bcm_infallible BCM_sha1_final(uint8_t out[SHA_DIGEST_LENGTH], SHA_CTX *c) { crypto_md32_final(&sha1_block_data_order, c->h, c->data, SHA_CBLOCK, &c->num, c->Nh, c->Nl, /*is_big_endian=*/1); sha1_output_state(out, c); FIPS_service_indicator_update_state(); - return 1; + return bcm_infallible_approved; } -void CRYPTO_fips_186_2_prf(uint8_t *out, size_t out_len, +bcm_infallible BCM_fips_186_2_prf(uint8_t *out, size_t out_len, const uint8_t xkey[SHA_DIGEST_LENGTH]) { // XKEY and XVAL are 160-bit values, but are internally right-padded up to // block size. See FIPS 186-2, Appendix 3.3. This buffer maintains both the @@ -130,8 +121,8 @@ // We always use a zero XSEED, so we can merge the inner and outer loops. // XVAL is also always equal to XKEY. SHA_CTX ctx; - SHA1_Init(&ctx); - SHA1_Transform(&ctx, block); + BCM_sha1_init(&ctx); + BCM_sha1_transform(&ctx, block); // XKEY = (1 + XKEY + w_i) mod 2^b uint32_t carry = 1; @@ -152,6 +143,7 @@ out += SHA_DIGEST_LENGTH; out_len -= SHA_DIGEST_LENGTH; } + return bcm_infallible_not_approved; } #define Xupdate(a, ix, ia, ib, ic, id) \
diff --git a/crypto/sha/sha1.c b/crypto/sha/sha1.c new file mode 100644 index 0000000..40586a0 --- /dev/null +++ b/crypto/sha/sha1.c
@@ -0,0 +1,52 @@ +/* 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 <openssl/sha.h> + +#include <openssl/mem.h> + +#include "../fipsmodule/bcm_interface.h" + +int SHA1_Init(SHA_CTX *sha) { + BCM_sha1_init(sha); + return 1; +} + +int SHA1_Update(SHA_CTX *sha, const void *data, size_t len) { + BCM_sha1_update(sha, data, len); + return 1; +} + +int SHA1_Final(uint8_t out[SHA_DIGEST_LENGTH], SHA_CTX *sha) { + BCM_sha1_final(out, sha); + return 1; +} + +uint8_t *SHA1(const uint8_t *data, size_t len, uint8_t out[SHA_DIGEST_LENGTH]) { + SHA_CTX ctx; + BCM_sha1_init(&ctx); + BCM_sha1_update(&ctx, data, len); + BCM_sha1_final(out, &ctx); + OPENSSL_cleanse(&ctx, sizeof(ctx)); + return out; +} + +void SHA1_Transform(SHA_CTX *sha, const uint8_t block[SHA_CBLOCK]) { + BCM_sha1_transform(sha, block); +} + +void CRYPTO_fips_186_2_prf(uint8_t *out, size_t out_len, + const uint8_t xkey[SHA_DIGEST_LENGTH]) { + BCM_fips_186_2_prf(out, out_len, xkey); +}
diff --git a/gen/sources.bzl b/gen/sources.bzl index 07df690..46b8aa7 100644 --- a/gen/sources.bzl +++ b/gen/sources.bzl
@@ -397,6 +397,7 @@ "crypto/rsa_extra/rsa_asn1.c", "crypto/rsa_extra/rsa_crypt.c", "crypto/rsa_extra/rsa_print.c", + "crypto/sha/sha1.c", "crypto/siphash/siphash.c", "crypto/spx/spx.c", "crypto/spx/spx_address.c", @@ -496,6 +497,7 @@ "include/openssl/asn1t.h", "include/openssl/base.h", "include/openssl/base64.h", + "include/openssl/bcm_public.h", "include/openssl/bio.h", "include/openssl/blake2.h", "include/openssl/blowfish.h",
diff --git a/gen/sources.cmake b/gen/sources.cmake index c994f60..f6fd81b 100644 --- a/gen/sources.cmake +++ b/gen/sources.cmake
@@ -411,6 +411,7 @@ crypto/rsa_extra/rsa_asn1.c crypto/rsa_extra/rsa_crypt.c crypto/rsa_extra/rsa_print.c + crypto/sha/sha1.c crypto/siphash/siphash.c crypto/spx/spx.c crypto/spx/spx_address.c @@ -512,6 +513,7 @@ include/openssl/asn1t.h include/openssl/base.h include/openssl/base64.h + include/openssl/bcm_public.h include/openssl/bio.h include/openssl/blake2.h include/openssl/blowfish.h
diff --git a/gen/sources.gni b/gen/sources.gni index 34d4acf..85d1211 100644 --- a/gen/sources.gni +++ b/gen/sources.gni
@@ -397,6 +397,7 @@ "crypto/rsa_extra/rsa_asn1.c", "crypto/rsa_extra/rsa_crypt.c", "crypto/rsa_extra/rsa_print.c", + "crypto/sha/sha1.c", "crypto/siphash/siphash.c", "crypto/spx/spx.c", "crypto/spx/spx_address.c", @@ -496,6 +497,7 @@ "include/openssl/asn1t.h", "include/openssl/base.h", "include/openssl/base64.h", + "include/openssl/bcm_public.h", "include/openssl/bio.h", "include/openssl/blake2.h", "include/openssl/blowfish.h",
diff --git a/gen/sources.json b/gen/sources.json index a818f8f..dfdbc04 100644 --- a/gen/sources.json +++ b/gen/sources.json
@@ -381,6 +381,7 @@ "crypto/rsa_extra/rsa_asn1.c", "crypto/rsa_extra/rsa_crypt.c", "crypto/rsa_extra/rsa_print.c", + "crypto/sha/sha1.c", "crypto/siphash/siphash.c", "crypto/spx/spx.c", "crypto/spx/spx_address.c", @@ -479,6 +480,7 @@ "include/openssl/asn1t.h", "include/openssl/base.h", "include/openssl/base64.h", + "include/openssl/bcm_public.h", "include/openssl/bio.h", "include/openssl/blake2.h", "include/openssl/blowfish.h",
diff --git a/include/openssl/bcm_public.h b/include/openssl/bcm_public.h new file mode 100644 index 0000000..f3797df --- /dev/null +++ b/include/openssl/bcm_public.h
@@ -0,0 +1,61 @@ +/* Copyright (c) 2024, Google LLC + * + * 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. */ + +#ifndef OPENSSL_HEADER_BCM_PUBLIC_H_ +#define OPENSSL_HEADER_BCM_PUBLIC_H_ + +#include <openssl/base.h> + +#if defined(__cplusplus) +extern "C" { +#endif + +// Public types referenced by BoringCrypto +// +// This header contains public types referenced by BCM. Such types are difficult +// to hide from the libcrypto interface, so we treat them as part of BCM. + +// BCM_SHA_CBLOCK is the block size of SHA-1. +#define BCM_SHA_CBLOCK 64 + +// SHA_CTX +struct sha_state_st { +#if defined(__cplusplus) || defined(OPENSSL_WINDOWS) + uint32_t h[5]; +#else + // wpa_supplicant accesses |h0|..|h4| so we must support those names for + // compatibility with it until it can be updated. Anonymous unions are only + // standard in C11, so disable this workaround in C++. + union { + uint32_t h[5]; + struct { + uint32_t h0; + uint32_t h1; + uint32_t h2; + uint32_t h3; + uint32_t h4; + }; + }; +#endif + uint32_t Nl, Nh; + uint8_t data[BCM_SHA_CBLOCK]; + unsigned num; +}; + + +#if defined(__cplusplus) +} // extern C +#endif + +#endif // OPENSSL_HEADER_BCM_PUBLIC_H_
diff --git a/include/openssl/sha.h b/include/openssl/sha.h index 9eca1ea..65a996c 100644 --- a/include/openssl/sha.h +++ b/include/openssl/sha.h
@@ -58,6 +58,7 @@ #define OPENSSL_HEADER_SHA_H #include <openssl/base.h> +#include <openssl/bcm_public.h> // IWYU pragma: export #if defined(__cplusplus) extern "C" { @@ -112,29 +113,6 @@ OPENSSL_EXPORT void CRYPTO_fips_186_2_prf( uint8_t *out, size_t out_len, const uint8_t xkey[SHA_DIGEST_LENGTH]); -struct sha_state_st { -#if defined(__cplusplus) || defined(OPENSSL_WINDOWS) - uint32_t h[5]; -#else - // wpa_supplicant accesses |h0|..|h4| so we must support those names for - // compatibility with it until it can be updated. Anonymous unions are only - // standard in C11, so disable this workaround in C++. - union { - uint32_t h[5]; - struct { - uint32_t h0; - uint32_t h1; - uint32_t h2; - uint32_t h3; - uint32_t h4; - }; - }; -#endif - uint32_t Nl, Nh; - uint8_t data[SHA_CBLOCK]; - unsigned num; -}; - // SHA-224.