diff --git a/.github/workflows/ci_linting.yml b/.github/workflows/ci_linting.yml index 7c4e517d70a..c72fa4f7e51 100644 --- a/.github/workflows/ci_linting.yml +++ b/.github/workflows/ci_linting.yml @@ -113,7 +113,7 @@ jobs: uses: harrisonkaiser/clang-format-action@verbose with: clang-format-version: '15' - include-regex: '^(\.\/)?(api|bin|crypto|stuffer|error|tls|utils|tests\/unit|tests\/testlib|docs\/examples).*\.(c|h)$' + include-regex: '^(\.\/)?(api|bin|crypto|stuffer|error|policy|tls|utils|tests\/unit|tests\/testlib|docs\/examples).*\.(c|h)$' nixflake: # The nix develop changes contain broken nixpkg dependenecies; the allow/impure flags workaround this. runs-on: ubuntu-latest diff --git a/CMakeLists.txt b/CMakeLists.txt index 0e976d0c115..ca636ad928e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,6 +53,9 @@ file(GLOB CRYPTO_SRC "crypto/*.c") file(GLOB ERROR_HEADERS "error/*.h") file(GLOB ERROR_SRC "error/*.c") +file(GLOB POLICY_HEADERS "policy/*.h") +file(GLOB POLICY_SRC "policy/*.c") + file(GLOB STUFFER_HEADERS "stuffer/*.h") file(GLOB STUFFER_SRC "stuffer/*.c") @@ -75,12 +78,14 @@ if(MSVC) source_group("Header Files\\s2n\\api" FILES ${API_HEADERS} ${API_UNSTABLE_HEADERS}) source_group("Header Files\\s2n\\crypto" FILES ${CRYPTO_HEADERS}) source_group("Header Files\\s2n\\error" FILES ${ERROR_HEADERS}) + source_group("Header Files\\s2n\\policy" FILES ${POLICY_HEADERS}) source_group("Header Files\\s2n\\stuffer" FILES ${STUFFER_HEADERS}) source_group("Header Files\\s2n\\tls" FILES ${TLS_HEADERS}) source_group("Header Files\\s2n\\utils" FILES ${UTILS_HEADERS}) source_group("Source Files\\crypto" FILES ${CRYPTO_SRC}) source_group("Source Files\\error" FILES ${ERROR_SRC}) + source_group("Source Files\\policy" FILES ${POLICY_SRC}) source_group("Source Files\\stuffer" FILES ${STUFFER_SRC}) source_group("Source Files\\tls" FILES ${TLS_SRC}) source_group("Source Files\\utils" FILES ${UTILS_SRC}) @@ -108,6 +113,7 @@ file(GLOB S2N_HEADERS ${API_UNSTABLE_HEADERS} ${CRYPTO_HEADERS} ${ERROR_HEADERS} + ${POLICY_HEADERS} ${STUFFER_HEADERS} ${TLS_HEADERS} ${UTILS_HEADERS} @@ -116,6 +122,7 @@ file(GLOB S2N_HEADERS file(GLOB S2N_SRC ${CRYPTO_SRC} ${ERROR_SRC} + ${POLICY_SRC} ${STUFFER_SRC} ${TLS_SRC} ${UTILS_SRC} diff --git a/Makefile b/Makefile index 545e6519031..029613bf121 100644 --- a/Makefile +++ b/Makefile @@ -49,6 +49,7 @@ include s2n.mk libs: $(MAKE) -C utils $(MAKE) -C error + $(MAKE) -C policy $(MAKE) -C stuffer $(MAKE) -C crypto $(MAKE) -C tls @@ -70,6 +71,7 @@ run-lcov: $(MAKE) -C bin lcov $(MAKE) -C crypto lcov $(MAKE) -C error lcov + $(MAKE) -C policy lcov $(MAKE) -C stuffer lcov $(MAKE) -C tests lcov $(MAKE) -C tls run-lcov @@ -88,6 +90,7 @@ indent: $(MAKE) -C crypto indentsource $(MAKE) -C utils indentsource $(MAKE) -C error indentsource + $(MAKE) -C policy indentsource $(MAKE) -C tls indent $(MAKE) -C bin indentsource @@ -119,6 +122,7 @@ clean: $(MAKE) -C crypto decruft $(MAKE) -C utils decruft $(MAKE) -C error decruft + $(MAKE) -C policy decruft $(MAKE) -C tls clean $(MAKE) -C bin decruft $(MAKE) -C lib decruft diff --git a/bindings/rust/extended/generate.sh b/bindings/rust/extended/generate.sh index 696cd57b99c..88f799c171b 100755 --- a/bindings/rust/extended/generate.sh +++ b/bindings/rust/extended/generate.sh @@ -19,6 +19,7 @@ cp -r \ ../../../api \ ../../../crypto \ ../../../error \ + ../../../policy \ ../../../stuffer \ ../../../tls \ ../../../utils \ diff --git a/codebuild/bin/fuzz_coverage_report.sh b/codebuild/bin/fuzz_coverage_report.sh index a35e4e77d4e..80f0eb0fbad 100755 --- a/codebuild/bin/fuzz_coverage_report.sh +++ b/codebuild/bin/fuzz_coverage_report.sh @@ -25,7 +25,7 @@ if [ "$#" -ne "0" ]; then fi FUZZ_TEST_DIR="tests/fuzz" -FUZZCOV_SOURCES="api bin crypto error stuffer tls utils" +FUZZCOV_SOURCES="api bin crypto error policy stuffer tls utils" # generate coverage report for each fuzz test printf "Generating coverage reports... \n" diff --git a/codebuild/bin/grep_simple_mistakes.sh b/codebuild/bin/grep_simple_mistakes.sh index c484538dd58..4681c395e3b 100755 --- a/codebuild/bin/grep_simple_mistakes.sh +++ b/codebuild/bin/grep_simple_mistakes.sh @@ -245,7 +245,7 @@ done ## Assert that there are no new uses of S2N_ERROR_IF # TODO add crypto, tls (see https://github.com/aws/s2n-tls/issues/2635) ############################################# -S2N_ERROR_IF_FREE="bin error scram stuffer utils tests" +S2N_ERROR_IF_FREE="bin error policy scram stuffer utils tests" for dir in $S2N_ERROR_IF_FREE; do files=$(find "$dir" -type f -name "*.c" -path "*") for file in $files; do diff --git a/codebuild/bin/run_cppcheck.sh b/codebuild/bin/run_cppcheck.sh index f9bcc0ffdc7..ce30cbeaf82 100755 --- a/codebuild/bin/run_cppcheck.sh +++ b/codebuild/bin/run_cppcheck.sh @@ -30,7 +30,7 @@ CPPCHECK_EXECUTABLE=${INSTALL_DIR}/cppcheck FAILED=0 $CPPCHECK_EXECUTABLE --version -$CPPCHECK_EXECUTABLE --std=c99 --error-exitcode=-1 --quiet --force -j 8 --enable=all --template='[{file}:{line}]: ({severity}:{id}) {message}' --inline-suppr --suppressions-list=codebuild/bin/cppcheck_suppressions.txt -I . -I ./tests api bin crypto error stuffer ./tests/unit tls utils || FAILED=1 +$CPPCHECK_EXECUTABLE --std=c99 --error-exitcode=-1 --quiet --force -j 8 --enable=all --template='[{file}:{line}]: ({severity}:{id}) {message}' --inline-suppr --suppressions-list=codebuild/bin/cppcheck_suppressions.txt -I . -I ./tests api bin crypto error policy stuffer ./tests/unit tls utils || FAILED=1 if [ $FAILED == 1 ]; then printf "\\033[31;1mFAILED cppcheck\\033[0m\\n" diff --git a/lib/Makefile b/lib/Makefile index d8e71639d85..34e18346399 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -13,7 +13,7 @@ # permissions and limitations under the License. # -OBJS = $(wildcard ../utils/*.o ../stuffer/*.o ../tls/*.o ../tls/*/*.o ../iana/*.o ../crypto/*.o ../error/*.o) +OBJS = $(wildcard ../utils/*.o ../stuffer/*.o ../tls/*.o ../tls/*/*.o ../iana/*.o ../crypto/*.o ../error/*.o ../policy/*.o) .PHONY : all all: libs2n.a libs2n.so libs2n.dylib diff --git a/nix/shell.sh b/nix/shell.sh index 6a440473af4..cba9f1eb33b 100644 --- a/nix/shell.sh +++ b/nix/shell.sh @@ -128,6 +128,8 @@ function check-clang-format {(set -e src_files+=" "; src_files+=`find ./error -name .git -prune -o -regextype posix-egrep -regex "$include_regex" -print`; src_files+=" "; + src_files+=`find ./policy -name .git -prune -o -regextype posix-egrep -regex "$include_regex" -print`; + src_files+=" "; src_files+=`find ./tls -name .git -prune -o -regextype posix-egrep -regex "$include_regex" -print`; src_files+=" "; src_files+=`find ./utils -name .git -prune -o -regextype posix-egrep -regex "$include_regex" -print`; @@ -152,6 +154,8 @@ function do-clang-format {(set -e src_files+=" "; src_files+=`find ./error -name .git -prune -o -regextype posix-egrep -regex "$include_regex" -print`; src_files+=" "; + src_files+=`find ./policy -name .git -prune -o -regextype posix-egrep -regex "$include_regex" -print`; + src_files+=" "; src_files+=`find ./tls -name .git -prune -o -regextype posix-egrep -regex "$include_regex" -print`; src_files+=" "; src_files+=`find ./utils -name .git -prune -o -regextype posix-egrep -regex "$include_regex" -print`; diff --git a/policy/Makefile b/policy/Makefile new file mode 100644 index 00000000000..1baa3eef27d --- /dev/null +++ b/policy/Makefile @@ -0,0 +1,22 @@ +# +# 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. +# + +SRCS=$(wildcard *.c) +OBJS=$(SRCS:.c=.o) + +.PHONY : all +all: $(OBJS) + +include ../s2n.mk diff --git a/policy/s2n_security_policy.c b/policy/s2n_security_policy.c new file mode 100644 index 00000000000..c57b0fc1e1e --- /dev/null +++ b/policy/s2n_security_policy.c @@ -0,0 +1,107 @@ +/* + * 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. + */ + +#include "policy/s2n_security_policy.h" + +/* Checks whether cipher preference supports TLS 1.3 based on whether it is configured + * with TLS 1.3 ciphers. Returns true or false. + */ +bool s2n_security_policy_supports_tls13(const struct s2n_security_policy *security_policy) +{ + if (security_policy == NULL) { + return false; + } + + for (uint8_t i = 0; security_policy_selection[i].version != NULL; i++) { + if (security_policy_selection[i].security_policy == security_policy) { + return security_policy_selection[i].supports_tls13 == 1; + } + } + + /* if cipher preference is not in the official list, compute the result */ + const struct s2n_cipher_preferences *cipher_preferences = security_policy->cipher_preferences; + if (cipher_preferences == NULL) { + return false; + } + + for (size_t i = 0; i < cipher_preferences->count; i++) { + if (cipher_preferences->suites[i]->minimum_required_tls_version >= S2N_TLS13) { + return true; + } + } + + return false; +} + +S2N_RESULT s2n_security_policy_validate_certificate_chain( + const struct s2n_security_policy *security_policy, + const struct s2n_cert_chain_and_key *cert_key_pair) +{ + RESULT_ENSURE_REF(security_policy); + RESULT_ENSURE_REF(cert_key_pair); + RESULT_ENSURE_REF(cert_key_pair->cert_chain); + + if (!security_policy->certificate_preferences_apply_locally) { + return S2N_RESULT_OK; + } + + struct s2n_cert *current = cert_key_pair->cert_chain->head; + while (current != NULL) { + RESULT_GUARD(s2n_security_policy_validate_cert_key(security_policy, ¤t->info, + S2N_ERR_SECURITY_POLICY_INCOMPATIBLE_CERT)); + RESULT_GUARD(s2n_security_policy_validate_cert_signature(security_policy, ¤t->info, + S2N_ERR_SECURITY_POLICY_INCOMPATIBLE_CERT)); + current = current->next; + } + return S2N_RESULT_OK; +} + +S2N_RESULT s2n_security_policy_validate_cert_signature(const struct s2n_security_policy *security_policy, + const struct s2n_cert_info *info, s2n_error error) +{ + RESULT_ENSURE_REF(info); + RESULT_ENSURE_REF(security_policy); + const struct s2n_signature_preferences *sig_preferences = security_policy->certificate_signature_preferences; + + if (sig_preferences != NULL) { + for (size_t i = 0; i < sig_preferences->count; i++) { + if (sig_preferences->signature_schemes[i]->libcrypto_nid == info->signature_nid) { + return S2N_RESULT_OK; + } + } + + RESULT_BAIL(error); + } + return S2N_RESULT_OK; +} + +S2N_RESULT s2n_security_policy_validate_cert_key(const struct s2n_security_policy *security_policy, + const struct s2n_cert_info *info, s2n_error error) +{ + RESULT_ENSURE_REF(info); + RESULT_ENSURE_REF(security_policy); + const struct s2n_certificate_key_preferences *key_preferences = security_policy->certificate_key_preferences; + + if (key_preferences != NULL) { + for (size_t i = 0; i < key_preferences->count; i++) { + if (key_preferences->certificate_keys[i]->public_key_libcrypto_nid == info->public_key_nid + && key_preferences->certificate_keys[i]->bits == info->public_key_bits) { + return S2N_RESULT_OK; + } + } + RESULT_BAIL(error); + } + return S2N_RESULT_OK; +} diff --git a/policy/s2n_security_policy.h b/policy/s2n_security_policy.h new file mode 100644 index 00000000000..8be4327c36f --- /dev/null +++ b/policy/s2n_security_policy.h @@ -0,0 +1,94 @@ +/* + * 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. + */ + +#pragma once + +#include + +#include "tls/s2n_certificate_keys.h" +#include "tls/s2n_cipher_preferences.h" +#include "tls/s2n_ecc_preferences.h" +#include "tls/s2n_kem_preferences.h" +#include "tls/s2n_security_rules.h" +#include "tls/s2n_signature_scheme.h" + +/* The s2n_security_policy struct is used to define acceptable and available + * algorithms for use in the TLS protocol. Note that the behavior of each field + * likely differs between different TLS versions, as the mechanics of cipher + * negotiation often have significant differences between TLS versions. + * + * In s2n-tls, the signature_algorithms extension only applies to signatures in + * CertificateVerify messages. To specify acceptable signature algorithms for + * certificates the certificate_signature_preferences field should be set in the + * security policy. + */ +struct s2n_security_policy { + uint8_t minimum_protocol_version; + /* TLS 1.0 - 1.2 - cipher preference includes multiple elements such + * as signature algorithms, record algorithms, and key exchange algorithms + * TLS 1.3 - cipher preference only determines record encryption + */ + const struct s2n_cipher_preferences *cipher_preferences; + /* kem_preferences is only used for Post-Quantum cryptography */ + const struct s2n_kem_preferences *kem_preferences; + /* This field roughly corresponds to the "signature_algorithms" extension. + * The client serializes this field of the security_policy to populate the + * extension, and it is also used by the server to choose an appropriate + * entry from the options supplied by the client. + * TLS 1.2 - optional extension to specify signature algorithms other than + * default: https://www.rfc-editor.org/rfc/rfc5246#section-7.4.1.4.1 + * TLS 1.3 - required extension specifying signature algorithms + */ + const struct s2n_signature_preferences *signature_preferences; + /* When this field is set, the endpoint will ensure that the signatures on + * the certificates in the peer's certificate chain are in the specified + * list. Note that s2n-tls does not support the signature_algorithms_cert + * extension. Unlike the signature_preferences field, this information is + * never transmitted to a peer. + */ + const struct s2n_signature_preferences *certificate_signature_preferences; + /* This field roughly corresponds to the information in the + * "supported_groups" extension. + * TLS 1.0 - 1.2 - "elliptic_curves" extension indicates supported groups + * for both key exchange and signature algorithms. + * TLS 1.3 - the "supported_groups" extension indicates the named groups + * which the client supports for key exchange + * https://www.rfc-editor.org/rfc/rfc8446#section-4.2.7 + */ + const struct s2n_ecc_preferences *ecc_preferences; + /* This field determines what public keys are allowed for use. It restricts + * both the type of the key (Elliptic Curve, RSA w/ Encryption, RSA PSS) and + * the size of the key. Note that this field structure is likely to change + * until https://github.com/aws/s2n-tls/issues/4435 is closed. + */ + const struct s2n_certificate_key_preferences *certificate_key_preferences; + /* This field controls whether the certificate_signature_preferences apply + * to local certs loaded on configs. + */ + bool certificate_preferences_apply_locally; + bool rules[S2N_SECURITY_RULES_COUNT]; +}; + +bool s2n_security_policy_supports_tls13(const struct s2n_security_policy *security_policy); + +/* Checks to see if a certificate has a signature algorithm that's in our + * certificate_signature_preferences list + */ +S2N_RESULT s2n_security_policy_validate_certificate_chain(const struct s2n_security_policy *security_policy, + const struct s2n_cert_chain_and_key *cert_key_pair); +S2N_RESULT s2n_security_policy_validate_cert_signature(const struct s2n_security_policy *security_policy, + const struct s2n_cert_info *info, s2n_error error); +S2N_RESULT s2n_security_policy_validate_cert_key(const struct s2n_security_policy *security_policy, + const struct s2n_cert_info *info, s2n_error error); diff --git a/scripts/s2n_safety_explicit_context/codemod.sh b/scripts/s2n_safety_explicit_context/codemod.sh index 46e300951f3..fe23c0c35f5 100755 --- a/scripts/s2n_safety_explicit_context/codemod.sh +++ b/scripts/s2n_safety_explicit_context/codemod.sh @@ -27,6 +27,7 @@ IGNORES=$( docker-images \ docs \ error \ + policy \ lib \ libcrypto-build \ libcrypto-root \ diff --git a/tests/fuzz/runFuzzTest.sh b/tests/fuzz/runFuzzTest.sh index 7580aa264e6..a6fb1d805dc 100755 --- a/tests/fuzz/runFuzzTest.sh +++ b/tests/fuzz/runFuzzTest.sh @@ -46,7 +46,7 @@ LIBFUZZER_ARGS+="-timeout=5 -max_len=4096 -print_final_stats=1 -max_total_time=$ TEST_SPECIFIC_OVERRIDES="${S2N_ROOT}/build/lib/lib${TEST_NAME}_overrides.so" GLOBAL_OVERRIDES="${S2N_ROOT}/build/lib/libglobal_overrides.so" -FUZZCOV_SOURCES="${S2N_ROOT}/api ${S2N_ROOT}/bin ${S2N_ROOT}/crypto ${S2N_ROOT}/error ${S2N_ROOT}/stuffer ${S2N_ROOT}/tls ${S2N_ROOT}/utils" +FUZZCOV_SOURCES="${S2N_ROOT}/api ${S2N_ROOT}/bin ${S2N_ROOT}/crypto ${S2N_ROOT}/error ${S2N_ROOT}/policy ${S2N_ROOT}/stuffer ${S2N_ROOT}/tls ${S2N_ROOT}/utils" # Use LD_PRELOAD_ to prevent symbol lookup errors in commands like mkdir. if [ -e $TEST_SPECIFIC_OVERRIDES ]; diff --git a/tests/saw/Makefile b/tests/saw/Makefile index 9633cbecd99..08fc89fb120 100644 --- a/tests/saw/Makefile +++ b/tests/saw/Makefile @@ -165,11 +165,17 @@ API_DIRS = $(sort $(dir $(API_COPY))) ERROR_C = $(wildcard ../../error/*.c) $(wildcard ../../error/*.h) ../../error/Makefile ERROR_COPY = $(addprefix s2n/error/, $(notdir $(ERROR_C))) +POLICY_C = $(wildcard ../../policy/*.c) $(wildcard ../../policy/*.h) ../../policy/Makefile +POLICY_COPY = $(addprefix s2n/policy/, $(notdir $(POLICY_C))) + LIB_COPY = s2n/lib/Makefile s2n/error : mkdir -p $@ +s2n/policy : + mkdir -p $@ + s2n/api : mkdir -p $(API_DIRS) @@ -193,12 +199,12 @@ export BITCODE_DIR := $(CURDIR)/bitcode/ tmp: mkdir -p tmp -bitcode/all_llvm.bc : s2n/crypto s2n/utils s2n/tls s2n/api s2n/error s2n/stuffer s2n/Makefile s2n/s2n.mk $(CRYPTO_COPY) $(PQ_CRYPTO_COPY) $(UTILS_COPY) $(TLS_COPY) $(API_COPY) $(ERROR_COPY) $(STUFFER_COPY) +bitcode/all_llvm.bc : s2n/crypto s2n/utils s2n/tls s2n/api s2n/error s2n/policy s2n/stuffer s2n/Makefile s2n/s2n.mk $(CRYPTO_COPY) $(PQ_CRYPTO_COPY) $(UTILS_COPY) $(TLS_COPY) $(API_COPY) $(ERROR_COPY) $(POLICY_COPY) $(STUFFER_COPY) ${MAKE} -C s2n bc ${MAKE} -C bitcode all_llvm.bc -s2n/lib/libs2n.so : s2n/crypto s2n/utils s2n/tls s2n/api s2n/error s2n/stuffer s2n/lib s2n/Makefile s2n/s2n.mk $(CRYPTO_COPY) $(UTILS_COPY) $(TLS_COPY) $(API_COPY) $(ERROR_COPY) $(STUFFER_COPY) $(LIB_COPY) +s2n/lib/libs2n.so : s2n/crypto s2n/utils s2n/tls s2n/api s2n/error s2n/policy s2n/stuffer s2n/lib s2n/Makefile s2n/s2n.mk $(CRYPTO_COPY) $(UTILS_COPY) $(TLS_COPY) $(API_COPY) $(ERROR_COPY) $(POLICY_COPY) $(STUFFER_COPY) $(LIB_COPY) ${MAKE} -C s2n libs NO_STACK_PROTECTOR=1 NO_INLINE=1 s2n/%.h : ../../%.h diff --git a/tls/s2n_security_policies.c b/tls/s2n_security_policies.c index 9d7eed24cba..3a8a442f9b3 100644 --- a/tls/s2n_security_policies.c +++ b/tls/s2n_security_policies.c @@ -1618,36 +1618,6 @@ bool s2n_pq_kem_is_extension_required(const struct s2n_security_policy *security return false; } -/* Checks whether cipher preference supports TLS 1.3 based on whether it is configured - * with TLS 1.3 ciphers. Returns true or false. - */ -bool s2n_security_policy_supports_tls13(const struct s2n_security_policy *security_policy) -{ - if (security_policy == NULL) { - return false; - } - - for (uint8_t i = 0; security_policy_selection[i].version != NULL; i++) { - if (security_policy_selection[i].security_policy == security_policy) { - return security_policy_selection[i].supports_tls13 == 1; - } - } - - /* if cipher preference is not in the official list, compute the result */ - const struct s2n_cipher_preferences *cipher_preferences = security_policy->cipher_preferences; - if (cipher_preferences == NULL) { - return false; - } - - for (size_t i = 0; i < cipher_preferences->count; i++) { - if (cipher_preferences->suites[i]->minimum_required_tls_version >= S2N_TLS13) { - return true; - } - } - - return false; -} - int s2n_connection_is_valid_for_cipher_preferences(struct s2n_connection *conn, const char *version) { POSIX_ENSURE_REF(conn); @@ -1732,64 +1702,3 @@ S2N_RESULT s2n_security_policy_get_version(const struct s2n_security_policy *sec } RESULT_BAIL(S2N_ERR_INVALID_SECURITY_POLICY); } - -S2N_RESULT s2n_security_policy_validate_cert_signature(const struct s2n_security_policy *security_policy, - const struct s2n_cert_info *info, s2n_error error) -{ - RESULT_ENSURE_REF(info); - RESULT_ENSURE_REF(security_policy); - const struct s2n_signature_preferences *sig_preferences = security_policy->certificate_signature_preferences; - - if (sig_preferences != NULL) { - for (size_t i = 0; i < sig_preferences->count; i++) { - if (sig_preferences->signature_schemes[i]->libcrypto_nid == info->signature_nid) { - return S2N_RESULT_OK; - } - } - - RESULT_BAIL(error); - } - return S2N_RESULT_OK; -} - -S2N_RESULT s2n_security_policy_validate_cert_key(const struct s2n_security_policy *security_policy, - const struct s2n_cert_info *info, s2n_error error) -{ - RESULT_ENSURE_REF(info); - RESULT_ENSURE_REF(security_policy); - const struct s2n_certificate_key_preferences *key_preferences = security_policy->certificate_key_preferences; - - if (key_preferences != NULL) { - for (size_t i = 0; i < key_preferences->count; i++) { - if (key_preferences->certificate_keys[i]->public_key_libcrypto_nid == info->public_key_nid - && key_preferences->certificate_keys[i]->bits == info->public_key_bits) { - return S2N_RESULT_OK; - } - } - RESULT_BAIL(error); - } - return S2N_RESULT_OK; -} - -S2N_RESULT s2n_security_policy_validate_certificate_chain( - const struct s2n_security_policy *security_policy, - const struct s2n_cert_chain_and_key *cert_key_pair) -{ - RESULT_ENSURE_REF(security_policy); - RESULT_ENSURE_REF(cert_key_pair); - RESULT_ENSURE_REF(cert_key_pair->cert_chain); - - if (!security_policy->certificate_preferences_apply_locally) { - return S2N_RESULT_OK; - } - - struct s2n_cert *current = cert_key_pair->cert_chain->head; - while (current != NULL) { - RESULT_GUARD(s2n_security_policy_validate_cert_key(security_policy, ¤t->info, - S2N_ERR_SECURITY_POLICY_INCOMPATIBLE_CERT)); - RESULT_GUARD(s2n_security_policy_validate_cert_signature(security_policy, ¤t->info, - S2N_ERR_SECURITY_POLICY_INCOMPATIBLE_CERT)); - current = current->next; - } - return S2N_RESULT_OK; -} diff --git a/tls/s2n_security_policies.h b/tls/s2n_security_policies.h index b837e95ac5a..88a5befd097 100644 --- a/tls/s2n_security_policies.h +++ b/tls/s2n_security_policies.h @@ -17,6 +17,7 @@ #include +#include "policy/s2n_security_policy.h" #include "tls/s2n_certificate_keys.h" #include "tls/s2n_cipher_preferences.h" #include "tls/s2n_ecc_preferences.h" @@ -27,63 +28,6 @@ /* Kept up-to-date by s2n_security_policies_test */ #define NUM_RSA_PSS_SCHEMES 6 -/* The s2n_security_policy struct is used to define acceptable and available - * algorithms for use in the TLS protocol. Note that the behavior of each field - * likely differs between different TLS versions, as the mechanics of cipher - * negotiation often have significant differences between TLS versions. - * - * In s2n-tls, the signature_algorithms extension only applies to signatures in - * CertificateVerify messages. To specify acceptable signature algorithms for - * certificates the certificate_signature_preferences field should be set in the - * security policy. - */ -struct s2n_security_policy { - uint8_t minimum_protocol_version; - /* TLS 1.0 - 1.2 - cipher preference includes multiple elements such - * as signature algorithms, record algorithms, and key exchange algorithms - * TLS 1.3 - cipher preference only determines record encryption - */ - const struct s2n_cipher_preferences *cipher_preferences; - /* kem_preferences is only used for Post-Quantum cryptography */ - const struct s2n_kem_preferences *kem_preferences; - /* This field roughly corresponds to the "signature_algorithms" extension. - * The client serializes this field of the security_policy to populate the - * extension, and it is also used by the server to choose an appropriate - * entry from the options supplied by the client. - * TLS 1.2 - optional extension to specify signature algorithms other than - * default: https://www.rfc-editor.org/rfc/rfc5246#section-7.4.1.4.1 - * TLS 1.3 - required extension specifying signature algorithms - */ - const struct s2n_signature_preferences *signature_preferences; - /* When this field is set, the endpoint will ensure that the signatures on - * the certificates in the peer's certificate chain are in the specified - * list. Note that s2n-tls does not support the signature_algorithms_cert - * extension. Unlike the signature_preferences field, this information is - * never transmitted to a peer. - */ - const struct s2n_signature_preferences *certificate_signature_preferences; - /* This field roughly corresponds to the information in the - * "supported_groups" extension. - * TLS 1.0 - 1.2 - "elliptic_curves" extension indicates supported groups - * for both key exchange and signature algorithms. - * TLS 1.3 - the "supported_groups" extension indicates the named groups - * which the client supports for key exchange - * https://www.rfc-editor.org/rfc/rfc8446#section-4.2.7 - */ - const struct s2n_ecc_preferences *ecc_preferences; - /* This field determines what public keys are allowed for use. It restricts - * both the type of the key (Elliptic Curve, RSA w/ Encryption, RSA PSS) and - * the size of the key. Note that this field structure is likely to change - * until https://github.com/aws/s2n-tls/issues/4435 is closed. - */ - const struct s2n_certificate_key_preferences *certificate_key_preferences; - /* This field controls whether the certificate_signature_preferences apply - * to local certs loaded on configs. - */ - bool certificate_preferences_apply_locally; - bool rules[S2N_SECURITY_RULES_COUNT]; -}; - struct s2n_security_policy_selection { const char *version; const struct s2n_security_policy *security_policy; @@ -215,22 +159,10 @@ extern const struct s2n_security_policy security_policy_20190122; extern const struct s2n_security_policy security_policy_null; int s2n_security_policies_init(); -int s2n_config_set_cipher_preferences(struct s2n_config *config, const char *version); -int s2n_connection_set_cipher_preferences(struct s2n_connection *conn, const char *version); bool s2n_ecc_is_extension_required(const struct s2n_security_policy *security_policy); bool s2n_pq_kem_is_extension_required(const struct s2n_security_policy *security_policy); -bool s2n_security_policy_supports_tls13(const struct s2n_security_policy *security_policy); int s2n_find_security_policy_from_version(const char *version, const struct s2n_security_policy **security_policy); int s2n_validate_kem_preferences(const struct s2n_kem_preferences *kem_preferences, bool pq_kem_extension_required); S2N_RESULT s2n_validate_certificate_signature_preferences(const struct s2n_signature_preferences *s2n_certificate_signature_preferences); S2N_RESULT s2n_security_policy_get_version(const struct s2n_security_policy *security_policy, const char **version); -/* Checks to see if a certificate has a signature algorithm that's in our - * certificate_signature_preferences list - */ -S2N_RESULT s2n_security_policy_validate_certificate_chain(const struct s2n_security_policy *security_policy, - const struct s2n_cert_chain_and_key *cert_key_pair); -S2N_RESULT s2n_security_policy_validate_cert_signature( - const struct s2n_security_policy *security_policy, const struct s2n_cert_info *info, s2n_error error); -S2N_RESULT s2n_security_policy_validate_cert_key( - const struct s2n_security_policy *security_policy, const struct s2n_cert_info *info, s2n_error error);