Skip to content

Commit 832c889

Browse files
authored
Migrate to const blobby parsing (#1916)
1 parent 5186264 commit 832c889

13 files changed

Lines changed: 502 additions & 492 deletions

File tree

Cargo.lock

Lines changed: 14 additions & 36 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,7 @@ members = [
1717
digest = { path = "digest" }
1818
signature = { path = "signature" }
1919

20+
# https://github.com/RustCrypto/utils/pull/1187
21+
blobby = { git = "https://github.com/RustCrypto/utils" }
2022
# https://github.com/RustCrypto/utils/pull/1192
21-
block-buffer = { git = "https://github.com/RustCrypto/utils.git" }
23+
block-buffer = { git = "https://github.com/RustCrypto/utils" }

aead/src/dev.rs

Lines changed: 93 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,80 @@
11
//! Development-related functionality
22
use crate::{
3-
Aead, AeadInOut, Nonce, Payload, Tag, TagPosition, array::typenum::Unsigned, inout::InOutBuf,
3+
Aead, AeadInOut, Payload, Tag, TagPosition, array::typenum::Unsigned, inout::InOutBuf,
44
};
55
pub use blobby;
6+
use crypto_common::KeyInit;
7+
8+
/// AEAD test vector
9+
#[derive(Debug, Clone, Copy)]
10+
pub struct TestVector {
11+
/// Initialization key
12+
pub key: &'static [u8],
13+
/// Nonce
14+
pub nonce: &'static [u8],
15+
/// Additional associated data
16+
pub aad: &'static [u8],
17+
/// Plaintext
18+
pub plaintext: &'static [u8],
19+
/// Ciphertext
20+
pub ciphertext: &'static [u8],
21+
/// Whether the test vector should pass (`[1]`) or fail (`[0]`)
22+
pub pass: &'static [u8],
23+
}
624

725
/// Run AEAD test for the provided passing test vector
8-
pub fn run_pass_test<C: AeadInOut>(
9-
cipher: &C,
10-
nonce: &Nonce<C>,
11-
aad: &[u8],
12-
pt: &[u8],
13-
ct: &[u8],
26+
pub fn pass_test<C: AeadInOut + KeyInit>(
27+
&TestVector {
28+
key,
29+
nonce,
30+
aad,
31+
plaintext,
32+
ciphertext,
33+
pass,
34+
}: &TestVector,
1435
) -> Result<(), &'static str> {
36+
assert_eq!(pass, &[1]);
37+
let nonce = nonce.try_into().expect("wrong nonce size");
38+
let cipher = <C as KeyInit>::new_from_slice(key).expect("failed to initialize the cipher");
39+
1540
let res = cipher
16-
.encrypt(nonce, Payload { aad, msg: pt })
41+
.encrypt(
42+
nonce,
43+
Payload {
44+
aad,
45+
msg: plaintext,
46+
},
47+
)
1748
.map_err(|_| "encryption failure")?;
18-
if res != ct {
49+
if res != ciphertext {
1950
return Err("encrypted data is different from target ciphertext");
2051
}
2152

2253
let res = cipher
23-
.decrypt(nonce, Payload { aad, msg: ct })
54+
.decrypt(
55+
nonce,
56+
Payload {
57+
aad,
58+
msg: ciphertext,
59+
},
60+
)
2461
.map_err(|_| "decryption failure")?;
25-
if res != pt {
62+
if res != plaintext {
2663
return Err("decrypted data is different from target plaintext");
2764
}
2865

2966
let (ct, tag) = match C::TAG_POSITION {
3067
TagPosition::Prefix => {
31-
let (tag, ct) = ct.split_at(C::TagSize::USIZE);
68+
let (tag, ct) = ciphertext.split_at(C::TagSize::USIZE);
3269
(ct, tag)
3370
}
34-
TagPosition::Postfix => ct.split_at(pt.len()),
71+
TagPosition::Postfix => ciphertext.split_at(plaintext.len()),
3572
};
3673
let tag: &Tag<C> = tag.try_into().expect("tag has correct length");
3774

3875
// Fill output buffer with "garbage" to test that its data does not get read during encryption
39-
let mut buf: alloc::vec::Vec<u8> = (0..pt.len()).map(|i| i as u8).collect();
40-
let inout_buf = InOutBuf::new(pt, &mut buf).expect("pt and buf have the same length");
76+
let mut buf: alloc::vec::Vec<u8> = (0..plaintext.len()).map(|i| i as u8).collect();
77+
let inout_buf = InOutBuf::new(plaintext, &mut buf).expect("pt and buf have the same length");
4178

4279
let calc_tag = cipher
4380
.encrypt_inout_detached(nonce, aad, inout_buf)
@@ -50,27 +87,43 @@ pub fn run_pass_test<C: AeadInOut>(
5087
}
5188

5289
// Fill output buffer with "garbage"
53-
buf.iter_mut().enumerate().for_each(|(i, v)| *v = i as u8);
90+
buf.iter_mut()
91+
.enumerate()
92+
.for_each(|(i, v): (usize, &mut u8)| *v = i as u8);
5493

5594
let inout_buf = InOutBuf::new(ct, &mut buf).expect("ct and buf have the same length");
5695
cipher
5796
.decrypt_inout_detached(nonce, aad, inout_buf, tag)
5897
.map_err(|_| "decrypt_inout_detached: decryption failure")?;
59-
if pt != buf {
98+
if plaintext != buf {
6099
return Err("decrypt_inout_detached: plaintext mismatch");
61100
}
62101

63102
Ok(())
64103
}
65104

66105
/// Run AEAD test for the provided failing test vector
67-
pub fn run_fail_test<C: AeadInOut>(
68-
cipher: &C,
69-
nonce: &Nonce<C>,
70-
aad: &[u8],
71-
ct: &[u8],
106+
pub fn fail_test<C: AeadInOut + KeyInit>(
107+
&TestVector {
108+
key,
109+
nonce,
110+
aad,
111+
ciphertext,
112+
pass,
113+
..
114+
}: &TestVector,
72115
) -> Result<(), &'static str> {
73-
let res = cipher.decrypt(nonce, Payload { aad, msg: ct });
116+
assert_eq!(pass, &[0]);
117+
let nonce = nonce.try_into().expect("wrong nonce size");
118+
let cipher = <C as KeyInit>::new_from_slice(key).expect("failed to initialize the cipher");
119+
120+
let res = cipher.decrypt(
121+
nonce,
122+
Payload {
123+
aad,
124+
msg: ciphertext,
125+
},
126+
);
74127
if res.is_ok() {
75128
Err("decryption must return error")
76129
} else {
@@ -84,33 +137,29 @@ macro_rules! new_test {
84137
($name:ident, $test_name:expr, $cipher:ty $(,)?) => {
85138
#[test]
86139
fn $name() {
87-
use $crate::KeyInit;
88-
use $crate::dev::blobby::Blob6Iterator;
89-
90-
let data = include_bytes!(concat!("data/", $test_name, ".blb"));
91-
for (i, row) in Blob6Iterator::new(data).unwrap().enumerate() {
92-
let [key, nonce, aad, pt, ct, status] = row.unwrap();
93-
let key = key.try_into().expect("wrong key size");
94-
let nonce = nonce.try_into().expect("wrong nonce size");
95-
let cipher = <$cipher as KeyInit>::new(key);
96-
97-
let res = match status {
98-
[0] => $crate::dev::run_fail_test(&cipher, nonce, aad, ct),
99-
[1] => $crate::dev::run_pass_test(&cipher, nonce, aad, pt, ct),
100-
_ => panic!("invalid value for pass flag"),
140+
use $crate::dev::TestVector;
141+
142+
$crate::dev::blobby::parse_into_structs!(
143+
include_bytes!(concat!("data/", $test_name, ".blb"));
144+
static TEST_VECTORS: &[
145+
TestVector { key, nonce, aad, plaintext, ciphertext, pass }
146+
];
147+
);
148+
149+
for (i, tv) in TEST_VECTORS.iter().enumerate() {
150+
let pass = tv.pass[0] == 1;
151+
let res = if pass {
152+
$crate::dev::pass_test::<$cipher>(tv)
153+
} else {
154+
$crate::dev::fail_test::<$cipher>(tv)
101155
};
102-
let mut pass = status[0] == 1;
156+
103157
if let Err(reason) = res {
104158
panic!(
105159
"\n\
106160
Failed test #{i}\n\
107161
reason:\t{reason:?}\n\
108-
key:\t{key:?}\n\
109-
nonce:\t{nonce:?}\n\
110-
aad:\t{aad:?}\n\
111-
plaintext:\t{pt:?}\n\
112-
ciphertext:\t{ct:?}\n\
113-
pass:\t{pass}\n"
162+
test vector:\t{tv:?}\n"
114163
);
115164
}
116165
}

aead/tests/dummy.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! This module defines dummy (horribly insecure!) AEAD implementations
22
//! to test implementation of the AEAD traits and helper macros in the `dev` module.
3+
#![cfg(feature = "dev")]
34
use aead::{
45
AeadCore, AeadInOut, Error, Key, KeyInit, KeySizeUser, Nonce, Result, Tag, TagPosition,
56
array::Array, consts::U8,
@@ -169,7 +170,5 @@ impl AeadInOut for PostfixDummyAead {
169170
}
170171
}
171172

172-
#[cfg(feature = "dev")]
173173
aead::new_test!(dummy_prefix, "prefix", PrefixDummyAead);
174-
#[cfg(feature = "dev")]
175174
aead::new_test!(dummy_postfix, "postfix", PostfixDummyAead);

cipher/src/dev.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1-
mod block;
2-
mod stream;
1+
//! Development-related functionality
2+
pub mod block;
3+
pub mod stream;
4+
5+
pub use blobby;

0 commit comments

Comments
 (0)