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.