#![forbid(
anonymous_parameters,
box_pointers,
legacy_directory_ownership,
missing_copy_implementations,
missing_debug_implementations,
missing_docs,
trivial_casts,
trivial_numeric_casts,
unsafe_code,
unstable_features,
unused_extern_crates,
unused_import_braces,
unused_qualifications,
unused_results,
variant_size_differences,
warnings,
)]
extern crate ring;
use ring::{aead, error, test};
use std::vec::Vec;
#[test]
fn aead_aes_gcm_128() {
test_aead(&aead::AES_128_GCM, "tests/aead_aes_128_gcm_tests.txt");
}
#[test]
fn aead_aes_gcm_256() {
test_aead(&aead::AES_256_GCM, "tests/aead_aes_256_gcm_tests.txt");
}
#[test]
fn aead_chacha20_poly1305() {
test_aead(&aead::CHACHA20_POLY1305,
"tests/aead_chacha20_poly1305_tests.txt");
}
fn test_aead(aead_alg: &'static aead::Algorithm, file_path: &str) {
test_aead_key_sizes(aead_alg);
test_aead_nonce_sizes(aead_alg).unwrap();
test::from_file(file_path, |section, test_case| {
assert_eq!(section, "");
let key_bytes = test_case.consume_bytes("KEY");
let nonce = test_case.consume_bytes("NONCE");
let plaintext = test_case.consume_bytes("IN");
let ad = test_case.consume_bytes("AD");
let mut ct = test_case.consume_bytes("CT");
let tag = test_case.consume_bytes("TAG");
let error = test_case.consume_optional_string("FAILS");
let tag_len = aead_alg.tag_len();
let mut s_in_out = plaintext.clone();
for _ in 0..tag_len {
s_in_out.push(0);
}
let s_key = aead::SealingKey::new(aead_alg, &key_bytes[..])?;
let s_result = aead::seal_in_place(&s_key, &nonce[..], &ad,
&mut s_in_out[..], tag_len);
let o_key = aead::OpeningKey::new(aead_alg, &key_bytes[..])?;
ct.extend(tag);
static MINIMAL_IN_PREFIX_LENS: [usize; 36] = [
0,
1,
2,
5,
8,
5 + 8 ,
15, 16, 17,
31, 32, 33,
47, 48, 49,
63, 64, 65,
79, 80, 81,
95, 96, 97,
111, 112, 113,
127, 128, 129,
143, 144, 145,
255, 256, 257, ];
let mut more_comprehensive_in_prefix_lengths = [0; 4096];
let in_prefix_lengths;
if cfg!(debug_assertions) {
in_prefix_lengths = &MINIMAL_IN_PREFIX_LENS[..];
} else {
for b in 0..more_comprehensive_in_prefix_lengths.len() {
more_comprehensive_in_prefix_lengths[b] = b;
}
in_prefix_lengths = &more_comprehensive_in_prefix_lengths[..];
}
let mut o_in_out = vec![123u8; 4096];
for in_prefix_len in in_prefix_lengths.iter() {
o_in_out.truncate(0);
for _ in 0..*in_prefix_len {
o_in_out.push(123);
}
o_in_out.extend_from_slice(&ct[..]);
let o_result = aead::open_in_place(&o_key, &nonce[..], &ad,
*in_prefix_len,
&mut o_in_out[..]);
match error {
None => {
assert_eq!(Ok(ct.len()), s_result);
assert_eq!(&ct[..], &s_in_out[..ct.len()]);
assert_eq!(&plaintext[..], o_result.unwrap());
},
Some(ref error) if error == "WRONG_NONCE_LENGTH" => {
assert_eq!(Err(error::Unspecified), s_result);
assert_eq!(Err(error::Unspecified), o_result);
},
Some(error) => {
unreachable!("Unexpected error test case: {}", error);
},
};
}
Ok(())
});
}
fn test_aead_key_sizes(aead_alg: &'static aead::Algorithm) {
let key_len = aead_alg.key_len();
let key_data = vec![0u8; key_len * 2];
assert!(aead::OpeningKey::new(aead_alg, &key_data[..key_len]).is_ok());
assert!(aead::SealingKey::new(aead_alg, &key_data[..key_len]).is_ok());
assert!(aead::OpeningKey::new(aead_alg, &key_data[..(key_len - 1)])
.is_err());
assert!(aead::SealingKey::new(aead_alg, &key_data[..(key_len - 1)])
.is_err());
assert!(aead::OpeningKey::new(aead_alg, &key_data[..(key_len + 1)])
.is_err());
assert!(aead::SealingKey::new(aead_alg, &key_data[..(key_len + 1)])
.is_err());
assert!(aead::OpeningKey::new(aead_alg, &key_data[..(key_len / 2)])
.is_err());
assert!(aead::SealingKey::new(aead_alg, &key_data[..(key_len / 2)])
.is_err());
assert!(aead::OpeningKey::new(aead_alg, &key_data[..(key_len * 2)])
.is_err());
assert!(aead::SealingKey::new(aead_alg, &key_data[..(key_len * 2)])
.is_err());
assert!(aead::OpeningKey::new(aead_alg, &[]).is_err());
assert!(aead::SealingKey::new(aead_alg, &[]).is_err());
assert!(aead::OpeningKey::new(aead_alg, &[0]).is_err());
assert!(aead::SealingKey::new(aead_alg, &[0]).is_err());
}
fn test_aead_nonce_sizes(aead_alg: &'static aead::Algorithm)
-> Result<(), error::Unspecified> {
let key_len = aead_alg.key_len();
let key_data = vec![0u8; key_len];
let s_key = aead::SealingKey::new(aead_alg, &key_data[..key_len])?;
let o_key = aead::OpeningKey::new(aead_alg, &key_data[..key_len])?;
let nonce_len = aead_alg.nonce_len();
let nonce = vec![0u8; nonce_len * 2];
let prefix_len = 0;
let tag_len = aead_alg.tag_len();
let ad: [u8; 0] = [];
let mut to_seal = b"hello, world".to_vec();
for _ in 0..tag_len {
to_seal.push(0);
}
let to_seal = &to_seal[..];
let mut to_open = Vec::from(to_seal);
let ciphertext_len =
aead::seal_in_place(&s_key, &nonce[..nonce_len], &ad, &mut to_open,
tag_len)?;
let to_open = &to_open[..ciphertext_len];
{
let mut in_out = Vec::from(to_seal);
assert!(aead::seal_in_place(&s_key, &nonce[..nonce_len], &ad,
&mut in_out, tag_len).is_ok());
}
{
let mut in_out = Vec::from(to_open);
assert!(aead::open_in_place(&o_key, &nonce[..nonce_len], &ad,
prefix_len, &mut in_out).is_ok());
}
{
let mut in_out = Vec::from(to_seal);
assert!(aead::seal_in_place(&s_key, &nonce[..(nonce_len - 1)], &ad,
&mut in_out, tag_len).is_err());
}
{
let mut in_out = Vec::from(to_open);
assert!(aead::open_in_place(&o_key, &nonce[..(nonce_len - 1)], &ad,
prefix_len, &mut in_out).is_err());
}
{
let mut in_out = Vec::from(to_seal);
assert!(aead::seal_in_place(&s_key, &nonce[..(nonce_len + 1)], &ad,
&mut in_out, tag_len).is_err());
}
{
let mut in_out = Vec::from(to_open);
assert!(aead::open_in_place(&o_key, &nonce[..(nonce_len + 1)], &ad,
prefix_len, &mut in_out).is_err());
}
{
let mut in_out = Vec::from(to_seal);
assert!(aead::seal_in_place(&s_key, &nonce[..(nonce_len / 2)], &ad,
&mut in_out, tag_len).is_err());
}
{
let mut in_out = Vec::from(to_open);
assert!(aead::open_in_place(&o_key, &nonce[..(nonce_len / 2)], &ad,
prefix_len, &mut in_out).is_err());
}
{
let mut in_out = Vec::from(to_seal);
assert!(aead::seal_in_place(&s_key, &nonce[..(nonce_len * 2)], &ad,
&mut in_out, tag_len).is_err());
}
{
let mut in_out = Vec::from(to_open);
assert!(aead::open_in_place(&o_key, &nonce[..(nonce_len * 2)], &ad,
prefix_len, &mut in_out).is_err());
}
{
let mut in_out = Vec::from(to_seal);
assert!(aead::seal_in_place(&s_key, &[], &ad, &mut in_out, tag_len)
.is_err());
}
{
let mut in_out = Vec::from(to_open);
assert!(aead::open_in_place(&o_key, &[], &ad, prefix_len,
&mut in_out).is_err());
}
{
let mut in_out = Vec::from(to_seal);
assert!(aead::seal_in_place(&s_key, &nonce[..1], &ad, &mut in_out,
tag_len).is_err());
}
{
let mut in_out = Vec::from(to_open);
assert!(aead::open_in_place(&o_key, &nonce[..1], &ad, prefix_len,
&mut in_out).is_err());
}
{
let mut in_out = Vec::from(to_seal);
assert!(aead::seal_in_place(&s_key, &nonce[..16], &ad, &mut in_out,
tag_len).is_err());
}
{
let mut in_out = Vec::from(to_open);
assert!(aead::open_in_place(&o_key, &nonce[..16], &ad, prefix_len,
&mut in_out).is_err());
}
Ok(())
}