-
Notifications
You must be signed in to change notification settings - Fork 253
Expand file tree
/
Copy pathdev.rs
More file actions
170 lines (146 loc) · 4.64 KB
/
Copy pathdev.rs
File metadata and controls
170 lines (146 loc) · 4.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
//! Development-related functionality
pub use blobby;
use crate::Aead;
use common::KeyInit;
/// AEAD test vector
#[derive(Debug, Clone, Copy)]
pub struct TestVector {
/// Initialization key
pub key: &'static [u8],
/// Nonce
pub nonce: &'static [u8],
/// Additional associated data
pub aad: &'static [u8],
/// Plaintext
pub plaintext: &'static [u8],
/// Ciphertext
pub ciphertext: &'static [u8],
}
/// Run AEAD test for the provided passing test vector
///
/// # Errors
/// - If the cipher has failed initialization with the provided key.
/// - If the AEAD mode has failed to pass the test vector.
pub fn pass_test<C: Aead + KeyInit>(
&TestVector {
key,
nonce,
aad,
plaintext,
ciphertext,
}: &TestVector,
) -> Result<(), &'static str> {
let cipher: C = KeyInit::new_from_slice(key).map_err(|_| "failed to initialize the cipher")?;
let res = cipher
.encrypt_into_vec(nonce, aad, plaintext)
.map_err(|_| "encryption failure")?;
if res != ciphertext {
return Err("encrypted data is different from target ciphertext");
}
let res = cipher
.decrypt_into_vec(nonce, aad, ciphertext)
.map_err(|_| "decryption failure")?;
if res != plaintext {
return Err("decrypted data is different from target plaintext");
}
let mut buf = ciphertext.to_vec();
// Flip one bit
buf[0] ^= 1;
let res = cipher.decrypt_within_vec(nonce, aad, &mut buf);
if res.is_ok() {
return Err("did not detect corrupted ciphertext");
}
if buf.iter().any(|&b| b != 0) {
return Err("the buffer was not zeroized after failure");
}
Ok(())
}
/// Run AEAD test for the provided failing test vector
///
/// # Errors
/// - If the cipher has failed initialization with the provided key.
/// - If the cipher has passed the test vector.
pub fn fail_test<C: Aead + KeyInit>(
&TestVector {
key,
nonce,
aad,
ciphertext,
..
}: &TestVector,
) -> Result<(), &'static str> {
let cipher: C = KeyInit::new_from_slice(key).map_err(|_| "failed to initialize the cipher")?;
let res = cipher.decrypt_into_vec(nonce, aad, ciphertext);
if res.is_ok() {
return Err("decryption must return error");
}
let mut buf = ciphertext.to_vec();
let res = cipher.decrypt_within_vec(nonce, aad, &mut buf);
if res.is_ok() {
return Err("decryption must return error");
}
if buf.iter().any(|&b| b != 0) {
return Err("the buffer was not zeroized after failure");
}
Ok(())
}
/// Define AEAD test for passing test vectors
#[macro_export]
macro_rules! new_pass_test {
($name:ident, $cipher:ty $(,)?) => {
$crate::new_pass_test!($name, stringify!($name), $cipher);
};
($name:ident, $test_name:expr, $cipher:ty $(,)?) => {
#[test]
fn $name() {
use $crate::dev::TestVector;
$crate::dev::blobby::parse_into_structs!(
include_bytes!(concat!("data/", $test_name, ".blb"));
static TEST_VECTORS: &[
TestVector { key, nonce, aad, plaintext, ciphertext }
];
);
for (i, tv) in TEST_VECTORS.iter().enumerate() {
let res = $crate::dev::pass_test::<$cipher>(tv);
if let Err(reason) = res {
panic!(
"\n\
Failed test #{i}\n\
reason:\t{reason:?}\n\
test vector:\t{tv:?}\n"
);
}
}
}
};
}
/// Define AEAD test for failing test vectors
#[macro_export]
macro_rules! new_fail_test {
($name:ident, $cipher:ty $(,)?) => {
$crate::new_fail_test!($name, stringify!($name), $cipher);
};
($name:ident, $test_name:expr, $cipher:ty $(,)?) => {
#[test]
fn $name() {
use $crate::dev::TestVector;
$crate::dev::blobby::parse_into_structs!(
include_bytes!(concat!("data/", $test_name, ".blb"));
static TEST_VECTORS: &[
TestVector { key, nonce, aad, plaintext, ciphertext }
];
);
for (i, tv) in TEST_VECTORS.iter().enumerate() {
let res = $crate::dev::fail_test::<$cipher>(tv);
if let Err(reason) = res {
panic!(
"\n\
Failed test #{i}\n\
reason:\t{reason:?}\n\
test vector:\t{tv:?}\n"
);
}
}
}
};
}