use ese_core::{verify_page_checksum, ChecksumResult, PAGE_SIZE};
fn make_page_with_correct_xor(payload: &[u8]) -> Vec<u8> {
let mut page = vec![0u8; PAGE_SIZE];
let len = payload.len().min(PAGE_SIZE - 8);
page[8..8 + len].copy_from_slice(&payload[..len]);
let seed: u32 = 0x89AB_CDEF;
let mut csum = seed;
for chunk in page[4..].chunks_exact(4) {
csum ^= u32::from_le_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]);
}
page[0..4].copy_from_slice(&csum.to_le_bytes());
page
}
fn make_page_with_wrong_xor() -> Vec<u8> {
let mut page = vec![0u8; PAGE_SIZE];
page[0..4].copy_from_slice(&0xDEAD_BEEFu32.to_le_bytes()); page[8] = 0x01; page
}
#[test]
fn verify_page_checksum_valid_for_correct_legacy_xor() {
let page = make_page_with_correct_xor(&[0xAA, 0xBB, 0xCC, 0xDD]);
let result = verify_page_checksum(&page, 1);
assert!(
matches!(result, ChecksumResult::Valid),
"correctly-computed XOR must return Valid, got {result:?}"
);
}
#[test]
fn verify_page_checksum_mismatch_for_wrong_xor() {
let page = make_page_with_wrong_xor();
let result = verify_page_checksum(&page, 2);
assert!(
matches!(result, ChecksumResult::LegacyXorMismatch { .. }),
"wrong XOR must return LegacyXorMismatch, got {result:?}"
);
}
#[test]
fn verify_page_checksum_mismatch_carries_values() {
let page = make_page_with_wrong_xor();
let result = verify_page_checksum(&page, 3);
if let ChecksumResult::LegacyXorMismatch { stored, computed } = result {
assert_eq!(stored, 0xDEAD_BEEF);
assert_ne!(computed, stored, "computed must differ from stored");
} else {
panic!("expected LegacyXorMismatch, got {result:?}");
}
}
#[test]
fn verify_page_checksum_unchecked_for_zero_stored() {
let page = vec![0u8; PAGE_SIZE]; let result = verify_page_checksum(&page, 4);
assert!(
matches!(result, ChecksumResult::Unknown),
"all-zero page must return Unknown, got {result:?}"
);
}
fn make_tampered_ecc_page() -> Vec<u8> {
let mut page = vec![0u8; PAGE_SIZE];
for i in (8..PAGE_SIZE).step_by(4) {
page[i] = 0x42;
}
let seed: u32 = 0x89AB_CDEF;
let mut xor_csum = seed;
for chunk in page[8..].chunks_exact(4) {
xor_csum ^= u32::from_le_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]);
}
let ecc = compute_ecc(&page[8..]);
page[0..4].copy_from_slice(&xor_csum.to_le_bytes());
page[4..8].copy_from_slice(&ecc.to_le_bytes());
page[8] ^= 0xFF;
page
}
fn compute_ecc(data: &[u8]) -> u32 {
let mut ecc: u32 = 0;
for (i, chunk) in data.chunks_exact(4).enumerate() {
let word = u32::from_le_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]);
ecc ^= word.rotate_left((i % 32) as u32);
}
ecc
}
#[test]
fn verify_page_checksum_ecc_mismatch_for_tampered_vista_page() {
let page = make_tampered_ecc_page();
let result = verify_page_checksum(&page, 5);
assert!(
matches!(result, ChecksumResult::EccMismatch),
"tampered ECC page must return EccMismatch, got {result:?}"
);
}