Skip to content

Commit b82e85a

Browse files
authored
replace test vectors with wycheproof-rs (#20)
1 parent 9f75f2e commit b82e85a

File tree

11 files changed

+73
-7482
lines changed

11 files changed

+73
-7482
lines changed

Cargo.toml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ rstest = "0.23.0"
3131
# Use aws_lc_rs to test our provider
3232
rustls = { version = "0.23.0", features = ["aws_lc_rs"] }
3333
rustls-pemfile = "2"
34-
serde = { version = "1.0.215", features = ["derive"] }
35-
serde_json = "1.0.133"
3634
webpki-roots = "0.26"
35+
wycheproof = { version = "0.6.0", default-features = false, features = [
36+
"aead",
37+
"hkdf",
38+
] }

src/aead.rs

Lines changed: 53 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -88,127 +88,99 @@ impl Algorithm {
8888

8989
#[cfg(test)]
9090
mod test {
91+
use wycheproof::{aead::TestFlag, TestResult};
9192

92-
use crate::test::schemas::aead;
93-
use std::{fs, path::PathBuf};
93+
fn test_aead(alg: super::Algorithm) {
94+
let test_name = match alg {
95+
super::Algorithm::Aes128Gcm | super::Algorithm::Aes256Gcm => {
96+
wycheproof::aead::TestName::AesGcm
97+
}
98+
#[cfg(all(chacha, not(feature = "fips")))]
99+
super::Algorithm::ChaCha20Poly1305 => wycheproof::aead::TestName::ChaCha20Poly1305,
100+
};
101+
let test_set = wycheproof::aead::TestSet::load(test_name).unwrap();
94102

95-
fn test_aes(alg: super::Algorithm) {
96-
let path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
97-
.join("src")
98-
.join("test")
99-
.join("vectors")
100-
.join("aes_gcm_test.json");
101-
let tests: aead::AeadTestFile =
102-
serde_json::from_str(&fs::read_to_string(path).unwrap()).unwrap();
103+
let mut counter = 0;
103104

104-
for group in tests
105+
for group in test_set
105106
.test_groups
106-
.unwrap()
107-
.iter()
108-
.filter(|group| group.key_size.unwrap() == 8 * i64::try_from(alg.key_size()).unwrap())
109-
.filter(|group| group.iv_size.unwrap() == 96)
107+
.into_iter()
108+
.filter(|group| group.key_size == 8 * alg.key_size())
109+
.filter(|group| group.nonce_size == 96)
110110
{
111-
for test in group.tests.as_ref().unwrap() {
112-
dbg!(test.tc_id);
113-
let key = test
114-
.key
115-
.as_deref()
116-
.map(|key| hex::decode(key).unwrap())
117-
.unwrap();
118-
let iv = test
119-
.iv
120-
.as_deref()
121-
.map(|iv| hex::decode(iv).unwrap())
122-
.unwrap();
123-
let aad = test
124-
.aad
125-
.as_deref()
126-
.map(|aad| hex::decode(aad).unwrap())
127-
.unwrap();
128-
let msg = test
129-
.msg
130-
.as_deref()
131-
.map(|msg| hex::decode(msg).unwrap())
132-
.unwrap();
133-
let ciphertext = test
134-
.ct
135-
.as_deref()
136-
.map(|ct| hex::decode(ct).unwrap())
137-
.unwrap();
138-
let tag = test
139-
.tag
140-
.as_deref()
141-
.map(|tag| hex::decode(tag).unwrap())
142-
.unwrap();
143-
111+
for test in group.tests {
112+
counter += 1;
144113
let mut iv_bytes = [0u8; 12];
145-
iv_bytes.copy_from_slice(&iv[0..12]);
114+
iv_bytes.copy_from_slice(&test.nonce[0..12]);
146115

147-
let mut actual_ciphertext = msg.clone();
116+
let mut actual_ciphertext = test.pt.to_vec();
148117
let actual_tag = alg
149-
.encrypt_in_place(&key, &iv_bytes, &aad, &mut actual_ciphertext)
118+
.encrypt_in_place(&test.key, &iv_bytes, &test.aad, &mut actual_ciphertext)
150119
.unwrap();
151120

152-
match test.result.as_ref().unwrap() {
153-
aead::Result::Invalid => {
154-
if test
155-
.flags
156-
.as_ref()
157-
.unwrap()
158-
.iter()
159-
.any(|flag| flag == "ModifiedTag")
160-
{
121+
match &test.result {
122+
TestResult::Invalid => {
123+
if test.flags.iter().any(|flag| *flag == TestFlag::ModifiedTag) {
161124
assert_ne!(
162125
actual_tag[..],
163-
tag[..],
126+
test.tag[..],
164127
"Expected incorrect tag. Id {}: {}",
165-
test.tc_id.unwrap(),
166-
test.comment.as_deref().unwrap()
128+
test.tc_id,
129+
test.comment
167130
);
168131
}
169132
}
170-
aead::Result::Valid | aead::Result::Acceptable => {
133+
TestResult::Valid | TestResult::Acceptable => {
171134
assert_eq!(
172-
actual_ciphertext,
173-
ciphertext,
135+
actual_ciphertext[..],
136+
test.ct[..],
174137
"Test case failed {}: {}",
175-
test.tc_id.unwrap(),
176-
test.comment.as_deref().unwrap()
138+
test.tc_id,
139+
test.comment
177140
);
178141
assert_eq!(
179142
actual_tag[..],
180-
tag[..],
143+
test.tag[..],
181144
"Test case failed {}: {}",
182-
test.tc_id.unwrap(),
183-
test.comment.as_deref().unwrap()
145+
test.tc_id,
146+
test.comment
184147
);
185148
}
186149
}
187150

188-
let mut data = ciphertext.to_vec();
189-
data.extend_from_slice(&tag);
190-
let res = alg.decrypt_in_place(&key, &iv_bytes, &aad, &mut data);
151+
let mut data = test.ct.to_vec();
152+
data.extend_from_slice(&test.tag);
153+
let res = alg.decrypt_in_place(&test.key, &iv_bytes, &test.aad, &mut data);
191154

192-
match test.result.as_ref().unwrap() {
193-
aead::Result::Invalid => {
155+
match &test.result {
156+
TestResult::Invalid => {
194157
assert!(res.is_err());
195158
}
196-
aead::Result::Valid | aead::Result::Acceptable => {
197-
assert_eq!(res, Ok(msg.len()));
198-
assert_eq!(&data[..res.unwrap()], &msg[..]);
159+
TestResult::Valid | TestResult::Acceptable => {
160+
assert_eq!(res, Ok(test.pt.len()));
161+
assert_eq!(&data[..res.unwrap()], &test.pt[..]);
199162
}
200163
}
201164
}
202165
}
166+
167+
// Ensure we ran some tests.
168+
assert!(counter > 50);
203169
}
204170

205171
#[test]
206172
fn test_aes_128() {
207-
test_aes(super::Algorithm::Aes128Gcm);
173+
test_aead(super::Algorithm::Aes128Gcm);
208174
}
209175

210176
#[test]
211177
fn test_aes_256() {
212-
test_aes(super::Algorithm::Aes256Gcm);
178+
test_aead(super::Algorithm::Aes256Gcm);
179+
}
180+
181+
#[cfg(all(chacha, not(feature = "fips")))]
182+
#[test]
183+
fn test_chacha() {
184+
test_aead(super::Algorithm::ChaCha20Poly1305);
213185
}
214186
}

src/hkdf.rs

Lines changed: 16 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -126,41 +126,29 @@ fn add_hkdf_info<T>(ctx: &mut PkeyCtxRef<T>, info: &[&[u8]]) -> Result<(), Error
126126

127127
#[cfg(test)]
128128
mod test {
129-
use crate::test::schemas::hkdf::{self, HkdfTestFile};
130129
use rustls::crypto::tls13::Hkdf;
131-
use std::{fs, path::PathBuf};
132-
133-
fn test_hkdf(hkdf: &dyn Hkdf, test_file: HkdfTestFile) {
134-
for test_group in test_file.test_groups.unwrap() {
135-
for test in test_group.tests.unwrap() {
136-
let salt = test.salt.as_deref().map(|salt| hex::decode(salt).unwrap());
137-
let ikm = test
138-
.ikm
139-
.as_deref()
140-
.map(|ikm| hex::decode(ikm).unwrap())
141-
.unwrap();
142-
let expected_okm = test
143-
.okm
144-
.as_deref()
145-
.map(|okm| hex::decode(okm).unwrap())
146-
.unwrap();
147-
let info = test.info.as_deref().map(|info| hex::decode(info).unwrap());
130+
use wycheproof::{hkdf::TestName, TestResult};
148131

132+
fn test_hkdf(hkdf: &dyn Hkdf, test_name: TestName) {
133+
let test_set = wycheproof::hkdf::TestSet::load(test_name).unwrap();
134+
135+
for test_group in test_set.test_groups {
136+
for test in test_group.tests {
149137
dbg!(&test);
150138

151-
let prk_expander = hkdf.extract_from_secret(salt.as_deref(), &ikm);
139+
let prk_expander = hkdf.extract_from_secret(Some(&test.salt), &test.ikm);
152140

153-
let mut okm = vec![0; test.size.unwrap().try_into().unwrap()];
154-
let res = prk_expander.expand_slice(&[info.as_deref().unwrap_or(&[])], &mut okm);
141+
let mut okm = vec![0; test.size];
142+
let res = prk_expander.expand_slice(&[&test.info], &mut okm);
155143

156-
match &test.result.unwrap() {
157-
hkdf::Result::Acceptable | hkdf::Result::Valid => {
144+
match &test.result {
145+
TestResult::Acceptable | TestResult::Valid => {
158146
assert!(res.is_ok());
159-
assert_eq!(okm, expected_okm, "Failed test: {}", test.comment.unwrap());
147+
assert_eq!(okm[..], test.okm[..], "Failed test: {}", test.comment);
160148
}
161-
hkdf::Result::Invalid => {
149+
TestResult::Invalid => {
162150
dbg!(&res);
163-
assert!(res.is_err(), "Failed test: {}", test.comment.unwrap())
151+
assert!(res.is_err(), "Failed test: {}", test.comment)
164152
}
165153
}
166154
}
@@ -171,25 +159,13 @@ mod test {
171159
fn hkdf_sha256() {
172160
let suite = crate::cipher_suite::TLS13_AES_128_GCM_SHA256;
173161
let hkdf = suite.tls13().unwrap().hkdf_provider;
174-
let path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
175-
.join("src")
176-
.join("test")
177-
.join("vectors")
178-
.join("hkdf_sha256_test.json");
179-
let tests: HkdfTestFile = serde_json::from_str(&fs::read_to_string(path).unwrap()).unwrap();
180-
test_hkdf(hkdf, tests);
162+
test_hkdf(hkdf, TestName::HkdfSha256);
181163
}
182164

183165
#[test]
184166
fn hkdf_sha384() {
185167
let suite = crate::cipher_suite::TLS13_AES_256_GCM_SHA384;
186168
let hkdf = suite.tls13().unwrap().hkdf_provider;
187-
let path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
188-
.join("src")
189-
.join("test")
190-
.join("vectors")
191-
.join("hkdf_sha384_test.json");
192-
let tests: HkdfTestFile = serde_json::from_str(&fs::read_to_string(path).unwrap()).unwrap();
193-
test_hkdf(hkdf, tests);
169+
test_hkdf(hkdf, TestName::HkdfSha384);
194170
}
195171
}

src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,6 @@ mod kx;
6969
mod prf;
7070
mod quic;
7171
mod signer;
72-
#[cfg(test)]
73-
mod test;
7472
#[cfg(feature = "tls12")]
7573
mod tls12;
7674
mod tls13;

src/test/mod.rs

Lines changed: 0 additions & 2 deletions
This file was deleted.

src/test/schemas/aead.rs

Lines changed: 0 additions & 79 deletions
This file was deleted.

0 commit comments

Comments
 (0)