#[test]
fn suite_inventory_matches_docs() {
assert_eq!(ferritls_rustls::cipher::TLS13_SUITE_NAMES.len(), 4);
assert!(ferritls_rustls::cipher::TLS13_SUITE_NAMES.contains(&"TLS_AES_128_GCM_SHA256"));
assert!(ferritls_rustls::cipher::TLS13_SUITE_NAMES.contains(&"TLS_AES_256_GCM_SHA384"));
assert!(ferritls_rustls::cipher::TLS13_SUITE_NAMES.contains(&"TLS_CHACHA20_POLY1305_SHA256"));
assert!(ferritls_rustls::cipher::TLS13_SUITE_NAMES.contains(&"TLS_AES_128_CCM_SHA256"));
}
#[test]
fn kx_group_names_are_stable() {
use rustls::NamedGroup;
assert_eq!(ferritls_rustls::kx::X25519_GROUP.name(), NamedGroup::X25519);
assert_eq!(
ferritls_rustls::kx::SECP256R1_GROUP.name(),
NamedGroup::secp256r1
);
assert_eq!(
ferritls_rustls::kx::SECP384R1_GROUP.name(),
NamedGroup::secp384r1
);
assert_eq!(
ferritls_rustls::kx::X25519MLKEM768_GROUP.name(),
NamedGroup::X25519MLKEM768
);
assert_eq!(ferritls_rustls::kx::ALL_KX_GROUPS.len(), 4);
assert_eq!(ferritls_rustls::kx::FIPS_KX_GROUPS.len(), 3);
assert_eq!(
ferritls_rustls::kx::ALL_KX_GROUPS[0].name(),
NamedGroup::X25519MLKEM768
);
assert_eq!(
ferritls_rustls::kx::FIPS_KX_GROUPS[0].name(),
NamedGroup::X25519MLKEM768
);
}
#[test]
fn default_provider_smoke() {
let p = ferritls_rustls::default_provider();
assert!(!p.fips(), "认证前 fips() 必须为 false");
assert_eq!(p.cipher_suites.len(), 4);
assert_eq!(p.kx_groups.len(), 4);
}
#[test]
fn fips_mode_provider_smoke() {
let p = ferritls_rustls::fips_mode_provider();
assert!(!p.fips());
assert_eq!(p.cipher_suites.len(), 3, "批准模式无 ChaCha20-Poly1305");
assert_eq!(
p.kx_groups.len(),
3,
"批准模式:X25519MLKEM768 混合 + P-256/384,无独立 X25519"
);
}
#[test]
fn x25519_mlkem768_roundtrip_and_rejects() {
use rustls::crypto::CompletedKeyExchange;
let group = ferritls_rustls::kx::X25519MLKEM768_GROUP;
let client = group.start().expect("client start");
assert_eq!(client.pub_key().len(), 1184 + 32, "客户端 share 形状");
let server: CompletedKeyExchange = group
.start_and_complete(client.pub_key())
.expect("server start_and_complete");
assert_eq!(server.pub_key.len(), 1088 + 32, "服务端 share 形状");
let mut bad_share = client.pub_key().to_vec();
bad_share.pop();
assert!(group.start_and_complete(&bad_share).is_err());
let client2 = group.start().expect("client start 2");
let server2 = group
.start_and_complete(client2.pub_key())
.expect("server 2");
let mut short = server2.pub_key.clone();
short.pop();
assert!(client2.complete(&short).is_err());
let ss_client = client.complete(&server.pub_key).expect("client complete");
assert_eq!(ss_client.secret_bytes().len(), 64, "ss = ML-KEM ‖ X25519");
assert_eq!(
ss_client.secret_bytes(),
server.secret.secret_bytes(),
"两侧共享秘密一致"
);
}