Stub out ChaCha20Poly1305RFC when fuzzing

This commit is contained in:
Matt Corallo 2018-03-19 17:34:51 -04:00
parent d18e54bd90
commit d0a3d0f728

View File

@ -10,93 +10,151 @@
// This is a port of Andrew Moons poly1305-donna
// https://github.com/floodyberry/poly1305-donna
use crypto::aead::{AeadEncryptor,AeadDecryptor};
use crypto::chacha20::ChaCha20;
use crypto::symmetriccipher::SynchronousStreamCipher;
use crypto::poly1305::Poly1305;
use crypto::mac::Mac;
use crypto::util::fixed_time_eq;
#[cfg(not(feature = "fuzztarget"))]
mod real_chachapoly {
use crypto::aead::{AeadEncryptor,AeadDecryptor};
use crypto::chacha20::ChaCha20;
use crypto::symmetriccipher::SynchronousStreamCipher;
use crypto::poly1305::Poly1305;
use crypto::mac::Mac;
use crypto::util::fixed_time_eq;
use util::byte_utils;
use util::byte_utils;
#[derive(Clone, Copy)]
pub struct ChaCha20Poly1305RFC {
cipher : ChaCha20,
mac: Poly1305,
finished: bool,
data_len: usize,
aad_len: u64,
#[derive(Clone, Copy)]
pub struct ChaCha20Poly1305RFC {
cipher : ChaCha20,
mac: Poly1305,
finished: bool,
data_len: usize,
aad_len: u64,
}
impl ChaCha20Poly1305RFC {
#[inline]
fn pad_mac_16(mac: &mut Poly1305, len: usize) {
if len % 16 != 0 {
mac.input(&[0; 16][0..16 - (len % 16)]);
}
}
pub fn new(key: &[u8], nonce: &[u8], aad: &[u8]) -> ChaCha20Poly1305RFC {
assert!(key.len() == 16 || key.len() == 32);
assert!(nonce.len() == 12);
// Ehh, I'm too lazy to *also* tweak ChaCha20 to make it RFC-compliant
assert!(nonce[0] == 0 && nonce[1] == 0 && nonce[2] == 0 && nonce[3] == 0);
let mut cipher = ChaCha20::new(key, &nonce[4..]);
let mut mac_key = [0u8; 64];
let zero_key = [0u8; 64];
cipher.process(&zero_key, &mut mac_key);
let mut mac = Poly1305::new(&mac_key[..32]);
mac.input(aad);
ChaCha20Poly1305RFC::pad_mac_16(&mut mac, aad.len());
ChaCha20Poly1305RFC {
cipher: cipher,
mac: mac,
finished: false,
data_len: 0,
aad_len: aad.len() as u64,
}
}
}
impl AeadEncryptor for ChaCha20Poly1305RFC {
fn encrypt(&mut self, input: &[u8], output: &mut [u8], out_tag: &mut [u8]) {
assert!(input.len() == output.len());
assert!(self.finished == false);
self.cipher.process(input, output);
self.data_len += input.len();
self.mac.input(output);
ChaCha20Poly1305RFC::pad_mac_16(&mut self.mac, self.data_len);
self.finished = true;
self.mac.input(&byte_utils::le64_to_array(self.aad_len));
self.mac.input(&byte_utils::le64_to_array(self.data_len as u64));
self.mac.raw_result(out_tag);
}
}
impl AeadDecryptor for ChaCha20Poly1305RFC {
fn decrypt(&mut self, input: &[u8], output: &mut [u8], tag: &[u8]) -> bool {
assert!(input.len() == output.len());
assert!(self.finished == false);
self.finished = true;
self.mac.input(input);
self.data_len += input.len();
ChaCha20Poly1305RFC::pad_mac_16(&mut self.mac, self.data_len);
self.mac.input(&byte_utils::le64_to_array(self.aad_len));
self.mac.input(&byte_utils::le64_to_array(self.data_len as u64));
let mut calc_tag = [0u8; 16];
self.mac.raw_result(&mut calc_tag);
if fixed_time_eq(&calc_tag, tag) {
self.cipher.process(input, output);
true
} else {
false
}
}
}
}
#[cfg(not(feature = "fuzztarget"))]
pub use self::real_chachapoly::ChaCha20Poly1305RFC;
impl ChaCha20Poly1305RFC {
#[inline]
fn pad_mac_16(mac: &mut Poly1305, len: usize) {
if len % 16 != 0 {
mac.input(&[0; 16][0..16 - (len % 16)]);
}
}
pub fn new(key: &[u8], nonce: &[u8], aad: &[u8]) -> ChaCha20Poly1305RFC {
assert!(key.len() == 16 || key.len() == 32);
assert!(nonce.len() == 12);
#[cfg(feature = "fuzztarget")]
mod fuzzy_chachapoly {
use crypto::aead::{AeadEncryptor,AeadDecryptor};
// Ehh, I'm too lazy to *also* tweak ChaCha20 to make it RFC-compliant
assert!(nonce[0] == 0 && nonce[1] == 0 && nonce[2] == 0 && nonce[3] == 0);
#[derive(Clone, Copy)]
pub struct ChaCha20Poly1305RFC {
tag: [u8; 16],
finished: bool,
}
impl ChaCha20Poly1305RFC {
pub fn new(key: &[u8], nonce: &[u8], _aad: &[u8]) -> ChaCha20Poly1305RFC {
assert!(key.len() == 16 || key.len() == 32);
assert!(nonce.len() == 12);
let mut cipher = ChaCha20::new(key, &nonce[4..]);
let mut mac_key = [0u8; 64];
let zero_key = [0u8; 64];
cipher.process(&zero_key, &mut mac_key);
// Ehh, I'm too lazy to *also* tweak ChaCha20 to make it RFC-compliant
assert!(nonce[0] == 0 && nonce[1] == 0 && nonce[2] == 0 && nonce[3] == 0);
let mut mac = Poly1305::new(&mac_key[..32]);
mac.input(aad);
ChaCha20Poly1305RFC::pad_mac_16(&mut mac, aad.len());
let mut tag = [0; 16];
tag.copy_from_slice(&key[0..16]);
ChaCha20Poly1305RFC {
cipher: cipher,
mac: mac,
finished: false,
data_len: 0,
aad_len: aad.len() as u64,
}
}
}
impl AeadEncryptor for ChaCha20Poly1305RFC {
fn encrypt(&mut self, input: &[u8], output: &mut [u8], out_tag: &mut [u8]) {
assert!(input.len() == output.len());
assert!(self.finished == false);
self.cipher.process(input, output);
self.data_len += input.len();
self.mac.input(output);
ChaCha20Poly1305RFC::pad_mac_16(&mut self.mac, self.data_len);
self.finished = true;
self.mac.input(&byte_utils::le64_to_array(self.aad_len));
self.mac.input(&byte_utils::le64_to_array(self.data_len as u64));
self.mac.raw_result(out_tag);
}
}
impl AeadDecryptor for ChaCha20Poly1305RFC {
fn decrypt(&mut self, input: &[u8], output: &mut [u8], tag: &[u8]) -> bool {
assert!(input.len() == output.len());
assert!(self.finished == false);
self.finished = true;
self.mac.input(input);
self.data_len += input.len();
ChaCha20Poly1305RFC::pad_mac_16(&mut self.mac, self.data_len);
self.mac.input(&byte_utils::le64_to_array(self.aad_len));
self.mac.input(&byte_utils::le64_to_array(self.data_len as u64));
let mut calc_tag = [0u8; 16];
self.mac.raw_result(&mut calc_tag);
if fixed_time_eq(&calc_tag, tag) {
self.cipher.process(input, output);
true
} else {
false
}
}
ChaCha20Poly1305RFC {
tag,
finished: false,
}
}
}
impl AeadEncryptor for ChaCha20Poly1305RFC {
fn encrypt(&mut self, input: &[u8], output: &mut [u8], out_tag: &mut [u8]) {
assert!(input.len() == output.len());
assert!(self.finished == false);
output.copy_from_slice(&input);
out_tag.copy_from_slice(&self.tag);
self.finished = true;
}
}
impl AeadDecryptor for ChaCha20Poly1305RFC {
fn decrypt(&mut self, input: &[u8], output: &mut [u8], tag: &[u8]) -> bool {
assert!(input.len() == output.len());
assert!(self.finished == false);
if tag[..] != self.tag[..] { return false; }
output.copy_from_slice(input);
self.finished = true;
true
}
}
}
#[cfg(feature = "fuzztarget")]
pub use self::fuzzy_chachapoly::ChaCha20Poly1305RFC;