#![allow(missing_docs)]
use rustls::{CipherSuite, NamedGroup, SignatureScheme};
pub mod named_groups {
use rustls::NamedGroup;
pub const MLKEM512: NamedGroup = NamedGroup::Unknown(0x0200);
pub const MLKEM768: NamedGroup = NamedGroup::Unknown(0x0201);
pub const MLKEM1024: NamedGroup = NamedGroup::Unknown(0x0202);
}
pub mod signature_schemes {
use rustls::SignatureScheme;
pub const MLDSA44: SignatureScheme = SignatureScheme::ML_DSA_44;
pub const MLDSA65: SignatureScheme = SignatureScheme::ML_DSA_65;
pub const MLDSA87: SignatureScheme = SignatureScheme::ML_DSA_87;
}
pub struct Tls13Aes128GcmSha256MlKem768;
impl Tls13Aes128GcmSha256MlKem768 {
pub fn suite(&self) -> CipherSuite {
CipherSuite::TLS13_AES_128_GCM_SHA256
}
pub fn key_exchange_groups(&self) -> Vec<NamedGroup> {
vec![named_groups::MLKEM768, named_groups::MLKEM1024]
}
}
pub struct Tls13Aes256GcmSha384MlKem1024;
impl Tls13Aes256GcmSha384MlKem1024 {
pub fn suite(&self) -> CipherSuite {
CipherSuite::TLS13_AES_256_GCM_SHA384
}
pub fn key_exchange_groups(&self) -> Vec<NamedGroup> {
vec![named_groups::MLKEM1024]
}
}
pub struct Tls13ChaCha20Poly1305Sha256MlKem768;
impl Tls13ChaCha20Poly1305Sha256MlKem768 {
pub fn suite(&self) -> CipherSuite {
CipherSuite::TLS13_CHACHA20_POLY1305_SHA256
}
pub fn key_exchange_groups(&self) -> Vec<NamedGroup> {
vec![named_groups::MLKEM768, named_groups::MLKEM1024]
}
}
pub static TLS13_AES_128_GCM_SHA256_MLKEM768: Tls13Aes128GcmSha256MlKem768 =
Tls13Aes128GcmSha256MlKem768;
pub static TLS13_AES_256_GCM_SHA384_MLKEM1024: Tls13Aes256GcmSha384MlKem1024 =
Tls13Aes256GcmSha384MlKem1024;
pub static TLS13_CHACHA20_POLY1305_SHA256_MLKEM768: Tls13ChaCha20Poly1305Sha256MlKem768 =
Tls13ChaCha20Poly1305Sha256MlKem768;
pub fn is_pqc_group(group: NamedGroup) -> bool {
matches!(
group,
named_groups::MLKEM512 | named_groups::MLKEM768 | named_groups::MLKEM1024
)
}
pub fn is_pqc_signature(scheme: SignatureScheme) -> bool {
matches!(
scheme,
signature_schemes::MLDSA44 | signature_schemes::MLDSA65 | signature_schemes::MLDSA87
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_pqc_group_detection() {
assert!(is_pqc_group(named_groups::MLKEM512));
assert!(is_pqc_group(named_groups::MLKEM768));
assert!(is_pqc_group(named_groups::MLKEM1024));
assert!(!is_pqc_group(NamedGroup::X25519));
assert!(!is_pqc_group(NamedGroup::Unknown(0x0017))); }
#[test]
fn test_pqc_signature_detection() {
assert!(is_pqc_signature(signature_schemes::MLDSA44));
assert!(is_pqc_signature(signature_schemes::MLDSA65));
assert!(is_pqc_signature(signature_schemes::MLDSA87));
assert!(!is_pqc_signature(SignatureScheme::ED25519));
assert!(!is_pqc_signature(SignatureScheme::ECDSA_NISTP256_SHA256));
}
#[test]
fn test_cipher_suite_properties() {
let suite = &TLS13_AES_128_GCM_SHA256_MLKEM768;
assert_eq!(suite.suite(), CipherSuite::TLS13_AES_128_GCM_SHA256);
let groups = suite.key_exchange_groups();
assert!(!groups.is_empty());
assert!(groups.iter().all(|&g| is_pqc_group(g)));
}
#[test]
fn test_named_group_codes() {
assert_eq!(u16::from(named_groups::MLKEM512), 0x0200);
assert_eq!(u16::from(named_groups::MLKEM768), 0x0201);
assert_eq!(u16::from(named_groups::MLKEM1024), 0x0202);
}
#[test]
fn test_signature_scheme_codes() {
assert_eq!(u16::from(signature_schemes::MLDSA44), 0x0904);
assert_eq!(u16::from(signature_schemes::MLDSA65), 0x0905);
assert_eq!(u16::from(signature_schemes::MLDSA87), 0x0906);
}
}