Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new PQ TLS Policies #4327

Merged
merged 3 commits into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions tests/unit/s2n_security_rules_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,15 @@ int main(int argc, char **argv)
.signature_preferences = &valid_sig_prefs,
.certificate_signature_preferences = &valid_sig_prefs,
.ecc_preferences = &valid_ecc_prefs,
.kem_preferences = &kem_preferences_null,
.minimum_protocol_version = VALID_VERSION,
};
const struct s2n_security_policy invalid_policy = {
.cipher_preferences = &invalid_cipher_prefs,
.signature_preferences = &invalid_sig_prefs,
.certificate_signature_preferences = &invalid_sig_prefs,
.ecc_preferences = &invalid_ecc_prefs,
.kem_preferences = &kem_preferences_null,
.minimum_protocol_version = EXAMPLE_INVALID_VERSION,
};

Expand Down
40 changes: 40 additions & 0 deletions tls/s2n_cipher_preferences.c
Original file line number Diff line number Diff line change
Expand Up @@ -1891,6 +1891,46 @@ const struct s2n_cipher_preferences cipher_preferences_pq_tls_1_3_2023_06_01 = {
.allow_chacha20_boosting = false,
};

struct s2n_cipher_suite *cipher_suites_20231213[] = {
&s2n_tls13_aes_128_gcm_sha256,
&s2n_tls13_aes_256_gcm_sha384,
&s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256,
&s2n_ecdhe_rsa_with_aes_128_gcm_sha256,
&s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384,
&s2n_ecdhe_rsa_with_aes_256_gcm_sha384,
&s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256,
&s2n_ecdhe_rsa_with_aes_128_cbc_sha256,
&s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384,
&s2n_ecdhe_rsa_with_aes_256_cbc_sha384,
&s2n_rsa_with_aes_128_gcm_sha256,
&s2n_rsa_with_aes_256_gcm_sha384,
&s2n_rsa_with_aes_128_cbc_sha256,
&s2n_rsa_with_aes_256_cbc_sha256,
Comment on lines +1905 to +1908
Copy link
Contributor Author

@alexw91 alexw91 Dec 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These RSA Key Exchange ciphers cause PQ-TLS-1-2-2023-12-13 to fail the S2N_FIPS_140_3 rule checks in s2n as they exist today, but it seems that s2n's checks might be stricter than necessary.

See this discussion about how RSA Key exchange ciphers are technically still allowed by FIPS if necessary, but no longer recommended and proposed a separate S2N_FIPS_140_3_LEGACY_SUPPORT rule.

While these guidelines do not recommend cipher suites using RSA key transport, there may be
circumstances in practice where RSA key transport is needed. For example, if an agency uses a
network appliance for regulatory or enterprise security purposes that only functions with these
cipher suites, then these cipher suites may need to be enabled.

And this NIST doc that deprecates PKCSv1.5 padding.

Effective as of the final publication of this revision of SP 800-131A, uses of PKCS 1,
version 1.5 and other RSA key-agreement or key-transport schemes that are not
compliant with SP 800-56B are deprecated.

After December 31, 2023, the use of PKCS1-v 1_5 padding scheme is disallowed.

Copy link
Contributor

@lrstewart lrstewart Jan 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We didn't end up including the "LEGACY_SUPPORT" version of the rule because csosto-pk was right that the FIPS docs are pretty clear that RSA kex / PKCSv1.5 is not allowed after 2023, regardless of circumstances. So I don't think the rule is stricter than necessary for RSA kex.

It's 2024 now ;)

};

const struct s2n_cipher_preferences cipher_preferences_20231213 = {
.count = s2n_array_len(cipher_suites_20231213),
.suites = cipher_suites_20231213,
};

struct s2n_cipher_suite *cipher_suites_20231214[] = {
&s2n_tls13_aes_128_gcm_sha256,
&s2n_tls13_aes_256_gcm_sha384,
&s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256,
&s2n_ecdhe_rsa_with_aes_128_gcm_sha256,
&s2n_ecdhe_ecdsa_with_aes_256_gcm_sha384,
&s2n_ecdhe_rsa_with_aes_256_gcm_sha384,
&s2n_ecdhe_ecdsa_with_aes_128_cbc_sha256,
&s2n_ecdhe_rsa_with_aes_128_cbc_sha256,
&s2n_ecdhe_ecdsa_with_aes_256_cbc_sha384,
&s2n_ecdhe_rsa_with_aes_256_cbc_sha384,
};

const struct s2n_cipher_preferences cipher_preferences_20231214 = {
.count = s2n_array_len(cipher_suites_20231214),
.suites = cipher_suites_20231214,
};

struct s2n_cipher_suite *cipher_suites_kms_fips_tls_1_2_2018_10[] = {
&s2n_ecdhe_rsa_with_aes_256_gcm_sha384,
&s2n_ecdhe_rsa_with_aes_128_gcm_sha256,
Expand Down
3 changes: 3 additions & 0 deletions tls/s2n_cipher_preferences.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ extern const struct s2n_cipher_preferences cipher_preferences_20210816_gcm;
extern const struct s2n_cipher_preferences cipher_preferences_20210825;
extern const struct s2n_cipher_preferences cipher_preferences_20210825_gcm;
extern const struct s2n_cipher_preferences cipher_preferences_20210831;
extern const struct s2n_cipher_preferences cipher_preferences_20231213;
extern const struct s2n_cipher_preferences cipher_preferences_20231214;

extern const struct s2n_cipher_preferences cipher_preferences_default_fips;

extern const struct s2n_cipher_preferences cipher_preferences_test_all;
Expand Down
16 changes: 16 additions & 0 deletions tls/s2n_kem_preferences.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ const struct s2n_kem_group *pq_kem_groups_r3_2023_06[] = {
&s2n_x25519_kyber_512_r3,
};

const struct s2n_kem_group *pq_kem_groups_r3_2023_12[] = {
&s2n_secp256r1_kyber_768_r3,
&s2n_secp384r1_kyber_768_r3,
&s2n_secp521r1_kyber_1024_r3,
&s2n_secp256r1_kyber_512_r3,
};

const struct s2n_kem_preferences kem_preferences_pq_tls_1_0_2021_05 = {
.kem_count = s2n_array_len(pq_kems_r3_2021_05),
.kems = pq_kems_r3_2021_05,
Expand All @@ -59,6 +66,15 @@ const struct s2n_kem_preferences kem_preferences_pq_tls_1_3_2023_06 = {
.tls13_pq_hybrid_draft_revision = 5
};

/* Same as kem_preferences_pq_tls_1_3_2023_06, but without x25519 */
const struct s2n_kem_preferences kem_preferences_pq_tls_1_3_2023_12 = {
.kem_count = 0,
.kems = NULL,
.tls13_kem_group_count = s2n_array_len(pq_kem_groups_r3_2023_12),
.tls13_kem_groups = pq_kem_groups_r3_2023_12,
.tls13_pq_hybrid_draft_revision = 5
};

const struct s2n_kem_preferences kem_preferences_all = {
.kem_count = s2n_array_len(pq_kems_r3_2021_05),
.kems = pq_kems_r3_2021_05,
Expand Down
1 change: 1 addition & 0 deletions tls/s2n_kem_preferences.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ extern const struct s2n_kem_group *pq_kem_groups_r3_2023_06[];
extern const struct s2n_kem_preferences kem_preferences_pq_tls_1_0_2021_05;
extern const struct s2n_kem_preferences kem_preferences_pq_tls_1_0_2023_01;
extern const struct s2n_kem_preferences kem_preferences_pq_tls_1_3_2023_06;
extern const struct s2n_kem_preferences kem_preferences_pq_tls_1_3_2023_12;
extern const struct s2n_kem_preferences kem_preferences_all;
extern const struct s2n_kem_preferences kem_preferences_null;

Expand Down
36 changes: 36 additions & 0 deletions tls/s2n_security_policies.c
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,39 @@ const struct s2n_security_policy security_policy_pq_tls_1_2_2023_10_10 = {
.ecc_preferences = &s2n_ecc_preferences_20200310,
};

/* General purpose "mostly" FIPS + PQ policy (with the exception of supporting RSA Key Exchange for backwards compatibility). */
const struct s2n_security_policy security_policy_pq_20231213 = {
.minimum_protocol_version = S2N_TLS12,
.cipher_preferences = &cipher_preferences_20231213,
.kem_preferences = &kem_preferences_pq_tls_1_3_2023_12,
.signature_preferences = &s2n_signature_preferences_20230317,
.ecc_preferences = &s2n_ecc_preferences_20201021,
};

/* General purpose FIPS + PQ policy that meets all current FIPS requirements. */
const struct s2n_security_policy security_policy_pq_20231214 = {
.minimum_protocol_version = S2N_TLS12,
.cipher_preferences = &cipher_preferences_20231214,
.kem_preferences = &kem_preferences_pq_tls_1_3_2023_12,
.signature_preferences = &s2n_signature_preferences_20230317,
.ecc_preferences = &s2n_ecc_preferences_20201021,
.rules = {
[S2N_FIPS_140_3] = true,
},
};

/* FIPS + PQ Policy that uses KMS's FIPS cipher preference list and meets all current FIPS requirements. */
const struct s2n_security_policy security_policy_pq_20231215 = {
.minimum_protocol_version = S2N_TLS12,
.cipher_preferences = &cipher_preferences_kms_fips_tls_1_2_2021_08,
.kem_preferences = &kem_preferences_pq_tls_1_3_2023_12,
.signature_preferences = &s2n_signature_preferences_20230317,
.ecc_preferences = &s2n_ecc_preferences_20201021,
.rules = {
[S2N_FIPS_140_3] = true,
},
};

const struct s2n_security_policy security_policy_kms_fips_tls_1_2_2018_10 = {
.minimum_protocol_version = S2N_TLS12,
.cipher_preferences = &cipher_preferences_kms_fips_tls_1_2_2018_10,
Expand Down Expand Up @@ -1103,6 +1136,9 @@ struct s2n_security_policy_selection security_policy_selection[] = {
{ .version = "PQ-TLS-1-2-2023-10-08", .security_policy = &security_policy_pq_tls_1_2_2023_10_08, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
{ .version = "PQ-TLS-1-2-2023-10-09", .security_policy = &security_policy_pq_tls_1_2_2023_10_09, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
{ .version = "PQ-TLS-1-2-2023-10-10", .security_policy = &security_policy_pq_tls_1_2_2023_10_10, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
{ .version = "PQ-TLS-1-2-2023-12-13", .security_policy = &security_policy_pq_20231213, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
{ .version = "PQ-TLS-1-2-2023-12-14", .security_policy = &security_policy_pq_20231214, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
{ .version = "PQ-TLS-1-2-2023-12-15", .security_policy = &security_policy_pq_20231215, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
{ .version = "20140601", .security_policy = &security_policy_20140601, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
{ .version = "20141001", .security_policy = &security_policy_20141001, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
{ .version = "20150202", .security_policy = &security_policy_20150202, .ecc_extension_required = 0, .pq_kem_extension_required = 0 },
Expand Down
14 changes: 14 additions & 0 deletions tls/s2n_security_rules.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,20 @@ S2N_RESULT s2n_security_rule_validate_policy(const struct s2n_security_rule *rul
"curve", curve->name, i + 1));
}

const struct s2n_kem_preferences *kem_prefs = policy->kem_preferences;
RESULT_ENSURE_REF(kem_prefs);
for (size_t i = 0; i < kem_prefs->tls13_kem_group_count; i++) {
const struct s2n_kem_group *kem_group = kem_prefs->tls13_kem_groups[i];
const struct s2n_ecc_named_curve *curve = kem_group->curve;
Comment on lines +172 to +173
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there any FIPS restrictions on the pq kems, or just the classical ones?

Copy link
Contributor Author

@alexw91 alexw91 Jan 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIST published new Key Derivation standards in 2020 that allow simple concatenation of a FIPS shared secret with a non-FIPS shared secret to still be considered allowed by FIPS, which is what the draft TLS 1.3 RFC does today. So no FIPS requirements apply to the PQ KEM's, just the FIPS ECDHE curves which are already FIPS approved.


In addition to the currently approved techniques for the generation of the shared secret Z as
specified in SP 800-56A and SP 800-56B, this Recommendation permits the use of a “hybrid”
shared secret of the form Z′ = Z || T, a concatenation consisting of a “standard” shared secret Z that
was generated during the execution of a key-establishment scheme (as currently specified in [SP
800-56A] or [SP 800-56B]) followed by an auxiliary shared secret T that has been generated using
some other method. 

From Section 2: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Cr2.pdf


3.3.  Shared secret calculation

   Here we also take a simple "concatenation approach": the two shared
   secrets are concatenated together and used as the shared secret in
   the existing TLS 1.3 key schedule.  Again, we do not add any
   additional structure (length fields) in the concatenation procedure:
   for both the traditional groups and Kyber, the shared secret output
   length is fixed for a specific elliptic curve or parameter set.

   In other words, the shared secret is calculated as

       concatenated_shared_secret = shared_secret_1 || shared_secret_2
...

   *FIPS-compliance of shared secret concatenation.* [NIST-SP-800-56C]
   or [NIST-SP-800-135] give NIST recommendations for key derivation
   methods in key exchange protocols.  Some hybrid combinations may
   combine the shared secret from a NIST-approved algorithm (e.g., ECDH
   using the nistp256/secp256r1 curve) with a shared secret from a non-
   approved algorithm (e.g., post-quantum).  [NIST-SP-800-56C] lists
   simple concatenation as an approved method for generation of a hybrid
   shared secret in which one of the constituent shared secret is from
   an approved method.

From section 3.3 of the draft Hybrid TLS 1.3 RFC: https://datatracker.ietf.org/doc/html/draft-ietf-tls-hybrid-design-09#section-3.3

RESULT_ENSURE_REF(curve);
bool is_valid = false;
RESULT_ENSURE_REF(rule->validate_curve);
RESULT_GUARD(rule->validate_curve(curve, &is_valid));
RESULT_GUARD(s2n_security_rule_result_process(result, is_valid,
error_msg_format_name, rule->name, policy_name,
"curve", curve->name, i + 1));
}

bool is_valid = false;
RESULT_ENSURE_REF(rule->validate_version);
RESULT_GUARD(rule->validate_version(policy->minimum_protocol_version, &is_valid));
Expand Down
Loading