diff --git a/crypto/s2n_fips.c b/crypto/s2n_fips.c index ff73433a6ce..1b2c0307069 100644 --- a/crypto/s2n_fips.c +++ b/crypto/s2n_fips.c @@ -26,17 +26,24 @@ static bool s2n_fips_mode_enabled = false; -/* FIPS mode can be checked if OpenSSL was configured and built for FIPS which then defines OPENSSL_FIPS. +/* Check if the linked libcrypto has FIPS mode enabled. * - * AWS-LC always defines FIPS_mode() that you can call and check what the library was built with. It does not define - * a public OPENSSL_FIPS/AWSLC_FIPS macro that we can (or need to) check here + * This method indicates the state of the libcrypto, NOT the state + * of s2n-tls and should ONLY be called during library initialization (i.e. + * s2n_init()). For example, if s2n-tls is using Openssl and FIPS_mode_set(1) + * is called after s2n_init() is called, then this method will return true + * while s2n_is_in_fips_mode() will return false and s2n-tls will not operate + * in FIPS mode. * - * Safeguard with macro's, for example because Libressl dosn't define - * FIPS_mode() by default. + * For AWS-LC, the FIPS_mode() method is always defined. If AWS-LC was built to + * support FIPS, FIPS_mode() always returns 1. * - * Note: FIPS_mode() does not change the FIPS state of libcrypto. This only returns the current state. Applications - * using s2n must call FIPS_mode_set(1) prior to s2n_init. - * */ + * For OpenSSL, OPENSSL_FIPS is defined if the libcrypto was built to support + * FIPS. The FIPS_mode() method is only present if OPENSSL_FIPS is defined, and + * only returns 1 if FIPS_mode_set(1) was used to enable FIPS mode. + * Applications wanting to enable FIPS mode with OpenSSL must call + * FIPS_mode_set(1) prior to calling s2n_init(). + */ bool s2n_libcrypto_is_fips(void) { #if defined(OPENSSL_FIPS) || defined(OPENSSL_IS_AWSLC) diff --git a/crypto/s2n_fips.h b/crypto/s2n_fips.h index f9eafef5907..9cce9b50bfa 100644 --- a/crypto/s2n_fips.h +++ b/crypto/s2n_fips.h @@ -23,7 +23,6 @@ int s2n_fips_init(void); bool s2n_is_in_fips_mode(void); -bool s2n_libcrypto_is_fips(void); struct s2n_cipher_suite; S2N_RESULT s2n_fips_validate_cipher_suite(const struct s2n_cipher_suite *cipher_suite, bool *valid); diff --git a/crypto/s2n_libcrypto.c b/crypto/s2n_libcrypto.c index 166e3bf86e3..fdaa6742df6 100644 --- a/crypto/s2n_libcrypto.c +++ b/crypto/s2n_libcrypto.c @@ -99,16 +99,32 @@ static S2N_RESULT s2n_libcrypto_validate_expected_version_number(void) } /* s2n_libcrypto_is_*() encodes the libcrypto version used at build-time. - * Currently only captures AWS-LC and BoringSSL. When a libcrypto-dependent - * branch is required, we prefer these functions where possible to reduce - # #ifs and avoid potential bugs where the header containing the #define is not - * included. + * + * When a libcrypto-dependent branch is required, we prefer these functions + * where possible to reduce #ifs and avoid potential bugs where the header + * containing the #define is not included. */ #if defined(OPENSSL_IS_AWSLC) && defined(OPENSSL_IS_BORINGSSL) #error "Both OPENSSL_IS_AWSLC and OPENSSL_IS_BORINGSSL are defined at the same time!" #endif +/* Attempt to detect if the libcrypto is OpenSSL. + * + * This check should be updated if s2n-tls adds support for a new libcrypto. + * + * Since several libcrypto implementations (such as BoringSSL and AWS-LC) are + * ABI compatible forks of OpenSSL, detecting OpenSSL is done by checking the + * absence of other known libcrypto variants. + */ +bool s2n_libcrypto_is_openssl() +{ + bool is_other_libcrypto_variant = + s2n_libcrypto_is_boringssl() || s2n_libcrypto_is_libressl() || s2n_libcrypto_is_awslc(); + + return !is_other_libcrypto_variant; +} + bool s2n_libcrypto_is_awslc() { #if defined(OPENSSL_IS_AWSLC) diff --git a/crypto/s2n_openssl.h b/crypto/s2n_openssl.h index cd43cb8f4e1..d09c249dbd2 100644 --- a/crypto/s2n_openssl.h +++ b/crypto/s2n_openssl.h @@ -56,6 +56,7 @@ #define S2N_LIBCRYPTO_SUPPORTS_CUSTOM_RAND 0 #endif +bool s2n_libcrypto_is_openssl(); bool s2n_libcrypto_is_awslc(); bool s2n_libcrypto_is_boringssl(); bool s2n_libcrypto_is_libressl(); diff --git a/tests/unit/s2n_build_test.c b/tests/unit/s2n_build_test.c index 87001ab3078..5acffb576f7 100644 --- a/tests/unit/s2n_build_test.c +++ b/tests/unit/s2n_build_test.c @@ -65,6 +65,43 @@ S2N_RESULT s2n_test_lowercase_copy(const char *input, char *destination, size_t return S2N_RESULT_OK; } +S2N_RESULT s2n_check_supported_libcrypto(const char *s2n_libcrypto) +{ + RESULT_ENSURE_REF(s2n_libcrypto); + + /* List of supported libcrypto variants we test with */ + const struct { + const char *libcrypto; + bool is_openssl; + } supported_libcrypto[] = { + { .libcrypto = "awslc", .is_openssl = false }, + { .libcrypto = "awslc-fips", .is_openssl = false }, + { .libcrypto = "awslc-fips-2022", .is_openssl = false }, + { .libcrypto = "boringssl", .is_openssl = false }, + { .libcrypto = "libressl", .is_openssl = false }, + { .libcrypto = "openssl-1.0.2", .is_openssl = true }, + { .libcrypto = "openssl-1.0.2-fips", .is_openssl = true }, + { .libcrypto = "openssl-1.1.1", .is_openssl = true }, + { .libcrypto = "openssl-3.0", .is_openssl = true }, + }; + + for (size_t i = 0; i < s2n_array_len(supported_libcrypto); i++) { + /* The linked libcryto is one of the known supported libcrypto variants */ + if (strcmp(s2n_libcrypto, supported_libcrypto[i].libcrypto) == 0) { + if (supported_libcrypto[i].is_openssl) { + EXPECT_TRUE(s2n_libcrypto_is_openssl()); + } else { + EXPECT_FALSE(s2n_libcrypto_is_openssl()); + } + + return S2N_RESULT_OK; + } + } + + /* Testing with an unexpected libcrypto. */ + return S2N_RESULT_ERROR; +} + int main() { BEGIN_TEST(); @@ -131,6 +168,15 @@ int main() } }; + /* Ensure we are testing with supported libcryto variants. + * + * We need to update s2n_libcrypto_is_openssl() when adding support + * for a new libcrypto. + */ + { + EXPECT_OK(s2n_check_supported_libcrypto(s2n_libcrypto)); + }; + END_TEST(); return 0; } diff --git a/tests/unit/s2n_openssl_test.c b/tests/unit/s2n_openssl_test.c index 11b14fa26a8..d48cc8b4bd9 100644 --- a/tests/unit/s2n_openssl_test.c +++ b/tests/unit/s2n_openssl_test.c @@ -26,15 +26,31 @@ int main(int argc, char** argv) END_TEST(); } - if (strcmp(env_libcrypto, "boringssl") == 0) { + /* Confirm "S2N_LIBCRYPTO" env variable matches the linked libcrypto. */ + if (strstr(env_libcrypto, "awslc") != NULL) { + EXPECT_TRUE(s2n_libcrypto_is_awslc()); + EXPECT_FALSE(s2n_libcrypto_is_boringssl()); + EXPECT_FALSE(s2n_libcrypto_is_libressl()); + EXPECT_FALSE(s2n_libcrypto_is_openssl()); + } else if (strcmp(env_libcrypto, "boringssl") == 0) { EXPECT_FALSE(s2n_libcrypto_is_awslc()); EXPECT_TRUE(s2n_libcrypto_is_boringssl()); - } else if (strstr(env_libcrypto, "awslc") != NULL) { - EXPECT_TRUE(s2n_libcrypto_is_awslc()); + EXPECT_FALSE(s2n_libcrypto_is_libressl()); + EXPECT_FALSE(s2n_libcrypto_is_openssl()); + } else if (strcmp(env_libcrypto, "libressl") == 0) { + EXPECT_FALSE(s2n_libcrypto_is_awslc()); EXPECT_FALSE(s2n_libcrypto_is_boringssl()); - } else { + EXPECT_TRUE(s2n_libcrypto_is_libressl()); + EXPECT_FALSE(s2n_libcrypto_is_openssl()); + } else if (strstr(env_libcrypto, "openssl") != NULL) { EXPECT_FALSE(s2n_libcrypto_is_awslc()); EXPECT_FALSE(s2n_libcrypto_is_boringssl()); + EXPECT_FALSE(s2n_libcrypto_is_libressl()); + EXPECT_TRUE(s2n_libcrypto_is_openssl()); + } else if (strcmp(env_libcrypto, "default") == 0) { + /* running with the default libcrypto on path */ + } else { + FAIL_MSG("Testing with an unexpected libcrypto."); } END_TEST(); diff --git a/tests/unit/s2n_pq_kem_test.c b/tests/unit/s2n_pq_kem_test.c index 355dbd0b83a..4c6d84f243a 100644 --- a/tests/unit/s2n_pq_kem_test.c +++ b/tests/unit/s2n_pq_kem_test.c @@ -41,7 +41,7 @@ int main() #if defined(OPENSSL_IS_AWSLC) && defined(AWSLC_API_VERSION) /* If using non-FIPS AWS-LC >= v1.6 (API vers. 21), expect Kyber512 KEM from AWS-LC */ - if (!s2n_libcrypto_is_fips() && AWSLC_API_VERSION >= 21) { + if (!s2n_is_in_fips_mode() && AWSLC_API_VERSION >= 21) { EXPECT_TRUE(s2n_libcrypto_supports_evp_kem()); } #endif diff --git a/utils/s2n_random.c b/utils/s2n_random.c index ac8f9817b1f..52904b13fda 100644 --- a/utils/s2n_random.c +++ b/utils/s2n_random.c @@ -48,6 +48,9 @@ #include #include #include +/* LibreSSL requires include. + * https://github.com/aws/s2n-tls/issues/153#issuecomment-129651643 + */ #include #include #include