Skip to content

Commit

Permalink
Merge pull request #4393 from Rohde-Schwarz/tls/ml_kem
Browse files Browse the repository at this point in the history
PQC: Add TLS 1.3 groups for (pure) ML-KEM-512, -768 and -1024
  • Loading branch information
randombit authored Dec 24, 2024
2 parents ed5e77e + 143eadf commit 960fdcf
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 9 deletions.
17 changes: 17 additions & 0 deletions src/lib/tls/tls_algos.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,16 @@ std::optional<Group_Params> Group_Params::from_string(std::string_view group_nam
return Group_Params::KYBER_1024_R3_OQS;
}

if(group_name == "ML-KEM-512") {
return Group_Params::ML_KEM_512;
}
if(group_name == "ML-KEM-768") {
return Group_Params::ML_KEM_768;
}
if(group_name == "ML-KEM-1024") {
return Group_Params::ML_KEM_1024;
}

if(group_name == "eFrodoKEM-640-SHAKE") {
return Group_Params::eFRODOKEM_640_SHAKE_OQS;
}
Expand Down Expand Up @@ -311,6 +321,13 @@ std::optional<std::string> Group_Params::to_string() const {
case Group_Params::KYBER_1024_R3_OQS:
return "Kyber-1024-r3";

case Group_Params::ML_KEM_512:
return "ML-KEM-512";
case Group_Params::ML_KEM_768:
return "ML-KEM-768";
case Group_Params::ML_KEM_1024:
return "ML-KEM-1024";

case Group_Params::eFRODOKEM_640_SHAKE_OQS:
return "eFrodoKEM-640-SHAKE";
case Group_Params::eFRODOKEM_976_SHAKE_OQS:
Expand Down
22 changes: 16 additions & 6 deletions src/lib/tls/tls_algos.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ Auth_Method BOTAN_TEST_API auth_method_from_string(std::string_view str);

#define BOTAN_TLS_KYBER_R3_DEPRECATED \
BOTAN_DEPRECATED( \
"Kyber r3 TLS support will be removed completely in Botan 3.7.0 (early 2025) see https://github.com/randombit/botan/issues/4403")
"Kyber r3 TLS support will be removed completely in Botan 3.7.0 (early 2025) use ML-KEM and see https://github.com/randombit/botan/issues/4403")

/*
* Matches with wire encoding
Expand Down Expand Up @@ -108,11 +108,16 @@ enum class Group_Params_Code : uint16_t {
KYBER_768_R3_OQS BOTAN_TLS_KYBER_R3_DEPRECATED = 0x023C,
KYBER_1024_R3_OQS BOTAN_TLS_KYBER_R3_DEPRECATED = 0x023D,

eFRODOKEM_640_SHAKE_OQS = 0x0201,
// https://datatracker.ietf.org/doc/draft-connolly-tls-mlkem-key-agreement/05/
ML_KEM_512 = 0x0200,
ML_KEM_768 = 0x0201,
ML_KEM_1024 = 0x0202,

eFRODOKEM_640_SHAKE_OQS = 0xFE01,
eFRODOKEM_976_SHAKE_OQS = 0x0203,
eFRODOKEM_1344_SHAKE_OQS = 0x0205,
eFRODOKEM_640_AES_OQS = 0x0200,
eFRODOKEM_976_AES_OQS = 0x0202,
eFRODOKEM_640_AES_OQS = 0xFE00,
eFRODOKEM_976_AES_OQS = 0xFE02,
eFRODOKEM_1344_AES_OQS = 0x0204,

// Cloudflare code points for hybrid PQC
Expand Down Expand Up @@ -202,6 +207,11 @@ class BOTAN_PUBLIC_API(3, 2) Group_Params final {
m_code == Group_Params_Code::FFDHE_8192;
}

constexpr bool is_pure_ml_kem() const {
return m_code == Group_Params_Code::ML_KEM_512 || m_code == Group_Params_Code::ML_KEM_768 ||
m_code == Group_Params_Code::ML_KEM_1024;
}

BOTAN_TLS_KYBER_R3_DEPRECATED constexpr bool is_pure_kyber() const {
BOTAN_DIAGNOSTIC_PUSH
BOTAN_DIAGNOSTIC_IGNORE_DEPRECATED_DECLARATIONS
Expand All @@ -227,7 +237,7 @@ class BOTAN_PUBLIC_API(3, 2) Group_Params final {
BOTAN_DIAGNOSTIC_PUSH
BOTAN_DIAGNOSTIC_IGNORE_DEPRECATED_DECLARATIONS

return is_pure_kyber() || is_pure_frodokem() || is_pqc_hybrid();
return is_pure_kyber() || is_pure_ml_kem() || is_pure_frodokem() || is_pqc_hybrid();

BOTAN_DIAGNOSTIC_POP
}
Expand Down Expand Up @@ -264,7 +274,7 @@ class BOTAN_PUBLIC_API(3, 2) Group_Params final {
BOTAN_DIAGNOSTIC_PUSH
BOTAN_DIAGNOSTIC_IGNORE_DEPRECATED_DECLARATIONS

return is_pure_kyber() || is_pure_frodokem() || is_pqc_hybrid();
return is_pure_kyber() || is_pure_ml_kem() || is_pure_frodokem() || is_pqc_hybrid();

BOTAN_DIAGNOSTIC_POP
}
Expand Down
16 changes: 16 additions & 0 deletions src/lib/tls/tls_callbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@
#include <botan/kyber.h>
#endif

#if defined(BOTAN_HAS_ML_KEM)
#include <botan/ml_kem.h>
#endif

#if defined(BOTAN_HAS_FRODOKEM)
#include <botan/frodokem.h>
#endif
Expand Down Expand Up @@ -228,6 +232,12 @@ std::unique_ptr<Public_Key> TLS::Callbacks::tls_deserialize_peer_public_key(
}
#endif

#if defined(BOTAN_HAS_ML_KEM)
if(group_params.is_pure_ml_kem()) {
return std::make_unique<ML_KEM_PublicKey>(key_bits, ML_KEM_Mode(group_params.to_string().value()));
}
#endif

#if defined(BOTAN_HAS_KYBER)
if(group_params.is_pure_kyber()) {
return std::make_unique<Kyber_PublicKey>(key_bits, KyberMode(group_params.to_string().value()));
Expand All @@ -244,6 +254,12 @@ std::unique_ptr<Public_Key> TLS::Callbacks::tls_deserialize_peer_public_key(
}

std::unique_ptr<Private_Key> TLS::Callbacks::tls_kem_generate_key(TLS::Group_Params group, RandomNumberGenerator& rng) {
#if defined(BOTAN_HAS_ML_KEM)
if(group.is_pure_ml_kem()) {
return std::make_unique<ML_KEM_PrivateKey>(rng, ML_KEM_Mode(group.to_string().value()));
}
#endif

#if defined(BOTAN_HAS_KYBER)
if(group.is_pure_kyber()) {
return std::make_unique<Kyber_PrivateKey>(rng, KyberMode(group.to_string().value()));
Expand Down
12 changes: 9 additions & 3 deletions src/scripts/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -1350,14 +1350,20 @@ def get_oqs_rootca():
TestConfig("test.openquantumsafe.org", "secp256r1/Kyber-768-r3", port=oqsp['p256_kyber768'], ca=oqs_test_ca),
TestConfig("test.openquantumsafe.org", "secp384r1/Kyber-768-r3", port=oqsp['p384_kyber768'], ca=oqs_test_ca),
TestConfig("test.openquantumsafe.org", "secp521r1/Kyber-1024-r3", port=oqsp['p521_kyber1024'], ca=oqs_test_ca),
# Currently oqs did not adopt the 0x0200, 0x0201 and 0x0202 code point defined in draft-connolly-tls-mlkem-key-agreement-05.
# Neither did they deploy a new server that re-assigns the respective Frodo code points that used those before.
# TODO: enable those tests once the code point are re-assigned by the OQS test server
# TestConfig("test.openquantumsafe.org", "ML-KEM-512", port=oqsp['mlkem512'], ca=oqs_test_ca),
# TestConfig("test.openquantumsafe.org", "ML-KEM-768", port=oqsp['mlkem768'], ca=oqs_test_ca),
# TestConfig("test.openquantumsafe.org", "ML-KEM-1024", port=oqsp['mlkem1024'], ca=oqs_test_ca),
TestConfig("test.openquantumsafe.org", "Kyber-512-r3", port=oqsp['kyber512'], ca=oqs_test_ca),
TestConfig("test.openquantumsafe.org", "Kyber-768-r3", port=oqsp['kyber768'], ca=oqs_test_ca),
TestConfig("test.openquantumsafe.org", "Kyber-1024-r3", port=oqsp['kyber1024'], ca=oqs_test_ca),
TestConfig("test.openquantumsafe.org", "eFrodoKEM-640-SHAKE", port=oqsp['frodo640shake'], ca=oqs_test_ca),
# TestConfig("test.openquantumsafe.org", "eFrodoKEM-640-SHAKE", port=oqsp['frodo640shake'], ca=oqs_test_ca),
TestConfig("test.openquantumsafe.org", "eFrodoKEM-976-SHAKE", port=oqsp['frodo976shake'], ca=oqs_test_ca),
TestConfig("test.openquantumsafe.org", "eFrodoKEM-1344-SHAKE", port=oqsp['frodo1344shake'], ca=oqs_test_ca),
TestConfig("test.openquantumsafe.org", "eFrodoKEM-640-AES", port=oqsp['frodo640aes'], ca=oqs_test_ca),
TestConfig("test.openquantumsafe.org", "eFrodoKEM-976-AES", port=oqsp['frodo976aes'], ca=oqs_test_ca),
# TestConfig("test.openquantumsafe.org", "eFrodoKEM-640-AES", port=oqsp['frodo640aes'], ca=oqs_test_ca),
# TestConfig("test.openquantumsafe.org", "eFrodoKEM-976-AES", port=oqsp['frodo976aes'], ca=oqs_test_ca),
TestConfig("test.openquantumsafe.org", "eFrodoKEM-1344-AES", port=oqsp['frodo1344aes'], ca=oqs_test_ca),
TestConfig("test.openquantumsafe.org", "x25519/eFrodoKEM-640-SHAKE", port=oqsp['x25519_frodo640shake'], ca=oqs_test_ca),
TestConfig("test.openquantumsafe.org", "x25519/eFrodoKEM-640-AES", port=oqsp['x25519_frodo640aes'], ca=oqs_test_ca),
Expand Down

0 comments on commit 960fdcf

Please sign in to comment.