From 404b56b4545a38b6babeca87fe8ce29bf8aebc44 Mon Sep 17 00:00:00 2001 From: Lindsay Stewart Date: Tue, 21 Mar 2023 17:08:40 -0700 Subject: [PATCH] Add new security policy (#3895) --- docs/USAGE-GUIDE.md | 9 +++- tests/unit/s2n_security_policies_test.c | 67 +++++++++++++++++++++++++ tls/s2n_cipher_preferences.c | 29 +++++++++++ tls/s2n_cipher_preferences.h | 1 + tls/s2n_security_policies.c | 10 ++++ tls/s2n_security_policies.h | 1 + tls/s2n_signature_scheme.c | 35 +++++++++++++ tls/s2n_signature_scheme.h | 1 + 8 files changed, 151 insertions(+), 2 deletions(-) diff --git a/docs/USAGE-GUIDE.md b/docs/USAGE-GUIDE.md index c87eb297e44..6d84cdf6dfd 100644 --- a/docs/USAGE-GUIDE.md +++ b/docs/USAGE-GUIDE.md @@ -413,17 +413,21 @@ The following chart maps the security policy version to protocol version and cip | "20190801" | | X | X | X | X | X | X | | X | | | | X | | | "20190802" | | X | X | X | X | X | X | | X | | | | X | | | "20200207" | | X | X | X | X | X | X | | X | | | | | | +| "20230317" | | | | X | X | X | | X | X | | | | X | | | "rfc9151" | | | | X | X | | | X | X | | | X | X | | | "CloudFront-TLS-1-2-2021" | | | | X | X | | X | X | X | | | | X | | | "CloudFront-TLS-1-2-2021-ChaCha20-Boosted" | | | | X | X | | X | X | X | | | | X | X | -The "default" and "default_tls13" version is special in that it will be updated with future s2n-tls changes and ciphersuites and protocol versions may be added and removed, or their internal order of preference might change. Numbered versions are fixed and will never change. +The "default" and "default_tls13" versions are special in that they will be updated with future s2n-tls changes and ciphersuites and protocol versions may be added and removed, or their internal order of preference might change. Numbered versions are fixed and will never change. +In general, customers prefer to use numbered versions for production use cases to prevent impact from library updates. + +"20230317" offers more limited but more secure options than "default". It only supports TLS1.2 and TLS1.3 and is FIPS compliant. Choose this policy if you don't need or want to support less secure legacy options like TLS1.1 or SHA1. "20160411" follows the same general preference order as "default". The main difference is it has a CBC cipher suite at the top. This is to accommodate certain Java clients that have poor GCM implementations. Users of s2n-tls who have found GCM to be hurting performance for their clients should consider this version. "20170405" is a FIPS compliant cipher suite preference list based on approved algorithms in the [FIPS 140-2 Annex A](http://csrc.nist.gov/publications/fips/fips140-2/fips1402annexa.pdf). Similarly to "20160411", this preference list has CBC cipher suites at the top to accommodate certain Java clients. Users of s2n-tls who plan to enable FIPS mode should consider this version. -The "rfc9151" security policy is derived from [Commercial National Security Algorithm (CNSA) Suite Profile for TLS and DTLS 1.2 and 1.3](https://datatracker.ietf.org/doc/html/rfc9151). +"rfc9151" is derived from [Commercial National Security Algorithm (CNSA) Suite Profile for TLS and DTLS 1.2 and 1.3](https://datatracker.ietf.org/doc/html/rfc9151). This policy restricts the algorithms allowed for signatures on certificates in the certificate chain to RSA or ECDSA with sha384, which may require you to update your certificates. s2n-tls does not expose an API to control the order of preference for each ciphersuite or protocol version. s2n-tls follows the following order: @@ -463,6 +467,7 @@ s2n-tls usually prefers AES over ChaCha20. However, some clients-- particularly | "20190801" | X | X | X | X | | "20190802" | X | X | X | X | | "20200207" | X | X | X | X | +| "20230317" | X | X | | X | | "rfc9151" | X | X | | X | Note that the default_tls13 security policy will never support legacy SHA-1 algorithms in TLS1.3, but will support diff --git a/tests/unit/s2n_security_policies_test.c b/tests/unit/s2n_security_policies_test.c index 00e86f6a7e7..36fdb316893 100644 --- a/tests/unit/s2n_security_policies_test.c +++ b/tests/unit/s2n_security_policies_test.c @@ -15,6 +15,7 @@ #include "tls/s2n_security_policies.h" +#include "crypto/s2n_rsa_pss.h" #include "crypto/s2n_rsa_signing.h" #include "pq-crypto/s2n_pq.h" #include "s2n_test.h" @@ -22,6 +23,36 @@ #include "tls/s2n_kem.h" #include "tls/s2n_signature_algorithms.h" +static S2N_RESULT s2n_test_security_policies_compatible(const struct s2n_security_policy *policy, + const char *default_policy, struct s2n_cert_chain_and_key *cert_chain) +{ + DEFER_CLEANUP(struct s2n_config *server_config = s2n_config_new(), + s2n_config_ptr_free); + RESULT_GUARD_POSIX(s2n_config_add_cert_chain_and_key_to_store(server_config, cert_chain)); + + DEFER_CLEANUP(struct s2n_config *client_config = s2n_config_new(), + s2n_config_ptr_free); + RESULT_GUARD_POSIX(s2n_config_set_unsafe_for_testing(client_config)); + + DEFER_CLEANUP(struct s2n_connection *server = s2n_connection_new(S2N_SERVER), + s2n_connection_ptr_free); + RESULT_GUARD_POSIX(s2n_connection_set_config(server, server_config)); + RESULT_GUARD_POSIX(s2n_connection_set_cipher_preferences(server, default_policy)); + + DEFER_CLEANUP(struct s2n_connection *client = s2n_connection_new(S2N_CLIENT), + s2n_connection_ptr_free); + RESULT_GUARD_POSIX(s2n_connection_set_config(client, client_config)); + client->security_policy_override = policy; + + DEFER_CLEANUP(struct s2n_test_io_pair test_io_pair = { 0 }, + s2n_io_pair_close); + RESULT_GUARD_POSIX(s2n_io_pair_init_non_blocking(&test_io_pair)); + RESULT_GUARD_POSIX(s2n_connections_set_io_pair(client, server, &test_io_pair)); + RESULT_GUARD_POSIX(s2n_negotiate_test_server_and_client(server, client)); + + return S2N_RESULT_OK; +} + int main(int argc, char **argv) { BEGIN_TEST(); @@ -29,6 +60,20 @@ int main(int argc, char **argv) EXPECT_TRUE(s2n_array_len(ALL_SUPPORTED_KEM_GROUPS) == S2N_SUPPORTED_KEM_GROUPS_COUNT); + DEFER_CLEANUP(struct s2n_cert_chain_and_key *rsa_chain_and_key = NULL, s2n_cert_chain_and_key_ptr_free); + EXPECT_SUCCESS(s2n_test_cert_chain_and_key_new(&rsa_chain_and_key, + S2N_DEFAULT_TEST_CERT_CHAIN, S2N_DEFAULT_TEST_PRIVATE_KEY)); + + DEFER_CLEANUP(struct s2n_cert_chain_and_key *ecdsa_chain_and_key = NULL, s2n_cert_chain_and_key_ptr_free); + EXPECT_SUCCESS(s2n_test_cert_chain_and_key_new(&ecdsa_chain_and_key, + S2N_DEFAULT_ECDSA_TEST_CERT_CHAIN, S2N_DEFAULT_ECDSA_TEST_PRIVATE_KEY)); + + DEFER_CLEANUP(struct s2n_cert_chain_and_key *rsa_pss_chain_and_key = NULL, s2n_cert_chain_and_key_ptr_free); + if (s2n_is_rsa_pss_certs_supported()) { + EXPECT_SUCCESS(s2n_test_cert_chain_and_key_new(&rsa_pss_chain_and_key, + S2N_RSA_PSS_2048_SHA256_LEAF_CERT, S2N_RSA_PSS_2048_SHA256_LEAF_KEY)); + } + /* Perform basic checks on all Security Policies. */ for (size_t policy_index = 0; security_policy_selection[policy_index].version != NULL; policy_index++) { const struct s2n_security_policy *security_policy = security_policy_selection[policy_index].security_policy; @@ -979,5 +1024,27 @@ int main(int argc, char **argv) EXPECT_ERROR_WITH_ERRNO(s2n_validate_certificate_signature_preferences(&test_certificate_signature_preferences), S2N_ERR_INVALID_SECURITY_POLICY); } + EXPECT_SUCCESS(s2n_reset_tls13_in_test()); + + /* Test that security policies are compatible with other policies */ + { + /* 20230317 */ + { + EXPECT_OK(s2n_test_security_policies_compatible(&security_policy_20230317, "default", rsa_chain_and_key)); + EXPECT_OK(s2n_test_security_policies_compatible(&security_policy_20230317, "default_tls13", rsa_chain_and_key)); + EXPECT_OK(s2n_test_security_policies_compatible(&security_policy_20230317, "default_fips", rsa_chain_and_key)); + EXPECT_OK(s2n_test_security_policies_compatible(&security_policy_20230317, "20230317", rsa_chain_and_key)); + + EXPECT_OK(s2n_test_security_policies_compatible(&security_policy_20230317, "default_tls13", ecdsa_chain_and_key)); + EXPECT_OK(s2n_test_security_policies_compatible(&security_policy_20230317, "default_fips", ecdsa_chain_and_key)); + EXPECT_OK(s2n_test_security_policies_compatible(&security_policy_20230317, "20230317", ecdsa_chain_and_key)); + + if (s2n_is_rsa_pss_certs_supported()) { + EXPECT_OK(s2n_test_security_policies_compatible(&security_policy_20230317, "default_tls13", rsa_pss_chain_and_key)); + EXPECT_OK(s2n_test_security_policies_compatible(&security_policy_20230317, "20230317", rsa_pss_chain_and_key)); + } + }; + }; + END_TEST(); } diff --git a/tls/s2n_cipher_preferences.c b/tls/s2n_cipher_preferences.c index fc17e958916..2187c9fb2df 100644 --- a/tls/s2n_cipher_preferences.c +++ b/tls/s2n_cipher_preferences.c @@ -273,6 +273,35 @@ const struct s2n_cipher_preferences cipher_preferences_20170210 = { .allow_chacha20_boosting = false, }; +/* + * TLS1.3 support. + * FIPS compliant. + * No DHE (would require extra setup with s2n_config_add_dhparams) + */ +struct s2n_cipher_suite *cipher_suites_20230317[] = { + /* TLS1.2 with ECDSA */ + &s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256, + &s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384, + &s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256, + &s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384, + + /* TLS1.2 with RSA */ + &s2n_ecdhe_rsa_with_aes_128_gcm_sha256, + &s2n_ecdhe_rsa_with_aes_256_gcm_sha384, + &s2n_ecdhe_rsa_with_aes_128_cbc_sha256, + &s2n_ecdhe_rsa_with_aes_256_cbc_sha384, + + /* TLS1.3 */ + &s2n_tls13_aes_128_gcm_sha256, + &s2n_tls13_aes_256_gcm_sha384, +}; + +const struct s2n_cipher_preferences cipher_preferences_20230317 = { + .count = s2n_array_len(cipher_suites_20230317), + .suites = cipher_suites_20230317, + .allow_chacha20_boosting = false, +}; + /* Same as 20160411, but with ChaCha20 added as 1st in Preference List */ struct s2n_cipher_suite *cipher_suites_20190122[] = { &s2n_ecdhe_rsa_with_chacha20_poly1305_sha256, diff --git a/tls/s2n_cipher_preferences.h b/tls/s2n_cipher_preferences.h index 54b5f2fe099..38e4e4e5946 100644 --- a/tls/s2n_cipher_preferences.h +++ b/tls/s2n_cipher_preferences.h @@ -27,6 +27,7 @@ struct s2n_cipher_preferences { bool allow_chacha20_boosting; }; +extern const struct s2n_cipher_preferences cipher_preferences_20230317; extern const struct s2n_cipher_preferences cipher_preferences_20140601; extern const struct s2n_cipher_preferences cipher_preferences_20141001; extern const struct s2n_cipher_preferences cipher_preferences_20150202; diff --git a/tls/s2n_security_policies.c b/tls/s2n_security_policies.c index a0aee179637..1f51175d7c7 100644 --- a/tls/s2n_security_policies.c +++ b/tls/s2n_security_policies.c @@ -51,6 +51,15 @@ const struct s2n_security_policy security_policy_default_fips = { .ecc_preferences = &s2n_ecc_preferences_default_fips, }; +const struct s2n_security_policy security_policy_20230317 = { + .minimum_protocol_version = S2N_TLS12, + .cipher_preferences = &cipher_preferences_20230317, + .kem_preferences = &kem_preferences_null, + .signature_preferences = &s2n_signature_preferences_20230317, + .certificate_signature_preferences = &s2n_signature_preferences_20230317, + .ecc_preferences = &s2n_ecc_preferences_20201021, +}; + const struct s2n_security_policy security_policy_20190801 = { .minimum_protocol_version = S2N_TLS10, .cipher_preferences = &cipher_preferences_20190801, @@ -787,6 +796,7 @@ struct s2n_security_policy_selection security_policy_selection[] = { { .version = "default", .security_policy = &security_policy_20170210, .ecc_extension_required = 0, .pq_kem_extension_required = 0 }, { .version = "default_tls13", .security_policy = &security_policy_default_tls13, .ecc_extension_required = 0, .pq_kem_extension_required = 0 }, { .version = "default_fips", .security_policy = &security_policy_default_fips, .ecc_extension_required = 0, .pq_kem_extension_required = 0 }, + { .version = "20230317", .security_policy = &security_policy_20230317, .ecc_extension_required = 0, .pq_kem_extension_required = 0 }, { .version = "ELBSecurityPolicy-TLS-1-0-2015-04", .security_policy = &security_policy_elb_2015_04, .ecc_extension_required = 0, .pq_kem_extension_required = 0 }, /* Not a mistake. TLS-1-0-2015-05 and 2016-08 are equivalent */ { .version = "ELBSecurityPolicy-TLS-1-0-2015-05", .security_policy = &security_policy_elb_2016_08, .ecc_extension_required = 0, .pq_kem_extension_required = 0 }, diff --git a/tls/s2n_security_policies.h b/tls/s2n_security_policies.h index 3828d7544f9..ad98ab6923a 100644 --- a/tls/s2n_security_policies.h +++ b/tls/s2n_security_policies.h @@ -63,6 +63,7 @@ extern const struct s2n_security_policy security_policy_20190214; extern const struct s2n_security_policy security_policy_20190214_gcm; extern const struct s2n_security_policy security_policy_20190801; extern const struct s2n_security_policy security_policy_20190802; +extern const struct s2n_security_policy security_policy_20230317; extern const struct s2n_security_policy security_policy_default_tls13; extern const struct s2n_security_policy security_policy_default_fips; extern const struct s2n_security_policy security_policy_test_all; diff --git a/tls/s2n_signature_scheme.c b/tls/s2n_signature_scheme.c index 4d674379f7c..bbea03abd92 100644 --- a/tls/s2n_signature_scheme.c +++ b/tls/s2n_signature_scheme.c @@ -282,6 +282,41 @@ const struct s2n_signature_preferences s2n_signature_preferences_default_fips = .signature_schemes = s2n_sig_scheme_pref_list_default_fips, }; +/* + * FIPS compliant. + * Supports TLS1.3. + * Prefers PSS over PKCS1. + */ +const struct s2n_signature_scheme* const s2n_sig_scheme_pref_list_20230317[] = { + /* RSA */ + &s2n_rsa_pss_rsae_sha256, + &s2n_rsa_pss_rsae_sha384, + &s2n_rsa_pss_rsae_sha512, + &s2n_rsa_pkcs1_sha256, + &s2n_rsa_pkcs1_sha384, + &s2n_rsa_pkcs1_sha512, + + /* TLS1.2 with ECDSA */ + &s2n_ecdsa_sha256, /* same iana value as TLS 1.3 s2n_ecdsa_secp256r1_sha256 */ + &s2n_ecdsa_sha384, /* same iana value as TLS 1.3 s2n_ecdsa_secp384r1_sha384 */ + &s2n_ecdsa_sha512, + + /* TLS1.3 with ECDSA */ + &s2n_ecdsa_secp256r1_sha256, + &s2n_ecdsa_secp384r1_sha384, + &s2n_ecdsa_secp521r1_sha512, + + /* TLS1.3 with RSA-PSS */ + &s2n_rsa_pss_pss_sha256, + &s2n_rsa_pss_pss_sha384, + &s2n_rsa_pss_pss_sha512, +}; + +const struct s2n_signature_preferences s2n_signature_preferences_20230317 = { + .count = s2n_array_len(s2n_sig_scheme_pref_list_20230317), + .signature_schemes = s2n_sig_scheme_pref_list_20230317, +}; + /* Add s2n_ecdsa_secp521r1_sha512 */ const struct s2n_signature_scheme* const s2n_sig_scheme_pref_list_20201021[] = { /* RSA PSS */ diff --git a/tls/s2n_signature_scheme.h b/tls/s2n_signature_scheme.h index c4700f4d1a5..a1c58db5ce4 100644 --- a/tls/s2n_signature_scheme.h +++ b/tls/s2n_signature_scheme.h @@ -73,6 +73,7 @@ extern const struct s2n_signature_scheme s2n_rsa_pss_rsae_sha256; extern const struct s2n_signature_scheme s2n_rsa_pss_rsae_sha384; extern const struct s2n_signature_scheme s2n_rsa_pss_rsae_sha512; +extern const struct s2n_signature_preferences s2n_signature_preferences_20230317; extern const struct s2n_signature_preferences s2n_signature_preferences_20140601; extern const struct s2n_signature_preferences s2n_signature_preferences_20200207; extern const struct s2n_signature_preferences s2n_signature_preferences_20201021;