diff --git a/include/mls/crypto.h b/include/mls/crypto.h index 16aefaab..6d54db51 100644 --- a/include/mls/crypto.h +++ b/include/mls/crypto.h @@ -52,6 +52,9 @@ struct CipherSuite P521_AES256GCM_SHA512_P521 = 0x0005, X448_CHACHA20POLY1305_SHA512_Ed448 = 0x0006, P384_AES256GCM_SHA384_P384 = 0x0007, + MLKEM768X25519_AES256GCM_SHA384_Ed25519 = 0x0008, + MLKEM768P256_AES256GCM_SHA384_P256 = 0x0009, + MLKEM1024P384_AES256GCM_SHA384_P384 = 0x000a, // GREASE values, included here mainly so that debugger output looks nice GREASE_0 = 0x0A0A, @@ -133,12 +136,23 @@ struct CipherSuite static const bytes& reference_label(); }; -#if WITH_BORINGSSL -extern const std::array all_supported_suites; +#if defined(WITH_BORINGSSL) +static constexpr size_t n_supported_x448_suites = 0; #else -extern const std::array all_supported_suites; +static constexpr size_t n_supported_x448_suites = 2; #endif +#if defined(WITH_PQ) +static constexpr size_t n_supported_pq_suites = 3; +#else +static constexpr size_t n_supported_pq_suites = 0; +#endif + +static constexpr size_t n_supported_suites = + 5 + n_supported_x448_suites + n_supported_pq_suites; +extern const std::array + all_supported_cipher_suites; + // Utilities using MLS_NAMESPACE::hpke::random_bytes; diff --git a/src/core_types.cpp b/src/core_types.cpp index a1774400..f02a2ba6 100644 --- a/src/core_types.cpp +++ b/src/core_types.cpp @@ -1,4 +1,5 @@ #include "mls/core_types.h" +#include "mls/crypto.h" #include "mls/messages.h" #include @@ -37,15 +38,6 @@ const std::array all_supported_versions = { ProtocolVersion::mls10 }; -const std::array all_supported_ciphersuites = { - CipherSuite::ID::X25519_AES128GCM_SHA256_Ed25519, - CipherSuite::ID::P256_AES128GCM_SHA256_P256, - CipherSuite::ID::X25519_CHACHA20POLY1305_SHA256_Ed25519, - CipherSuite::ID::X448_AES256GCM_SHA512_Ed448, - CipherSuite::ID::P521_AES256GCM_SHA512_P521, - CipherSuite::ID::X448_CHACHA20POLY1305_SHA512_Ed448, -}; - const std::array all_supported_credentials = { CredentialType::basic, CredentialType::x509, @@ -58,7 +50,7 @@ Capabilities::create_default() { return { { all_supported_versions.begin(), all_supported_versions.end() }, - { all_supported_ciphersuites.begin(), all_supported_ciphersuites.end() }, + { all_supported_cipher_suites.begin(), all_supported_cipher_suites.end() }, { /* No non-default extensions */ }, { /* No non-default proposals */ }, { all_supported_credentials.begin(), all_supported_credentials.end() }, diff --git a/src/crypto.cpp b/src/crypto.cpp index 8d859c0e..5b4fe851 100644 --- a/src/crypto.cpp +++ b/src/crypto.cpp @@ -130,7 +130,32 @@ CipherSuite::get() const Digest::get(), Signature::get(), }; -#endif +#endif // !defined(WITH_BORINGSSL) + +#if defined(WITH_PQ) + static const auto ciphers_MLKEM768X25519_AES256GCM_SHA384_Ed25519 = + CipherSuite::Ciphers{ + HPKE( + KEM::ID::MLKEM768_X25519, KDF::ID::HKDF_SHA384, AEAD::ID::AES_256_GCM), + Digest::get(), + Signature::get(), + }; + + static const auto ciphers_MLKEM768P256_AES256GCM_SHA384_P256 = + CipherSuite::Ciphers{ + HPKE(KEM::ID::MLKEM768_P256, KDF::ID::HKDF_SHA384, AEAD::ID::AES_256_GCM), + Digest::get(), + Signature::get(), + }; + + static const auto ciphers_MLKEM1024P384_AES256GCM_SHA384_P384 = + CipherSuite::Ciphers{ + HPKE( + KEM::ID::MLKEM1024_P384, KDF::ID::HKDF_SHA384, AEAD::ID::AES_256_GCM), + Digest::get(), + Signature::get(), + }; +#endif // defined(WITH_PQ) switch (id) { case ID::unknown: @@ -159,6 +184,17 @@ CipherSuite::get() const return ciphers_X448_CHACHA20POLY1305_SHA512_Ed448; #endif +#if !defined(P256_SHA256) + case ID::MLKEM768X25519_AES256GCM_SHA384_Ed25519: + return ciphers_MLKEM768X25519_AES256GCM_SHA384_Ed25519; + + case ID::MLKEM768P256_AES256GCM_SHA384_P256: + return ciphers_MLKEM768P256_AES256GCM_SHA384_P256; + + case ID::MLKEM1024P384_AES256GCM_SHA384_P384: + return ciphers_MLKEM1024P384_AES256GCM_SHA384_P384; +#endif + default: throw InvalidParameterError("Unsupported ciphersuite"); } @@ -200,25 +236,23 @@ CipherSuite::derive_tree_secret(const bytes& secret, return expand_with_label(secret, label, tls::marshal(generation), length); } -#if WITH_BORINGSSL -const std::array all_supported_suites = { - CipherSuite::ID::X25519_AES128GCM_SHA256_Ed25519, - CipherSuite::ID::P256_AES128GCM_SHA256_P256, - CipherSuite::ID::X25519_CHACHA20POLY1305_SHA256_Ed25519, - CipherSuite::ID::P521_AES256GCM_SHA512_P521, - CipherSuite::ID::P384_AES256GCM_SHA384_P384, -}; -#else -const std::array all_supported_suites = { - CipherSuite::ID::X25519_AES128GCM_SHA256_Ed25519, - CipherSuite::ID::P256_AES128GCM_SHA256_P256, - CipherSuite::ID::X25519_CHACHA20POLY1305_SHA256_Ed25519, - CipherSuite::ID::P521_AES256GCM_SHA512_P521, - CipherSuite::ID::P384_AES256GCM_SHA384_P384, - CipherSuite::ID::X448_CHACHA20POLY1305_SHA512_Ed448, - CipherSuite::ID::X448_AES256GCM_SHA512_Ed448, -}; +const std::array + all_supported_cipher_suites = { + CipherSuite::ID::X25519_AES128GCM_SHA256_Ed25519, + CipherSuite::ID::P256_AES128GCM_SHA256_P256, + CipherSuite::ID::X25519_CHACHA20POLY1305_SHA256_Ed25519, + CipherSuite::ID::P521_AES256GCM_SHA512_P521, + CipherSuite::ID::P384_AES256GCM_SHA384_P384, +#if !defined(WITH_BORINGSSL) + CipherSuite::ID::X448_CHACHA20POLY1305_SHA512_Ed448, + CipherSuite::ID::X448_AES256GCM_SHA512_Ed448, #endif +#if defined(WITH_PQ) + CipherSuite::ID::MLKEM768X25519_AES256GCM_SHA384_Ed25519, + CipherSuite::ID::MLKEM768P256_AES256GCM_SHA384_P256, + CipherSuite::ID::MLKEM1024P384_AES256GCM_SHA384_P384, +#endif + }; // MakeKeyPackageRef(value) = KDF.expand( // KDF.extract("", value), "MLS 1.0 KeyPackage Reference", 16) diff --git a/src/state.cpp b/src/state.cpp index daddfdc6..ab5e911f 100644 --- a/src/state.cpp +++ b/src/state.cpp @@ -1847,8 +1847,8 @@ State::valid(const ReInit& reinit) { // Check that the version and CipherSuite are ones we support auto supported_version = (reinit.version == ProtocolVersion::mls10); - auto supported_suite = - stdx::contains(all_supported_suites, reinit.cipher_suite.cipher_suite()); + auto supported_suite = stdx::contains(all_supported_cipher_suites, + reinit.cipher_suite.cipher_suite()); return supported_version && supported_suite; } diff --git a/test/crypto.cpp b/test/crypto.cpp index 5666a6ea..5abde2a0 100644 --- a/test/crypto.cpp +++ b/test/crypto.cpp @@ -12,7 +12,7 @@ TEST_CASE("Basic HPKE") auto context = random_bytes(100); auto original = random_bytes(100); - for (auto suite_id : all_supported_suites) { + for (auto suite_id : all_supported_cipher_suites) { auto suite = CipherSuite{ suite_id }; auto s = bytes{ 0, 1, 2, 3 }; @@ -38,7 +38,7 @@ TEST_CASE("Basic HPKE") TEST_CASE("HPKE Key Serialization") { - for (auto suite_id : all_supported_suites) { + for (auto suite_id : all_supported_cipher_suites) { auto suite = CipherSuite{ suite_id }; auto x = HPKEPrivateKey::derive(suite, { 0, 1, 2, 3 }); auto gX = x.public_key; @@ -54,7 +54,7 @@ TEST_CASE("HPKE Key Serialization") TEST_CASE("Basic Signature") { - for (auto suite_id : all_supported_suites) { + for (auto suite_id : all_supported_cipher_suites) { auto suite = CipherSuite{ suite_id }; auto a = SignaturePrivateKey::generate(suite); auto b = SignaturePrivateKey::generate(suite); @@ -77,7 +77,7 @@ TEST_CASE("Basic Signature") TEST_CASE("Signature Key Serializion") { - for (auto suite_id : all_supported_suites) { + for (auto suite_id : all_supported_cipher_suites) { auto suite = CipherSuite{ suite_id }; auto x = SignaturePrivateKey::generate(suite); auto gX = x.public_key; @@ -92,7 +92,7 @@ TEST_CASE("Signature Key Serializion") TEST_CASE("Signature Key JWK Import/Export") { - for (auto suite_id : all_supported_suites) { + for (auto suite_id : all_supported_cipher_suites) { const auto suite = CipherSuite{ suite_id }; const auto priv = SignaturePrivateKey::generate(suite); const auto pub = priv.public_key; @@ -128,7 +128,7 @@ TEST_CASE("Signature Key JWK Import/Export") TEST_CASE("Crypto Interop") { - for (auto suite : all_supported_suites) { + for (auto suite : all_supported_cipher_suites) { auto tv = CryptoBasicsTestVector{ suite }; REQUIRE(tv.verify() == std::nullopt); } diff --git a/test/key_schedule.cpp b/test/key_schedule.cpp index a934af42..bb971721 100644 --- a/test/key_schedule.cpp +++ b/test/key_schedule.cpp @@ -7,7 +7,7 @@ using namespace mls_vectors; TEST_CASE("Secret Tree Interop") { - for (auto suite : all_supported_suites) { + for (auto suite : all_supported_cipher_suites) { const auto tv = SecretTreeTestVector{ suite, 15, { 1, 10 } }; REQUIRE(tv.verify() == std::nullopt); } @@ -15,7 +15,7 @@ TEST_CASE("Secret Tree Interop") TEST_CASE("PSK Secret Interop") { - for (auto suite : all_supported_suites) { + for (auto suite : all_supported_cipher_suites) { const auto tv = PSKSecretTestVector{ suite, 5 }; REQUIRE(tv.verify() == std::nullopt); } @@ -23,7 +23,7 @@ TEST_CASE("PSK Secret Interop") TEST_CASE("Key Schedule Interop") { - for (auto suite : all_supported_suites) { + for (auto suite : all_supported_cipher_suites) { auto tv = KeyScheduleTestVector{ suite, 15 }; REQUIRE(tv.verify() == std::nullopt); } diff --git a/test/messages.cpp b/test/messages.cpp index a2f514fa..9df77770 100644 --- a/test/messages.cpp +++ b/test/messages.cpp @@ -162,7 +162,7 @@ TEST_CASE("Messages Interop") TEST_CASE("Message Protection Interop") { - for (auto suite : all_supported_suites) { + for (auto suite : all_supported_cipher_suites) { auto tv = MessageProtectionTestVector{ suite }; REQUIRE(tv.verify() == std::nullopt); } diff --git a/test/treekem.cpp b/test/treekem.cpp index dae3aaa1..6bf18ea5 100644 --- a/test/treekem.cpp +++ b/test/treekem.cpp @@ -299,7 +299,7 @@ TEST_CASE_METHOD(TreeKEMTest, "TreeKEM encap/decap") TEST_CASE("TreeKEM Interop", "[.][all]") { - for (auto suite : all_supported_suites) { + for (auto suite : all_supported_cipher_suites) { for (auto structure : treekem_test_tree_structures) { auto tv = TreeKEMTestVector{ suite, structure }; REQUIRE(tv.verify() == std::nullopt);