From 9cad13eea1ad907e5742d1257784baf2e2f1dd9f Mon Sep 17 00:00:00 2001 From: Adam Langley Date: Fri, 4 Feb 2022 14:32:26 -0800 Subject: [PATCH] Perform SHA-$x and HMAC KAT before integrity check. AS10.20 requires that the self-test for the integrity algorithm pass before the integrity check itself. IG 10.3.A requires an HMAC self-test now. Therefore run these tests before the integrity check. Since we also need the ability to run all self-tests, both SHA self-tests and the HMAC test are run again when running self-tests. I'm assuming that they're so fast that it doesn't matter. Change-Id: I6b23b6fd3cb6107edd7420bc8680780719bd41d2 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/51328 Reviewed-by: David Benjamin --- crypto/fipsmodule/bcm.c | 8 ++ crypto/fipsmodule/self_check/self_check.c | 104 ++++++++++++++-------- crypto/internal.h | 13 ++- util/fipstools/break-tests.sh | 2 +- 4 files changed, 89 insertions(+), 38 deletions(-) diff --git a/crypto/fipsmodule/bcm.c b/crypto/fipsmodule/bcm.c index f83c6f52e..35494c4a0 100644 --- a/crypto/fipsmodule/bcm.c +++ b/crypto/fipsmodule/bcm.c @@ -196,9 +196,17 @@ BORINGSSL_bcm_power_on_self_test(void) { #if defined(OPENSSL_AARCH64) || defined(OPENSSL_ANDROID) uint8_t result[SHA256_DIGEST_LENGTH]; const EVP_MD *const kHashFunction = EVP_sha256(); + if (!boringssl_self_test_sha256() || + !boringssl_self_test_hmac_sha256()) { + goto err; + } #else uint8_t result[SHA512_DIGEST_LENGTH]; const EVP_MD *const kHashFunction = EVP_sha512(); + if (!boringssl_self_test_sha512() || + !boringssl_self_test_hmac_sha256()) { + goto err; + } #endif static const uint8_t kHMACKey[64] = {0}; diff --git a/crypto/fipsmodule/self_check/self_check.c b/crypto/fipsmodule/self_check/self_check.c index e91f2f62c..8b15d83b9 100644 --- a/crypto/fipsmodule/self_check/self_check.c +++ b/crypto/fipsmodule/self_check/self_check.c @@ -536,11 +536,74 @@ err: return ret; } +static const uint8_t kPlaintext[64] = + "BoringCryptoModule FIPS KAT Encryption and Decryption Plaintext!"; + +int boringssl_self_test_sha256(void) { + static const uint8_t kPlaintextSHA256[32] = { + 0x37, 0xbd, 0x70, 0x53, 0x72, 0xfc, 0xd4, 0x03, 0x79, 0x70, 0xfb, + 0x06, 0x95, 0xb1, 0x2a, 0x82, 0x48, 0xe1, 0x3e, 0xf2, 0x33, 0xfb, + 0xef, 0x29, 0x81, 0x22, 0x45, 0x40, 0x43, 0x70, 0xce, +#if !defined(BORINGSSL_FIPS_BREAK_SHA_256) + 0x0f +#else + 0x00 +#endif + }; + uint8_t output[SHA256_DIGEST_LENGTH]; + + // SHA-256 KAT + SHA256(kPlaintext, sizeof(kPlaintext), output); + return check_test(kPlaintextSHA256, output, sizeof(kPlaintextSHA256), + "SHA-256 KAT"); +} + +int boringssl_self_test_sha512(void) { + static const uint8_t kPlaintextSHA512[64] = { + 0x08, 0x6a, 0x1c, 0x84, 0x61, 0x9d, 0x8e, 0xb3, 0xc0, 0x97, 0x4e, + 0xa1, 0x9f, 0x9c, 0xdc, 0xaf, 0x3b, 0x5c, 0x31, 0xf0, 0xf2, 0x74, + 0xc3, 0xbd, 0x6e, 0xd6, 0x1e, 0xb2, 0xbb, 0x34, 0x74, 0x72, 0x5c, + 0x51, 0x29, 0x8b, 0x87, 0x3a, 0xa3, 0xf2, 0x25, 0x23, 0xd4, 0x1c, + 0x82, 0x1b, 0xfe, 0xd3, 0xc6, 0xee, 0xb5, 0xd6, 0xaf, 0x07, 0x7b, + 0x98, 0xca, 0xa7, 0x01, 0xf3, 0x94, 0xf3, 0x68, +#if !defined(BORINGSSL_FIPS_BREAK_SHA_512) + 0x14 +#else + 0x00 +#endif + }; + uint8_t output[SHA512_DIGEST_LENGTH]; + + // SHA-512 KAT + SHA512(kPlaintext, sizeof(kPlaintext), output); + return check_test(kPlaintextSHA512, output, sizeof(kPlaintextSHA512), + "SHA-512 KAT"); +} + +int boringssl_self_test_hmac_sha256(void) { + static const uint8_t kPlaintextHMACSHA256[32] = { + 0x08, 0x0b, 0xa8, 0x16, 0xdf, 0xcb, 0x7a, 0xa0, 0xdc, 0xc7, 0x8d, + 0xb5, 0x4b, 0x68, 0xb0, 0x3b, 0x92, 0x03, 0x0f, 0xb7, 0xe2, 0x1e, + 0x42, 0x63, 0x0c, 0xf3, 0x64, 0xf9, 0xad, 0xe0, 0x66, +#if !defined(BORINGSSL_FIPS_BREAK_HMAC_SHA_256) + 0x85 +#else + 0x00 +#endif + }; + uint8_t output[EVP_MAX_MD_SIZE]; + + unsigned output_len; + HMAC(EVP_sha256(), kPlaintext, sizeof(kPlaintext), kPlaintext, + sizeof(kPlaintext), output, &output_len); + return output_len == sizeof(kPlaintextHMACSHA256) && + check_test(kPlaintextHMACSHA256, output, sizeof(kPlaintextHMACSHA256), + "HMAC-SHA-256 KAT"); +} + int BORINGSSL_self_test(void) { static const uint8_t kAESKey[16] = "BoringCrypto Key"; static const uint8_t kAESIV[16] = {0}; - static const uint8_t kPlaintext[64] = - "BoringCryptoModule FIPS KAT Encryption and Decryption Plaintext!"; static const uint8_t kAESCBCCiphertext[64] = { 0x87, 0x2d, 0x98, 0xc2, 0xcc, 0x31, 0x5b, 0x41, 0xe0, 0xfa, 0x7b, 0x0a, 0x71, 0xc0, 0x42, 0xbf, 0x4f, 0x61, 0xd0, 0x0d, 0x58, 0x8c, @@ -575,29 +638,6 @@ int BORINGSSL_self_test(void) { 0x28 #else 0x00 -#endif - }; - static const uint8_t kPlaintextSHA256[32] = { - 0x37, 0xbd, 0x70, 0x53, 0x72, 0xfc, 0xd4, 0x03, 0x79, 0x70, 0xfb, - 0x06, 0x95, 0xb1, 0x2a, 0x82, 0x48, 0xe1, 0x3e, 0xf2, 0x33, 0xfb, - 0xef, 0x29, 0x81, 0x22, 0x45, 0x40, 0x43, 0x70, 0xce, -#if !defined(BORINGSSL_FIPS_BREAK_SHA_256) - 0x0f -#else - 0x00 -#endif - }; - static const uint8_t kPlaintextSHA512[64] = { - 0x08, 0x6a, 0x1c, 0x84, 0x61, 0x9d, 0x8e, 0xb3, 0xc0, 0x97, 0x4e, - 0xa1, 0x9f, 0x9c, 0xdc, 0xaf, 0x3b, 0x5c, 0x31, 0xf0, 0xf2, 0x74, - 0xc3, 0xbd, 0x6e, 0xd6, 0x1e, 0xb2, 0xbb, 0x34, 0x74, 0x72, 0x5c, - 0x51, 0x29, 0x8b, 0x87, 0x3a, 0xa3, 0xf2, 0x25, 0x23, 0xd4, 0x1c, - 0x82, 0x1b, 0xfe, 0xd3, 0xc6, 0xee, 0xb5, 0xd6, 0xaf, 0x07, 0x7b, - 0x98, 0xca, 0xa7, 0x01, 0xf3, 0x94, 0xf3, 0x68, -#if !defined(BORINGSSL_FIPS_BREAK_SHA_512) - 0x14 -#else - 0x00 #endif }; const uint8_t kDRBGEntropy[48] = @@ -723,17 +763,9 @@ int BORINGSSL_self_test(void) { goto err; } - // SHA-256 KAT - SHA256(kPlaintext, sizeof(kPlaintext), output); - if (!check_test(kPlaintextSHA256, output, sizeof(kPlaintextSHA256), - "SHA-256 KAT")) { - goto err; - } - - // SHA-512 KAT - SHA512(kPlaintext, sizeof(kPlaintext), output); - if (!check_test(kPlaintextSHA512, output, sizeof(kPlaintextSHA512), - "SHA-512 KAT")) { + if (!boringssl_self_test_sha256() || + !boringssl_self_test_sha512() || + !boringssl_self_test_hmac_sha256()) { goto err; } diff --git a/crypto/internal.h b/crypto/internal.h index 9d7b486f4..fe2ba39da 100644 --- a/crypto/internal.h +++ b/crypto/internal.h @@ -932,11 +932,22 @@ static inline uint64_t CRYPTO_rotr_u64(uint64_t value, int shift) { // FIPS functions. #if defined(BORINGSSL_FIPS) + // BORINGSSL_FIPS_abort is called when a FIPS power-on or continuous test // fails. It prevents any further cryptographic operations by the current // process. void BORINGSSL_FIPS_abort(void) __attribute__((noreturn)); -#endif + +#endif // FIPS + +// boringssl_self_test_sha256 performs a SHA-256 KAT. +int boringssl_self_test_sha256(void); + +// boringssl_self_test_sha512 performs a SHA-512 KAT. +int boringssl_self_test_sha512(void); + +// boringssl_self_test_hmac_sha256 performs an HMAC-SHA-256 KAT. +int boringssl_self_test_hmac_sha256(void); #if defined(BORINGSSL_FIPS_COUNTERS) void boringssl_fips_inc_counter(enum fips_counter_t counter); diff --git a/util/fipstools/break-tests.sh b/util/fipstools/break-tests.sh index 84c24eeff..a0e4e53e6 100644 --- a/util/fipstools/break-tests.sh +++ b/util/fipstools/break-tests.sh @@ -22,7 +22,7 @@ set -x -TESTS="NONE ECDSA_PWCT CRNG RSA_PWCT AES_CBC AES_GCM DES SHA_1 SHA_256 SHA_512 RSA_SIG DRBG ECDSA_SIG Z_COMPUTATION TLS_KDF FFC_DH" +TESTS="NONE ECDSA_PWCT CRNG RSA_PWCT AES_CBC AES_GCM DES SHA_1 SHA_256 SHA_512 HMAC_SHA_256 RSA_SIG DRBG ECDSA_SIG Z_COMPUTATION TLS_KDF FFC_DH" if [ "x$1" = "xbuild" ]; then for test in $TESTS; do