Split FIPS KATs into fast and slow groups.

The provision of FIPS that allowed the tests to be skipped based on a
flag-file has been removed in 140-3. Therefore we expect to run the fast
KATs on start-up, but to defer to slower ones until the functionality in
question is first used. So this change splits off the fast KATs and
removes support for skipping KATs based on a flag-file.

Change-Id: Ib24cb1739cfef93e4a1349d786a0257ee1083cfb
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/51326
Reviewed-by: David Benjamin <davidben@google.com>
fips-20220613
Adam Langley 3 years ago committed by Adam Langley
parent a919539777
commit 15565a8984
  1. 6
      crypto/fipsmodule/FIPS.md
  2. 6
      crypto/fipsmodule/bcm.c
  3. 519
      crypto/fipsmodule/self_check/self_check.c
  4. 8
      crypto/internal.h

@ -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.

@ -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;

@ -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

@ -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

Loading…
Cancel
Save