From c936e91d8572177e64d0d6ad5dbd5064e4be6bc2 Mon Sep 17 00:00:00 2001 From: Sam Clark <3758302+goatgoose@users.noreply.github.com> Date: Tue, 18 Feb 2025 19:02:56 -0500 Subject: [PATCH] feat: Option to disable RAND engine override (#5108) --- CMakeLists.txt | 7 +++ .../spec/buildspec_disable_rand_override.yml | 53 +++++++++++++++++++ codebuild/spec/buildspec_generalbatch.yml | 6 +++ docs/BUILD.md | 14 +++++ tests/unit/s2n_random_test.c | 8 +++ utils/s2n_random.c | 2 + 6 files changed, 90 insertions(+) create mode 100644 codebuild/spec/buildspec_disable_rand_override.yml 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..65802da6414 --- /dev/null +++ b/codebuild/spec/buildspec_disable_rand_override.yml @@ -0,0 +1,53 @@ +--- +# 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" + CTEST_OUTPUT_ON_FAILURE: 1 + +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: + # CTEST_PARALLEL_LEVEL is set outside of env/variables to ensure that `nproc` is evaluated. + - 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'" 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..6da13c33446 100644 --- a/docs/BUILD.md +++ b/docs/BUILD.md @@ -227,3 +227,17 @@ cmake --build ./build -j $(nproc) CTEST_PARALLEL_LEVEL=$(nproc) ctest --test-dir build ``` + +## 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 is the case for AWS-LC. + +The s2n-tls RAND engine may conflict with some environments that use the same libcrypto as s2n-tls. For example, other applications or libraries may have certain requirements for the libcrypto RAND engine that the s2n-tls implementation doesn't provide. Other applications or libraries might also need to implement their own custom RAND engines. If the s2n-tls RAND engine conflicts with your environment, consider enabling libcrypto interning with the `S2N_INTERN_LIBCRYPTO` CMake option, which will build s2n-tls with its own copy of the 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 the concerns described above are confirmed to be inapplicable to your use case. diff --git a/tests/unit/s2n_random_test.c b/tests/unit/s2n_random_test.c index 80577f485f4..41c45493e93 100644 --- a/tests/unit/s2n_random_test.c +++ b/tests/unit/s2n_random_test.c @@ -918,6 +918,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 bcb69ec6f81..f3a01706f4f 100644 --- a/utils/s2n_random.c +++ b/utils/s2n_random.c @@ -559,6 +559,8 @@ bool s2n_supports_custom_rand(void) /* OpenSSL 1.0.2-fips is excluded to match historical behavior */ /* OPENSSL_FIPS is only defined for 1.0.2-fips, not 3.x-fips */ return false; +#elif defined(S2N_DISABLE_RAND_ENGINE_OVERRIDE) + return false; #else return s2n_libcrypto_is_openssl() && !s2n_is_in_fips_mode(); #endif