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

Update FIPS rules for ML-KEM #4829

Merged
merged 1 commit into from
Oct 14, 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 crypto/s2n_fips.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <stdbool.h>

#include "api/s2n.h"
#include "tls/s2n_kem.h"
#include "utils/s2n_result.h"

#pragma once
Expand All @@ -30,4 +31,5 @@ struct s2n_signature_scheme;
S2N_RESULT s2n_fips_validate_signature_scheme(const struct s2n_signature_scheme *sig_alg, bool *valid);
struct s2n_ecc_named_curve;
S2N_RESULT s2n_fips_validate_curve(const struct s2n_ecc_named_curve *curve, bool *valid);
S2N_RESULT s2n_fips_validate_hybrid_group(const struct s2n_kem_group *hybrid_group, bool *valid);
S2N_RESULT s2n_fips_validate_version(uint8_t version, bool *valid);
44 changes: 44 additions & 0 deletions crypto/s2n_fips_rules.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,50 @@ S2N_RESULT s2n_fips_validate_curve(const struct s2n_ecc_named_curve *curve, bool
return S2N_RESULT_OK;
}

/* https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.203.pdf */
const struct s2n_kem *fips_kems[] = {
&s2n_mlkem_768
};

S2N_RESULT s2n_fips_validate_kem(const struct s2n_kem *kem, bool *valid)
{
RESULT_ENSURE_REF(kem);
RESULT_ENSURE_REF(valid);
*valid = false;

for (size_t i = 0; i < s2n_array_len(fips_kems); i++) {
if (fips_kems[i] == kem) {
*valid = true;
return S2N_RESULT_OK;
}
}
return S2N_RESULT_OK;
}

S2N_RESULT s2n_fips_validate_hybrid_group(const struct s2n_kem_group *hybrid_group, bool *valid)
{
RESULT_ENSURE_REF(hybrid_group);
RESULT_ENSURE_REF(valid);
*valid = false;

/* The first share in a Hybrid Group must be FIPS-approved, see page 33 of NIST 800-56Cr2.
*
* "Recommendation is expanded to permit the use of “hybrid” shared secrets of the form Z' = Z || T,
* which is 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."
*
* https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Cr2.pdf
*/
if (hybrid_group->send_kem_first) {
RESULT_GUARD(s2n_fips_validate_kem(hybrid_group->kem, valid));
} else {
RESULT_GUARD(s2n_fips_validate_curve(hybrid_group->curve, valid));
}

return S2N_RESULT_OK;
}

S2N_RESULT s2n_fips_validate_version(uint8_t version, bool *valid)
{
RESULT_ENSURE_REF(valid);
Expand Down
44 changes: 42 additions & 2 deletions tests/unit/s2n_security_rules_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,19 @@ static S2N_RESULT s2n_test_curve_rule(const struct s2n_ecc_named_curve *curve, b
return S2N_RESULT_OK;
}

const struct s2n_kem_group *VALID_HYBRID_GROUP = &s2n_secp256r1_mlkem_768;
const struct s2n_kem_group *EXAMPLE_INVALID_HYBRID_GROUP = &s2n_x25519_kyber_512_r3;
static S2N_RESULT s2n_test_hybrid_group_rule(const struct s2n_kem_group *hybrid_group, bool *valid)
{
RESULT_ENSURE_REF(valid);
if (hybrid_group == VALID_HYBRID_GROUP) {
*valid = true;
} else {
*valid = false;
}
return S2N_RESULT_OK;
}

const uint8_t VALID_VERSION = S2N_TLS12;
const uint8_t EXAMPLE_INVALID_VERSION = S2N_TLS11;
static S2N_RESULT s2n_test_version(uint8_t version, bool *valid)
Expand All @@ -86,6 +99,7 @@ int main(int argc, char **argv)
.validate_sig_scheme = s2n_test_sig_scheme_rule,
.validate_cert_sig_scheme = s2n_test_sig_scheme_rule,
.validate_curve = s2n_test_curve_rule,
.validate_hybrid_group = s2n_test_hybrid_group_rule,
.validate_version = s2n_test_version,
};

Expand Down Expand Up @@ -121,20 +135,35 @@ int main(int argc, char **argv)
.count = 1,
};

const struct s2n_kem_preferences valid_kem_preferences = {
.kem_count = 0,
.kems = NULL,
.tls13_kem_groups = &VALID_HYBRID_GROUP,
.tls13_kem_group_count = 1,
};

const struct s2n_kem_preferences invalid_kem_preferences = {
.kem_count = 0,
.kems = NULL,
.tls13_kem_groups = &EXAMPLE_INVALID_HYBRID_GROUP,
.tls13_kem_group_count = 1,
};

const struct s2n_security_policy valid_policy = {
.cipher_preferences = &valid_cipher_prefs,
.signature_preferences = &valid_sig_prefs,
.certificate_signature_preferences = &valid_sig_prefs,
.ecc_preferences = &valid_ecc_prefs,
.kem_preferences = &kem_preferences_null,
.kem_preferences = &valid_kem_preferences,
.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,
.kem_preferences = &invalid_kem_preferences,
.minimum_protocol_version = EXAMPLE_INVALID_VERSION,
};

Expand Down Expand Up @@ -202,6 +231,17 @@ int main(int argc, char **argv)
EXPECT_TRUE(result.found_error);
};

/* Test: only hybrid group invalid */
{
struct s2n_security_policy test_policy = valid_policy;
test_policy.kem_preferences = &invalid_kem_preferences;

struct s2n_security_rule_result result = { 0 };
EXPECT_OK(s2n_security_rule_validate_policy(
&test_rule, &test_policy, &result));
EXPECT_TRUE(result.found_error);
};

/* Test: only version invalid */
{
struct s2n_security_policy test_policy = valid_policy;
Expand Down
19 changes: 14 additions & 5 deletions tls/s2n_security_rules.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ static S2N_RESULT s2n_security_rule_all_curves(
return S2N_RESULT_OK;
}

static S2N_RESULT s2n_security_rule_all_hybrid_groups(
const struct s2n_kem_group *hybrid_group, bool *valid)
{
RESULT_ENSURE_REF(valid);
*valid = true;
return S2N_RESULT_OK;
}

static S2N_RESULT s2n_security_rule_all_versions(uint8_t version, bool *valid)
{
RESULT_ENSURE_REF(valid);
Expand All @@ -84,6 +92,7 @@ const struct s2n_security_rule security_rule_definitions[S2N_SECURITY_RULES_COUN
.validate_sig_scheme = s2n_security_rule_all_sig_schemes,
.validate_cert_sig_scheme = s2n_security_rule_all_sig_schemes,
.validate_curve = s2n_security_rule_all_curves,
.validate_hybrid_group = s2n_security_rule_all_hybrid_groups,
.validate_version = s2n_security_rule_all_versions,
},
[S2N_FIPS_140_3] = {
Expand All @@ -92,6 +101,7 @@ const struct s2n_security_rule security_rule_definitions[S2N_SECURITY_RULES_COUN
.validate_sig_scheme = s2n_fips_validate_signature_scheme,
.validate_cert_sig_scheme = s2n_fips_validate_signature_scheme,
.validate_curve = s2n_fips_validate_curve,
.validate_hybrid_group = s2n_fips_validate_hybrid_group,
.validate_version = s2n_fips_validate_version,
},
};
Expand Down Expand Up @@ -169,14 +179,13 @@ S2N_RESULT s2n_security_rule_validate_policy(const struct s2n_security_rule *rul
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;
RESULT_ENSURE_REF(curve);
RESULT_ENSURE_REF(kem_group);
bool is_valid = false;
RESULT_ENSURE_REF(rule->validate_curve);
RESULT_GUARD(rule->validate_curve(curve, &is_valid));
RESULT_ENSURE_REF(rule->validate_hybrid_group);
RESULT_GUARD(rule->validate_hybrid_group(kem_group, &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));
"kem_group", kem_group->name, i + 1));
}

bool is_valid = false;
Expand Down
2 changes: 2 additions & 0 deletions tls/s2n_security_rules.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#pragma once

#include "stuffer/s2n_stuffer.h"
#include "tls/s2n_kem.h"
#include "utils/s2n_result.h"

typedef enum {
Expand Down Expand Up @@ -43,6 +44,7 @@ struct s2n_security_rule {
S2N_RESULT (*validate_sig_scheme)(const struct s2n_signature_scheme *sig_scheme, bool *valid);
S2N_RESULT (*validate_cert_sig_scheme)(const struct s2n_signature_scheme *sig_scheme, bool *valid);
S2N_RESULT (*validate_curve)(const struct s2n_ecc_named_curve *curve, bool *valid);
S2N_RESULT (*validate_hybrid_group)(const struct s2n_kem_group *hybrid_group, bool *valid);
S2N_RESULT (*validate_version)(uint8_t version, bool *valid);
};

Expand Down
Loading