#![cfg(mlkem)]
mod common;
use wolfcrypt_wrapper::mlkem::MlKem;
#[cfg(random)]
use wolfcrypt_wrapper::random::RNG;
#[test]
fn test_type_constants() {
assert_eq!(MlKem::TYPE_512, 0);
assert_eq!(MlKem::TYPE_768, 1);
assert_eq!(MlKem::TYPE_1024, 2);
}
#[test]
fn test_shared_constants() {
assert_eq!(MlKem::SYM_SIZE, 32);
assert_eq!(MlKem::SHARED_SECRET_SIZE, 32);
assert_eq!(MlKem::MAKEKEY_RAND_SIZE, 64);
assert_eq!(MlKem::ENC_RAND_SIZE, 32);
}
#[test]
fn test_new() {
common::setup();
MlKem::new(MlKem::TYPE_512).expect("Error with new() TYPE_512");
MlKem::new(MlKem::TYPE_768).expect("Error with new() TYPE_768");
MlKem::new(MlKem::TYPE_1024).expect("Error with new() TYPE_1024");
}
#[test]
fn test_new_ex() {
common::setup();
MlKem::new_ex(MlKem::TYPE_768, None, None).expect("Error with new_ex()");
}
#[test]
fn test_size_queries() {
common::setup();
for key_type in [MlKem::TYPE_512, MlKem::TYPE_768, MlKem::TYPE_1024] {
let key = MlKem::new(key_type).expect("Error with new()");
let pub_size = key.public_key_size().expect("Error with public_key_size()");
let priv_size = key
.private_key_size()
.expect("Error with private_key_size()");
let ct_size = key
.cipher_text_size()
.expect("Error with cipher_text_size()");
let ss_size = key
.shared_secret_size()
.expect("Error with shared_secret_size()");
assert!(
pub_size > 0,
"public_key_size must be positive for key_type {}",
key_type
);
assert!(
priv_size > 0,
"private_key_size must be positive for key_type {}",
key_type
);
assert!(
ct_size > 0,
"cipher_text_size must be positive for key_type {}",
key_type
);
assert_eq!(
ss_size,
MlKem::SHARED_SECRET_SIZE,
"shared_secret_size must equal SHARED_SECRET_SIZE for key_type {}",
key_type
);
}
}
#[test]
#[cfg(random)]
fn test_encap_decap_type512() {
common::setup();
let mut rng = RNG::new().expect("Error creating RNG");
let mut key =
MlKem::generate(MlKem::TYPE_512, &mut rng).expect("Error with generate() TYPE_512");
let ct_size = key
.cipher_text_size()
.expect("Error with cipher_text_size()");
let ss_size = key
.shared_secret_size()
.expect("Error with shared_secret_size()");
let mut ct = vec![0u8; ct_size];
let mut ss_enc = vec![0u8; ss_size];
key.encapsulate(&mut ct, &mut ss_enc, &mut rng)
.expect("Error with encapsulate()");
let mut ss_dec = vec![0u8; ss_size];
key.decapsulate(&mut ss_dec, &ct)
.expect("Error with decapsulate()");
assert_eq!(
ss_enc, ss_dec,
"Shared secrets must match after encap/decap"
);
}
#[test]
#[cfg(random)]
fn test_encap_decap_type768() {
common::setup();
let mut rng = RNG::new().expect("Error creating RNG");
let mut key =
MlKem::generate(MlKem::TYPE_768, &mut rng).expect("Error with generate() TYPE_768");
let ct_size = key
.cipher_text_size()
.expect("Error with cipher_text_size()");
let ss_size = key
.shared_secret_size()
.expect("Error with shared_secret_size()");
let mut ct = vec![0u8; ct_size];
let mut ss_enc = vec![0u8; ss_size];
key.encapsulate(&mut ct, &mut ss_enc, &mut rng)
.expect("Error with encapsulate()");
let mut ss_dec = vec![0u8; ss_size];
key.decapsulate(&mut ss_dec, &ct)
.expect("Error with decapsulate()");
assert_eq!(
ss_enc, ss_dec,
"Shared secrets must match after encap/decap"
);
let mut ct_tampered = ct.clone();
ct_tampered[0] ^= 0xFF;
let mut ss_tampered = vec![0u8; ss_size];
key.decapsulate(&mut ss_tampered, &ct_tampered)
.expect("Error with decapsulate() on tampered ct");
assert_ne!(
ss_enc, ss_tampered,
"Tampered ct must yield different shared secret"
);
}
#[test]
#[cfg(random)]
fn test_encap_decap_type1024() {
common::setup();
let mut rng = RNG::new().expect("Error creating RNG");
let mut key =
MlKem::generate(MlKem::TYPE_1024, &mut rng).expect("Error with generate() TYPE_1024");
let ct_size = key
.cipher_text_size()
.expect("Error with cipher_text_size()");
let ss_size = key
.shared_secret_size()
.expect("Error with shared_secret_size()");
let mut ct = vec![0u8; ct_size];
let mut ss_enc = vec![0u8; ss_size];
key.encapsulate(&mut ct, &mut ss_enc, &mut rng)
.expect("Error with encapsulate()");
let mut ss_dec = vec![0u8; ss_size];
key.decapsulate(&mut ss_dec, &ct)
.expect("Error with decapsulate()");
assert_eq!(
ss_enc, ss_dec,
"Shared secrets must match after encap/decap"
);
}
#[test]
fn test_generate_with_random_determinism() {
common::setup();
let rand = [0x42u8; 64];
let key1 = MlKem::generate_with_random(MlKem::TYPE_768, &rand)
.expect("Error with generate_with_random() first call");
let key2 = MlKem::generate_with_random(MlKem::TYPE_768, &rand)
.expect("Error with generate_with_random() second call");
let pub_size = key1
.public_key_size()
.expect("Error with public_key_size()");
let mut pub1 = vec![0u8; pub_size];
let mut pub2 = vec![0u8; pub_size];
key1.encode_public_key(&mut pub1)
.expect("Error with encode_public_key() key1");
key2.encode_public_key(&mut pub2)
.expect("Error with encode_public_key() key2");
assert_eq!(pub1, pub2, "Same random must yield same public key");
let priv_size = key1
.private_key_size()
.expect("Error with private_key_size()");
let mut priv1 = vec![0u8; priv_size];
let mut priv2 = vec![0u8; priv_size];
key1.encode_private_key(&mut priv1)
.expect("Error with encode_private_key() key1");
key2.encode_private_key(&mut priv2)
.expect("Error with encode_private_key() key2");
assert_eq!(priv1, priv2, "Same random must yield same private key");
}
#[test]
fn test_encapsulate_with_random_determinism() {
common::setup();
let key_rand = [0x11u8; 64];
let enc_rand = [0x22u8; 32];
let mut key = MlKem::generate_with_random(MlKem::TYPE_768, &key_rand)
.expect("Error with generate_with_random()");
let ct_size = key
.cipher_text_size()
.expect("Error with cipher_text_size()");
let ss_size = key
.shared_secret_size()
.expect("Error with shared_secret_size()");
let mut ct1 = vec![0u8; ct_size];
let mut ss1 = vec![0u8; ss_size];
key.encapsulate_with_random(&mut ct1, &mut ss1, &enc_rand)
.expect("Error with encapsulate_with_random() first call");
let mut ct2 = vec![0u8; ct_size];
let mut ss2 = vec![0u8; ss_size];
key.encapsulate_with_random(&mut ct2, &mut ss2, &enc_rand)
.expect("Error with encapsulate_with_random() second call");
assert_eq!(ct1, ct2, "Same inputs must yield same cipher text");
assert_eq!(ss1, ss2, "Same inputs must yield same shared secret");
let mut ss_dec = vec![0u8; ss_size];
key.decapsulate(&mut ss_dec, &ct1)
.expect("Error with decapsulate()");
assert_eq!(
ss1, ss_dec,
"Shared secret from encapsulate must match decapsulate"
);
}
#[test]
#[cfg(random)]
fn test_encode_decode_public_key() {
common::setup();
let mut rng = RNG::new().expect("Error creating RNG");
let mut key = MlKem::generate(MlKem::TYPE_768, &mut rng).expect("Error with generate()");
let pub_size = key.public_key_size().expect("Error with public_key_size()");
let ct_size = key
.cipher_text_size()
.expect("Error with cipher_text_size()");
let ss_size = key
.shared_secret_size()
.expect("Error with shared_secret_size()");
let mut pub_buf = vec![0u8; pub_size];
let written = key
.encode_public_key(&mut pub_buf)
.expect("Error with encode_public_key()");
assert_eq!(written, pub_size);
let mut pub_key = MlKem::new(MlKem::TYPE_768).expect("Error with new()");
pub_key
.decode_public_key(&pub_buf)
.expect("Error with decode_public_key()");
let mut ct = vec![0u8; ct_size];
let mut ss_enc = vec![0u8; ss_size];
pub_key
.encapsulate(&mut ct, &mut ss_enc, &mut rng)
.expect("Error with encapsulate() via imported public key");
let mut ss_dec = vec![0u8; ss_size];
key.decapsulate(&mut ss_dec, &ct)
.expect("Error with decapsulate()");
assert_eq!(
ss_enc, ss_dec,
"Shared secrets must match after public key import"
);
}
#[test]
#[cfg(random)]
fn test_encode_decode_private_key() {
common::setup();
let mut rng = RNG::new().expect("Error creating RNG");
let mut key = MlKem::generate(MlKem::TYPE_768, &mut rng).expect("Error with generate()");
let priv_size = key
.private_key_size()
.expect("Error with private_key_size()");
let ct_size = key
.cipher_text_size()
.expect("Error with cipher_text_size()");
let ss_size = key
.shared_secret_size()
.expect("Error with shared_secret_size()");
let mut priv_buf = vec![0u8; priv_size];
let written = key
.encode_private_key(&mut priv_buf)
.expect("Error with encode_private_key()");
assert_eq!(written, priv_size);
let mut ct = vec![0u8; ct_size];
let mut ss_enc = vec![0u8; ss_size];
key.encapsulate(&mut ct, &mut ss_enc, &mut rng)
.expect("Error with encapsulate()");
let mut priv_key = MlKem::new(MlKem::TYPE_768).expect("Error with new()");
priv_key
.decode_private_key(&priv_buf)
.expect("Error with decode_private_key()");
let mut ss_dec = vec![0u8; ss_size];
priv_key
.decapsulate(&mut ss_dec, &ct)
.expect("Error with decapsulate() via imported private key");
assert_eq!(
ss_enc, ss_dec,
"Shared secrets must match after private key import"
);
}
#[test]
#[cfg(random)]
fn test_encap_decap_all_types() {
common::setup();
let mut rng = RNG::new().expect("Error creating RNG");
for key_type in [MlKem::TYPE_512, MlKem::TYPE_768, MlKem::TYPE_1024] {
let mut key = MlKem::generate(key_type, &mut rng).expect("Error with generate()");
let ct_size = key
.cipher_text_size()
.expect("Error with cipher_text_size()");
let ss_size = key
.shared_secret_size()
.expect("Error with shared_secret_size()");
let mut ct = vec![0u8; ct_size];
let mut ss_enc = vec![0u8; ss_size];
key.encapsulate(&mut ct, &mut ss_enc, &mut rng)
.expect("Error with encapsulate()");
let mut ss_dec = vec![0u8; ss_size];
key.decapsulate(&mut ss_dec, &ct)
.expect("Error with decapsulate()");
assert_eq!(
ss_enc, ss_dec,
"Shared secrets must match for key_type {}",
key_type
);
assert_eq!(
ss_size,
MlKem::SHARED_SECRET_SIZE,
"Shared secret size must equal SHARED_SECRET_SIZE for key_type {}",
key_type
);
}
}