use similar_asserts::assert_eq;
use std::assert_matches;
use test_utils::AegisTestCase;
use philbin::{
careful::Nonce,
easy::{
AssociatedData, AuthTag128, Ciphertext, CiphertextMut, Error, Key,
Plaintext, PlaintextMut, Result,
},
};
macro_rules! gen_buffer_len_tests {
(
$algo_mod:ident // Should be a `philbin::careful` algo submod
) => {
#[rstest::rstest]
fn encryption_short_buffer(
#[from(test_utils::$algo_mod::example)]
expected: test_utils::AegisTestCase,
) -> anyhow::Result<()> {
buf_len_tests::verify_encryption_short_buffer(
philbin::careful::$algo_mod::encrypt_to_slice_detached,
expected,
)
}
#[rstest::rstest]
fn encryption_long_buffer(
#[from(test_utils::$algo_mod::example)]
expected: test_utils::AegisTestCase,
) -> anyhow::Result<()> {
buf_len_tests::verify_encryption_long_buffer(
philbin::careful::$algo_mod::encrypt_to_slice_detached,
expected,
)
}
#[rstest::rstest]
fn decryption_short_buffer(
#[from(test_utils::$algo_mod::example)]
expected: test_utils::AegisTestCase,
) -> anyhow::Result<()> {
buf_len_tests::verify_decryption_short_buffer(
philbin::careful::$algo_mod::decrypt_to_slice_detached,
expected,
)
}
#[rstest::rstest]
fn decryption_long_buffer(
#[from(test_utils::$algo_mod::example)]
expected: test_utils::AegisTestCase,
) -> anyhow::Result<()> {
buf_len_tests::verify_decryption_long_buffer(
philbin::careful::$algo_mod::decrypt_to_slice_detached,
expected,
)
}
};
}
pub(crate) use gen_buffer_len_tests;
pub fn verify_encryption_short_buffer<const KEY_BYTES: usize>(
func: fn(
Plaintext,
AssociatedData,
&Key<KEY_BYTES>,
Nonce<KEY_BYTES>,
CiphertextMut,
) -> Result<AuthTag128>,
expected: AegisTestCase,
) -> anyhow::Result<()> {
let mut actual_ciphertext = vec![0; 11];
assert_matches!(
func(
Plaintext::new(&expected.plaintext),
AssociatedData::new(&expected.associated_data),
&Key::<KEY_BYTES>::from_bytes(expected.key)?,
Nonce::<KEY_BYTES>::new(*expected.nonce.as_array().unwrap())?,
CiphertextMut::new(&mut actual_ciphertext),
),
Err(Error::OutputBufferTooSmall)
);
assert_eq!(&vec![0; actual_ciphertext.len()], &actual_ciphertext);
Ok(())
}
pub fn verify_encryption_long_buffer<const KEY_BYTES: usize>(
func: fn(
Plaintext,
AssociatedData,
&Key<KEY_BYTES>,
Nonce<KEY_BYTES>,
CiphertextMut,
) -> Result<AuthTag128>,
expected: AegisTestCase,
) -> anyhow::Result<()> {
let mut actual_ciphertext = vec![0; expected.plaintext.len() + 100];
let actual_tag: AuthTag128 = func(
Plaintext::new(&expected.plaintext),
AssociatedData::new(&expected.associated_data),
&Key::<KEY_BYTES>::from_bytes(expected.key)?,
Nonce::<KEY_BYTES>::new(*expected.nonce.as_array().unwrap())?,
CiphertextMut::new(&mut actual_ciphertext),
)?;
assert_eq!(
expected.ciphertext,
actual_ciphertext[..expected.ciphertext.len()]
);
assert_eq!(expected.tag128, actual_tag);
let rest_of_buffer = &actual_ciphertext[expected.ciphertext.len()..];
assert_eq!(&vec![0; rest_of_buffer.len()], &rest_of_buffer);
Ok(())
}
pub fn verify_decryption_short_buffer<const KEY_BYTES: usize>(
func: fn(
Ciphertext,
&AuthTag128,
AssociatedData,
&Key<KEY_BYTES>,
Nonce<KEY_BYTES>,
PlaintextMut,
) -> Result<()>,
expected: AegisTestCase,
) -> anyhow::Result<()> {
let mut actual_plaintext = vec![0; 11];
assert_matches!(
func(
Ciphertext::new(&expected.ciphertext),
&expected.tag128,
AssociatedData::new(&expected.associated_data),
&Key::<KEY_BYTES>::from_bytes(expected.key)?,
Nonce::<KEY_BYTES>::new(*expected.nonce.as_array().unwrap())?,
PlaintextMut::new(&mut actual_plaintext),
),
Err(Error::OutputBufferTooSmall)
);
assert_eq!(&vec![0; actual_plaintext.len()], &actual_plaintext);
Ok(())
}
pub fn verify_decryption_long_buffer<const KEY_BYTES: usize>(
func: fn(
Ciphertext,
&AuthTag128,
AssociatedData,
&Key<KEY_BYTES>,
Nonce<KEY_BYTES>,
PlaintextMut,
) -> Result<()>,
expected: AegisTestCase,
) -> anyhow::Result<()> {
let mut actual_plaintext = vec![0; expected.ciphertext.len() + 100];
func(
Ciphertext::new(&expected.ciphertext),
&expected.tag128,
AssociatedData::new(&expected.associated_data),
&Key::<KEY_BYTES>::from_bytes(expected.key)?,
Nonce::<KEY_BYTES>::new(*expected.nonce.as_array().unwrap())?,
PlaintextMut::new(&mut actual_plaintext),
)?;
assert_eq!(
expected.plaintext,
actual_plaintext[..expected.plaintext.len()]
);
let rest_of_buffer = &actual_plaintext[expected.plaintext.len()..];
assert_eq!(&vec![0; rest_of_buffer.len()], &rest_of_buffer);
Ok(())
}