diff --git a/CMakeLists.txt b/CMakeLists.txt index 08c2bb476a0..6ad07d88bed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,8 @@ loaded in an application with an otherwise conflicting libcrypto version." OFF) option(S2N_LTO, "Enables link time optimizations when building s2n-tls." OFF) option(S2N_STACKTRACE "Enables stacktrace functionality in s2n-tls. Note that this functionality is only available on platforms that support execinfo." ON) +option(S2N_OVERRIDE_LIBCRYPTO_RAND_ENGINE "Allow s2n-tls to override the libcrypto random implementation with the custom +s2n-tls implementation, when appropriate. Disabling this flag is not recommended. See docs/BUILD.md for details." ON) option(COVERAGE "Enable profiling collection for code coverage calculation" OFF) option(BUILD_TESTING "Build tests for s2n-tls. By default only unit tests are built." ON) option(S2N_INTEG_TESTS "Enable the integrationv2 tests" OFF) @@ -247,6 +249,11 @@ if (COVERAGE) target_link_options(${PROJECT_NAME} PUBLIC -fprofile-instr-generate -fcoverage-mapping) endif() +if (NOT S2N_OVERRIDE_LIBCRYPTO_RAND_ENGINE) + message(STATUS "Disabling libcrypto RAND engine override") + add_definitions(-DS2N_DISABLE_RAND_ENGINE_OVERRIDE) +endif() + # For interning, we need to find the static libcrypto library. Cmake configs # can branch on the variable BUILD_SHARED_LIBS to e.g. avoid having to define # multiple targets. An example is AWS-LC: diff --git a/codebuild/spec/buildspec_disable_rand_override.yml b/codebuild/spec/buildspec_disable_rand_override.yml new file mode 100644 index 00000000000..23a47f3361d --- /dev/null +++ b/codebuild/spec/buildspec_disable_rand_override.yml @@ -0,0 +1,52 @@ +--- +# 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 + +env: + shell: bash + variables: + # Select a libcrypto where s2n-tls will override the RAND engine by default. + S2N_LIBCRYPTO: "openssl-1.0.2" + +phases: + build: + on-failure: ABORT + commands: + - | + cmake . -Brand_override_enabled \ + -DCMAKE_PREFIX_PATH=/usr/local/"${S2N_LIBCRYPTO}" \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo + - cmake --build ./rand_override_enabled -- -j $(nproc) + - | + cmake . -Brand_override_disabled \ + -DCMAKE_PREFIX_PATH=/usr/local/"${S2N_LIBCRYPTO}" \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DS2N_OVERRIDE_LIBCRYPTO_RAND_ENGINE=0 + - cmake --build ./rand_override_disabled -- -j $(nproc) + post_build: + on-failure: ABORT + commands: + - export CTEST_OUTPUT_ON_FAILURE=1 + - export CTEST_PARALLEL_LEVEL=$(nproc) + # Run the s2n-tls tests with the assumption that the RAND engine override feature will be + # disabled. This will enable tests that ensure it's disabled. + - export S2N_DISABLE_RAND_ENGINE_OVERRIDE_EXPECTED=1 + - make -C rand_override_disabled test + # If the RAND engine override is not actually disabled, tests that expect it to be should fail. + - echo "The following is a negative test, and is expected to fail." + - | + ! make -C rand_override_enabled test -- ARGS="-R 's2n_random_test'" + # The tests should succeed without this assumption. + - unset S2N_DISABLE_RAND_ENGINE_OVERRIDE_EXPECTED + - make -C rand_override_enabled test -- ARGS="-R 's2n_random_test'" \ No newline at end of file diff --git a/codebuild/spec/buildspec_generalbatch.yml b/codebuild/spec/buildspec_generalbatch.yml index 192449a331e..bb9249063e2 100644 --- a/codebuild/spec/buildspec_generalbatch.yml +++ b/codebuild/spec/buildspec_generalbatch.yml @@ -277,3 +277,9 @@ batch: privileged-mode: true compute-type: BUILD_GENERAL1_LARGE image: 024603541914.dkr.ecr.us-west-2.amazonaws.com/docker:ubuntu22codebuild + - identifier: DisableRandOverride + buildspec: codebuild/spec/buildspec_disable_rand_override.yml + env: + privileged-mode: true + compute-type: BUILD_GENERAL1_LARGE + image: 024603541914.dkr.ecr.us-west-2.amazonaws.com/docker:ubuntu22codebuild diff --git a/docs/BUILD.md b/docs/BUILD.md index 1773fa9442c..ea537f7f383 100644 --- a/docs/BUILD.md +++ b/docs/BUILD.md @@ -106,6 +106,20 @@ The entire list of s2n-tls CMake options can be viewed with the following comman cmake . -LH ``` +### RAND engine override + +By default, s2n-tls may override the libcrypto random implementation with its custom implementation. This allows the libcrypto APIs invoked by s2n-tls to internally use the s2n-tls random implementation when fetching random bytes. + +The motivation for this behavior is twofold: +1. Ensure that s2n-tls usage is safe when linked to a libcrypto with known issues in its random implementation, such as OpenSSL 1.0.2. See https://wiki.openssl.org/index.php/Random_fork-safety for details. +2. Ensure that s2n-tls usage is safe when used in snapshot environments. Some applications, such as [Lambda SnapStart](https://docs.aws.amazon.com/lambda/latest/dg/snapstart.html), take a snapshot of the memory and disk state, and later restore this state to a virtual machine. Precautions must be taken when running inside a restored snapshot environment to ensure that randomly generated data remains unique between restored snapshots. See the Lambda SnapStart documentation for details: https://docs.aws.amazon.com/lambda/latest/dg/snapstart-uniqueness.html + +When both of the above concerns are known to be mitigated in the linked libcrypto's random implementation, s2n-tls will not override the libcrypto's implementation, as this the case for AWS-LC. + +The s2n-tls RAND engine may conflict with some environments that link to the same libcrypto as s2n-tls if, for example, the environment has certain requirements for the libcrypto RAND engine that the s2n-tls implementation doesn't provide, or if the environment implements its own RAND engine. In this case, consider enabling libcrypto interning with the `S2N_INTERN_LIBCRYPTO` CMake option, which will build s2n-tls with its own libcrypto that's isolated from the rest of the environment. + +If the s2n-tls RAND engine conflicts with your environment and enabling libcrypto interning is not a viable option, s2n-tls can be forced to disable overriding the RAND engine by setting the `S2N_OVERRIDE_LIBCRYPTO_RAND_ENGINE` CMake flag to false when building s2n-tls. This is not recommended unless both of concerns described above are confirmed to not be applicable for your use case. + ## Building with a specific libcrypto s2n-tls has a dependency on a libcrypto library. A supported libcrypto must be linked to s2n-tls when building. The following libcrypto libraries are currently supported: diff --git a/tests/unit/s2n_random_test.c b/tests/unit/s2n_random_test.c index 0fbbfb823e8..dacba679058 100644 --- a/tests/unit/s2n_random_test.c +++ b/tests/unit/s2n_random_test.c @@ -917,6 +917,14 @@ int main(int argc, char **argv) EXPECT_TRUE(s2n_libcrypto_is_openssl()); EXPECT_FALSE(s2n_is_in_fips_mode()); } + + /* Ensure that disabling the S2N_OVERRIDE_LIBCRYPTO_RAND_ENGINE CMake option disables the + * custom rand override feature. When the S2N_DISABLE_RAND_ENGINE_OVERRIDE_EXPECTED + * environment variable is set, this CMake option is expected to be disabled. + */ + if (getenv("S2N_DISABLE_RAND_ENGINE_OVERRIDE_EXPECTED")) { + EXPECT_FALSE(s2n_supports_custom_rand()); + } }; /* For each test case, creates a child process that runs the test case. diff --git a/utils/s2n_random.c b/utils/s2n_random.c index 233a76b3060..379131e05e2 100644 --- a/utils/s2n_random.c +++ b/utils/s2n_random.c @@ -556,6 +556,8 @@ bool s2n_supports_custom_rand(void) { #if !defined(S2N_LIBCRYPTO_SUPPORTS_ENGINE) return false; +#elif defined(S2N_DISABLE_RAND_ENGINE_OVERRIDE) + return false; #else return s2n_libcrypto_is_openssl() && !s2n_is_in_fips_mode(); #endif