use crate::{aes::testing, testing::Outcome};
use bolero::check;
use core::convert::TryInto;
macro_rules! impl_tests {
($name:ident, $test_vectors:expr) => {
mod $name {
use super::*;
use crate::aes::$name::KEY_LEN;
use hex_literal::hex;
use testing::$name::Implementation;
fn ensure_match(impls: &[Implementation], key: [u8; KEY_LEN], input: &[u8]) -> Vec<u8> {
let mut outcomes = vec![];
for imp in impls {
let key = imp.new(key);
let name = imp.name();
let mut output = input.to_vec();
key.encrypt(&mut output);
let outcome = Outcome {
name,
output: output.clone(),
};
outcomes.push(outcome);
key.decrypt(&mut output);
assert_eq!(&output[..], input);
}
let first = &outcomes[0].output;
let all_match = outcomes[1..].iter().all(|res| first == &res.output);
assert!(all_match, "{:#?}", outcomes);
core::mem::take(&mut outcomes[0].output)
}
#[test]
fn differential_test() {
let impls = testing::$name::implementations();
assert!(!impls.is_empty());
check!().for_each(|bytes| {
if bytes.len() < KEY_LEN {
return;
}
let (key, input) = bytes.split_at(KEY_LEN);
let key = key.try_into().unwrap();
ensure_match(impls, key, input);
})
}
#[test]
fn test_vectors() {
let impls = testing::$name::implementations();
assert!(!impls.is_empty());
let tests = $test_vectors;
for (key, plaintext, ciphertext) in tests.iter() {
let actual = ensure_match(impls, *key, plaintext);
assert_eq!(actual, ciphertext);
}
}
}
};
}
impl_tests!(aes128, {
vec![
(
hex!("000102030405060708090a0b0c0d0e0f"),
hex!("00112233445566778899aabbccddeeff"),
hex!("69c4e0d86a7b0430d8cdb78070b4c55a"),
),
(
hex!("00000000000000000000000000000000"),
hex!("80000000000000000000000000000000"),
hex!("3ad78e726c1ec02b7ebfe92b23d9ec34"),
),
(
hex!("00000000000000000000000000000000"),
hex!("c0000000000000000000000000000000"),
hex!("aae5939c8efdf2f04e60b9fe7117b2c2"),
),
(
hex!("00000000000000000000000000000000"),
hex!("e0000000000000000000000000000000"),
hex!("f031d4d74f5dcbf39daaf8ca3af6e527"),
),
]
});
impl_tests!(aes256, {
vec![
(
hex!("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"),
hex!("00112233445566778899aabbccddeeff"),
hex!("8ea2b7ca516745bfeafc49904b496089"),
),
(
hex!("0000000000000000000000000000000000000000000000000000000000000000"),
hex!("80000000000000000000000000000000"),
hex!("ddc6bf790c15760d8d9aeb6f9a75fd4e"),
),
(
hex!("0000000000000000000000000000000000000000000000000000000000000000"),
hex!("c0000000000000000000000000000000"),
hex!("0a6bdc6d4c1e6280301fd8e97ddbe601"),
),
(
hex!("0000000000000000000000000000000000000000000000000000000000000000"),
hex!("e0000000000000000000000000000000"),
hex!("9b80eefb7ebe2d2b16247aa0efc72f5d"),
),
]
});