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.