1616#include "tls/s2n_security_policies.h"
1717
1818#include "api/s2n.h"
19+ #include "crypto/s2n_pq.h"
1920#include "tls/s2n_certificate_keys.h"
2021#include "tls/s2n_connection.h"
2122#include "utils/s2n_safety.h"
@@ -1398,6 +1399,15 @@ const struct s2n_security_policy security_policy_test_all_tls13 = {
13981399 },
13991400};
14001401
1402+ const struct s2n_security_policy security_policy_test_pq_only = {
1403+ .minimum_protocol_version = S2N_TLS13 ,
1404+ .cipher_preferences = & cipher_preferences_cloudfront_upstream_2025_08_08_tls13 ,
1405+ .kem_preferences = & kem_preferences_pq_tls_1_3_ietf_2025_07 ,
1406+ .signature_preferences = & s2n_signature_preferences_20240501 ,
1407+ .certificate_signature_preferences = & s2n_signature_preferences_20240501 ,
1408+ .ecc_preferences = & s2n_ecc_preferences_null ,
1409+ };
1410+
14011411const struct s2n_security_policy security_policy_20200207 = {
14021412 .minimum_protocol_version = S2N_SSLv3 ,
14031413 .cipher_preferences = & cipher_preferences_test_all_tls13 ,
@@ -1570,6 +1580,7 @@ struct s2n_security_policy_selection security_policy_selection[] = {
15701580 { .version = "test_ecdsa_priority" , .security_policy = & security_policy_test_ecdsa_priority , .ecc_extension_required = 0 , .pq_kem_extension_required = 0 },
15711581 { .version = "test_all_tls12" , .security_policy = & security_policy_test_all_tls12 , .ecc_extension_required = 0 , .pq_kem_extension_required = 0 },
15721582 { .version = "test_all_tls13" , .security_policy = & security_policy_test_all_tls13 , .ecc_extension_required = 0 , .pq_kem_extension_required = 0 },
1583+ { .version = "test_pq_only" , .security_policy = & security_policy_test_pq_only , .ecc_extension_required = 0 , .pq_kem_extension_required = 0 },
15731584 { .version = "null" , .security_policy = & security_policy_null , .ecc_extension_required = 0 , .pq_kem_extension_required = 0 },
15741585 { .version = NULL , .security_policy = NULL , .ecc_extension_required = 0 , .pq_kem_extension_required = 0 }
15751586};
@@ -1615,7 +1626,7 @@ int s2n_find_security_policy_from_version(const char *version, const struct s2n_
16151626 POSIX_BAIL (S2N_ERR_INVALID_SECURITY_POLICY );
16161627}
16171628
1618- int s2n_config_set_security_policy (struct s2n_config * config , const struct s2n_security_policy * security_policy )
1629+ static int s2n_config_validate_security_policy (struct s2n_config * config , const struct s2n_security_policy * security_policy )
16191630{
16201631 POSIX_ENSURE_REF (config );
16211632 POSIX_ENSURE_REF (security_policy );
@@ -1627,8 +1638,25 @@ int s2n_config_set_security_policy(struct s2n_config *config, const struct s2n_s
16271638 /* If the security policy's minimum version is higher than what libcrypto supports, return an error. */
16281639 POSIX_ENSURE ((security_policy -> minimum_protocol_version <= s2n_get_highest_fully_supported_tls_version ()), S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED );
16291640
1641+ if (security_policy == & security_policy_null ) {
1642+ return S2N_SUCCESS ;
1643+ }
1644+
1645+ /* Ensure that an ECC or PQ key exchange can occur. */
1646+ uint32_t ecc_available = security_policy -> ecc_preferences -> count ;
1647+ uint32_t kem_groups_available = 0 ;
1648+ POSIX_GUARD_RESULT (s2n_kem_preferences_groups_available (security_policy -> kem_preferences , & kem_groups_available ));
1649+ POSIX_ENSURE (ecc_available + kem_groups_available > 0 , S2N_ERR_INVALID_SECURITY_POLICY );
1650+
16301651 /* If the config contains certificates violating the security policy cert preferences, return an error. */
16311652 POSIX_GUARD_RESULT (s2n_config_validate_loaded_certificates (config , security_policy ));
1653+ return S2N_SUCCESS ;
1654+ }
1655+
1656+ int s2n_config_set_security_policy (struct s2n_config * config , const struct s2n_security_policy * security_policy )
1657+ {
1658+ POSIX_ENSURE_REF (config );
1659+ POSIX_GUARD (s2n_config_validate_security_policy (config , security_policy ));
16321660 config -> security_policy = security_policy ;
16331661 return 0 ;
16341662}
@@ -1644,19 +1672,7 @@ int s2n_config_set_cipher_preferences(struct s2n_config *config, const char *ver
16441672int s2n_connection_set_security_policy (struct s2n_connection * conn , const struct s2n_security_policy * security_policy )
16451673{
16461674 POSIX_ENSURE_REF (conn );
1647- POSIX_ENSURE_REF (security_policy );
1648- POSIX_ENSURE_REF (security_policy -> cipher_preferences );
1649- POSIX_ENSURE_REF (security_policy -> kem_preferences );
1650- POSIX_ENSURE_REF (security_policy -> signature_preferences );
1651- POSIX_ENSURE_REF (security_policy -> ecc_preferences );
1652-
1653- /* If the security policy's minimum version is higher than what libcrypto supports, return an error. */
1654- POSIX_ENSURE ((security_policy -> minimum_protocol_version <= s2n_get_highest_fully_supported_tls_version ()), S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED );
1655-
1656- /* If the certificates loaded in the config are incompatible with the security
1657- * policy's certificate preferences, return an error. */
1658- POSIX_GUARD_RESULT (s2n_config_validate_loaded_certificates (conn -> config , security_policy ));
1659-
1675+ POSIX_GUARD (s2n_config_validate_security_policy (conn -> config , security_policy ));
16601676 conn -> security_policy_override = security_policy ;
16611677 return 0 ;
16621678}
@@ -1688,8 +1704,15 @@ int s2n_security_policies_init()
16881704 }
16891705
16901706 if (security_policy != & security_policy_null ) {
1691- /* All policies must have at least one ecc curve configured. */
1692- S2N_ERROR_IF (ecc_preference -> count == 0 , S2N_ERR_INVALID_SECURITY_POLICY );
1707+ /* All policies must have at least one ecc curve or PQ kem group configured. */
1708+ bool ecc_kx_supported = ecc_preference -> count > 0 ;
1709+ bool pq_kx_supported = kem_preference -> tls13_kem_group_count > 0 ;
1710+ POSIX_ENSURE (ecc_kx_supported || pq_kx_supported , S2N_ERR_INVALID_SECURITY_POLICY );
1711+
1712+ /* A PQ key exchange is only supported in TLS 1.3, so PQ-only policies must require TLS 1.3.*/
1713+ if (!ecc_kx_supported ) {
1714+ POSIX_ENSURE (security_policy -> minimum_protocol_version >= S2N_TLS13 , S2N_ERR_INVALID_SECURITY_POLICY );
1715+ }
16931716 }
16941717
16951718 for (int j = 0 ; j < cipher_preference -> count ; j ++ ) {
0 commit comments