Skip to content

Commit 27e6e5b

Browse files
committed
aead: adds a dev::BicephalBuffer to smoke tests misuse of get_in
1 parent 204a4e0 commit 27e6e5b

File tree

1 file changed

+131
-0
lines changed

1 file changed

+131
-0
lines changed

aead/src/dev.rs

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
//! Development-related functionality
22
pub use blobby;
33

4+
#[cfg(all(feature = "alloc", feature = "inout"))]
5+
use {crate::Tag, crypto_common::typenum::Unsigned};
6+
#[cfg(feature = "alloc")]
7+
use {alloc::vec, alloc::vec::Vec, core::fmt, inout::InOutBuf};
8+
49
/// Define AEAD test
510
#[macro_export]
611
macro_rules! new_test {
@@ -45,6 +50,8 @@ macro_rules! new_test {
4550
if res != pt {
4651
return Err("decrypted data is different from target plaintext");
4752
}
53+
54+
$crate::dev::new_test_impl_inout(cipher, nonce, aad, pt, ct, pass)?;
4855
Ok(())
4956
}
5057

@@ -75,3 +82,127 @@ macro_rules! new_test {
7582
}
7683
};
7784
}
85+
86+
/// Helper to run tests against the inout API.
87+
#[cfg(not(all(feature = "alloc", feature = "inout")))]
88+
pub fn new_test_impl_inout<T: crate::AeadInOut>(
89+
cipher: T,
90+
nonce: &crate::Nonce<T>,
91+
aad: &[u8],
92+
pt: &[u8],
93+
ct: &[u8],
94+
pass: bool,
95+
) -> Result<(), &'static str> {
96+
Ok(())
97+
}
98+
99+
/// Helper to run tests against the inout API.
100+
#[cfg(all(feature = "alloc", feature = "inout"))]
101+
pub fn new_test_impl_inout<T: crate::AeadInOut>(
102+
cipher: T,
103+
nonce: &crate::Nonce<T>,
104+
aad: &[u8],
105+
pt: &[u8],
106+
ct: &[u8],
107+
pass: bool,
108+
) -> Result<(), &'static str> {
109+
// Here we assume this is a postfix tagged AEAD
110+
let (ciphertext, expected_tag) = ct.split_at(ct.len() - T::TagSize::to_usize());
111+
let expected_tag = Tag::<T>::try_from(expected_tag).unwrap();
112+
113+
if !pass {
114+
let mut payload = MockBuffer::from(ciphertext);
115+
let res = cipher.decrypt_inout_detached(nonce, aad, payload.to_in_out_buf(), &expected_tag);
116+
if res.is_ok() {
117+
return Err("Decryption must return an error");
118+
}
119+
return Ok(());
120+
}
121+
122+
let mut payload = MockBuffer::from(pt);
123+
let tag = cipher
124+
.encrypt_inout_detached(nonce, aad, payload.to_in_out_buf())
125+
.map_err(|_| "encryption failure")?;
126+
127+
// Here we assume this is a postfix tagged AEAD
128+
let (ciphertext, _tag) = ct.split_at(ct.len() - T::TagSize::to_usize());
129+
if payload.as_ref() != ciphertext {
130+
return Err("encrypted data is different from target ciphertext");
131+
}
132+
133+
let mut payload = MockBuffer::from(ciphertext);
134+
cipher
135+
.decrypt_inout_detached(nonce, aad, payload.to_in_out_buf(), &tag)
136+
.map_err(|_| "decryption failure")?;
137+
138+
if payload.as_ref() != pt {
139+
return Err("decrypted data is different from target plaintext");
140+
}
141+
142+
Ok(())
143+
}
144+
145+
/// [`MockBuffer`] is meant for testing InOut-backed APIs.
146+
///
147+
/// It will split the initial buffer in two different backing buffers. The out buffer will be
148+
/// zeroed.
149+
#[cfg(feature = "alloc")]
150+
pub struct MockBuffer {
151+
in_buf: Vec<u8>,
152+
out_buf: Vec<u8>,
153+
}
154+
155+
#[cfg(feature = "alloc")]
156+
impl AsRef<[u8]> for MockBuffer {
157+
fn as_ref(&self) -> &[u8] {
158+
&self.out_buf
159+
}
160+
}
161+
162+
#[cfg(feature = "alloc")]
163+
impl From<&[u8]> for MockBuffer {
164+
fn from(buf: &[u8]) -> Self {
165+
Self {
166+
in_buf: buf.to_vec(),
167+
out_buf: vec![0u8; buf.len()],
168+
}
169+
}
170+
}
171+
172+
#[cfg(feature = "alloc")]
173+
impl From<Vec<u8>> for MockBuffer {
174+
fn from(buf: Vec<u8>) -> Self {
175+
Self {
176+
out_buf: vec![0u8; buf.len()],
177+
in_buf: buf,
178+
}
179+
}
180+
}
181+
182+
#[cfg(feature = "alloc")]
183+
impl MockBuffer {
184+
/// Get an [`InOutBuf`] from a [`MockBuffer`]
185+
pub fn to_in_out_buf(&mut self) -> InOutBuf<'_, '_, u8> {
186+
InOutBuf::new(self.in_buf.as_slice(), self.out_buf.as_mut_slice())
187+
.expect("Invariant violation")
188+
}
189+
190+
/// Return the length of the payload
191+
#[inline]
192+
pub fn len(&self) -> usize {
193+
self.in_buf.len()
194+
}
195+
196+
/// Is the payload empty?
197+
#[inline]
198+
pub fn is_empty(&self) -> bool {
199+
self.in_buf.is_empty()
200+
}
201+
}
202+
203+
#[cfg(feature = "alloc")]
204+
impl fmt::Debug for MockBuffer {
205+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
206+
write!(f, "MockBuffer {{...}}")
207+
}
208+
}

0 commit comments

Comments
 (0)