diff --git a/crypto/fipsmodule/FIPS.md b/crypto/fipsmodule/FIPS.md index d3b3890fc..29fc68887 100644 --- a/crypto/fipsmodule/FIPS.md +++ b/crypto/fipsmodule/FIPS.md @@ -61,12 +61,6 @@ There is a second interface to the RNG which allows the caller to supply bytes t FIPS requires that RNG state be zeroed when the process exits. In order to implement this, all per-thread RNG states are tracked in a linked list and a destructor function is included which clears them. In order for this to be safe in the presence of threads, a lock is used to stop all other threads from using the RNG once this process has begun. Thus the main thread exiting may cause other threads to deadlock, and drawing on entropy in a destructor function may also deadlock. -## Self-test optimisation - -On Android, the self-tests are optimised in line with [IG](https://csrc.nist.gov/csrc/media/projects/cryptographic-module-validation-program/documents/fips140-2/fips1402ig.pdf) section 9.11. The module will always perform the integrity test at power-on, but the self-tests will test for the presence of a file named after the hex encoded, HMAC-SHA-256 hash of the module in `/dev/boringssl/selftest/`. If such a file is found then the self-tests are skipped. Otherwise, after the self-tests complete successfully, that file will be written. Any I/O errors are ignored and, if they occur when testing for the presence of the file, the module acts as if it's not present. - -It is intended that a `tmpfs` be mounted at that location in order to skip running the self tests for every process once they have already passed in a given instance of the operating system. - ## Integrity Test FIPS-140 mandates that a module calculate an HMAC of its own code in a constructor function and compare the result to a known-good value. Typical code produced by a C compiler includes large numbers of relocations: places in the machine code where the linker needs to resolve and inject the final value of a symbolic expression. These relocations mean that the bytes that make up any specific bit of code generally aren't known until the final link has completed. diff --git a/crypto/fipsmodule/bcm.c b/crypto/fipsmodule/bcm.c index bab30cf5a..f83c6f52e 100644 --- a/crypto/fipsmodule/bcm.c +++ b/crypto/fipsmodule/bcm.c @@ -239,15 +239,11 @@ BORINGSSL_bcm_power_on_self_test(void) { } OPENSSL_cleanse(result, sizeof(result)); // FIPS 140-3, AS05.10. +#endif // OPENSSL_ASAN - if (!boringssl_fips_self_test(BORINGSSL_bcm_text_hash, sizeof(result))) { - goto err; - } -#else if (!BORINGSSL_self_test()) { goto err; } -#endif // OPENSSL_ASAN return; diff --git a/crypto/fipsmodule/self_check/self_check.c b/crypto/fipsmodule/self_check/self_check.c index 9dacf91f0..da018f1f6 100644 --- a/crypto/fipsmodule/self_check/self_check.c +++ b/crypto/fipsmodule/self_check/self_check.c @@ -46,21 +46,6 @@ int BORINGSSL_self_test(void) { #else -#if defined(BORINGSSL_FIPS) && defined(OPENSSL_ANDROID) -// FIPS builds on Android will test for flag files, named after the module hash, -// in /dev/boringssl/selftest/. If such a flag file exists, it's assumed that -// self-tests have already passed and thus do not need to be repeated. (The -// integrity tests always run, however.) -// -// If self-tests complete successfully and the environment variable named in -// |kFlagWriteEnableEnvVar| is present, then the flag file will be created. The -// flag file isn't written without the environment variable being set in order -// to avoid SELinux violations on Android. -#define BORINGSSL_FIPS_SELF_TEST_FLAG_FILE -static const char kFlagPrefix[] = "/dev/boringssl/selftest/"; -static const char kFlagWriteEnableEnvVar[] = "BORINGSSL_SELF_TEST_CREATE_FLAG"; -#endif - static void hexdump(const uint8_t *in, size_t len) { for (size_t i = 0; i < len; i++) { fprintf(stderr, "%02x", in[i]); @@ -288,104 +273,11 @@ err: return NULL; } -#if defined(OPENSSL_ANDROID) -#define MODULE_DIGEST_SIZE SHA256_DIGEST_LENGTH -#else -#define MODULE_DIGEST_SIZE SHA512_DIGEST_LENGTH -#endif - -int boringssl_fips_self_test( - const uint8_t *module_hash, size_t module_hash_len) { -#if defined(BORINGSSL_FIPS_SELF_TEST_FLAG_FILE) - char flag_path[sizeof(kFlagPrefix) + 2 * MODULE_DIGEST_SIZE]; - if (module_hash_len != 0) { - if (module_hash_len != MODULE_DIGEST_SIZE) { - fprintf(stderr, - "module hash of length %zu does not match expected length %d\n", - module_hash_len, MODULE_DIGEST_SIZE); - BORINGSSL_FIPS_abort(); - } - - // Test whether the flag file exists. - memcpy(flag_path, kFlagPrefix, sizeof(kFlagPrefix) - 1); - static const char kHexTable[17] = "0123456789abcdef"; - for (size_t i = 0; i < MODULE_DIGEST_SIZE; i++) { - flag_path[sizeof(kFlagPrefix) - 1 + 2 * i] = - kHexTable[module_hash[i] >> 4]; - flag_path[sizeof(kFlagPrefix) - 1 + 2 * i + 1] = - kHexTable[module_hash[i] & 15]; - } - flag_path[sizeof(flag_path) - 1] = 0; - - if (access(flag_path, F_OK) == 0) { - // Flag file found. Skip self-tests. - return 1; - } - } -#endif // BORINGSSL_FIPS_SELF_TEST_FLAG_FILE - - 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, - 0xf7, 0x05, 0xfb, 0x94, 0x89, 0xd3, 0xbc, 0xaa, 0x1a, 0x50, 0x45, - 0x1f, 0xc3, 0x8c, 0xb8, 0x98, 0x86, 0xa3, 0xe3, 0x6c, 0xfc, 0xad, - 0x3a, 0xb5, 0x59, 0x27, 0x7d, 0x21, 0x07, 0xca, 0x4c, 0x1d, 0x55, - 0x34, 0xdd, 0x5a, 0x2d, 0xc4, 0xb4, 0xf5, 0xa8, -#if !defined(BORINGSSL_FIPS_BREAK_AES_CBC) - 0x35 -#else - 0x00 -#endif - }; - static const uint8_t kAESGCMCiphertext[80] = { - 0x4a, 0xd8, 0xe7, 0x7d, 0x78, 0xd7, 0x7d, 0x5e, 0xb2, 0x11, 0xb6, 0xc9, - 0xa4, 0xbc, 0xb2, 0xae, 0xbe, 0x93, 0xd1, 0xb7, 0xfe, 0x65, 0xc1, 0x82, - 0x2a, 0xb6, 0x71, 0x5f, 0x1a, 0x7c, 0xe0, 0x1b, 0x2b, 0xe2, 0x53, 0xfa, - 0xa0, 0x47, 0xfa, 0xd7, 0x8f, 0xb1, 0x4a, 0xc4, 0xdc, 0x89, 0xf9, 0xb4, - 0x14, 0x4d, 0xde, 0x95, 0xea, 0x29, 0x69, 0x76, 0x81, 0xa3, 0x5c, 0x33, - 0xd8, 0x37, 0xd8, 0xfa, 0x47, 0x19, 0x46, 0x2f, 0xf1, 0x90, 0xb7, 0x61, - 0x8f, 0x6f, 0xdd, 0x31, 0x3f, 0x6a, 0x64, -#if !defined(BORINGSSL_FIPS_BREAK_AES_GCM) - 0x0d -#else - 0x00 -#endif - }; - static const uint8_t kPlaintextSHA1[20] = { - 0xc6, 0xf8, 0xc9, 0x63, 0x1c, 0x14, 0x23, 0x62, 0x9b, 0xbd, - 0x55, 0x82, 0xf4, 0xd6, 0x1d, 0xf2, 0xab, 0x7d, 0xc8, -#if !defined(BORINGSSL_FIPS_BREAK_SHA_1) - 0x28 -#else - 0x00 -#endif - }; - static const uint8_t kPlaintextSHA256[32] = { +static int boringssl_self_test_slow(void) { + static const uint8_t kExampleDigest[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 + 0xef, 0x29, 0x81, 0x22, 0x45, 0x40, 0x43, 0x70, 0xce, 0x0f, }; static const uint8_t kRSASignature[256] = { 0x62, 0x66, 0x4b, 0xe3, 0xb1, 0xd2, 0x83, 0xf1, 0xa8, 0x56, 0x2b, 0x33, @@ -414,43 +306,6 @@ int boringssl_fips_self_test( 0x64 #else 0x00 -#endif - }; - const uint8_t kDRBGEntropy[48] = - "BCM Known Answer Test DBRG Initial Entropy "; - const uint8_t kDRBGPersonalization[18] = "BCMPersonalization"; - const uint8_t kDRBGAD[16] = "BCM DRBG KAT AD "; - const uint8_t kDRBGOutput[64] = { - 0x1d, 0x63, 0xdf, 0x05, 0x51, 0x49, 0x22, 0x46, 0xcd, 0x9b, 0xc5, - 0xbb, 0xf1, 0x5d, 0x44, 0xae, 0x13, 0x78, 0xb1, 0xe4, 0x7c, 0xf1, - 0x96, 0x33, 0x3d, 0x60, 0xb6, 0x29, 0xd4, 0xbb, 0x6b, 0x44, 0xf9, - 0xef, 0xd9, 0xf4, 0xa2, 0xba, 0x48, 0xea, 0x39, 0x75, 0x59, 0x32, - 0xf7, 0x31, 0x2c, 0x98, 0x14, 0x2b, 0x49, 0xdf, 0x02, 0xb6, 0x5d, - 0x71, 0x09, 0x50, 0xdb, 0x23, 0xdb, 0xe5, 0x22, -#if !defined(BORINGSSL_FIPS_BREAK_DRBG) - 0x95 -#else - 0x00 -#endif - }; - const uint8_t kDRBGEntropy2[48] = - "BCM Known Answer Test DBRG Reseed Entropy "; - const uint8_t kDRBGReseedOutput[64] = { - 0xa4, 0x77, 0x05, 0xdb, 0x14, 0x11, 0x76, 0x71, 0x42, 0x5b, 0xd8, - 0xd7, 0xa5, 0x4f, 0x8b, 0x39, 0xf2, 0x10, 0x4a, 0x50, 0x5b, 0xa2, - 0xc8, 0xf0, 0xbb, 0x3e, 0xa1, 0xa5, 0x90, 0x7d, 0x54, 0xd9, 0xc6, - 0xb0, 0x96, 0xc0, 0x2b, 0x7e, 0x9b, 0xc9, 0xa1, 0xdd, 0x78, 0x2e, - 0xd5, 0xa8, 0x66, 0x16, 0xbd, 0x18, 0x3c, 0xf2, 0xaa, 0x7a, 0x2b, - 0x37, 0xf9, 0xab, 0x35, 0x64, 0x15, 0x01, 0x3f, 0xc4, - }; - const uint8_t kECDSASigR[32] = { - 0x67, 0x80, 0xc5, 0xfc, 0x70, 0x27, 0x5e, 0x2c, 0x70, 0x61, 0xa0, - 0xe7, 0x87, 0x7b, 0xb1, 0x74, 0xde, 0xad, 0xeb, 0x98, 0x87, 0x02, - 0x7f, 0x3f, 0xa8, 0x36, 0x54, 0x15, 0x8b, 0xa7, 0xf5, -#if !defined(BORINGSSL_FIPS_BREAK_ECDSA_SIG) - 0x0c, -#else - 0x00, #endif }; const uint8_t kECDSASigS[32] = { @@ -487,34 +342,9 @@ int boringssl_fips_self_test( 0x00, #endif }; - const uint8_t kTLSOutput[32] = { - 0x67, 0x85, 0xde, 0x60, 0xfc, 0x0a, 0x83, 0xe9, 0xa2, 0x2a, 0xb3, - 0xf0, 0x27, 0x0c, 0xba, 0xf7, 0xfa, 0x82, 0x3d, 0x14, 0x77, 0x1d, - 0x86, 0x29, 0x79, 0x39, 0x77, 0x8a, 0xd5, 0x0e, 0x9d, -#if !defined(BORINGSSL_FIPS_BREAK_TLS_KDF) - 0x32, -#else - 0x00, -#endif - }; - const uint8_t kTLSSecret[32] = { - 0xbf, 0xe4, 0xb7, 0xe0, 0x26, 0x55, 0x5f, 0x6a, 0xdf, 0x5d, 0x27, - 0xd6, 0x89, 0x99, 0x2a, 0xd6, 0xf7, 0x65, 0x66, 0x07, 0x4b, 0x55, - 0x5f, 0x64, 0x55, 0xcd, 0xd5, 0x77, 0xa4, 0xc7, 0x09, 0x61, - }; - const char kTLSLabel[] = "FIPS self test"; - const uint8_t kTLSSeed1[16] = { - 0x8f, 0x0d, 0xe8, 0xb6, 0x90, 0x8f, 0xb1, 0xd2, - 0x6d, 0x51, 0xf4, 0x79, 0x18, 0x63, 0x51, 0x65, - }; - const uint8_t kTLSSeed2[16] = { - 0x7d, 0x24, 0x1a, 0x9d, 0x3c, 0x59, 0xbf, 0x3c, - 0x31, 0x1e, 0x2b, 0x21, 0x41, 0x8d, 0x32, 0x81, - }; - // kFFDHE2048PublicValueData is an arbitrary public value, mod // kFFDHE2048Data. (The private key happens to be 4096.) - static const BN_ULONG kFFDHE2048PublicValueData[] = { + const BN_ULONG kFFDHE2048PublicValueData[] = { TOBN(0x187be36b, 0xd38a4fa1), TOBN(0x0a152f39, 0x6458f3b8), TOBN(0x0570187e, 0xc422eeb7), TOBN(0x18af7482, 0x91173f2a), TOBN(0xe9fdac6a, 0xcff4eaaa), TOBN(0xf6afebb7, 0x6e589d6c), @@ -532,7 +362,6 @@ int boringssl_fips_self_test( TOBN(0xbae7b0b3, 0x6e362dc0), TOBN(0xa57c73bd, 0xdc70fb82), TOBN(0xfaff50d2, 0x9d573457), TOBN(0x352bd399, 0xbe84058e), }; - const uint8_t kDHOutput[2048 / 8] = { 0x2a, 0xe6, 0xd3, 0xa6, 0x13, 0x58, 0x8e, 0xce, 0x53, 0xaa, 0xf6, 0x5d, 0x9a, 0xae, 0x02, 0x12, 0xf5, 0x80, 0x3d, 0x06, 0x09, 0x76, 0xac, 0x57, @@ -562,9 +391,18 @@ int boringssl_fips_self_test( 0x00, #endif }; + const uint8_t kECDSASigR[32] = { + 0x67, 0x80, 0xc5, 0xfc, 0x70, 0x27, 0x5e, 0x2c, 0x70, 0x61, 0xa0, + 0xe7, 0x87, 0x7b, 0xb1, 0x74, 0xde, 0xad, 0xeb, 0x98, 0x87, 0x02, + 0x7f, 0x3f, 0xa8, 0x36, 0x54, 0x15, 0x8b, 0xa7, 0xf5, +#if !defined(BORINGSSL_FIPS_BREAK_ECDSA_SIG) + 0x0c, +#else + 0x00, +#endif + }; - EVP_AEAD_CTX aead_ctx; - EVP_AEAD_CTX_zero(&aead_ctx); + int ret = 0; RSA *rsa_key = NULL; EC_KEY *ec_key = NULL; EC_GROUP *ec_group = NULL; @@ -572,89 +410,8 @@ int boringssl_fips_self_test( EC_POINT *ec_point_out = NULL; BIGNUM *ec_scalar = NULL; ECDSA_SIG *sig = NULL; - int ret = 0; - - AES_KEY aes_key; - uint8_t aes_iv[16]; uint8_t output[256]; - // AES-CBC Encryption KAT - memcpy(aes_iv, kAESIV, sizeof(kAESIV)); - if (AES_set_encrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key) != 0) { - fprintf(stderr, "AES_set_encrypt_key failed.\n"); - goto err; - } - AES_cbc_encrypt(kPlaintext, output, sizeof(kPlaintext), &aes_key, aes_iv, - AES_ENCRYPT); - if (!check_test(kAESCBCCiphertext, output, sizeof(kAESCBCCiphertext), - "AES-CBC Encryption KAT")) { - goto err; - } - - // AES-CBC Decryption KAT - memcpy(aes_iv, kAESIV, sizeof(kAESIV)); - if (AES_set_decrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key) != 0) { - fprintf(stderr, "AES_set_decrypt_key failed.\n"); - goto err; - } - AES_cbc_encrypt(kAESCBCCiphertext, output, sizeof(kAESCBCCiphertext), - &aes_key, aes_iv, AES_DECRYPT); - if (!check_test(kPlaintext, output, sizeof(kPlaintext), - "AES-CBC Decryption KAT")) { - goto err; - } - - size_t out_len; - uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH]; - OPENSSL_memset(nonce, 0, sizeof(nonce)); - if (!EVP_AEAD_CTX_init(&aead_ctx, EVP_aead_aes_128_gcm(), kAESKey, - sizeof(kAESKey), 0, NULL)) { - fprintf(stderr, "EVP_AEAD_CTX_init for AES-128-GCM failed.\n"); - goto err; - } - - // AES-GCM Encryption KAT - if (!EVP_AEAD_CTX_seal(&aead_ctx, output, &out_len, sizeof(output), nonce, - EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()), - kPlaintext, sizeof(kPlaintext), NULL, 0) || - !check_test(kAESGCMCiphertext, output, sizeof(kAESGCMCiphertext), - "AES-GCM Encryption KAT")) { - fprintf(stderr, "EVP_AEAD_CTX_seal for AES-128-GCM failed.\n"); - goto err; - } - - // AES-GCM Decryption KAT - if (!EVP_AEAD_CTX_open(&aead_ctx, output, &out_len, sizeof(output), nonce, - EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()), - kAESGCMCiphertext, sizeof(kAESGCMCiphertext), NULL, - 0) || - !check_test(kPlaintext, output, sizeof(kPlaintext), - "AES-GCM Decryption KAT")) { - fprintf(stderr, "EVP_AEAD_CTX_open for AES-128-GCM failed.\n"); - goto err; - } - - // SHA-1 KAT - SHA1(kPlaintext, sizeof(kPlaintext), output); - if (!check_test(kPlaintextSHA1, output, sizeof(kPlaintextSHA1), - "SHA-1 KAT")) { - 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")) { - goto err; - } - rsa_key = self_test_rsa_key(); if (rsa_key == NULL) { fprintf(stderr, "RSA KeyGen failed\n"); @@ -668,7 +425,7 @@ int boringssl_fips_self_test( // triggers an entropy draw. rsa_key->flags |= RSA_FLAG_NO_BLINDING; - if (!RSA_sign(NID_sha256, kPlaintextSHA256, sizeof(kPlaintextSHA256), output, + if (!RSA_sign(NID_sha256, kExampleDigest, sizeof(kExampleDigest), output, &sig_len, rsa_key) || !check_test(kRSASignature, output, sizeof(kRSASignature), "RSA Sign KAT")) { @@ -677,7 +434,7 @@ int boringssl_fips_self_test( } // RSA Verify KAT - if (!RSA_verify(NID_sha256, kPlaintextSHA256, sizeof(kPlaintextSHA256), + if (!RSA_verify(NID_sha256, kExampleDigest, sizeof(kExampleDigest), kRSASignature, sizeof(kRSASignature), rsa_key)) { fprintf(stderr, "RSA Verify KAT failed.\n"); goto err; @@ -696,7 +453,7 @@ int boringssl_fips_self_test( ecdsa_k[31] = 42; sig = ecdsa_sign_with_nonce_for_known_answer_test( - kPlaintextSHA256, sizeof(kPlaintextSHA256), ec_key, ecdsa_k, + kExampleDigest, sizeof(kExampleDigest), ec_key, ecdsa_k, sizeof(ecdsa_k)); uint8_t ecdsa_r_bytes[sizeof(kECDSASigR)]; @@ -712,7 +469,7 @@ int boringssl_fips_self_test( goto err; } - if (!ECDSA_do_verify(kPlaintextSHA256, sizeof(kPlaintextSHA256), sig, + if (!ECDSA_do_verify(kExampleDigest, sizeof(kExampleDigest), sig, ec_key)) { fprintf(stderr, "ECDSA verification KAT failed.\n"); goto err; @@ -765,6 +522,221 @@ int boringssl_fips_self_test( goto err; } + ret = 1; + +err: + RSA_free(rsa_key); + EC_KEY_free(ec_key); + EC_POINT_free(ec_point_in); + EC_POINT_free(ec_point_out); + EC_GROUP_free(ec_group); + BN_free(ec_scalar); + ECDSA_SIG_free(sig); + + return ret; +} + +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, + 0xf7, 0x05, 0xfb, 0x94, 0x89, 0xd3, 0xbc, 0xaa, 0x1a, 0x50, 0x45, + 0x1f, 0xc3, 0x8c, 0xb8, 0x98, 0x86, 0xa3, 0xe3, 0x6c, 0xfc, 0xad, + 0x3a, 0xb5, 0x59, 0x27, 0x7d, 0x21, 0x07, 0xca, 0x4c, 0x1d, 0x55, + 0x34, 0xdd, 0x5a, 0x2d, 0xc4, 0xb4, 0xf5, 0xa8, +#if !defined(BORINGSSL_FIPS_BREAK_AES_CBC) + 0x35 +#else + 0x00 +#endif + }; + static const uint8_t kAESGCMCiphertext[80] = { + 0x4a, 0xd8, 0xe7, 0x7d, 0x78, 0xd7, 0x7d, 0x5e, 0xb2, 0x11, 0xb6, 0xc9, + 0xa4, 0xbc, 0xb2, 0xae, 0xbe, 0x93, 0xd1, 0xb7, 0xfe, 0x65, 0xc1, 0x82, + 0x2a, 0xb6, 0x71, 0x5f, 0x1a, 0x7c, 0xe0, 0x1b, 0x2b, 0xe2, 0x53, 0xfa, + 0xa0, 0x47, 0xfa, 0xd7, 0x8f, 0xb1, 0x4a, 0xc4, 0xdc, 0x89, 0xf9, 0xb4, + 0x14, 0x4d, 0xde, 0x95, 0xea, 0x29, 0x69, 0x76, 0x81, 0xa3, 0x5c, 0x33, + 0xd8, 0x37, 0xd8, 0xfa, 0x47, 0x19, 0x46, 0x2f, 0xf1, 0x90, 0xb7, 0x61, + 0x8f, 0x6f, 0xdd, 0x31, 0x3f, 0x6a, 0x64, +#if !defined(BORINGSSL_FIPS_BREAK_AES_GCM) + 0x0d +#else + 0x00 +#endif + }; + static const uint8_t kPlaintextSHA1[20] = { + 0xc6, 0xf8, 0xc9, 0x63, 0x1c, 0x14, 0x23, 0x62, 0x9b, 0xbd, + 0x55, 0x82, 0xf4, 0xd6, 0x1d, 0xf2, 0xab, 0x7d, 0xc8, +#if !defined(BORINGSSL_FIPS_BREAK_SHA_1) + 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] = + "BCM Known Answer Test DBRG Initial Entropy "; + const uint8_t kDRBGPersonalization[18] = "BCMPersonalization"; + const uint8_t kDRBGAD[16] = "BCM DRBG KAT AD "; + const uint8_t kDRBGOutput[64] = { + 0x1d, 0x63, 0xdf, 0x05, 0x51, 0x49, 0x22, 0x46, 0xcd, 0x9b, 0xc5, + 0xbb, 0xf1, 0x5d, 0x44, 0xae, 0x13, 0x78, 0xb1, 0xe4, 0x7c, 0xf1, + 0x96, 0x33, 0x3d, 0x60, 0xb6, 0x29, 0xd4, 0xbb, 0x6b, 0x44, 0xf9, + 0xef, 0xd9, 0xf4, 0xa2, 0xba, 0x48, 0xea, 0x39, 0x75, 0x59, 0x32, + 0xf7, 0x31, 0x2c, 0x98, 0x14, 0x2b, 0x49, 0xdf, 0x02, 0xb6, 0x5d, + 0x71, 0x09, 0x50, 0xdb, 0x23, 0xdb, 0xe5, 0x22, +#if !defined(BORINGSSL_FIPS_BREAK_DRBG) + 0x95 +#else + 0x00 +#endif + }; + const uint8_t kDRBGEntropy2[48] = + "BCM Known Answer Test DBRG Reseed Entropy "; + const uint8_t kDRBGReseedOutput[64] = { + 0xa4, 0x77, 0x05, 0xdb, 0x14, 0x11, 0x76, 0x71, 0x42, 0x5b, 0xd8, + 0xd7, 0xa5, 0x4f, 0x8b, 0x39, 0xf2, 0x10, 0x4a, 0x50, 0x5b, 0xa2, + 0xc8, 0xf0, 0xbb, 0x3e, 0xa1, 0xa5, 0x90, 0x7d, 0x54, 0xd9, 0xc6, + 0xb0, 0x96, 0xc0, 0x2b, 0x7e, 0x9b, 0xc9, 0xa1, 0xdd, 0x78, 0x2e, + 0xd5, 0xa8, 0x66, 0x16, 0xbd, 0x18, 0x3c, 0xf2, 0xaa, 0x7a, 0x2b, + 0x37, 0xf9, 0xab, 0x35, 0x64, 0x15, 0x01, 0x3f, 0xc4, + }; + const uint8_t kTLSOutput[32] = { + 0x67, 0x85, 0xde, 0x60, 0xfc, 0x0a, 0x83, 0xe9, 0xa2, 0x2a, 0xb3, + 0xf0, 0x27, 0x0c, 0xba, 0xf7, 0xfa, 0x82, 0x3d, 0x14, 0x77, 0x1d, + 0x86, 0x29, 0x79, 0x39, 0x77, 0x8a, 0xd5, 0x0e, 0x9d, +#if !defined(BORINGSSL_FIPS_BREAK_TLS_KDF) + 0x32, +#else + 0x00, +#endif + }; + const uint8_t kTLSSecret[32] = { + 0xbf, 0xe4, 0xb7, 0xe0, 0x26, 0x55, 0x5f, 0x6a, 0xdf, 0x5d, 0x27, + 0xd6, 0x89, 0x99, 0x2a, 0xd6, 0xf7, 0x65, 0x66, 0x07, 0x4b, 0x55, + 0x5f, 0x64, 0x55, 0xcd, 0xd5, 0x77, 0xa4, 0xc7, 0x09, 0x61, + }; + const char kTLSLabel[] = "FIPS self test"; + const uint8_t kTLSSeed1[16] = { + 0x8f, 0x0d, 0xe8, 0xb6, 0x90, 0x8f, 0xb1, 0xd2, + 0x6d, 0x51, 0xf4, 0x79, 0x18, 0x63, 0x51, 0x65, + }; + const uint8_t kTLSSeed2[16] = { + 0x7d, 0x24, 0x1a, 0x9d, 0x3c, 0x59, 0xbf, 0x3c, + 0x31, 0x1e, 0x2b, 0x21, 0x41, 0x8d, 0x32, 0x81, + }; + + EVP_AEAD_CTX aead_ctx; + EVP_AEAD_CTX_zero(&aead_ctx); + int ret = 0; + + AES_KEY aes_key; + uint8_t aes_iv[16]; + uint8_t output[256]; + + // AES-CBC Encryption KAT + memcpy(aes_iv, kAESIV, sizeof(kAESIV)); + if (AES_set_encrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key) != 0) { + fprintf(stderr, "AES_set_encrypt_key failed.\n"); + goto err; + } + AES_cbc_encrypt(kPlaintext, output, sizeof(kPlaintext), &aes_key, aes_iv, + AES_ENCRYPT); + if (!check_test(kAESCBCCiphertext, output, sizeof(kAESCBCCiphertext), + "AES-CBC Encryption KAT")) { + goto err; + } + + // AES-CBC Decryption KAT + memcpy(aes_iv, kAESIV, sizeof(kAESIV)); + if (AES_set_decrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key) != 0) { + fprintf(stderr, "AES_set_decrypt_key failed.\n"); + goto err; + } + AES_cbc_encrypt(kAESCBCCiphertext, output, sizeof(kAESCBCCiphertext), + &aes_key, aes_iv, AES_DECRYPT); + if (!check_test(kPlaintext, output, sizeof(kPlaintext), + "AES-CBC Decryption KAT")) { + goto err; + } + + size_t out_len; + uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH]; + OPENSSL_memset(nonce, 0, sizeof(nonce)); + if (!EVP_AEAD_CTX_init(&aead_ctx, EVP_aead_aes_128_gcm(), kAESKey, + sizeof(kAESKey), 0, NULL)) { + fprintf(stderr, "EVP_AEAD_CTX_init for AES-128-GCM failed.\n"); + goto err; + } + + // AES-GCM Encryption KAT + if (!EVP_AEAD_CTX_seal(&aead_ctx, output, &out_len, sizeof(output), nonce, + EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()), + kPlaintext, sizeof(kPlaintext), NULL, 0) || + !check_test(kAESGCMCiphertext, output, sizeof(kAESGCMCiphertext), + "AES-GCM Encryption KAT")) { + fprintf(stderr, "EVP_AEAD_CTX_seal for AES-128-GCM failed.\n"); + goto err; + } + + // AES-GCM Decryption KAT + if (!EVP_AEAD_CTX_open(&aead_ctx, output, &out_len, sizeof(output), nonce, + EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()), + kAESGCMCiphertext, sizeof(kAESGCMCiphertext), NULL, + 0) || + !check_test(kPlaintext, output, sizeof(kPlaintext), + "AES-GCM Decryption KAT")) { + fprintf(stderr, "EVP_AEAD_CTX_open for AES-128-GCM failed.\n"); + goto err; + } + + // SHA-1 KAT + SHA1(kPlaintext, sizeof(kPlaintext), output); + if (!check_test(kPlaintextSHA1, output, sizeof(kPlaintextSHA1), + "SHA-1 KAT")) { + 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")) { + goto err; + } + // DBRG KAT CTR_DRBG_STATE drbg; if (!CTR_DRBG_init(&drbg, kDRBGEntropy, kDRBGPersonalization, @@ -800,33 +772,12 @@ int boringssl_fips_self_test( goto err; } - ret = 1; - -#if defined(BORINGSSL_FIPS_SELF_TEST_FLAG_FILE) - // Tests were successful. Write flag file if requested. - if (module_hash_len != 0 && getenv(kFlagWriteEnableEnvVar) != NULL) { - const int fd = open(flag_path, O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (fd >= 0) { - close(fd); - } - } -#endif // BORINGSSL_FIPS_SELF_TEST_FLAG_FILE + ret = boringssl_self_test_slow(); err: EVP_AEAD_CTX_cleanup(&aead_ctx); - RSA_free(rsa_key); - EC_KEY_free(ec_key); - EC_POINT_free(ec_point_in); - EC_POINT_free(ec_point_out); - EC_GROUP_free(ec_group); - BN_free(ec_scalar); - ECDSA_SIG_free(sig); return ret; } -int BORINGSSL_self_test(void) { - return boringssl_fips_self_test(NULL, 0); -} - #endif // !_MSC_VER diff --git a/crypto/internal.h b/crypto/internal.h index 42f94d5de..9d7b486f4 100644 --- a/crypto/internal.h +++ b/crypto/internal.h @@ -938,14 +938,6 @@ static inline uint64_t CRYPTO_rotr_u64(uint64_t value, int shift) { void BORINGSSL_FIPS_abort(void) __attribute__((noreturn)); #endif -// boringssl_fips_self_test runs the FIPS KAT-based self tests. It returns one -// on success and zero on error. The argument is the integrity hash of the FIPS -// module and may be used to check and write flag files to suppress duplicate -// self-tests. If |module_hash_len| is zero then no flag file will be checked -// nor written and tests will always be run. -int boringssl_fips_self_test(const uint8_t *module_hash, - size_t module_hash_len); - #if defined(BORINGSSL_FIPS_COUNTERS) void boringssl_fips_inc_counter(enum fips_counter_t counter); #else