Stub out ChaCha20Poly1305RFC when fuzzing
authorMatt Corallo <git@bluematt.me>
Mon, 19 Mar 2018 21:34:51 +0000 (17:34 -0400)
committerMatt Corallo <git@bluematt.me>
Fri, 23 Mar 2018 17:16:24 +0000 (13:16 -0400)
src/util/chacha20poly1305rfc.rs

index f9391db01f727741c76a4c7c912da37ee30f6df8..9c86d44b4949e24e86abcc043d5c2de885cef7c1 100644 (file)
 // 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;
-
-use util::byte_utils;
-
-#[derive(Clone, Copy)]
-pub struct ChaCha20Poly1305RFC {
-    cipher  : ChaCha20,
-    mac: Poly1305,
-    finished: bool,
-    data_len: usize,
-    aad_len: u64,
+#[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;
+
+       #[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
+                       }
+               }
+       }
 }
-
-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;
+
+#[cfg(feature = "fuzztarget")]
+mod fuzzy_chachapoly {
+       use crypto::aead::{AeadEncryptor,AeadDecryptor};
+
+       #[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);
+
+                       // 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 tag = [0; 16];
+                       tag.copy_from_slice(&key[0..16]);
+
+                       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;