#![cfg(all(feature = "lms", wolfssl_lms))]
use wolfcrypt::lms::{LmsParams, LmsSigningKey, LmsVerifyingKey};
const TEST_PARAMS: LmsParams = LmsParams::L1_H5_W8;
#[test]
fn pub_len_is_nonzero() {
let result = LmsVerifyingKey::from_public_bytes(TEST_PARAMS, &[]);
assert!(result.is_err(), "empty public key should be rejected");
}
#[test]
fn wrong_pub_key_length_rejected() {
let result = LmsVerifyingKey::from_public_bytes(TEST_PARAMS, &[0x42]);
assert!(result.is_err(), "1-byte public key should be rejected");
let long = vec![0u8; 4096];
let result = LmsVerifyingKey::from_public_bytes(TEST_PARAMS, &long);
assert!(result.is_err(), "4096-byte public key should be rejected");
}
#[test]
fn params_constants_are_sensible() {
assert_eq!(LmsParams::L1_H5_W8.levels, 1);
assert_eq!(LmsParams::L1_H5_W8.height, 5);
assert_eq!(LmsParams::L1_H5_W8.winternitz, 8);
assert_eq!(LmsParams::L2_H5_W8.levels, 2);
assert_eq!(LmsParams::L2_H5_W8.height, 5);
assert_eq!(LmsParams::L2_H5_W8.winternitz, 8);
assert_eq!(LmsParams::L1_H10_W4.levels, 1);
assert_eq!(LmsParams::L1_H10_W4.height, 10);
assert_eq!(LmsParams::L1_H10_W4.winternitz, 4);
assert_eq!(LmsParams::L2_H10_W4.levels, 2);
assert_eq!(LmsParams::L2_H10_W4.height, 10);
assert_eq!(LmsParams::L2_H10_W4.winternitz, 4);
}
#[test]
fn verify_garbage_signature_fails() {
let sizes_to_try = [56, 60, 64, 48];
let mut key_opt = None;
for &size in &sizes_to_try {
let fake_pub = vec![0u8; size];
if let Ok(key) = LmsVerifyingKey::from_public_bytes(TEST_PARAMS, &fake_pub) {
key_opt = Some(key);
break;
}
}
if let Some(key) = key_opt {
let msg = b"test message";
let garbage_sig = vec![0xAA; 128];
let result = key.verify(msg, &garbage_sig);
assert!(result.is_err(), "garbage signature must not verify");
}
}
#[test]
fn params_equality() {
assert_eq!(LmsParams::L1_H5_W8, LmsParams::L1_H5_W8);
assert_ne!(LmsParams::L1_H5_W8, LmsParams::L2_H5_W8);
assert_ne!(LmsParams::L1_H5_W8, LmsParams::L1_H10_W4);
}
#[cfg(feature = "rand")]
mod signing {
use super::*;
use wolfcrypt::rand::WolfRng;
#[test]
fn sign_then_verify() {
let mut rng = WolfRng::new().expect("RNG init");
let mut sk = LmsSigningKey::generate(TEST_PARAMS, &mut rng).expect("keygen");
let msg = b"LMS round-trip test";
let sig = sk.sign(msg).expect("sign");
let pub_bytes = sk.export_public().expect("export pub");
let vk = LmsVerifyingKey::from_public_bytes(TEST_PARAMS, &pub_bytes).expect("import pub");
vk.verify(msg, &sig).expect("verify must succeed");
}
#[test]
fn verify_wrong_message_fails() {
let mut rng = WolfRng::new().expect("RNG init");
let mut sk = LmsSigningKey::generate(TEST_PARAMS, &mut rng).expect("keygen");
let sig = sk.sign(b"correct message").expect("sign");
let pub_bytes = sk.export_public().expect("export pub");
let vk = LmsVerifyingKey::from_public_bytes(TEST_PARAMS, &pub_bytes).expect("import pub");
let result = vk.verify(b"wrong message", &sig);
assert!(result.is_err(), "wrong message must not verify");
}
#[test]
fn remaining_signatures_positive() {
let mut rng = WolfRng::new().expect("RNG init");
let sk = LmsSigningKey::generate(TEST_PARAMS, &mut rng).expect("keygen");
assert!(
sk.remaining_signatures() > 0,
"freshly generated key should have sigs left"
);
}
}