diff --git a/codebuild/spec/buildspec_openssl3fips.yml b/codebuild/spec/buildspec_openssl3fips.yml new file mode 100644 index 00000000000..4ede818eb32 --- /dev/null +++ b/codebuild/spec/buildspec_openssl3fips.yml @@ -0,0 +1,34 @@ +--- +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You may not use +# this file except in compliance with the License. A copy of the License is +# located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing permissions and +# limitations under the License. + +version: 0.2 + +phases: + build: + on-failure: ABORT + commands: + - | + cmake . -Bbuild \ + -DCMAKE_PREFIX_PATH=/usr/local/openssl-3.0-fips \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DASAN=ON \ + -DUBSAN=ON + - cmake --build ./build -- -j $(nproc) + post_build: + on-failure: ABORT + commands: + - export CTEST_OUTPUT_ON_FAILURE=1 + - export CTEST_PARALLEL_LEVEL=$(nproc) + # openssl3fips is still a work-in-progress. Not all tests pass. + - make -C build test -- ARGS="-R 's2n_build_test|s2n_fips_test'" diff --git a/crypto/s2n_fips.c b/crypto/s2n_fips.c index b38a4d86ffd..85b03ca955e 100644 --- a/crypto/s2n_fips.c +++ b/crypto/s2n_fips.c @@ -45,6 +45,8 @@ bool s2n_libcrypto_is_fips(void) if (FIPS_mode() == 1) { return true; } +#elif S2N_OPENSSL_VERSION_AT_LEAST(3, 0, 0) + return EVP_default_properties_is_fips_enabled(NULL); #endif return false; } @@ -52,9 +54,22 @@ bool s2n_libcrypto_is_fips(void) int s2n_fips_init(void) { s2n_fips_mode_enabled = s2n_libcrypto_is_fips(); -#if defined(OPENSSL_FIPS) + + /* When using Openssl, ONLY 3.0 currently supports FIPS. + * openssl-1.0.2-fips is no longer supported. + * openssl > 3.0 will likely have a FIPS 140-3 certificate instead of a + * FIPS 140-2 certificate, which will require additional review in order + * to properly integrate. + */ +#if defined(OPENSSL_FIPS) || S2N_OPENSSL_VERSION_AT_LEAST(3, 1, 0) POSIX_ENSURE(!s2n_fips_mode_enabled, S2N_ERR_FIPS_MODE_UNSUPPORTED); #endif + + /* For now, openssl is only supported for testing */ + if (s2n_libcrypto_is_openssl_fips()) { + POSIX_ENSURE(s2n_in_unit_test(), S2N_ERR_FIPS_MODE_UNSUPPORTED); + } + return S2N_SUCCESS; } diff --git a/crypto/s2n_libcrypto.c b/crypto/s2n_libcrypto.c index a3172dc5d93..3497af60881 100644 --- a/crypto/s2n_libcrypto.c +++ b/crypto/s2n_libcrypto.c @@ -125,6 +125,11 @@ bool s2n_libcrypto_is_openssl(void) return !is_other_libcrypto_variant; } +bool s2n_libcrypto_is_openssl_fips(void) +{ + return s2n_libcrypto_is_openssl() && s2n_is_in_fips_mode(); +} + bool s2n_libcrypto_is_awslc() { #if defined(OPENSSL_IS_AWSLC) @@ -134,6 +139,11 @@ bool s2n_libcrypto_is_awslc() #endif } +bool s2n_libcrypto_is_awslc_fips(void) +{ + return s2n_libcrypto_is_awslc() && s2n_is_in_fips_mode(); +} + uint64_t s2n_libcrypto_awslc_api_version(void) { #if defined(OPENSSL_IS_AWSLC) diff --git a/crypto/s2n_openssl.h b/crypto/s2n_openssl.h index eaee87700c3..cd2763a8fe2 100644 --- a/crypto/s2n_openssl.h +++ b/crypto/s2n_openssl.h @@ -51,6 +51,8 @@ #endif bool s2n_libcrypto_is_openssl(void); +bool s2n_libcrypto_is_openssl_fips(void); bool s2n_libcrypto_is_awslc(); +bool s2n_libcrypto_is_awslc_fips(void); 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 6bab8a80e99..7c161e7b4dd 100644 --- a/tests/unit/s2n_build_test.c +++ b/tests/unit/s2n_build_test.c @@ -73,6 +73,7 @@ S2N_RESULT s2n_check_supported_libcrypto(const char *s2n_libcrypto) const struct { const char *libcrypto; bool is_openssl; + bool is_opensslfips; } supported_libcrypto[] = { { .libcrypto = "awslc", .is_openssl = false }, { .libcrypto = "awslc-fips", .is_openssl = false }, @@ -83,24 +84,24 @@ S2N_RESULT s2n_check_supported_libcrypto(const char *s2n_libcrypto) { .libcrypto = "openssl-1.0.2-fips", .is_openssl = true }, { .libcrypto = "openssl-1.1.1", .is_openssl = true }, { .libcrypto = "openssl-3.0", .is_openssl = true }, + { .libcrypto = "openssl-3.0-fips", .is_openssl = true, .is_opensslfips = true }, { .libcrypto = "openssl-3.4", .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; + if (strcmp(s2n_libcrypto, supported_libcrypto[i].libcrypto) != 0) { + continue; } + EXPECT_EQUAL(s2n_libcrypto_is_openssl(), supported_libcrypto[i].is_openssl); + EXPECT_EQUAL(s2n_libcrypto_is_openssl_fips(), supported_libcrypto[i].is_opensslfips); + return S2N_RESULT_OK; } - /* Testing with an unexpected libcrypto. */ - return S2N_RESULT_ERROR; + /* Fail if no matching libcrypto was found. + * Since we check for openssl via process of elimination, we must know + * and test the full list of non-openssl libcryptos. + */ + FAIL_MSG("Unknown libcrypto - update supported_libcrypto list"); } int main() @@ -128,16 +129,13 @@ int main() END_TEST(); } - /* Ensure that FIPS mode is enabled when linked to AWS-LC-FIPS, and disabled when linked to AWS-LC */ - if (strstr(s2n_libcrypto, "awslc") != NULL) { - s2n_fips_mode fips_mode = S2N_FIPS_MODE_DISABLED; - EXPECT_SUCCESS(s2n_get_fips_mode(&fips_mode)); - - if (strstr(s2n_libcrypto, "fips") != NULL) { - EXPECT_EQUAL(fips_mode, S2N_FIPS_MODE_ENABLED); - } else { - EXPECT_EQUAL(fips_mode, S2N_FIPS_MODE_DISABLED); - } + /* Ensure that FIPS mode is enabled only when linked to a fips library */ + s2n_fips_mode fips_mode = S2N_FIPS_MODE_DISABLED; + EXPECT_SUCCESS(s2n_get_fips_mode(&fips_mode)); + if (strstr(s2n_libcrypto, "fips") && !strstr(s2n_libcrypto, "1.0.2")) { + EXPECT_EQUAL(fips_mode, S2N_FIPS_MODE_ENABLED); + } else { + EXPECT_EQUAL(fips_mode, S2N_FIPS_MODE_DISABLED); } char s2n_libcrypto_copy[MAX_LIBCRYPTO_NAME_LEN] = { 0 }; @@ -151,7 +149,8 @@ int main() { if (strstr(name, "awslc") != NULL) { /* Early versions of awslc's SSLeay_version return an inaccurate value left over - * after its fork from BoringSSL. */ + * after its fork from BoringSSL. + */ EXPECT_TRUE(s2n_libcrypto_is_awslc()); } else { /* Any other library should have the name of the library (modulo case) in its version string. */ diff --git a/tests/unit/s2n_fips_test.c b/tests/unit/s2n_fips_test.c index c4e5bdc134e..31274231d1b 100644 --- a/tests/unit/s2n_fips_test.c +++ b/tests/unit/s2n_fips_test.c @@ -49,5 +49,20 @@ int main() } } + /* Test: FIPS mode not currently supported for openssl outside of tests. */ + if (s2n_libcrypto_is_openssl_fips()) { + /* s2n_fips_init was already called by BEGIN_TEST. + * Call it again to confirm that we are allowed to call it repeatedly. + */ + EXPECT_SUCCESS(s2n_fips_init()); + + EXPECT_SUCCESS(s2n_in_unit_test_set(false)); + EXPECT_FAILURE_WITH_ERRNO(s2n_fips_init(), S2N_ERR_FIPS_MODE_UNSUPPORTED); + EXPECT_SUCCESS(s2n_in_unit_test_set(true)); + + /* Make sure s2n_fips_init still works */ + EXPECT_SUCCESS(s2n_fips_init()); + } + END_TEST(); }