Move cryptographic algorithms and utilities to a new `crypto` mod 2024-01-crypto-module
authorMatt Corallo <git@bluematt.me>
Mon, 15 Jan 2024 01:25:10 +0000 (01:25 +0000)
committerMatt Corallo <git@bluematt.me>
Tue, 16 Jan 2024 20:07:08 +0000 (20:07 +0000)
As we'd generally like the `lightning` crate to, over time, have
more modules rather than being very monolithic, we should move the
cryptographic things into their own module, which we do here.

We also take this opportunity to move stream adapters into their
own module and make clear that the ChaChaPoly `decrypt` method is
variable time.

25 files changed:
lightning/src/blinded_path/message.rs
lightning/src/blinded_path/utils.rs
lightning/src/chain/channelmonitor.rs
lightning/src/crypto/chacha20.rs [new file with mode: 0644]
lightning/src/crypto/chacha20poly1305rfc.rs [new file with mode: 0644]
lightning/src/crypto/mod.rs [new file with mode: 0644]
lightning/src/crypto/poly1305.rs [new file with mode: 0644]
lightning/src/crypto/streams.rs [new file with mode: 0644]
lightning/src/crypto/utils.rs [new file with mode: 0644]
lightning/src/lib.rs
lightning/src/ln/chan_utils.rs
lightning/src/ln/inbound_payment.rs
lightning/src/ln/monitor_tests.rs
lightning/src/ln/msgs.rs
lightning/src/ln/onion_utils.rs
lightning/src/ln/peer_channel_encryptor.rs
lightning/src/onion_message/packet.rs
lightning/src/routing/router.rs
lightning/src/sign/mod.rs
lightning/src/util/chacha20.rs [deleted file]
lightning/src/util/chacha20poly1305rfc.rs [deleted file]
lightning/src/util/crypto.rs [deleted file]
lightning/src/util/mod.rs
lightning/src/util/poly1305.rs [deleted file]
lightning/src/util/scid_utils.rs

index 2631a05f660c4e886a6db37d9e8fa3b6e76f6708..3a5541fa1468272f3859972bca2cdfb4f8053ee8 100644 (file)
@@ -8,7 +8,7 @@ use crate::ln::onion_utils;
 use crate::onion_message::packet::ControlTlvs;
 use crate::prelude::*;
 use crate::sign::{NodeSigner, Recipient};
-use crate::util::chacha20poly1305rfc::ChaChaPolyReadAdapter;
+use crate::crypto::streams::ChaChaPolyReadAdapter;
 use crate::util::ser::{FixedLengthReader, LengthReadableArgs, Writeable, Writer};
 
 use core::mem;
index 7ddb39c1b68fbce0a93fca0637e604b70b393b90..d4894a86aa1a9069abdc9b2e073cd0a31c789048 100644 (file)
@@ -19,7 +19,7 @@ use super::{BlindedHop, BlindedPath};
 use crate::ln::msgs::DecodeError;
 use crate::ln::onion_utils;
 use crate::onion_message::messenger::Destination;
-use crate::util::chacha20poly1305rfc::ChaChaPolyWriteAdapter;
+use crate::crypto::streams::ChaChaPolyWriteAdapter;
 use crate::util::ser::{Readable, Writeable};
 
 use crate::io;
index bcc324a5582af9d0f6c399034d7cf4e0b2327161..c81a48b78ac8b4aa6fba1facae191f7190e27d51 100644 (file)
@@ -4808,7 +4808,7 @@ mod tests {
                                preimages_slice_to_htlcs!($preimages_slice).into_iter().map(|(htlc, _)| (htlc, None)).collect()
                        }
                }
-               let dummy_sig = crate::util::crypto::sign(&secp_ctx,
+               let dummy_sig = crate::crypto::utils::sign(&secp_ctx,
                        &bitcoin::secp256k1::Message::from_slice(&[42; 32]).unwrap(),
                        &SecretKey::from_slice(&[42; 32]).unwrap());
 
diff --git a/lightning/src/crypto/chacha20.rs b/lightning/src/crypto/chacha20.rs
new file mode 100644 (file)
index 0000000..d6fd3a7
--- /dev/null
@@ -0,0 +1,686 @@
+// This file was stolen from rust-crypto.
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+#[cfg(not(fuzzing))]
+mod real_chacha {
+       use core::cmp;
+       use core::convert::TryInto;
+
+       #[derive(Clone, Copy, PartialEq, Eq)]
+       #[allow(non_camel_case_types)]
+       struct u32x4(pub u32, pub u32, pub u32, pub u32);
+       impl ::core::ops::Add for u32x4 {
+               type Output = u32x4;
+               #[inline]
+               fn add(self, rhs: u32x4) -> u32x4 {
+                       u32x4(self.0.wrapping_add(rhs.0),
+                             self.1.wrapping_add(rhs.1),
+                             self.2.wrapping_add(rhs.2),
+                             self.3.wrapping_add(rhs.3))
+               }
+       }
+       impl ::core::ops::Sub for u32x4 {
+               type Output = u32x4;
+               #[inline]
+               fn sub(self, rhs: u32x4) -> u32x4 {
+                       u32x4(self.0.wrapping_sub(rhs.0),
+                             self.1.wrapping_sub(rhs.1),
+                             self.2.wrapping_sub(rhs.2),
+                             self.3.wrapping_sub(rhs.3))
+               }
+       }
+       impl ::core::ops::BitXor for u32x4 {
+               type Output = u32x4;
+               #[inline]
+               fn bitxor(self, rhs: u32x4) -> u32x4 {
+                       u32x4(self.0 ^ rhs.0, self.1 ^ rhs.1, self.2 ^ rhs.2, self.3 ^ rhs.3)
+               }
+       }
+       impl ::core::ops::Shr<u8> for u32x4 {
+               type Output = u32x4;
+               #[inline]
+               fn shr(self, shr: u8) -> u32x4 {
+                       u32x4(self.0 >> shr, self.1 >> shr, self.2 >> shr, self.3 >> shr)
+               }
+       }
+       impl ::core::ops::Shl<u8> for u32x4 {
+               type Output = u32x4;
+               #[inline]
+               fn shl(self, shl: u8) -> u32x4 {
+                       u32x4(self.0 << shl, self.1 << shl, self.2 << shl, self.3 << shl)
+               }
+       }
+       impl u32x4 {
+               #[inline]
+               fn from_bytes(bytes: &[u8]) -> Self {
+                       assert_eq!(bytes.len(), 4*4);
+                       Self (
+                               u32::from_le_bytes(bytes[0*4..1*4].try_into().expect("len is 4")),
+                               u32::from_le_bytes(bytes[1*4..2*4].try_into().expect("len is 4")),
+                               u32::from_le_bytes(bytes[2*4..3*4].try_into().expect("len is 4")),
+                               u32::from_le_bytes(bytes[3*4..4*4].try_into().expect("len is 4")),
+                       )
+               }
+       }
+
+       const BLOCK_SIZE: usize = 64;
+
+       #[derive(Clone,Copy)]
+       struct ChaChaState {
+               a: u32x4,
+               b: u32x4,
+               c: u32x4,
+               d: u32x4
+       }
+
+       #[derive(Copy)]
+       pub struct ChaCha20 {
+               state  : ChaChaState,
+               output : [u8; BLOCK_SIZE],
+               offset : usize,
+       }
+
+       impl Clone for ChaCha20 { fn clone(&self) -> ChaCha20 { *self } }
+
+       macro_rules! swizzle {
+               ($b: expr, $c: expr, $d: expr) => {{
+                       let u32x4(b10, b11, b12, b13) = $b;
+                       $b = u32x4(b11, b12, b13, b10);
+                       let u32x4(c10, c11, c12, c13) = $c;
+                       $c = u32x4(c12, c13,c10, c11);
+                       let u32x4(d10, d11, d12, d13) = $d;
+                       $d = u32x4(d13, d10, d11, d12);
+               }}
+       }
+
+       macro_rules! state_to_buffer {
+               ($state: expr, $output: expr) => {{
+                       let u32x4(a1, a2, a3, a4) = $state.a;
+                       let u32x4(b1, b2, b3, b4) = $state.b;
+                       let u32x4(c1, c2, c3, c4) = $state.c;
+                       let u32x4(d1, d2, d3, d4) = $state.d;
+                       let lens = [
+                               a1,a2,a3,a4,
+                               b1,b2,b3,b4,
+                               c1,c2,c3,c4,
+                               d1,d2,d3,d4
+                       ];
+                       for i in 0..lens.len() {
+                               $output[i*4..(i+1)*4].copy_from_slice(&lens[i].to_le_bytes());
+                       }
+               }}
+       }
+
+       macro_rules! round{
+               ($state: expr) => {{
+                       $state.a = $state.a + $state.b;
+                       rotate!($state.d, $state.a, 16);
+                       $state.c = $state.c + $state.d;
+                       rotate!($state.b, $state.c, 12);
+                       $state.a = $state.a + $state.b;
+                       rotate!($state.d, $state.a, 8);
+                       $state.c = $state.c + $state.d;
+                       rotate!($state.b, $state.c, 7);
+               }}
+       }
+
+       macro_rules! rotate {
+               ($a: expr, $b: expr, $rot: expr) => {{
+                       let v = $a ^ $b;
+                       let r = 32 - $rot;
+                       let right = v >> r;
+                       $a = (v << $rot) ^ right
+               }}
+       }
+
+       impl ChaCha20 {
+               pub fn new(key: &[u8], nonce: &[u8]) -> ChaCha20 {
+                       assert!(key.len() == 16 || key.len() == 32);
+                       assert!(nonce.len() == 8 || nonce.len() == 12);
+
+                       ChaCha20{ state: ChaCha20::expand(key, nonce), output: [0u8; BLOCK_SIZE], offset: 64 }
+               }
+
+               /// Get one block from a ChaCha stream.
+               pub fn get_single_block(key: &[u8; 32], nonce: &[u8; 16]) -> [u8; 32] {
+                       let mut chacha = ChaCha20 { state: ChaCha20::expand(key, nonce), output: [0u8; BLOCK_SIZE], offset: 64 };
+                       let mut chacha_bytes = [0; 32];
+                       chacha.process_in_place(&mut chacha_bytes);
+                       chacha_bytes
+               }
+
+               /// Encrypts `src` into `dest` using a single block from a ChaCha stream. Passing `dest` as
+               /// `src` in a second call will decrypt it.
+               pub fn encrypt_single_block(
+                       key: &[u8; 32], nonce: &[u8; 16], dest: &mut [u8], src: &[u8]
+               ) {
+                       debug_assert_eq!(dest.len(), src.len());
+                       debug_assert!(dest.len() <= 32);
+
+                       let block = ChaCha20::get_single_block(key, nonce);
+                       for i in 0..dest.len() {
+                               dest[i] = block[i] ^ src[i];
+                       }
+               }
+
+               /// Same as `encrypt_single_block` only operates on a fixed-size input in-place.
+               pub fn encrypt_single_block_in_place(
+                       key: &[u8; 32], nonce: &[u8; 16], bytes: &mut [u8; 32]
+               ) {
+                       let block = ChaCha20::get_single_block(key, nonce);
+                       for i in 0..bytes.len() {
+                               bytes[i] = block[i] ^ bytes[i];
+                       }
+               }
+
+               fn expand(key: &[u8], nonce: &[u8]) -> ChaChaState {
+                       let constant = match key.len() {
+                               16 => b"expand 16-byte k",
+                               32 => b"expand 32-byte k",
+                               _  => unreachable!(),
+                       };
+                       ChaChaState {
+                               a: u32x4::from_bytes(&constant[0..16]),
+                               b: u32x4::from_bytes(&key[0..16]),
+                               c: if key.len() == 16 {
+                                       u32x4::from_bytes(&key[0..16])
+                               } else {
+                                       u32x4::from_bytes(&key[16..32])
+                               },
+                               d: if nonce.len() == 16 {
+                                       u32x4::from_bytes(&nonce[0..16])
+                               } else if nonce.len() == 12 {
+                                       let mut nonce4 = [0; 4*4];
+                                       nonce4[4..].copy_from_slice(nonce);
+                                       u32x4::from_bytes(&nonce4)
+                               } else {
+                                       let mut nonce4 = [0; 4*4];
+                                       nonce4[8..].copy_from_slice(nonce);
+                                       u32x4::from_bytes(&nonce4)
+                               }
+                       }
+               }
+
+               // put the the next BLOCK_SIZE keystream bytes into self.output
+               fn update(&mut self) {
+                       let mut state = self.state;
+
+                       for _ in 0..10 {
+                               round!(state);
+                               swizzle!(state.b, state.c, state.d);
+                               round!(state);
+                               swizzle!(state.d, state.c, state.b);
+                       }
+                       state.a = state.a + self.state.a;
+                       state.b = state.b + self.state.b;
+                       state.c = state.c + self.state.c;
+                       state.d = state.d + self.state.d;
+
+                       state_to_buffer!(state, self.output);
+
+                       self.state.d = self.state.d + u32x4(1, 0, 0, 0);
+                       let u32x4(c12, _, _, _) = self.state.d;
+                       if c12 == 0 {
+                               // we could increment the other counter word with an 8 byte nonce
+                               // but other implementations like boringssl have this same
+                               // limitation
+                               panic!("counter is exhausted");
+                       }
+
+                       self.offset = 0;
+               }
+
+               #[inline] // Useful cause input may be 0s on stack that should be optimized out
+               pub fn process(&mut self, input: &[u8], output: &mut [u8]) {
+                       assert!(input.len() == output.len());
+                       let len = input.len();
+                       let mut i = 0;
+                       while i < len {
+                               // If there is no keystream available in the output buffer,
+                               // generate the next block.
+                               if self.offset == BLOCK_SIZE {
+                                       self.update();
+                               }
+
+                               // Process the min(available keystream, remaining input length).
+                               let count = cmp::min(BLOCK_SIZE - self.offset, len - i);
+                               // explicitly assert lengths to avoid bounds checks:
+                               assert!(output.len() >= i + count);
+                               assert!(input.len() >= i + count);
+                               assert!(self.output.len() >= self.offset + count);
+                               for j in 0..count {
+                                       output[i + j] = input[i + j] ^ self.output[self.offset + j];
+                               }
+                               i += count;
+                               self.offset += count;
+                       }
+               }
+
+               pub fn process_in_place(&mut self, input_output: &mut [u8]) {
+                       let len = input_output.len();
+                       let mut i = 0;
+                       while i < len {
+                               // If there is no keystream available in the output buffer,
+                               // generate the next block.
+                               if self.offset == BLOCK_SIZE {
+                                       self.update();
+                               }
+
+                               // Process the min(available keystream, remaining input length).
+                               let count = cmp::min(BLOCK_SIZE - self.offset, len - i);
+                               // explicitly assert lengths to avoid bounds checks:
+                               assert!(input_output.len() >= i + count);
+                               assert!(self.output.len() >= self.offset + count);
+                               for j in 0..count {
+                                       input_output[i + j] ^= self.output[self.offset + j];
+                               }
+                               i += count;
+                               self.offset += count;
+                       }
+               }
+
+               #[cfg(test)]
+               pub fn seek_to_block(&mut self, block_offset: u32) {
+                       self.state.d.0 = block_offset;
+                       self.update();
+               }
+       }
+}
+#[cfg(not(fuzzing))]
+pub use self::real_chacha::ChaCha20;
+
+#[cfg(fuzzing)]
+mod fuzzy_chacha {
+       pub struct ChaCha20 {}
+
+       impl ChaCha20 {
+               pub fn new(key: &[u8], nonce: &[u8]) -> ChaCha20 {
+                       assert!(key.len() == 16 || key.len() == 32);
+                       assert!(nonce.len() == 8 || nonce.len() == 12);
+                       Self {}
+               }
+
+               pub fn get_single_block(_key: &[u8; 32], _nonce: &[u8; 16]) -> [u8; 32] {
+                       [0; 32]
+               }
+
+               pub fn encrypt_single_block(
+                       _key: &[u8; 32], _nonce: &[u8; 16], dest: &mut [u8], src: &[u8]
+               ) {
+                       debug_assert_eq!(dest.len(), src.len());
+                       debug_assert!(dest.len() <= 32);
+               }
+
+               pub fn encrypt_single_block_in_place(
+                       _key: &[u8; 32], _nonce: &[u8; 16], _bytes: &mut [u8; 32]
+               ) {}
+
+               pub fn process(&mut self, input: &[u8], output: &mut [u8]) {
+                       output.copy_from_slice(input);
+               }
+
+               pub fn process_in_place(&mut self, _input_output: &mut [u8]) {}
+       }
+}
+#[cfg(fuzzing)]
+pub use self::fuzzy_chacha::ChaCha20;
+
+#[cfg(test)]
+mod test {
+       use alloc::vec;
+       use alloc::vec::{Vec};
+       use core::convert::TryInto;
+       use core::iter::repeat;
+
+       use super::ChaCha20;
+
+       #[test]
+       fn test_chacha20_256_tls_vectors() {
+               struct TestVector {
+                       key:   [u8; 32],
+                       nonce: [u8; 8],
+                       keystream: Vec<u8>,
+               }
+               // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
+               let test_vectors = vec!(
+                       TestVector{
+                               key: [
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               ],
+                               nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
+                               keystream: vec!(
+                                       0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
+                                       0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
+                                       0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
+                                       0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
+                                       0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
+                                       0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
+                                       0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
+                                       0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
+                               ),
+                       }, TestVector{
+                               key: [
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+                               ],
+                               nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
+                               keystream: vec!(
+                                       0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96,
+                                       0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96,
+                                       0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60,
+                                       0x4f, 0x45, 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41,
+                                       0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, 0xd2,
+                                       0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c,
+                                       0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81,
+                                       0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
+                               ),
+                       }, TestVector{
+                               key: [
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               ],
+                               nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ],
+                               keystream: vec!(
+                                       0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5,
+                                       0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a,
+                                       0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13,
+                                       0x4f, 0xcb, 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31,
+                                       0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, 0x45,
+                                       0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b,
+                                       0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e,
+                                       0x44, 0x5f, 0x41, 0xe3,
+                               ),
+                       }, TestVector{
+                               key: [
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               ],
+                               nonce: [ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
+                               keystream: vec!(
+                                       0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
+                                       0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
+                                       0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac,
+                                       0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32,
+                                       0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c,
+                                       0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54,
+                                       0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d,
+                                       0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
+                               ),
+                       }, TestVector{
+                               key: [
+                                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                                       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+                                       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+                                       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+                               ],
+                               nonce: [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ],
+                               keystream: vec!(
+                                       0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69,
+                                       0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75,
+                                       0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93,
+                                       0xec, 0x01, 0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1,
+                                       0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, 0x41,
+                                       0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69,
+                                       0x05, 0xd3, 0xbe, 0x59, 0xea, 0x1c, 0x53, 0xf1,
+                                       0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a,
+                                       0x38, 0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94,
+                                       0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, 0xde, 0x66,
+                                       0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58,
+                                       0x89, 0xfb, 0x60, 0xe8, 0x46, 0x29, 0xc9, 0xbd,
+                                       0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56,
+                                       0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e,
+                                       0x09, 0xa7, 0xe7, 0x78, 0x49, 0x2b, 0x56, 0x2e,
+                                       0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7,
+                                       0x9d, 0xb9, 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15,
+                                       0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f, 0xc3,
+                                       0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a,
+                                       0x97, 0xa5, 0xf5, 0x76, 0xfe, 0x06, 0x40, 0x25,
+                                       0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5,
+                                       0x07, 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69,
+                                       0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, 0xc9, 0xc4,
+                                       0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7,
+                                       0x0e, 0xaf, 0x46, 0xf7, 0x6d, 0xad, 0x39, 0x79,
+                                       0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a,
+                                       0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a,
+                                       0x94, 0xdf, 0x76, 0x28, 0xfe, 0x4e, 0xaa, 0xf2,
+                                       0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a,
+                                       0xd0, 0xf9, 0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09,
+                                       0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a,
+                                       0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9,
+                               ),
+                       },
+               );
+
+               for tv in test_vectors.iter() {
+                       let mut c = ChaCha20::new(&tv.key, &tv.nonce);
+                       let input: Vec<u8> = repeat(0).take(tv.keystream.len()).collect();
+                       let mut output: Vec<u8> = repeat(0).take(input.len()).collect();
+                       c.process(&input[..], &mut output[..]);
+                       assert_eq!(output, tv.keystream);
+               }
+       }
+
+       #[test]
+       fn test_chacha20_256_tls_vectors_96_nonce() {
+               struct TestVector {
+                       key:   [u8; 32],
+                       nonce: [u8; 12],
+                       keystream: Vec<u8>,
+               }
+               // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
+               let test_vectors = vec!(
+                       TestVector{
+                               key: [
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               ],
+                               nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
+                               keystream: vec!(
+                                       0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
+                                       0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
+                                       0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
+                                       0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
+                                       0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
+                                       0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
+                                       0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
+                                       0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
+                               ),
+                       }, TestVector{
+                               key: [
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+                               ],
+                               nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
+                               keystream: vec!(
+                                       0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96,
+                                       0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96,
+                                       0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60,
+                                       0x4f, 0x45, 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41,
+                                       0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, 0xd2,
+                                       0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c,
+                                       0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81,
+                                       0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
+                               ),
+                       }, TestVector{
+                               key: [
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               ],
+                               nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ],
+                               keystream: vec!(
+                                       0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5,
+                                       0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a,
+                                       0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13,
+                                       0x4f, 0xcb, 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31,
+                                       0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, 0x45,
+                                       0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b,
+                                       0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e,
+                                       0x44, 0x5f, 0x41, 0xe3,
+                               ),
+                       }, TestVector{
+                               key: [
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               ],
+                               nonce: [ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
+                               keystream: vec!(
+                                       0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
+                                       0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
+                                       0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac,
+                                       0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32,
+                                       0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c,
+                                       0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54,
+                                       0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d,
+                                       0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
+                               ),
+                       }, TestVector{
+                               key: [
+                                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                                       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+                                       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+                                       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+                               ],
+                               nonce: [0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ],
+                               keystream: vec!(
+                                       0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69,
+                                       0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75,
+                                       0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93,
+                                       0xec, 0x01, 0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1,
+                                       0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, 0x41,
+                                       0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69,
+                                       0x05, 0xd3, 0xbe, 0x59, 0xea, 0x1c, 0x53, 0xf1,
+                                       0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a,
+                                       0x38, 0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94,
+                                       0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, 0xde, 0x66,
+                                       0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58,
+                                       0x89, 0xfb, 0x60, 0xe8, 0x46, 0x29, 0xc9, 0xbd,
+                                       0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56,
+                                       0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e,
+                                       0x09, 0xa7, 0xe7, 0x78, 0x49, 0x2b, 0x56, 0x2e,
+                                       0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7,
+                                       0x9d, 0xb9, 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15,
+                                       0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f, 0xc3,
+                                       0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a,
+                                       0x97, 0xa5, 0xf5, 0x76, 0xfe, 0x06, 0x40, 0x25,
+                                       0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5,
+                                       0x07, 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69,
+                                       0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, 0xc9, 0xc4,
+                                       0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7,
+                                       0x0e, 0xaf, 0x46, 0xf7, 0x6d, 0xad, 0x39, 0x79,
+                                       0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a,
+                                       0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a,
+                                       0x94, 0xdf, 0x76, 0x28, 0xfe, 0x4e, 0xaa, 0xf2,
+                                       0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a,
+                                       0xd0, 0xf9, 0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09,
+                                       0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a,
+                                       0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9,
+                               ),
+                       },
+               );
+
+               for tv in test_vectors.iter() {
+                       let mut c = ChaCha20::new(&tv.key, &tv.nonce);
+                       let input: Vec<u8> = repeat(0).take(tv.keystream.len()).collect();
+                       let mut output: Vec<u8> = repeat(0).take(input.len()).collect();
+                       c.process(&input[..], &mut output[..]);
+                       assert_eq!(output, tv.keystream);
+               }
+       }
+
+       #[test]
+       fn get_single_block() {
+               // Test that `get_single_block` (which takes a 16-byte nonce) is equivalent to getting a block
+               // using a 12-byte nonce, with the block starting at the counter offset given by the remaining 4
+               // bytes.
+               let key = [
+                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+                       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+                       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+               ];
+               let nonce_16bytes = [
+                       0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b
+               ];
+               let counter_pos = &nonce_16bytes[..4];
+               let nonce_12bytes = &nonce_16bytes[4..];
+
+               // Initialize a ChaCha20 instance with its counter starting at 0.
+               let mut chacha20 = ChaCha20::new(&key, nonce_12bytes);
+               // Seek its counter to the block at counter_pos.
+               chacha20.seek_to_block(u32::from_le_bytes(counter_pos.try_into().unwrap()));
+               let mut block_bytes = [0; 32];
+               chacha20.process_in_place(&mut block_bytes);
+
+               assert_eq!(ChaCha20::get_single_block(&key, &nonce_16bytes), block_bytes);
+       }
+
+       #[test]
+       fn encrypt_single_block() {
+               let key = [
+                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+                       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+                       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+               ];
+               let nonce = [
+                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+                       0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+               ];
+               let bytes = [1; 32];
+
+               let mut encrypted_bytes = [0; 32];
+               ChaCha20::encrypt_single_block(&key, &nonce, &mut encrypted_bytes, &bytes);
+
+               let mut decrypted_bytes = [0; 32];
+               ChaCha20::encrypt_single_block(&key, &nonce, &mut decrypted_bytes, &encrypted_bytes);
+
+               assert_eq!(bytes, decrypted_bytes);
+       }
+
+       #[test]
+       fn encrypt_single_block_in_place() {
+               let key = [
+                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+                       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+                       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+               ];
+               let nonce = [
+                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+                       0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+               ];
+               let unencrypted_bytes = [1; 32];
+               let mut bytes = unencrypted_bytes;
+
+               ChaCha20::encrypt_single_block_in_place(&key, &nonce, &mut bytes);
+               assert_ne!(bytes, unencrypted_bytes);
+
+               ChaCha20::encrypt_single_block_in_place(&key, &nonce, &mut bytes);
+               assert_eq!(bytes, unencrypted_bytes);
+       }
+}
diff --git a/lightning/src/crypto/chacha20poly1305rfc.rs b/lightning/src/crypto/chacha20poly1305rfc.rs
new file mode 100644 (file)
index 0000000..4ca9744
--- /dev/null
@@ -0,0 +1,237 @@
+// ring has a garbage API so its use is avoided, but rust-crypto doesn't have RFC-variant poly1305
+// Instead, we steal rust-crypto's implementation and tweak it to match the RFC.
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+//
+// This is a port of Andrew Moons poly1305-donna
+// https://github.com/floodyberry/poly1305-donna
+
+#[cfg(not(fuzzing))]
+mod real_chachapoly {
+       use super::super::chacha20::ChaCha20;
+       use super::super::poly1305::Poly1305;
+       use super::super::fixed_time_eq;
+
+       #[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,
+                               mac,
+                               finished: false,
+                               data_len: 0,
+                               aad_len: aad.len() as u64,
+                       }
+               }
+
+               pub 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(&self.aad_len.to_le_bytes());
+                       self.mac.input(&(self.data_len as u64).to_le_bytes());
+                       self.mac.raw_result(out_tag);
+               }
+
+               pub fn encrypt_full_message_in_place(&mut self, input_output: &mut [u8], out_tag: &mut [u8]) {
+                       self.encrypt_in_place(input_output);
+                       self.finish_and_get_tag(out_tag);
+               }
+
+               // Encrypt `input_output` in-place. To finish and calculate the tag, use `finish_and_get_tag`
+               // below.
+               pub(in super::super) fn encrypt_in_place(&mut self, input_output: &mut [u8]) {
+                       debug_assert!(self.finished == false);
+                       self.cipher.process_in_place(input_output);
+                       self.data_len += input_output.len();
+                       self.mac.input(input_output);
+               }
+
+               // If we were previously encrypting with `encrypt_in_place`, this method can be used to finish
+               // encrypting and calculate the tag.
+               pub(in super::super) fn finish_and_get_tag(&mut self, out_tag: &mut [u8]) {
+                       debug_assert!(self.finished == false);
+                       ChaCha20Poly1305RFC::pad_mac_16(&mut self.mac, self.data_len);
+                       self.finished = true;
+                       self.mac.input(&self.aad_len.to_le_bytes());
+                       self.mac.input(&(self.data_len as u64).to_le_bytes());
+                       self.mac.raw_result(out_tag);
+               }
+
+               /// Decrypt the `input`, checking the given `tag` prior to writing the decrypted contents
+               /// into `output`. Note that, because `output` is not touched until the `tag` is checked,
+               /// this decryption is *variable time*.
+               pub fn variable_time_decrypt(&mut self, input: &[u8], output: &mut [u8], tag: &[u8]) -> Result<(), ()> {
+                       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(&self.aad_len.to_le_bytes());
+                       self.mac.input(&(self.data_len as u64).to_le_bytes());
+
+                       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);
+                               Ok(())
+                       } else {
+                               Err(())
+                       }
+               }
+
+               pub fn check_decrypt_in_place(&mut self, input_output: &mut [u8], tag: &[u8]) -> Result<(), ()> {
+                       self.decrypt_in_place(input_output);
+                       if self.finish_and_check_tag(tag) { Ok(()) } else { Err(()) }
+               }
+
+               /// Decrypt in place, without checking the tag. Use `finish_and_check_tag` to check it
+               /// later when decryption finishes.
+               ///
+               /// Should never be `pub` because the public API should always enforce tag checking.
+               pub(in super::super) fn decrypt_in_place(&mut self, input_output: &mut [u8]) {
+                       debug_assert!(self.finished == false);
+                       self.mac.input(input_output);
+                       self.data_len += input_output.len();
+                       self.cipher.process_in_place(input_output);
+               }
+
+               /// If we were previously decrypting with `just_decrypt_in_place`, this method must be used
+               /// to check the tag. Returns whether or not the tag is valid.
+               pub(in super::super) fn finish_and_check_tag(&mut self, tag: &[u8]) -> bool {
+                       debug_assert!(self.finished == false);
+                       self.finished = true;
+                       ChaCha20Poly1305RFC::pad_mac_16(&mut self.mac, self.data_len);
+                       self.mac.input(&self.aad_len.to_le_bytes());
+                       self.mac.input(&(self.data_len as u64).to_le_bytes());
+
+                       let mut calc_tag =  [0u8; 16];
+                       self.mac.raw_result(&mut calc_tag);
+                       if fixed_time_eq(&calc_tag, tag) {
+                               true
+                       } else {
+                               false
+                       }
+               }
+       }
+}
+#[cfg(not(fuzzing))]
+pub use self::real_chachapoly::ChaCha20Poly1305RFC;
+
+#[cfg(fuzzing)]
+mod fuzzy_chachapoly {
+       #[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,
+                       }
+               }
+
+               pub 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;
+               }
+
+               pub fn encrypt_full_message_in_place(&mut self, input_output: &mut [u8], out_tag: &mut [u8]) {
+                       self.encrypt_in_place(input_output);
+                       self.finish_and_get_tag(out_tag);
+               }
+
+               pub(in super::super) fn encrypt_in_place(&mut self, _input_output: &mut [u8]) {
+                       assert!(self.finished == false);
+               }
+
+               pub(in super::super) fn finish_and_get_tag(&mut self, out_tag: &mut [u8]) {
+                       assert!(self.finished == false);
+                       out_tag.copy_from_slice(&self.tag);
+                       self.finished = true;
+               }
+
+               pub fn variable_time_decrypt(&mut self, input: &[u8], output: &mut [u8], tag: &[u8]) -> Result<(), ()> {
+                       assert!(input.len() == output.len());
+                       assert!(self.finished == false);
+
+                       if tag[..] != self.tag[..] { return Err(()); }
+                       output.copy_from_slice(input);
+                       self.finished = true;
+                       Ok(())
+               }
+
+               pub fn check_decrypt_in_place(&mut self, input_output: &mut [u8], tag: &[u8]) -> Result<(), ()> {
+                       self.decrypt_in_place(input_output);
+                       if self.finish_and_check_tag(tag) { Ok(()) } else { Err(()) }
+               }
+
+               pub(in super::super) fn decrypt_in_place(&mut self, _input: &mut [u8]) {
+                       assert!(self.finished == false);
+               }
+
+               pub(in super::super) fn finish_and_check_tag(&mut self, tag: &[u8]) -> bool {
+                       if tag[..] != self.tag[..] { return false; }
+                       self.finished = true;
+                       true
+               }
+       }
+}
+#[cfg(fuzzing)]
+pub use self::fuzzy_chachapoly::ChaCha20Poly1305RFC;
diff --git a/lightning/src/crypto/mod.rs b/lightning/src/crypto/mod.rs
new file mode 100644 (file)
index 0000000..6efd120
--- /dev/null
@@ -0,0 +1,8 @@
+use bitcoin::hashes::cmp::fixed_time_eq;
+
+pub(crate) mod chacha20;
+#[cfg(not(fuzzing))]
+pub(crate) mod poly1305;
+pub(crate) mod chacha20poly1305rfc;
+pub(crate) mod streams;
+pub(crate) mod utils;
diff --git a/lightning/src/crypto/poly1305.rs b/lightning/src/crypto/poly1305.rs
new file mode 100644 (file)
index 0000000..a1b9fba
--- /dev/null
@@ -0,0 +1,341 @@
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+// This is a port of Andrew Moons poly1305-donna
+// https://github.com/floodyberry/poly1305-donna
+
+use core::cmp::min;
+use core::convert::TryInto;
+
+#[derive(Clone, Copy)]
+pub struct Poly1305 {
+       r         : [u32; 5],
+       h         : [u32; 5],
+       pad       : [u32; 4],
+       leftover  : usize,
+       buffer    : [u8; 16],
+       finalized : bool,
+}
+
+impl Poly1305 {
+       pub fn new(key: &[u8]) -> Poly1305 {
+               assert!(key.len() == 32);
+               let mut poly = Poly1305{ r: [0u32; 5], h: [0u32; 5], pad: [0u32; 4], leftover: 0, buffer: [0u8; 16], finalized: false };
+
+               // r &= 0xffffffc0ffffffc0ffffffc0fffffff
+               poly.r[0] = (u32::from_le_bytes(key[ 0.. 4].try_into().expect("len is 4"))     ) & 0x3ffffff;
+               poly.r[1] = (u32::from_le_bytes(key[ 3.. 7].try_into().expect("len is 4")) >> 2) & 0x3ffff03;
+               poly.r[2] = (u32::from_le_bytes(key[ 6..10].try_into().expect("len is 4")) >> 4) & 0x3ffc0ff;
+               poly.r[3] = (u32::from_le_bytes(key[ 9..13].try_into().expect("len is 4")) >> 6) & 0x3f03fff;
+               poly.r[4] = (u32::from_le_bytes(key[12..16].try_into().expect("len is 4")) >> 8) & 0x00fffff;
+
+               poly.pad[0] = u32::from_le_bytes(key[16..20].try_into().expect("len is 4"));
+               poly.pad[1] = u32::from_le_bytes(key[20..24].try_into().expect("len is 4"));
+               poly.pad[2] = u32::from_le_bytes(key[24..28].try_into().expect("len is 4"));
+               poly.pad[3] = u32::from_le_bytes(key[28..32].try_into().expect("len is 4"));
+
+               poly
+       }
+
+       fn block(&mut self, m: &[u8]) {
+               let hibit : u32 = if self.finalized { 0 } else { 1 << 24 };
+
+               let r0 = self.r[0];
+               let r1 = self.r[1];
+               let r2 = self.r[2];
+               let r3 = self.r[3];
+               let r4 = self.r[4];
+
+               let s1 = r1 * 5;
+               let s2 = r2 * 5;
+               let s3 = r3 * 5;
+               let s4 = r4 * 5;
+
+               let mut h0 = self.h[0];
+               let mut h1 = self.h[1];
+               let mut h2 = self.h[2];
+               let mut h3 = self.h[3];
+               let mut h4 = self.h[4];
+
+               // h += m
+               h0 += (u32::from_le_bytes(m[ 0.. 4].try_into().expect("len is 4"))     ) & 0x3ffffff;
+               h1 += (u32::from_le_bytes(m[ 3.. 7].try_into().expect("len is 4")) >> 2) & 0x3ffffff;
+               h2 += (u32::from_le_bytes(m[ 6..10].try_into().expect("len is 4")) >> 4) & 0x3ffffff;
+               h3 += (u32::from_le_bytes(m[ 9..13].try_into().expect("len is 4")) >> 6) & 0x3ffffff;
+               h4 += (u32::from_le_bytes(m[12..16].try_into().expect("len is 4")) >> 8) | hibit;
+
+               // h *= r
+               let     d0 = (h0 as u64 * r0 as u64) + (h1 as u64 * s4 as u64) + (h2 as u64 * s3 as u64) + (h3 as u64 * s2 as u64) + (h4 as u64 * s1 as u64);
+               let mut d1 = (h0 as u64 * r1 as u64) + (h1 as u64 * r0 as u64) + (h2 as u64 * s4 as u64) + (h3 as u64 * s3 as u64) + (h4 as u64 * s2 as u64);
+               let mut d2 = (h0 as u64 * r2 as u64) + (h1 as u64 * r1 as u64) + (h2 as u64 * r0 as u64) + (h3 as u64 * s4 as u64) + (h4 as u64 * s3 as u64);
+               let mut d3 = (h0 as u64 * r3 as u64) + (h1 as u64 * r2 as u64) + (h2 as u64 * r1 as u64) + (h3 as u64 * r0 as u64) + (h4 as u64 * s4 as u64);
+               let mut d4 = (h0 as u64 * r4 as u64) + (h1 as u64 * r3 as u64) + (h2 as u64 * r2 as u64) + (h3 as u64 * r1 as u64) + (h4 as u64 * r0 as u64);
+
+               // (partial) h %= p
+               let mut c : u32;
+                               c = (d0 >> 26) as u32; h0 = d0 as u32 & 0x3ffffff;
+               d1 += c as u64; c = (d1 >> 26) as u32; h1 = d1 as u32 & 0x3ffffff;
+               d2 += c as u64; c = (d2 >> 26) as u32; h2 = d2 as u32 & 0x3ffffff;
+               d3 += c as u64; c = (d3 >> 26) as u32; h3 = d3 as u32 & 0x3ffffff;
+               d4 += c as u64; c = (d4 >> 26) as u32; h4 = d4 as u32 & 0x3ffffff;
+               h0 += c * 5;    c = h0 >> 26; h0 = h0 & 0x3ffffff;
+               h1 += c;
+
+               self.h[0] = h0;
+               self.h[1] = h1;
+               self.h[2] = h2;
+               self.h[3] = h3;
+               self.h[4] = h4;
+       }
+
+       pub fn finish(&mut self) {
+               if self.leftover > 0 {
+                       self.buffer[self.leftover] = 1;
+                       for i in self.leftover+1..16 {
+                               self.buffer[i] = 0;
+                       }
+                       self.finalized = true;
+                       let tmp = self.buffer;
+                       self.block(&tmp);
+               }
+
+               // fully carry h
+               let mut h0 = self.h[0];
+               let mut h1 = self.h[1];
+               let mut h2 = self.h[2];
+               let mut h3 = self.h[3];
+               let mut h4 = self.h[4];
+
+               let mut c : u32;
+                            c = h1 >> 26; h1 = h1 & 0x3ffffff;
+               h2 +=     c; c = h2 >> 26; h2 = h2 & 0x3ffffff;
+               h3 +=     c; c = h3 >> 26; h3 = h3 & 0x3ffffff;
+               h4 +=     c; c = h4 >> 26; h4 = h4 & 0x3ffffff;
+               h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff;
+               h1 +=     c;
+
+               // compute h + -p
+               let mut g0 = h0.wrapping_add(5); c = g0 >> 26; g0 &= 0x3ffffff;
+               let mut g1 = h1.wrapping_add(c); c = g1 >> 26; g1 &= 0x3ffffff;
+               let mut g2 = h2.wrapping_add(c); c = g2 >> 26; g2 &= 0x3ffffff;
+               let mut g3 = h3.wrapping_add(c); c = g3 >> 26; g3 &= 0x3ffffff;
+               let mut g4 = h4.wrapping_add(c).wrapping_sub(1 << 26);
+
+               // select h if h < p, or h + -p if h >= p
+               let mut mask = (g4 >> (32 - 1)).wrapping_sub(1);
+               g0 &= mask;
+               g1 &= mask;
+               g2 &= mask;
+               g3 &= mask;
+               g4 &= mask;
+               mask = !mask;
+               h0 = (h0 & mask) | g0;
+               h1 = (h1 & mask) | g1;
+               h2 = (h2 & mask) | g2;
+               h3 = (h3 & mask) | g3;
+               h4 = (h4 & mask) | g4;
+
+               // h = h % (2^128)
+               h0 = ((h0      ) | (h1 << 26)) & 0xffffffff;
+               h1 = ((h1 >>  6) | (h2 << 20)) & 0xffffffff;
+               h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff;
+               h3 = ((h3 >> 18) | (h4 <<  8)) & 0xffffffff;
+
+               // h = mac = (h + pad) % (2^128)
+               let mut f : u64;
+               f = h0 as u64 + self.pad[0] as u64            ; h0 = f as u32;
+               f = h1 as u64 + self.pad[1] as u64 + (f >> 32); h1 = f as u32;
+               f = h2 as u64 + self.pad[2] as u64 + (f >> 32); h2 = f as u32;
+               f = h3 as u64 + self.pad[3] as u64 + (f >> 32); h3 = f as u32;
+
+               self.h[0] = h0;
+               self.h[1] = h1;
+               self.h[2] = h2;
+               self.h[3] = h3;
+       }
+
+       pub fn input(&mut self, data: &[u8]) {
+               assert!(!self.finalized);
+               let mut m = data;
+
+               if self.leftover > 0 {
+                       let want = min(16 - self.leftover, m.len());
+                       for i in 0..want {
+                               self.buffer[self.leftover+i] = m[i];
+                       }
+                       m = &m[want..];
+                       self.leftover += want;
+
+                       if self.leftover < 16 {
+                               return;
+                       }
+
+                       // self.block(self.buffer[..]);
+                       let tmp = self.buffer;
+                       self.block(&tmp);
+
+                       self.leftover = 0;
+               }
+
+               while m.len() >= 16 {
+                       self.block(&m[0..16]);
+                       m = &m[16..];
+               }
+
+               for i in 0..m.len() {
+                       self.buffer[i] = m[i];
+               }
+               self.leftover = m.len();
+       }
+
+       pub fn raw_result(&mut self, output: &mut [u8]) {
+               assert!(output.len() >= 16);
+               if !self.finalized{
+                       self.finish();
+               }
+               output[0..4].copy_from_slice(&self.h[0].to_le_bytes());
+               output[4..8].copy_from_slice(&self.h[1].to_le_bytes());
+               output[8..12].copy_from_slice(&self.h[2].to_le_bytes());
+               output[12..16].copy_from_slice(&self.h[3].to_le_bytes());
+       }
+}
+
+#[cfg(test)]
+mod test {
+       use core::iter::repeat;
+       use alloc::vec::Vec;
+
+       use super::Poly1305;
+
+       fn poly1305(key: &[u8], msg: &[u8], mac: &mut [u8]) {
+               let mut poly = Poly1305::new(key);
+               poly.input(msg);
+               poly.raw_result(mac);
+       }
+
+       #[test]
+       fn test_nacl_vector() {
+               let key = [
+                       0xee,0xa6,0xa7,0x25,0x1c,0x1e,0x72,0x91,
+                       0x6d,0x11,0xc2,0xcb,0x21,0x4d,0x3c,0x25,
+                       0x25,0x39,0x12,0x1d,0x8e,0x23,0x4e,0x65,
+                       0x2d,0x65,0x1f,0xa4,0xc8,0xcf,0xf8,0x80,
+               ];
+
+               let msg = [
+                       0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73,
+                       0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce,
+                       0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4,
+                       0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a,
+                       0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b,
+                       0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72,
+                       0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2,
+                       0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38,
+                       0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a,
+                       0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae,
+                       0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea,
+                       0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda,
+                       0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde,
+                       0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3,
+                       0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6,
+                       0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74,
+                       0xe3,0x55,0xa5,
+               ];
+
+               let expected = [
+                       0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5,
+                       0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9,
+               ];
+
+               let mut mac = [0u8; 16];
+               poly1305(&key, &msg, &mut mac);
+               assert_eq!(&mac[..], &expected[..]);
+
+               let mut poly = Poly1305::new(&key);
+               poly.input(&msg[0..32]);
+               poly.input(&msg[32..96]);
+               poly.input(&msg[96..112]);
+               poly.input(&msg[112..120]);
+               poly.input(&msg[120..124]);
+               poly.input(&msg[124..126]);
+               poly.input(&msg[126..127]);
+               poly.input(&msg[127..128]);
+               poly.input(&msg[128..129]);
+               poly.input(&msg[129..130]);
+               poly.input(&msg[130..131]);
+               poly.raw_result(&mut mac);
+               assert_eq!(&mac[..], &expected[..]);
+       }
+
+       #[test]
+       fn donna_self_test() {
+               let wrap_key = [
+                       0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+               ];
+
+               let wrap_msg = [
+                       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+               ];
+
+               let wrap_mac = [
+                       0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+               ];
+
+               let mut mac = [0u8; 16];
+               poly1305(&wrap_key, &wrap_msg, &mut mac);
+               assert_eq!(&mac[..], &wrap_mac[..]);
+
+               let total_key = [
+                       0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xff,
+                       0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xff, 0xff,
+                       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                       0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+               ];
+
+               let total_mac = [
+                       0x64, 0xaf, 0xe2, 0xe8, 0xd6, 0xad, 0x7b, 0xbd,
+                       0xd2, 0x87, 0xf9, 0x7c, 0x44, 0x62, 0x3d, 0x39,
+               ];
+
+               let mut tpoly = Poly1305::new(&total_key);
+               for i in 0..256 {
+                       let key: Vec<u8> = repeat(i as u8).take(32).collect();
+                       let msg: Vec<u8> = repeat(i as u8).take(256).collect();
+                       let mut mac = [0u8; 16];
+                       poly1305(&key[..], &msg[0..i], &mut mac);
+                       tpoly.input(&mac);
+               }
+               tpoly.raw_result(&mut mac);
+               assert_eq!(&mac[..], &total_mac[..]);
+       }
+
+       #[test]
+       fn test_tls_vectors() {
+               // from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
+               let key = b"this is 32-byte key for Poly1305";
+               let msg = [0u8; 32];
+               let expected = [
+                       0x49, 0xec, 0x78, 0x09, 0x0e, 0x48, 0x1e, 0xc6,
+                       0xc2, 0x6b, 0x33, 0xb9, 0x1c, 0xcc, 0x03, 0x07,
+               ];
+               let mut mac = [0u8; 16];
+               poly1305(key, &msg, &mut mac);
+               assert_eq!(&mac[..], &expected[..]);
+
+               let msg = b"Hello world!";
+               let expected= [
+                       0xa6, 0xf7, 0x45, 0x00, 0x8f, 0x81, 0xc9, 0x16,
+                       0xa2, 0x0d, 0xcc, 0x74, 0xee, 0xf2, 0xb2, 0xf0,
+               ];
+               poly1305(key, msg, &mut mac);
+               assert_eq!(&mac[..], &expected[..]);
+       }
+}
diff --git a/lightning/src/crypto/streams.rs b/lightning/src/crypto/streams.rs
new file mode 100644 (file)
index 0000000..14921a3
--- /dev/null
@@ -0,0 +1,211 @@
+use crate::crypto::chacha20::ChaCha20;
+use crate::crypto::chacha20poly1305rfc::ChaCha20Poly1305RFC;
+
+use crate::ln::msgs::DecodeError;
+use crate::util::ser::{FixedLengthReader, LengthRead, LengthReadableArgs, Readable, Writeable, Writer};
+use crate::io::{self, Read, Write};
+
+pub(crate) struct ChaChaReader<'a, R: io::Read> {
+       pub chacha: &'a mut ChaCha20,
+       pub read: R,
+}
+impl<'a, R: io::Read> io::Read for ChaChaReader<'a, R> {
+       fn read(&mut self, dest: &mut [u8]) -> Result<usize, io::Error> {
+               let res = self.read.read(dest)?;
+               if res > 0 {
+                       self.chacha.process_in_place(&mut dest[0..res]);
+               }
+               Ok(res)
+       }
+}
+
+/// Enables the use of the serialization macros for objects that need to be simultaneously encrypted and
+/// serialized. This allows us to avoid an intermediate Vec allocation.
+pub(crate) struct ChaChaPolyWriteAdapter<'a, W: Writeable> {
+       pub rho: [u8; 32],
+       pub writeable: &'a W,
+}
+
+impl<'a, W: Writeable> ChaChaPolyWriteAdapter<'a, W> {
+       #[allow(unused)] // This will be used for onion messages soon
+       pub fn new(rho: [u8; 32], writeable: &'a W) -> ChaChaPolyWriteAdapter<'a, W> {
+               Self { rho, writeable }
+       }
+}
+
+impl<'a, T: Writeable> Writeable for ChaChaPolyWriteAdapter<'a, T> {
+       // Simultaneously write and encrypt Self::writeable.
+       fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
+               let mut chacha = ChaCha20Poly1305RFC::new(&self.rho, &[0; 12], &[]);
+               let mut chacha_stream = ChaChaPolyWriter { chacha: &mut chacha, write: w };
+               self.writeable.write(&mut chacha_stream)?;
+               let mut tag = [0 as u8; 16];
+               chacha.finish_and_get_tag(&mut tag);
+               tag.write(w)?;
+
+               Ok(())
+       }
+}
+
+/// Enables the use of the serialization macros for objects that need to be simultaneously decrypted and
+/// deserialized. This allows us to avoid an intermediate Vec allocation.
+pub(crate) struct ChaChaPolyReadAdapter<R: Readable> {
+       pub readable: R,
+}
+
+impl<T: Readable> LengthReadableArgs<[u8; 32]> for ChaChaPolyReadAdapter<T> {
+       // Simultaneously read and decrypt an object from a LengthRead, storing it in Self::readable.
+       // LengthRead must be used instead of std::io::Read because we need the total length to separate
+       // out the tag at the end.
+       fn read<R: LengthRead>(mut r: &mut R, secret: [u8; 32]) -> Result<Self, DecodeError> {
+               if r.total_bytes() < 16 { return Err(DecodeError::InvalidValue) }
+
+               let mut chacha = ChaCha20Poly1305RFC::new(&secret, &[0; 12], &[]);
+               let decrypted_len = r.total_bytes() - 16;
+               let s = FixedLengthReader::new(&mut r, decrypted_len);
+               let mut chacha_stream = ChaChaPolyReader { chacha: &mut chacha, read: s };
+               let readable: T = Readable::read(&mut chacha_stream)?;
+               chacha_stream.read.eat_remaining()?;
+
+               let mut tag = [0 as u8; 16];
+               r.read_exact(&mut tag)?;
+               if !chacha.finish_and_check_tag(&tag) {
+                       return Err(DecodeError::InvalidValue)
+               }
+
+               Ok(Self { readable })
+       }
+}
+
+
+/// Enables simultaneously reading and decrypting a ChaCha20Poly1305RFC stream from a std::io::Read.
+struct ChaChaPolyReader<'a, R: Read> {
+       pub chacha: &'a mut ChaCha20Poly1305RFC,
+       pub read: R,
+}
+
+impl<'a, R: Read> Read for ChaChaPolyReader<'a, R> {
+       // Decrypt bytes from Self::read into `dest`.
+       // `ChaCha20Poly1305RFC::finish_and_check_tag` must be called to check the tag after all reads
+       // complete.
+       fn read(&mut self, dest: &mut [u8]) -> Result<usize, io::Error> {
+               let res = self.read.read(dest)?;
+               if res > 0 {
+                       self.chacha.decrypt_in_place(&mut dest[0..res]);
+               }
+               Ok(res)
+       }
+}
+
+/// Enables simultaneously writing and encrypting a byte stream into a Writer.
+struct ChaChaPolyWriter<'a, W: Writer> {
+       pub chacha: &'a mut ChaCha20Poly1305RFC,
+       pub write: &'a mut W,
+}
+
+impl<'a, W: Writer> Writer for ChaChaPolyWriter<'a, W> {
+       // Encrypt then write bytes from `src` into Self::write.
+       // `ChaCha20Poly1305RFC::finish_and_get_tag` can be called to retrieve the tag after all writes
+       // complete.
+       fn write_all(&mut self, src: &[u8]) -> Result<(), io::Error> {
+               let mut src_idx = 0;
+               while src_idx < src.len() {
+                       let mut write_buffer = [0; 8192];
+                       let bytes_written = (&mut write_buffer[..]).write(&src[src_idx..]).expect("In-memory writes can't fail");
+                       self.chacha.encrypt_in_place(&mut write_buffer[..bytes_written]);
+                       self.write.write_all(&write_buffer[..bytes_written])?;
+                       src_idx += bytes_written;
+               }
+               Ok(())
+       }
+}
+
+
+#[cfg(test)]
+mod tests {
+       use crate::ln::msgs::DecodeError;
+       use super::{ChaChaPolyReadAdapter, ChaChaPolyWriteAdapter};
+       use crate::util::ser::{self, FixedLengthReader, LengthReadableArgs, Writeable};
+
+       // Used for for testing various lengths of serialization.
+       #[derive(Debug, PartialEq, Eq)]
+       struct TestWriteable {
+               field1: Vec<u8>,
+               field2: Vec<u8>,
+               field3: Vec<u8>,
+       }
+       impl_writeable_tlv_based!(TestWriteable, {
+               (1, field1, required_vec),
+               (2, field2, required_vec),
+               (3, field3, required_vec),
+       });
+
+       #[test]
+       fn test_chacha_stream_adapters() {
+               // Check that ChaChaPolyReadAdapter and ChaChaPolyWriteAdapter correctly encode and decode an
+               // encrypted object.
+               macro_rules! check_object_read_write {
+                       ($obj: expr) => {
+                               // First, serialize the object, encrypted with ChaCha20Poly1305.
+                               let rho = [42; 32];
+                               let writeable_len = $obj.serialized_length() as u64 + 16;
+                               let write_adapter = ChaChaPolyWriteAdapter::new(rho, &$obj);
+                               let encrypted_writeable_bytes = write_adapter.encode();
+                               let encrypted_writeable = &encrypted_writeable_bytes[..];
+
+                               // Now deserialize the object back and make sure it matches the original.
+                               let mut rd = FixedLengthReader::new(encrypted_writeable, writeable_len);
+                               let read_adapter = <ChaChaPolyReadAdapter<TestWriteable>>::read(&mut rd, rho).unwrap();
+                               assert_eq!($obj, read_adapter.readable);
+                       };
+               }
+
+               // Try a big object that will require multiple write buffers.
+               let big_writeable = TestWriteable {
+                       field1: vec![43],
+                       field2: vec![44; 4192],
+                       field3: vec![45; 4192 + 1],
+               };
+               check_object_read_write!(big_writeable);
+
+               // Try a small object that fits into one write buffer.
+               let small_writeable = TestWriteable {
+                       field1: vec![43],
+                       field2: vec![44],
+                       field3: vec![45],
+               };
+               check_object_read_write!(small_writeable);
+       }
+
+       fn do_chacha_stream_adapters_ser_macros() -> Result<(), DecodeError> {
+               let writeable = TestWriteable {
+                       field1: vec![43],
+                       field2: vec![44; 4192],
+                       field3: vec![45; 4192 + 1],
+               };
+
+               // First, serialize the object into a TLV stream, encrypted with ChaCha20Poly1305.
+               let rho = [42; 32];
+               let write_adapter = ChaChaPolyWriteAdapter::new(rho, &writeable);
+               let mut writer = ser::VecWriter(Vec::new());
+               encode_tlv_stream!(&mut writer, {
+                       (1, write_adapter, required),
+               });
+
+               // Now deserialize the object back and make sure it matches the original.
+               let mut read_adapter: Option<ChaChaPolyReadAdapter<TestWriteable>> = None;
+               decode_tlv_stream!(&writer.0[..], {
+                       (1, read_adapter, (option: LengthReadableArgs, rho)),
+               });
+               assert_eq!(writeable, read_adapter.unwrap().readable);
+
+               Ok(())
+       }
+
+       #[test]
+       fn chacha_stream_adapters_ser_macros() {
+               // Test that our stream adapters work as expected with the TLV macros.
+               // This also serves to test the `option: $trait` variant of the `_decode_tlv` ser macro.
+               do_chacha_stream_adapters_ser_macros().unwrap()
+       }
+}
diff --git a/lightning/src/crypto/utils.rs b/lightning/src/crypto/utils.rs
new file mode 100644 (file)
index 0000000..98963c7
--- /dev/null
@@ -0,0 +1,83 @@
+use bitcoin::hashes::{Hash, HashEngine};
+use bitcoin::hashes::hmac::{Hmac, HmacEngine};
+use bitcoin::hashes::sha256::Hash as Sha256;
+use bitcoin::secp256k1::{Message, Secp256k1, SecretKey, ecdsa::Signature, Signing};
+
+use crate::sign::EntropySource;
+
+use core::ops::Deref;
+
+macro_rules! hkdf_extract_expand {
+       ($salt: expr, $ikm: expr) => {{
+               let mut hmac = HmacEngine::<Sha256>::new($salt);
+               hmac.input($ikm);
+               let prk = Hmac::from_engine(hmac).to_byte_array();
+               let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
+               hmac.input(&[1; 1]);
+               let t1 = Hmac::from_engine(hmac).to_byte_array();
+               let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
+               hmac.input(&t1);
+               hmac.input(&[2; 1]);
+               (t1, Hmac::from_engine(hmac).to_byte_array(), prk)
+       }};
+       ($salt: expr, $ikm: expr, 2) => {{
+               let (k1, k2, _) = hkdf_extract_expand!($salt, $ikm);
+               (k1, k2)
+       }};
+       ($salt: expr, $ikm: expr, 5) => {{
+               let (k1, k2, prk) = hkdf_extract_expand!($salt, $ikm);
+
+               let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
+               hmac.input(&k2);
+               hmac.input(&[3; 1]);
+               let k3 = Hmac::from_engine(hmac).to_byte_array();
+
+               let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
+               hmac.input(&k3);
+               hmac.input(&[4; 1]);
+               let k4 = Hmac::from_engine(hmac).to_byte_array();
+
+               let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
+               hmac.input(&k4);
+               hmac.input(&[5; 1]);
+               let k5 = Hmac::from_engine(hmac).to_byte_array();
+
+               (k1, k2, k3, k4, k5)
+       }}
+}
+
+pub fn hkdf_extract_expand_twice(salt: &[u8], ikm: &[u8]) -> ([u8; 32], [u8; 32]) {
+       hkdf_extract_expand!(salt, ikm, 2)
+}
+
+pub fn hkdf_extract_expand_5x(salt: &[u8], ikm: &[u8]) -> ([u8; 32], [u8; 32], [u8; 32], [u8; 32], [u8; 32]) {
+       hkdf_extract_expand!(salt, ikm, 5)
+}
+
+#[inline]
+pub fn sign<C: Signing>(ctx: &Secp256k1<C>, msg: &Message, sk: &SecretKey) -> Signature {
+       #[cfg(feature = "grind_signatures")]
+       let sig = ctx.sign_ecdsa_low_r(msg, sk);
+       #[cfg(not(feature = "grind_signatures"))]
+       let sig = ctx.sign_ecdsa(msg, sk);
+       sig
+}
+
+#[inline]
+#[allow(unused_variables)]
+pub fn sign_with_aux_rand<C: Signing, ES: Deref>(
+       ctx: &Secp256k1<C>, msg: &Message, sk: &SecretKey, entropy_source: &ES
+) -> Signature where ES::Target: EntropySource {
+       #[cfg(feature = "grind_signatures")]
+       let sig = loop {
+               let sig = ctx.sign_ecdsa_with_noncedata(msg, sk, &entropy_source.get_secure_random_bytes());
+               if sig.serialize_compact()[0] < 0x80 {
+                       break sig;
+               }
+       };
+       #[cfg(all(not(feature = "grind_signatures"), not(feature = "_test_vectors")))]
+       let sig = ctx.sign_ecdsa_with_noncedata(msg, sk, &entropy_source.get_secure_random_bytes());
+       #[cfg(all(not(feature = "grind_signatures"), feature = "_test_vectors"))]
+       let sig = sign(ctx, msg, sk);
+       sig
+}
index 6eefb3983cca95f1bb0351a43bfddf39d2be58db..160f632415b472238b18f728e43c990fdf002f45 100644 (file)
@@ -84,6 +84,8 @@ pub mod onion_message;
 pub mod blinded_path;
 pub mod events;
 
+pub(crate) mod crypto;
+
 #[cfg(feature = "std")]
 /// Re-export of either `core2::io` or `std::io`, depending on the `std` feature flag.
 pub use std::io;
index 672e3aa862e460e94f26451ebff4ff39293eb4e9..18c4d83406c1bdbcdb673b0461062de62f400b0a 100644 (file)
@@ -45,7 +45,7 @@ use crate::ln::channel::{INITIAL_COMMITMENT_NUMBER, ANCHOR_OUTPUT_VALUE_SATOSHI}
 use core::ops::Deref;
 use crate::chain;
 use crate::ln::features::ChannelTypeFeatures;
-use crate::util::crypto::{sign, sign_with_aux_rand};
+use crate::crypto::utils::{sign, sign_with_aux_rand};
 use super::channel_keys::{DelayedPaymentBasepoint, DelayedPaymentKey, HtlcKey, HtlcBasepoint, RevocationKey, RevocationBasepoint};
 
 /// Maximum number of one-way in-flight HTLC (protocol-level value).
index 2ee93a6c46efca8ef2c1d6904f7c7d6553205ca1..eeae514fdf3ce4097f79487ed09ceace231cadd4 100644 (file)
@@ -18,8 +18,8 @@ use crate::sign::{KeyMaterial, EntropySource};
 use crate::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
 use crate::ln::msgs;
 use crate::ln::msgs::MAX_VALUE_MSAT;
-use crate::util::chacha20::ChaCha20;
-use crate::util::crypto::hkdf_extract_expand_5x;
+use crate::crypto::chacha20::ChaCha20;
+use crate::crypto::utils::hkdf_extract_expand_5x;
 use crate::util::errors::APIError;
 use crate::util::logger::Logger;
 
index 74740a6f2279d6549ba57b443b473410e26fbef6..b62701814399d99240354d1200908b61732e99ae 100644 (file)
@@ -19,7 +19,7 @@ use crate::ln::channel;
 use crate::ln::channelmanager::{BREAKDOWN_TIMEOUT, PaymentId, RecipientOnionFields};
 use crate::ln::msgs::ChannelMessageHandler;
 use crate::util::config::UserConfig;
-use crate::util::crypto::sign;
+use crate::crypto::utils::sign;
 use crate::util::ser::Writeable;
 use crate::util::scid_utils::block_from_scid;
 use crate::util::test_utils;
index 1794aefe7ef80bda8629d4e0c08aae95afac57df..efd04d143d93a98d211608d59040671a52c758b1 100644 (file)
@@ -53,7 +53,7 @@ use crate::io::{self, Cursor, Read};
 use crate::io_extras::read_to_end;
 
 use crate::events::{EventsProvider, MessageSendEventsProvider};
-use crate::util::chacha20poly1305rfc::ChaChaPolyReadAdapter;
+use crate::crypto::streams::ChaChaPolyReadAdapter;
 use crate::util::logger;
 use crate::util::ser::{LengthReadable, LengthReadableArgs, Readable, ReadableArgs, Writeable, Writer, WithoutLength, FixedLengthReader, HighZeroBytesDroppedBigSize, Hostname, TransactionU16LenLimited, BigSize};
 use crate::util::base32;
index ac0bb6189c6d750e92b4fdf5f6d061cca46d2cb2..d9455fc1de2472f935e5cf1daf1b979c7820394f 100644 (file)
@@ -14,7 +14,8 @@ use crate::ln::wire::Encode;
 use crate::routing::gossip::NetworkUpdate;
 use crate::routing::router::{BlindedTail, Path, RouteHop};
 use crate::sign::NodeSigner;
-use crate::util::chacha20::{ChaCha20, ChaChaReader};
+use crate::crypto::chacha20::ChaCha20;
+use crate::crypto::streams::ChaChaReader;
 use crate::util::errors::{self, APIError};
 use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer, LengthCalculatingWriter};
 use crate::util::logger::Logger;
index c9e1ac47886956eb3a6532d6008ca6d6e62992f7..51e34bdb96967428e432cba2c8a082e1f6352b72 100644 (file)
@@ -24,8 +24,8 @@ use bitcoin::secp256k1;
 
 use hex::DisplayHex;
 
-use crate::util::chacha20poly1305rfc::ChaCha20Poly1305RFC;
-use crate::util::crypto::hkdf_extract_expand_twice;
+use crate::crypto::chacha20poly1305rfc::ChaCha20Poly1305RFC;
+use crate::crypto::utils::hkdf_extract_expand_twice;
 use crate::util::ser::VecWriter;
 
 use core::ops::Deref;
@@ -188,7 +188,7 @@ impl PeerChannelEncryptor {
                nonce[4..].copy_from_slice(&n.to_le_bytes()[..]);
 
                let mut chacha = ChaCha20Poly1305RFC::new(key, &nonce, h);
-               if !chacha.decrypt(&cyphertext[0..cyphertext.len() - 16], res, &cyphertext[cyphertext.len() - 16..]) {
+               if chacha.variable_time_decrypt(&cyphertext[0..cyphertext.len() - 16], res, &cyphertext[cyphertext.len() - 16..]).is_err() {
                        return Err(LightningError{err: "Bad MAC".to_owned(), action: msgs::ErrorAction::DisconnectPeer{ msg: None }});
                }
                Ok(())
index 5ce02c54d08800b777a0c2c3a25f27ba1ffae462..d9349fdadbfaba6c1f0d08c265c48bf14da49bb7 100644 (file)
@@ -19,7 +19,7 @@ use crate::ln::msgs::DecodeError;
 use crate::ln::onion_utils;
 use super::messenger::CustomOnionMessageHandler;
 use super::offers::OffersMessage;
-use crate::util::chacha20poly1305rfc::{ChaChaPolyReadAdapter, ChaChaPolyWriteAdapter};
+use crate::crypto::streams::{ChaChaPolyReadAdapter, ChaChaPolyWriteAdapter};
 use crate::util::logger::Logger;
 use crate::util::ser::{BigSize, FixedLengthReader, LengthRead, LengthReadable, LengthReadableArgs, Readable, ReadableArgs, Writeable, Writer};
 
index 277661862e3361d72a3b3b44975a928422a87db9..0b19369a4aa74bf95ed1cc4e3f038c6b381f486d 100644 (file)
@@ -26,7 +26,7 @@ use crate::routing::scoring::{ChannelUsage, LockableScore, ScoreLookUp};
 use crate::sign::EntropySource;
 use crate::util::ser::{Writeable, Readable, ReadableArgs, Writer};
 use crate::util::logger::{Level, Logger};
-use crate::util::chacha20::ChaCha20;
+use crate::crypto::chacha20::ChaCha20;
 
 use crate::io;
 use crate::prelude::*;
@@ -3195,7 +3195,7 @@ mod tests {
        use crate::offers::invoice::BlindedPayInfo;
        use crate::util::config::UserConfig;
        use crate::util::test_utils as ln_test_utils;
-       use crate::util::chacha20::ChaCha20;
+       use crate::crypto::chacha20::ChaCha20;
        use crate::util::ser::{Readable, Writeable};
        #[cfg(c_bindings)]
        use crate::util::ser::Writer;
index 4e418f049bbc9867a7a2a7920706e17c135ed23e..c4bb6fb8020ed8d5d1ee3c32a862f44b19a82737 100644 (file)
@@ -38,7 +38,7 @@ use bitcoin::secp256k1::schnorr;
 use bitcoin::{secp256k1, Sequence, Witness, Txid};
 
 use crate::util::transaction_utils;
-use crate::util::crypto::{hkdf_extract_expand_twice, sign, sign_with_aux_rand};
+use crate::crypto::utils::{hkdf_extract_expand_twice, sign, sign_with_aux_rand};
 use crate::util::ser::{Writeable, Writer, Readable, ReadableArgs};
 use crate::chain::transaction::OutPoint;
 use crate::ln::channel::ANCHOR_OUTPUT_VALUE_SATOSHI;
@@ -65,7 +65,7 @@ use crate::sign::ecdsa::{EcdsaChannelSigner, WriteableEcdsaChannelSigner};
 #[cfg(taproot)]
 use crate::sign::taproot::TaprootChannelSigner;
 use crate::util::atomic_counter::AtomicCounter;
-use crate::util::chacha20::ChaCha20;
+use crate::crypto::chacha20::ChaCha20;
 use crate::util::invoice::construct_invoice_preimage;
 
 pub(crate) mod type_resolver;
diff --git a/lightning/src/util/chacha20.rs b/lightning/src/util/chacha20.rs
deleted file mode 100644 (file)
index 865a09f..0000000
+++ /dev/null
@@ -1,701 +0,0 @@
-// This file was stolen from rust-crypto.
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
-// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
-// You may not use this file except in accordance with one or both of these
-// licenses.
-
-use crate::io;
-
-#[cfg(not(fuzzing))]
-mod real_chacha {
-       use core::cmp;
-       use core::convert::TryInto;
-
-       #[derive(Clone, Copy, PartialEq, Eq)]
-       #[allow(non_camel_case_types)]
-       struct u32x4(pub u32, pub u32, pub u32, pub u32);
-       impl ::core::ops::Add for u32x4 {
-               type Output = u32x4;
-               #[inline]
-               fn add(self, rhs: u32x4) -> u32x4 {
-                       u32x4(self.0.wrapping_add(rhs.0),
-                             self.1.wrapping_add(rhs.1),
-                             self.2.wrapping_add(rhs.2),
-                             self.3.wrapping_add(rhs.3))
-               }
-       }
-       impl ::core::ops::Sub for u32x4 {
-               type Output = u32x4;
-               #[inline]
-               fn sub(self, rhs: u32x4) -> u32x4 {
-                       u32x4(self.0.wrapping_sub(rhs.0),
-                             self.1.wrapping_sub(rhs.1),
-                             self.2.wrapping_sub(rhs.2),
-                             self.3.wrapping_sub(rhs.3))
-               }
-       }
-       impl ::core::ops::BitXor for u32x4 {
-               type Output = u32x4;
-               #[inline]
-               fn bitxor(self, rhs: u32x4) -> u32x4 {
-                       u32x4(self.0 ^ rhs.0, self.1 ^ rhs.1, self.2 ^ rhs.2, self.3 ^ rhs.3)
-               }
-       }
-       impl ::core::ops::Shr<u8> for u32x4 {
-               type Output = u32x4;
-               #[inline]
-               fn shr(self, shr: u8) -> u32x4 {
-                       u32x4(self.0 >> shr, self.1 >> shr, self.2 >> shr, self.3 >> shr)
-               }
-       }
-       impl ::core::ops::Shl<u8> for u32x4 {
-               type Output = u32x4;
-               #[inline]
-               fn shl(self, shl: u8) -> u32x4 {
-                       u32x4(self.0 << shl, self.1 << shl, self.2 << shl, self.3 << shl)
-               }
-       }
-       impl u32x4 {
-               #[inline]
-               fn from_bytes(bytes: &[u8]) -> Self {
-                       assert_eq!(bytes.len(), 4*4);
-                       Self (
-                               u32::from_le_bytes(bytes[0*4..1*4].try_into().expect("len is 4")),
-                               u32::from_le_bytes(bytes[1*4..2*4].try_into().expect("len is 4")),
-                               u32::from_le_bytes(bytes[2*4..3*4].try_into().expect("len is 4")),
-                               u32::from_le_bytes(bytes[3*4..4*4].try_into().expect("len is 4")),
-                       )
-               }
-       }
-
-       const BLOCK_SIZE: usize = 64;
-
-       #[derive(Clone,Copy)]
-       struct ChaChaState {
-               a: u32x4,
-               b: u32x4,
-               c: u32x4,
-               d: u32x4
-       }
-
-       #[derive(Copy)]
-       pub struct ChaCha20 {
-               state  : ChaChaState,
-               output : [u8; BLOCK_SIZE],
-               offset : usize,
-       }
-
-       impl Clone for ChaCha20 { fn clone(&self) -> ChaCha20 { *self } }
-
-       macro_rules! swizzle {
-               ($b: expr, $c: expr, $d: expr) => {{
-                       let u32x4(b10, b11, b12, b13) = $b;
-                       $b = u32x4(b11, b12, b13, b10);
-                       let u32x4(c10, c11, c12, c13) = $c;
-                       $c = u32x4(c12, c13,c10, c11);
-                       let u32x4(d10, d11, d12, d13) = $d;
-                       $d = u32x4(d13, d10, d11, d12);
-               }}
-       }
-
-       macro_rules! state_to_buffer {
-               ($state: expr, $output: expr) => {{
-                       let u32x4(a1, a2, a3, a4) = $state.a;
-                       let u32x4(b1, b2, b3, b4) = $state.b;
-                       let u32x4(c1, c2, c3, c4) = $state.c;
-                       let u32x4(d1, d2, d3, d4) = $state.d;
-                       let lens = [
-                               a1,a2,a3,a4,
-                               b1,b2,b3,b4,
-                               c1,c2,c3,c4,
-                               d1,d2,d3,d4
-                       ];
-                       for i in 0..lens.len() {
-                               $output[i*4..(i+1)*4].copy_from_slice(&lens[i].to_le_bytes());
-                       }
-               }}
-       }
-
-       macro_rules! round{
-               ($state: expr) => {{
-                       $state.a = $state.a + $state.b;
-                       rotate!($state.d, $state.a, 16);
-                       $state.c = $state.c + $state.d;
-                       rotate!($state.b, $state.c, 12);
-                       $state.a = $state.a + $state.b;
-                       rotate!($state.d, $state.a, 8);
-                       $state.c = $state.c + $state.d;
-                       rotate!($state.b, $state.c, 7);
-               }}
-       }
-
-       macro_rules! rotate {
-               ($a: expr, $b: expr, $rot: expr) => {{
-                       let v = $a ^ $b;
-                       let r = 32 - $rot;
-                       let right = v >> r;
-                       $a = (v << $rot) ^ right
-               }}
-       }
-
-       impl ChaCha20 {
-               pub fn new(key: &[u8], nonce: &[u8]) -> ChaCha20 {
-                       assert!(key.len() == 16 || key.len() == 32);
-                       assert!(nonce.len() == 8 || nonce.len() == 12);
-
-                       ChaCha20{ state: ChaCha20::expand(key, nonce), output: [0u8; BLOCK_SIZE], offset: 64 }
-               }
-
-               /// Get one block from a ChaCha stream.
-               pub fn get_single_block(key: &[u8; 32], nonce: &[u8; 16]) -> [u8; 32] {
-                       let mut chacha = ChaCha20 { state: ChaCha20::expand(key, nonce), output: [0u8; BLOCK_SIZE], offset: 64 };
-                       let mut chacha_bytes = [0; 32];
-                       chacha.process_in_place(&mut chacha_bytes);
-                       chacha_bytes
-               }
-
-               /// Encrypts `src` into `dest` using a single block from a ChaCha stream. Passing `dest` as
-               /// `src` in a second call will decrypt it.
-               pub fn encrypt_single_block(
-                       key: &[u8; 32], nonce: &[u8; 16], dest: &mut [u8], src: &[u8]
-               ) {
-                       debug_assert_eq!(dest.len(), src.len());
-                       debug_assert!(dest.len() <= 32);
-
-                       let block = ChaCha20::get_single_block(key, nonce);
-                       for i in 0..dest.len() {
-                               dest[i] = block[i] ^ src[i];
-                       }
-               }
-
-               /// Same as `encrypt_single_block` only operates on a fixed-size input in-place.
-               pub fn encrypt_single_block_in_place(
-                       key: &[u8; 32], nonce: &[u8; 16], bytes: &mut [u8; 32]
-               ) {
-                       let block = ChaCha20::get_single_block(key, nonce);
-                       for i in 0..bytes.len() {
-                               bytes[i] = block[i] ^ bytes[i];
-                       }
-               }
-
-               fn expand(key: &[u8], nonce: &[u8]) -> ChaChaState {
-                       let constant = match key.len() {
-                               16 => b"expand 16-byte k",
-                               32 => b"expand 32-byte k",
-                               _  => unreachable!(),
-                       };
-                       ChaChaState {
-                               a: u32x4::from_bytes(&constant[0..16]),
-                               b: u32x4::from_bytes(&key[0..16]),
-                               c: if key.len() == 16 {
-                                       u32x4::from_bytes(&key[0..16])
-                               } else {
-                                       u32x4::from_bytes(&key[16..32])
-                               },
-                               d: if nonce.len() == 16 {
-                                       u32x4::from_bytes(&nonce[0..16])
-                               } else if nonce.len() == 12 {
-                                       let mut nonce4 = [0; 4*4];
-                                       nonce4[4..].copy_from_slice(nonce);
-                                       u32x4::from_bytes(&nonce4)
-                               } else {
-                                       let mut nonce4 = [0; 4*4];
-                                       nonce4[8..].copy_from_slice(nonce);
-                                       u32x4::from_bytes(&nonce4)
-                               }
-                       }
-               }
-
-               // put the the next BLOCK_SIZE keystream bytes into self.output
-               fn update(&mut self) {
-                       let mut state = self.state;
-
-                       for _ in 0..10 {
-                               round!(state);
-                               swizzle!(state.b, state.c, state.d);
-                               round!(state);
-                               swizzle!(state.d, state.c, state.b);
-                       }
-                       state.a = state.a + self.state.a;
-                       state.b = state.b + self.state.b;
-                       state.c = state.c + self.state.c;
-                       state.d = state.d + self.state.d;
-
-                       state_to_buffer!(state, self.output);
-
-                       self.state.d = self.state.d + u32x4(1, 0, 0, 0);
-                       let u32x4(c12, _, _, _) = self.state.d;
-                       if c12 == 0 {
-                               // we could increment the other counter word with an 8 byte nonce
-                               // but other implementations like boringssl have this same
-                               // limitation
-                               panic!("counter is exhausted");
-                       }
-
-                       self.offset = 0;
-               }
-
-               #[inline] // Useful cause input may be 0s on stack that should be optimized out
-               pub fn process(&mut self, input: &[u8], output: &mut [u8]) {
-                       assert!(input.len() == output.len());
-                       let len = input.len();
-                       let mut i = 0;
-                       while i < len {
-                               // If there is no keystream available in the output buffer,
-                               // generate the next block.
-                               if self.offset == BLOCK_SIZE {
-                                       self.update();
-                               }
-
-                               // Process the min(available keystream, remaining input length).
-                               let count = cmp::min(BLOCK_SIZE - self.offset, len - i);
-                               // explicitly assert lengths to avoid bounds checks:
-                               assert!(output.len() >= i + count);
-                               assert!(input.len() >= i + count);
-                               assert!(self.output.len() >= self.offset + count);
-                               for j in 0..count {
-                                       output[i + j] = input[i + j] ^ self.output[self.offset + j];
-                               }
-                               i += count;
-                               self.offset += count;
-                       }
-               }
-
-               pub fn process_in_place(&mut self, input_output: &mut [u8]) {
-                       let len = input_output.len();
-                       let mut i = 0;
-                       while i < len {
-                               // If there is no keystream available in the output buffer,
-                               // generate the next block.
-                               if self.offset == BLOCK_SIZE {
-                                       self.update();
-                               }
-
-                               // Process the min(available keystream, remaining input length).
-                               let count = cmp::min(BLOCK_SIZE - self.offset, len - i);
-                               // explicitly assert lengths to avoid bounds checks:
-                               assert!(input_output.len() >= i + count);
-                               assert!(self.output.len() >= self.offset + count);
-                               for j in 0..count {
-                                       input_output[i + j] ^= self.output[self.offset + j];
-                               }
-                               i += count;
-                               self.offset += count;
-                       }
-               }
-
-               #[cfg(test)]
-               pub fn seek_to_block(&mut self, block_offset: u32) {
-                       self.state.d.0 = block_offset;
-                       self.update();
-               }
-       }
-}
-#[cfg(not(fuzzing))]
-pub use self::real_chacha::ChaCha20;
-
-#[cfg(fuzzing)]
-mod fuzzy_chacha {
-       pub struct ChaCha20 {}
-
-       impl ChaCha20 {
-               pub fn new(key: &[u8], nonce: &[u8]) -> ChaCha20 {
-                       assert!(key.len() == 16 || key.len() == 32);
-                       assert!(nonce.len() == 8 || nonce.len() == 12);
-                       Self {}
-               }
-
-               pub fn get_single_block(_key: &[u8; 32], _nonce: &[u8; 16]) -> [u8; 32] {
-                       [0; 32]
-               }
-
-               pub fn encrypt_single_block(
-                       _key: &[u8; 32], _nonce: &[u8; 16], dest: &mut [u8], src: &[u8]
-               ) {
-                       debug_assert_eq!(dest.len(), src.len());
-                       debug_assert!(dest.len() <= 32);
-               }
-
-               pub fn encrypt_single_block_in_place(
-                       _key: &[u8; 32], _nonce: &[u8; 16], _bytes: &mut [u8; 32]
-               ) {}
-
-               pub fn process(&mut self, input: &[u8], output: &mut [u8]) {
-                       output.copy_from_slice(input);
-               }
-
-               pub fn process_in_place(&mut self, _input_output: &mut [u8]) {}
-       }
-}
-#[cfg(fuzzing)]
-pub use self::fuzzy_chacha::ChaCha20;
-
-pub(crate) struct ChaChaReader<'a, R: io::Read> {
-       pub chacha: &'a mut ChaCha20,
-       pub read: R,
-}
-impl<'a, R: io::Read> io::Read for ChaChaReader<'a, R> {
-       fn read(&mut self, dest: &mut [u8]) -> Result<usize, io::Error> {
-               let res = self.read.read(dest)?;
-               if res > 0 {
-                       self.chacha.process_in_place(&mut dest[0..res]);
-               }
-               Ok(res)
-       }
-}
-
-#[cfg(test)]
-mod test {
-       use crate::prelude::*;
-       use core::iter::repeat;
-
-       use super::ChaCha20;
-       use std::convert::TryInto;
-
-       #[test]
-       fn test_chacha20_256_tls_vectors() {
-               struct TestVector {
-                       key:   [u8; 32],
-                       nonce: [u8; 8],
-                       keystream: Vec<u8>,
-               }
-               // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
-               let test_vectors = vec!(
-                       TestVector{
-                               key: [
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                               ],
-                               nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
-                               keystream: vec!(
-                                       0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
-                                       0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
-                                       0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
-                                       0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
-                                       0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
-                                       0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
-                                       0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
-                                       0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
-                               ),
-                       }, TestVector{
-                               key: [
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-                               ],
-                               nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
-                               keystream: vec!(
-                                       0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96,
-                                       0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96,
-                                       0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60,
-                                       0x4f, 0x45, 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41,
-                                       0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, 0xd2,
-                                       0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c,
-                                       0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81,
-                                       0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
-                               ),
-                       }, TestVector{
-                               key: [
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                               ],
-                               nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ],
-                               keystream: vec!(
-                                       0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5,
-                                       0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a,
-                                       0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13,
-                                       0x4f, 0xcb, 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31,
-                                       0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, 0x45,
-                                       0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b,
-                                       0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e,
-                                       0x44, 0x5f, 0x41, 0xe3,
-                               ),
-                       }, TestVector{
-                               key: [
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                               ],
-                               nonce: [ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
-                               keystream: vec!(
-                                       0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
-                                       0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
-                                       0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac,
-                                       0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32,
-                                       0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c,
-                                       0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54,
-                                       0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d,
-                                       0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
-                               ),
-                       }, TestVector{
-                               key: [
-                                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-                                       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-                                       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-                                       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-                               ],
-                               nonce: [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ],
-                               keystream: vec!(
-                                       0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69,
-                                       0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75,
-                                       0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93,
-                                       0xec, 0x01, 0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1,
-                                       0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, 0x41,
-                                       0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69,
-                                       0x05, 0xd3, 0xbe, 0x59, 0xea, 0x1c, 0x53, 0xf1,
-                                       0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a,
-                                       0x38, 0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94,
-                                       0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, 0xde, 0x66,
-                                       0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58,
-                                       0x89, 0xfb, 0x60, 0xe8, 0x46, 0x29, 0xc9, 0xbd,
-                                       0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56,
-                                       0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e,
-                                       0x09, 0xa7, 0xe7, 0x78, 0x49, 0x2b, 0x56, 0x2e,
-                                       0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7,
-                                       0x9d, 0xb9, 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15,
-                                       0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f, 0xc3,
-                                       0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a,
-                                       0x97, 0xa5, 0xf5, 0x76, 0xfe, 0x06, 0x40, 0x25,
-                                       0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5,
-                                       0x07, 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69,
-                                       0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, 0xc9, 0xc4,
-                                       0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7,
-                                       0x0e, 0xaf, 0x46, 0xf7, 0x6d, 0xad, 0x39, 0x79,
-                                       0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a,
-                                       0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a,
-                                       0x94, 0xdf, 0x76, 0x28, 0xfe, 0x4e, 0xaa, 0xf2,
-                                       0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a,
-                                       0xd0, 0xf9, 0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09,
-                                       0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a,
-                                       0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9,
-                               ),
-                       },
-               );
-
-               for tv in test_vectors.iter() {
-                       let mut c = ChaCha20::new(&tv.key, &tv.nonce);
-                       let input: Vec<u8> = repeat(0).take(tv.keystream.len()).collect();
-                       let mut output: Vec<u8> = repeat(0).take(input.len()).collect();
-                       c.process(&input[..], &mut output[..]);
-                       assert_eq!(output, tv.keystream);
-               }
-       }
-
-       #[test]
-       fn test_chacha20_256_tls_vectors_96_nonce() {
-               struct TestVector {
-                       key:   [u8; 32],
-                       nonce: [u8; 12],
-                       keystream: Vec<u8>,
-               }
-               // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
-               let test_vectors = vec!(
-                       TestVector{
-                               key: [
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                               ],
-                               nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
-                               keystream: vec!(
-                                       0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
-                                       0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
-                                       0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
-                                       0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
-                                       0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
-                                       0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
-                                       0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
-                                       0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
-                               ),
-                       }, TestVector{
-                               key: [
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-                               ],
-                               nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
-                               keystream: vec!(
-                                       0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96,
-                                       0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96,
-                                       0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60,
-                                       0x4f, 0x45, 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41,
-                                       0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, 0xd2,
-                                       0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c,
-                                       0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81,
-                                       0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
-                               ),
-                       }, TestVector{
-                               key: [
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                               ],
-                               nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ],
-                               keystream: vec!(
-                                       0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5,
-                                       0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a,
-                                       0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13,
-                                       0x4f, 0xcb, 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31,
-                                       0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, 0x45,
-                                       0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b,
-                                       0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e,
-                                       0x44, 0x5f, 0x41, 0xe3,
-                               ),
-                       }, TestVector{
-                               key: [
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                               ],
-                               nonce: [ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
-                               keystream: vec!(
-                                       0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
-                                       0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
-                                       0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac,
-                                       0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32,
-                                       0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c,
-                                       0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54,
-                                       0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d,
-                                       0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
-                               ),
-                       }, TestVector{
-                               key: [
-                                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-                                       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-                                       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-                                       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-                               ],
-                               nonce: [0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ],
-                               keystream: vec!(
-                                       0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69,
-                                       0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75,
-                                       0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93,
-                                       0xec, 0x01, 0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1,
-                                       0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, 0x41,
-                                       0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69,
-                                       0x05, 0xd3, 0xbe, 0x59, 0xea, 0x1c, 0x53, 0xf1,
-                                       0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a,
-                                       0x38, 0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94,
-                                       0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, 0xde, 0x66,
-                                       0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58,
-                                       0x89, 0xfb, 0x60, 0xe8, 0x46, 0x29, 0xc9, 0xbd,
-                                       0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56,
-                                       0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e,
-                                       0x09, 0xa7, 0xe7, 0x78, 0x49, 0x2b, 0x56, 0x2e,
-                                       0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7,
-                                       0x9d, 0xb9, 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15,
-                                       0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f, 0xc3,
-                                       0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a,
-                                       0x97, 0xa5, 0xf5, 0x76, 0xfe, 0x06, 0x40, 0x25,
-                                       0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5,
-                                       0x07, 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69,
-                                       0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, 0xc9, 0xc4,
-                                       0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7,
-                                       0x0e, 0xaf, 0x46, 0xf7, 0x6d, 0xad, 0x39, 0x79,
-                                       0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a,
-                                       0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a,
-                                       0x94, 0xdf, 0x76, 0x28, 0xfe, 0x4e, 0xaa, 0xf2,
-                                       0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a,
-                                       0xd0, 0xf9, 0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09,
-                                       0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a,
-                                       0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9,
-                               ),
-                       },
-               );
-
-               for tv in test_vectors.iter() {
-                       let mut c = ChaCha20::new(&tv.key, &tv.nonce);
-                       let input: Vec<u8> = repeat(0).take(tv.keystream.len()).collect();
-                       let mut output: Vec<u8> = repeat(0).take(input.len()).collect();
-                       c.process(&input[..], &mut output[..]);
-                       assert_eq!(output, tv.keystream);
-               }
-       }
-
-       #[test]
-       fn get_single_block() {
-               // Test that `get_single_block` (which takes a 16-byte nonce) is equivalent to getting a block
-               // using a 12-byte nonce, with the block starting at the counter offset given by the remaining 4
-               // bytes.
-               let key = [
-                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-                       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-                       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-                       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-               ];
-               let nonce_16bytes = [
-                       0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b
-               ];
-               let counter_pos = &nonce_16bytes[..4];
-               let nonce_12bytes = &nonce_16bytes[4..];
-
-               // Initialize a ChaCha20 instance with its counter starting at 0.
-               let mut chacha20 = ChaCha20::new(&key, nonce_12bytes);
-               // Seek its counter to the block at counter_pos.
-               chacha20.seek_to_block(u32::from_le_bytes(counter_pos.try_into().unwrap()));
-               let mut block_bytes = [0; 32];
-               chacha20.process_in_place(&mut block_bytes);
-
-               assert_eq!(ChaCha20::get_single_block(&key, &nonce_16bytes), block_bytes);
-       }
-
-       #[test]
-       fn encrypt_single_block() {
-               let key = [
-                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-                       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-                       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-                       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-               ];
-               let nonce = [
-                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
-                       0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-               ];
-               let bytes = [1; 32];
-
-               let mut encrypted_bytes = [0; 32];
-               ChaCha20::encrypt_single_block(&key, &nonce, &mut encrypted_bytes, &bytes);
-
-               let mut decrypted_bytes = [0; 32];
-               ChaCha20::encrypt_single_block(&key, &nonce, &mut decrypted_bytes, &encrypted_bytes);
-
-               assert_eq!(bytes, decrypted_bytes);
-       }
-
-       #[test]
-       fn encrypt_single_block_in_place() {
-               let key = [
-                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-                       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-                       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-                       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-               ];
-               let nonce = [
-                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
-                       0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-               ];
-               let unencrypted_bytes = [1; 32];
-               let mut bytes = unencrypted_bytes;
-
-               ChaCha20::encrypt_single_block_in_place(&key, &nonce, &mut bytes);
-               assert_ne!(bytes, unencrypted_bytes);
-
-               ChaCha20::encrypt_single_block_in_place(&key, &nonce, &mut bytes);
-               assert_eq!(bytes, unencrypted_bytes);
-       }
-}
diff --git a/lightning/src/util/chacha20poly1305rfc.rs b/lightning/src/util/chacha20poly1305rfc.rs
deleted file mode 100644 (file)
index d5792e0..0000000
+++ /dev/null
@@ -1,427 +0,0 @@
-// ring has a garbage API so its use is avoided, but rust-crypto doesn't have RFC-variant poly1305
-// Instead, we steal rust-crypto's implementation and tweak it to match the RFC.
-//
-// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
-// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
-// You may not use this file except in accordance with one or both of these
-// licenses.
-//
-// This is a port of Andrew Moons poly1305-donna
-// https://github.com/floodyberry/poly1305-donna
-
-use crate::ln::msgs::DecodeError;
-use crate::util::ser::{FixedLengthReader, LengthRead, LengthReadableArgs, Readable, Writeable, Writer};
-use crate::io::{self, Read, Write};
-
-#[cfg(not(fuzzing))]
-mod real_chachapoly {
-       use crate::util::chacha20::ChaCha20;
-       use crate::util::poly1305::Poly1305;
-       use bitcoin::hashes::cmp::fixed_time_eq;
-
-       #[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,
-                               mac,
-                               finished: false,
-                               data_len: 0,
-                               aad_len: aad.len() as u64,
-                       }
-               }
-
-               pub 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(&self.aad_len.to_le_bytes());
-                       self.mac.input(&(self.data_len as u64).to_le_bytes());
-                       self.mac.raw_result(out_tag);
-               }
-
-               pub fn encrypt_full_message_in_place(&mut self, input_output: &mut [u8], out_tag: &mut [u8]) {
-                       self.encrypt_in_place(input_output);
-                       self.finish_and_get_tag(out_tag);
-               }
-
-               // Encrypt `input_output` in-place. To finish and calculate the tag, use `finish_and_get_tag`
-               // below.
-               pub(super) fn encrypt_in_place(&mut self, input_output: &mut [u8]) {
-                       debug_assert!(self.finished == false);
-                       self.cipher.process_in_place(input_output);
-                       self.data_len += input_output.len();
-                       self.mac.input(input_output);
-               }
-
-               // If we were previously encrypting with `encrypt_in_place`, this method can be used to finish
-               // encrypting and calculate the tag.
-               pub(super) fn finish_and_get_tag(&mut self, out_tag: &mut [u8]) {
-                       debug_assert!(self.finished == false);
-                       ChaCha20Poly1305RFC::pad_mac_16(&mut self.mac, self.data_len);
-                       self.finished = true;
-                       self.mac.input(&self.aad_len.to_le_bytes());
-                       self.mac.input(&(self.data_len as u64).to_le_bytes());
-                       self.mac.raw_result(out_tag);
-               }
-
-               pub 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(&self.aad_len.to_le_bytes());
-                       self.mac.input(&(self.data_len as u64).to_le_bytes());
-
-                       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
-                       }
-               }
-
-               pub fn check_decrypt_in_place(&mut self, input_output: &mut [u8], tag: &[u8]) -> Result<(), ()> {
-                       self.decrypt_in_place(input_output);
-                       if self.finish_and_check_tag(tag) { Ok(()) } else { Err(()) }
-               }
-
-               /// Decrypt in place, without checking the tag. Use `finish_and_check_tag` to check it
-               /// later when decryption finishes.
-               ///
-               /// Should never be `pub` because the public API should always enforce tag checking.
-               pub(super) fn decrypt_in_place(&mut self, input_output: &mut [u8]) {
-                       debug_assert!(self.finished == false);
-                       self.mac.input(input_output);
-                       self.data_len += input_output.len();
-                       self.cipher.process_in_place(input_output);
-               }
-
-               /// If we were previously decrypting with `just_decrypt_in_place`, this method must be used
-               /// to check the tag. Returns whether or not the tag is valid.
-               pub(super) fn finish_and_check_tag(&mut self, tag: &[u8]) -> bool {
-                       debug_assert!(self.finished == false);
-                       self.finished = true;
-                       ChaCha20Poly1305RFC::pad_mac_16(&mut self.mac, self.data_len);
-                       self.mac.input(&self.aad_len.to_le_bytes());
-                       self.mac.input(&(self.data_len as u64).to_le_bytes());
-
-                       let mut calc_tag =  [0u8; 16];
-                       self.mac.raw_result(&mut calc_tag);
-                       if fixed_time_eq(&calc_tag, tag) {
-                               true
-                       } else {
-                               false
-                       }
-               }
-       }
-}
-#[cfg(not(fuzzing))]
-pub use self::real_chachapoly::ChaCha20Poly1305RFC;
-
-/// Enables simultaneously reading and decrypting a ChaCha20Poly1305RFC stream from a std::io::Read.
-struct ChaChaPolyReader<'a, R: Read> {
-       pub chacha: &'a mut ChaCha20Poly1305RFC,
-       pub read: R,
-}
-
-impl<'a, R: Read> Read for ChaChaPolyReader<'a, R> {
-       // Decrypt bytes from Self::read into `dest`.
-       // `ChaCha20Poly1305RFC::finish_and_check_tag` must be called to check the tag after all reads
-       // complete.
-       fn read(&mut self, dest: &mut [u8]) -> Result<usize, io::Error> {
-               let res = self.read.read(dest)?;
-               if res > 0 {
-                       self.chacha.decrypt_in_place(&mut dest[0..res]);
-               }
-               Ok(res)
-       }
-}
-
-/// Enables simultaneously writing and encrypting a byte stream into a Writer.
-struct ChaChaPolyWriter<'a, W: Writer> {
-       pub chacha: &'a mut ChaCha20Poly1305RFC,
-       pub write: &'a mut W,
-}
-
-impl<'a, W: Writer> Writer for ChaChaPolyWriter<'a, W> {
-       // Encrypt then write bytes from `src` into Self::write.
-       // `ChaCha20Poly1305RFC::finish_and_get_tag` can be called to retrieve the tag after all writes
-       // complete.
-       fn write_all(&mut self, src: &[u8]) -> Result<(), io::Error> {
-               let mut src_idx = 0;
-               while src_idx < src.len() {
-                       let mut write_buffer = [0; 8192];
-                       let bytes_written = (&mut write_buffer[..]).write(&src[src_idx..]).expect("In-memory writes can't fail");
-                       self.chacha.encrypt_in_place(&mut write_buffer[..bytes_written]);
-                       self.write.write_all(&write_buffer[..bytes_written])?;
-                       src_idx += bytes_written;
-               }
-               Ok(())
-       }
-}
-
-/// Enables the use of the serialization macros for objects that need to be simultaneously encrypted and
-/// serialized. This allows us to avoid an intermediate Vec allocation.
-pub(crate) struct ChaChaPolyWriteAdapter<'a, W: Writeable> {
-       pub rho: [u8; 32],
-       pub writeable: &'a W,
-}
-
-impl<'a, W: Writeable> ChaChaPolyWriteAdapter<'a, W> {
-       #[allow(unused)] // This will be used for onion messages soon
-       pub fn new(rho: [u8; 32], writeable: &'a W) -> ChaChaPolyWriteAdapter<'a, W> {
-               Self { rho, writeable }
-       }
-}
-
-impl<'a, T: Writeable> Writeable for ChaChaPolyWriteAdapter<'a, T> {
-       // Simultaneously write and encrypt Self::writeable.
-       fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
-               let mut chacha = ChaCha20Poly1305RFC::new(&self.rho, &[0; 12], &[]);
-               let mut chacha_stream = ChaChaPolyWriter { chacha: &mut chacha, write: w };
-               self.writeable.write(&mut chacha_stream)?;
-               let mut tag = [0 as u8; 16];
-               chacha.finish_and_get_tag(&mut tag);
-               tag.write(w)?;
-
-               Ok(())
-       }
-}
-
-/// Enables the use of the serialization macros for objects that need to be simultaneously decrypted and
-/// deserialized. This allows us to avoid an intermediate Vec allocation.
-pub(crate) struct ChaChaPolyReadAdapter<R: Readable> {
-       pub readable: R,
-}
-
-impl<T: Readable> LengthReadableArgs<[u8; 32]> for ChaChaPolyReadAdapter<T> {
-       // Simultaneously read and decrypt an object from a LengthRead, storing it in Self::readable.
-       // LengthRead must be used instead of std::io::Read because we need the total length to separate
-       // out the tag at the end.
-       fn read<R: LengthRead>(mut r: &mut R, secret: [u8; 32]) -> Result<Self, DecodeError> {
-               if r.total_bytes() < 16 { return Err(DecodeError::InvalidValue) }
-
-               let mut chacha = ChaCha20Poly1305RFC::new(&secret, &[0; 12], &[]);
-               let decrypted_len = r.total_bytes() - 16;
-               let s = FixedLengthReader::new(&mut r, decrypted_len);
-               let mut chacha_stream = ChaChaPolyReader { chacha: &mut chacha, read: s };
-               let readable: T = Readable::read(&mut chacha_stream)?;
-               chacha_stream.read.eat_remaining()?;
-
-               let mut tag = [0 as u8; 16];
-               r.read_exact(&mut tag)?;
-               if !chacha.finish_and_check_tag(&tag) {
-                       return Err(DecodeError::InvalidValue)
-               }
-
-               Ok(Self { readable })
-       }
-}
-
-#[cfg(fuzzing)]
-mod fuzzy_chachapoly {
-       #[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,
-                       }
-               }
-
-               pub 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;
-               }
-
-               pub fn encrypt_full_message_in_place(&mut self, input_output: &mut [u8], out_tag: &mut [u8]) {
-                       self.encrypt_in_place(input_output);
-                       self.finish_and_get_tag(out_tag);
-               }
-
-               pub(super) fn encrypt_in_place(&mut self, _input_output: &mut [u8]) {
-                       assert!(self.finished == false);
-               }
-
-               pub(super) fn finish_and_get_tag(&mut self, out_tag: &mut [u8]) {
-                       assert!(self.finished == false);
-                       out_tag.copy_from_slice(&self.tag);
-                       self.finished = true;
-               }
-
-               pub 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
-               }
-
-               pub fn check_decrypt_in_place(&mut self, input_output: &mut [u8], tag: &[u8]) -> Result<(), ()> {
-                       self.decrypt_in_place(input_output);
-                       if self.finish_and_check_tag(tag) { Ok(()) } else { Err(()) }
-               }
-
-               pub(super) fn decrypt_in_place(&mut self, _input: &mut [u8]) {
-                       assert!(self.finished == false);
-               }
-
-               pub(super) fn finish_and_check_tag(&mut self, tag: &[u8]) -> bool {
-                       if tag[..] != self.tag[..] { return false; }
-                       self.finished = true;
-                       true
-               }
-       }
-}
-#[cfg(fuzzing)]
-pub use self::fuzzy_chachapoly::ChaCha20Poly1305RFC;
-
-#[cfg(test)]
-mod tests {
-       use crate::ln::msgs::DecodeError;
-       use super::{ChaChaPolyReadAdapter, ChaChaPolyWriteAdapter};
-       use crate::util::ser::{self, FixedLengthReader, LengthReadableArgs, Writeable};
-
-       // Used for for testing various lengths of serialization.
-       #[derive(Debug, PartialEq, Eq)]
-       struct TestWriteable {
-               field1: Vec<u8>,
-               field2: Vec<u8>,
-               field3: Vec<u8>,
-       }
-       impl_writeable_tlv_based!(TestWriteable, {
-               (1, field1, required_vec),
-               (2, field2, required_vec),
-               (3, field3, required_vec),
-       });
-
-       #[test]
-       fn test_chacha_stream_adapters() {
-               // Check that ChaChaPolyReadAdapter and ChaChaPolyWriteAdapter correctly encode and decode an
-               // encrypted object.
-               macro_rules! check_object_read_write {
-                       ($obj: expr) => {
-                               // First, serialize the object, encrypted with ChaCha20Poly1305.
-                               let rho = [42; 32];
-                               let writeable_len = $obj.serialized_length() as u64 + 16;
-                               let write_adapter = ChaChaPolyWriteAdapter::new(rho, &$obj);
-                               let encrypted_writeable_bytes = write_adapter.encode();
-                               let encrypted_writeable = &encrypted_writeable_bytes[..];
-
-                               // Now deserialize the object back and make sure it matches the original.
-                               let mut rd = FixedLengthReader::new(encrypted_writeable, writeable_len);
-                               let read_adapter = <ChaChaPolyReadAdapter<TestWriteable>>::read(&mut rd, rho).unwrap();
-                               assert_eq!($obj, read_adapter.readable);
-                       };
-               }
-
-               // Try a big object that will require multiple write buffers.
-               let big_writeable = TestWriteable {
-                       field1: vec![43],
-                       field2: vec![44; 4192],
-                       field3: vec![45; 4192 + 1],
-               };
-               check_object_read_write!(big_writeable);
-
-               // Try a small object that fits into one write buffer.
-               let small_writeable = TestWriteable {
-                       field1: vec![43],
-                       field2: vec![44],
-                       field3: vec![45],
-               };
-               check_object_read_write!(small_writeable);
-       }
-
-       fn do_chacha_stream_adapters_ser_macros() -> Result<(), DecodeError> {
-               let writeable = TestWriteable {
-                       field1: vec![43],
-                       field2: vec![44; 4192],
-                       field3: vec![45; 4192 + 1],
-               };
-
-               // First, serialize the object into a TLV stream, encrypted with ChaCha20Poly1305.
-               let rho = [42; 32];
-               let write_adapter = ChaChaPolyWriteAdapter::new(rho, &writeable);
-               let mut writer = ser::VecWriter(Vec::new());
-               encode_tlv_stream!(&mut writer, {
-                       (1, write_adapter, required),
-               });
-
-               // Now deserialize the object back and make sure it matches the original.
-               let mut read_adapter: Option<ChaChaPolyReadAdapter<TestWriteable>> = None;
-               decode_tlv_stream!(&writer.0[..], {
-                       (1, read_adapter, (option: LengthReadableArgs, rho)),
-               });
-               assert_eq!(writeable, read_adapter.unwrap().readable);
-
-               Ok(())
-       }
-
-       #[test]
-       fn chacha_stream_adapters_ser_macros() {
-               // Test that our stream adapters work as expected with the TLV macros.
-               // This also serves to test the `option: $trait` variant of the `_decode_tlv` ser macro.
-               do_chacha_stream_adapters_ser_macros().unwrap()
-       }
-}
diff --git a/lightning/src/util/crypto.rs b/lightning/src/util/crypto.rs
deleted file mode 100644 (file)
index 98963c7..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-use bitcoin::hashes::{Hash, HashEngine};
-use bitcoin::hashes::hmac::{Hmac, HmacEngine};
-use bitcoin::hashes::sha256::Hash as Sha256;
-use bitcoin::secp256k1::{Message, Secp256k1, SecretKey, ecdsa::Signature, Signing};
-
-use crate::sign::EntropySource;
-
-use core::ops::Deref;
-
-macro_rules! hkdf_extract_expand {
-       ($salt: expr, $ikm: expr) => {{
-               let mut hmac = HmacEngine::<Sha256>::new($salt);
-               hmac.input($ikm);
-               let prk = Hmac::from_engine(hmac).to_byte_array();
-               let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
-               hmac.input(&[1; 1]);
-               let t1 = Hmac::from_engine(hmac).to_byte_array();
-               let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
-               hmac.input(&t1);
-               hmac.input(&[2; 1]);
-               (t1, Hmac::from_engine(hmac).to_byte_array(), prk)
-       }};
-       ($salt: expr, $ikm: expr, 2) => {{
-               let (k1, k2, _) = hkdf_extract_expand!($salt, $ikm);
-               (k1, k2)
-       }};
-       ($salt: expr, $ikm: expr, 5) => {{
-               let (k1, k2, prk) = hkdf_extract_expand!($salt, $ikm);
-
-               let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
-               hmac.input(&k2);
-               hmac.input(&[3; 1]);
-               let k3 = Hmac::from_engine(hmac).to_byte_array();
-
-               let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
-               hmac.input(&k3);
-               hmac.input(&[4; 1]);
-               let k4 = Hmac::from_engine(hmac).to_byte_array();
-
-               let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
-               hmac.input(&k4);
-               hmac.input(&[5; 1]);
-               let k5 = Hmac::from_engine(hmac).to_byte_array();
-
-               (k1, k2, k3, k4, k5)
-       }}
-}
-
-pub fn hkdf_extract_expand_twice(salt: &[u8], ikm: &[u8]) -> ([u8; 32], [u8; 32]) {
-       hkdf_extract_expand!(salt, ikm, 2)
-}
-
-pub fn hkdf_extract_expand_5x(salt: &[u8], ikm: &[u8]) -> ([u8; 32], [u8; 32], [u8; 32], [u8; 32], [u8; 32]) {
-       hkdf_extract_expand!(salt, ikm, 5)
-}
-
-#[inline]
-pub fn sign<C: Signing>(ctx: &Secp256k1<C>, msg: &Message, sk: &SecretKey) -> Signature {
-       #[cfg(feature = "grind_signatures")]
-       let sig = ctx.sign_ecdsa_low_r(msg, sk);
-       #[cfg(not(feature = "grind_signatures"))]
-       let sig = ctx.sign_ecdsa(msg, sk);
-       sig
-}
-
-#[inline]
-#[allow(unused_variables)]
-pub fn sign_with_aux_rand<C: Signing, ES: Deref>(
-       ctx: &Secp256k1<C>, msg: &Message, sk: &SecretKey, entropy_source: &ES
-) -> Signature where ES::Target: EntropySource {
-       #[cfg(feature = "grind_signatures")]
-       let sig = loop {
-               let sig = ctx.sign_ecdsa_with_noncedata(msg, sk, &entropy_source.get_secure_random_bytes());
-               if sig.serialize_compact()[0] < 0x80 {
-                       break sig;
-               }
-       };
-       #[cfg(all(not(feature = "grind_signatures"), not(feature = "_test_vectors")))]
-       let sig = ctx.sign_ecdsa_with_noncedata(msg, sk, &entropy_source.get_secure_random_bytes());
-       #[cfg(all(not(feature = "grind_signatures"), feature = "_test_vectors"))]
-       let sig = sign(ctx, msg, sk);
-       sig
-}
index e86885a83dbd0160b42bc103ecb5e737ea39bb7b..f2116032786ce9c6bbed6de0c4e1d82883874ba0 100644 (file)
@@ -29,10 +29,6 @@ pub(crate) mod base32;
 
 pub(crate) mod atomic_counter;
 pub(crate) mod byte_utils;
-pub(crate) mod chacha20;
-#[cfg(not(fuzzing))]
-pub(crate) mod poly1305;
-pub(crate) mod chacha20poly1305rfc;
 pub(crate) mod transaction_utils;
 pub(crate) mod scid_utils;
 pub(crate) mod time;
@@ -43,9 +39,6 @@ pub mod indexed_map;
 #[macro_use]
 pub(crate) mod macro_logger;
 
-/// Cryptography utilities.
-pub(crate) mod crypto;
-
 // These have to come after macro_logger to build
 pub mod logger;
 pub mod config;
diff --git a/lightning/src/util/poly1305.rs b/lightning/src/util/poly1305.rs
deleted file mode 100644 (file)
index 1abda74..0000000
+++ /dev/null
@@ -1,341 +0,0 @@
-// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
-// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
-// You may not use this file except in accordance with one or both of these
-// licenses.
-
-// This is a port of Andrew Moons poly1305-donna
-// https://github.com/floodyberry/poly1305-donna
-
-use core::cmp::min;
-use core::convert::TryInto;
-
-#[derive(Clone, Copy)]
-pub struct Poly1305 {
-       r         : [u32; 5],
-       h         : [u32; 5],
-       pad       : [u32; 4],
-       leftover  : usize,
-       buffer    : [u8; 16],
-       finalized : bool,
-}
-
-impl Poly1305 {
-       pub fn new(key: &[u8]) -> Poly1305 {
-               assert!(key.len() == 32);
-               let mut poly = Poly1305{ r: [0u32; 5], h: [0u32; 5], pad: [0u32; 4], leftover: 0, buffer: [0u8; 16], finalized: false };
-
-               // r &= 0xffffffc0ffffffc0ffffffc0fffffff
-               poly.r[0] = (u32::from_le_bytes(key[ 0.. 4].try_into().expect("len is 4"))     ) & 0x3ffffff;
-               poly.r[1] = (u32::from_le_bytes(key[ 3.. 7].try_into().expect("len is 4")) >> 2) & 0x3ffff03;
-               poly.r[2] = (u32::from_le_bytes(key[ 6..10].try_into().expect("len is 4")) >> 4) & 0x3ffc0ff;
-               poly.r[3] = (u32::from_le_bytes(key[ 9..13].try_into().expect("len is 4")) >> 6) & 0x3f03fff;
-               poly.r[4] = (u32::from_le_bytes(key[12..16].try_into().expect("len is 4")) >> 8) & 0x00fffff;
-
-               poly.pad[0] = u32::from_le_bytes(key[16..20].try_into().expect("len is 4"));
-               poly.pad[1] = u32::from_le_bytes(key[20..24].try_into().expect("len is 4"));
-               poly.pad[2] = u32::from_le_bytes(key[24..28].try_into().expect("len is 4"));
-               poly.pad[3] = u32::from_le_bytes(key[28..32].try_into().expect("len is 4"));
-
-               poly
-       }
-
-       fn block(&mut self, m: &[u8]) {
-               let hibit : u32 = if self.finalized { 0 } else { 1 << 24 };
-
-               let r0 = self.r[0];
-               let r1 = self.r[1];
-               let r2 = self.r[2];
-               let r3 = self.r[3];
-               let r4 = self.r[4];
-
-               let s1 = r1 * 5;
-               let s2 = r2 * 5;
-               let s3 = r3 * 5;
-               let s4 = r4 * 5;
-
-               let mut h0 = self.h[0];
-               let mut h1 = self.h[1];
-               let mut h2 = self.h[2];
-               let mut h3 = self.h[3];
-               let mut h4 = self.h[4];
-
-               // h += m
-               h0 += (u32::from_le_bytes(m[ 0.. 4].try_into().expect("len is 4"))     ) & 0x3ffffff;
-               h1 += (u32::from_le_bytes(m[ 3.. 7].try_into().expect("len is 4")) >> 2) & 0x3ffffff;
-               h2 += (u32::from_le_bytes(m[ 6..10].try_into().expect("len is 4")) >> 4) & 0x3ffffff;
-               h3 += (u32::from_le_bytes(m[ 9..13].try_into().expect("len is 4")) >> 6) & 0x3ffffff;
-               h4 += (u32::from_le_bytes(m[12..16].try_into().expect("len is 4")) >> 8) | hibit;
-
-               // h *= r
-               let     d0 = (h0 as u64 * r0 as u64) + (h1 as u64 * s4 as u64) + (h2 as u64 * s3 as u64) + (h3 as u64 * s2 as u64) + (h4 as u64 * s1 as u64);
-               let mut d1 = (h0 as u64 * r1 as u64) + (h1 as u64 * r0 as u64) + (h2 as u64 * s4 as u64) + (h3 as u64 * s3 as u64) + (h4 as u64 * s2 as u64);
-               let mut d2 = (h0 as u64 * r2 as u64) + (h1 as u64 * r1 as u64) + (h2 as u64 * r0 as u64) + (h3 as u64 * s4 as u64) + (h4 as u64 * s3 as u64);
-               let mut d3 = (h0 as u64 * r3 as u64) + (h1 as u64 * r2 as u64) + (h2 as u64 * r1 as u64) + (h3 as u64 * r0 as u64) + (h4 as u64 * s4 as u64);
-               let mut d4 = (h0 as u64 * r4 as u64) + (h1 as u64 * r3 as u64) + (h2 as u64 * r2 as u64) + (h3 as u64 * r1 as u64) + (h4 as u64 * r0 as u64);
-
-               // (partial) h %= p
-               let mut c : u32;
-                               c = (d0 >> 26) as u32; h0 = d0 as u32 & 0x3ffffff;
-               d1 += c as u64; c = (d1 >> 26) as u32; h1 = d1 as u32 & 0x3ffffff;
-               d2 += c as u64; c = (d2 >> 26) as u32; h2 = d2 as u32 & 0x3ffffff;
-               d3 += c as u64; c = (d3 >> 26) as u32; h3 = d3 as u32 & 0x3ffffff;
-               d4 += c as u64; c = (d4 >> 26) as u32; h4 = d4 as u32 & 0x3ffffff;
-               h0 += c * 5;    c = h0 >> 26; h0 = h0 & 0x3ffffff;
-               h1 += c;
-
-               self.h[0] = h0;
-               self.h[1] = h1;
-               self.h[2] = h2;
-               self.h[3] = h3;
-               self.h[4] = h4;
-       }
-
-       pub fn finish(&mut self) {
-               if self.leftover > 0 {
-                       self.buffer[self.leftover] = 1;
-                       for i in self.leftover+1..16 {
-                               self.buffer[i] = 0;
-                       }
-                       self.finalized = true;
-                       let tmp = self.buffer;
-                       self.block(&tmp);
-               }
-
-               // fully carry h
-               let mut h0 = self.h[0];
-               let mut h1 = self.h[1];
-               let mut h2 = self.h[2];
-               let mut h3 = self.h[3];
-               let mut h4 = self.h[4];
-
-               let mut c : u32;
-                            c = h1 >> 26; h1 = h1 & 0x3ffffff;
-               h2 +=     c; c = h2 >> 26; h2 = h2 & 0x3ffffff;
-               h3 +=     c; c = h3 >> 26; h3 = h3 & 0x3ffffff;
-               h4 +=     c; c = h4 >> 26; h4 = h4 & 0x3ffffff;
-               h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff;
-               h1 +=     c;
-
-               // compute h + -p
-               let mut g0 = h0.wrapping_add(5); c = g0 >> 26; g0 &= 0x3ffffff;
-               let mut g1 = h1.wrapping_add(c); c = g1 >> 26; g1 &= 0x3ffffff;
-               let mut g2 = h2.wrapping_add(c); c = g2 >> 26; g2 &= 0x3ffffff;
-               let mut g3 = h3.wrapping_add(c); c = g3 >> 26; g3 &= 0x3ffffff;
-               let mut g4 = h4.wrapping_add(c).wrapping_sub(1 << 26);
-
-               // select h if h < p, or h + -p if h >= p
-               let mut mask = (g4 >> (32 - 1)).wrapping_sub(1);
-               g0 &= mask;
-               g1 &= mask;
-               g2 &= mask;
-               g3 &= mask;
-               g4 &= mask;
-               mask = !mask;
-               h0 = (h0 & mask) | g0;
-               h1 = (h1 & mask) | g1;
-               h2 = (h2 & mask) | g2;
-               h3 = (h3 & mask) | g3;
-               h4 = (h4 & mask) | g4;
-
-               // h = h % (2^128)
-               h0 = ((h0      ) | (h1 << 26)) & 0xffffffff;
-               h1 = ((h1 >>  6) | (h2 << 20)) & 0xffffffff;
-               h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff;
-               h3 = ((h3 >> 18) | (h4 <<  8)) & 0xffffffff;
-
-               // h = mac = (h + pad) % (2^128)
-               let mut f : u64;
-               f = h0 as u64 + self.pad[0] as u64            ; h0 = f as u32;
-               f = h1 as u64 + self.pad[1] as u64 + (f >> 32); h1 = f as u32;
-               f = h2 as u64 + self.pad[2] as u64 + (f >> 32); h2 = f as u32;
-               f = h3 as u64 + self.pad[3] as u64 + (f >> 32); h3 = f as u32;
-
-               self.h[0] = h0;
-               self.h[1] = h1;
-               self.h[2] = h2;
-               self.h[3] = h3;
-       }
-
-       pub fn input(&mut self, data: &[u8]) {
-               assert!(!self.finalized);
-               let mut m = data;
-
-               if self.leftover > 0 {
-                       let want = min(16 - self.leftover, m.len());
-                       for i in 0..want {
-                               self.buffer[self.leftover+i] = m[i];
-                       }
-                       m = &m[want..];
-                       self.leftover += want;
-
-                       if self.leftover < 16 {
-                               return;
-                       }
-
-                       // self.block(self.buffer[..]);
-                       let tmp = self.buffer;
-                       self.block(&tmp);
-
-                       self.leftover = 0;
-               }
-
-               while m.len() >= 16 {
-                       self.block(&m[0..16]);
-                       m = &m[16..];
-               }
-
-               for i in 0..m.len() {
-                       self.buffer[i] = m[i];
-               }
-               self.leftover = m.len();
-       }
-
-       pub fn raw_result(&mut self, output: &mut [u8]) {
-               assert!(output.len() >= 16);
-               if !self.finalized{
-                       self.finish();
-               }
-               output[0..4].copy_from_slice(&self.h[0].to_le_bytes());
-               output[4..8].copy_from_slice(&self.h[1].to_le_bytes());
-               output[8..12].copy_from_slice(&self.h[2].to_le_bytes());
-               output[12..16].copy_from_slice(&self.h[3].to_le_bytes());
-       }
-}
-
-#[cfg(test)]
-mod test {
-       use crate::prelude::*;
-       use core::iter::repeat;
-
-       use crate::util::poly1305::Poly1305;
-
-       fn poly1305(key: &[u8], msg: &[u8], mac: &mut [u8]) {
-               let mut poly = Poly1305::new(key);
-               poly.input(msg);
-               poly.raw_result(mac);
-       }
-
-       #[test]
-       fn test_nacl_vector() {
-               let key = [
-                       0xee,0xa6,0xa7,0x25,0x1c,0x1e,0x72,0x91,
-                       0x6d,0x11,0xc2,0xcb,0x21,0x4d,0x3c,0x25,
-                       0x25,0x39,0x12,0x1d,0x8e,0x23,0x4e,0x65,
-                       0x2d,0x65,0x1f,0xa4,0xc8,0xcf,0xf8,0x80,
-               ];
-
-               let msg = [
-                       0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73,
-                       0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce,
-                       0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4,
-                       0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a,
-                       0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b,
-                       0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72,
-                       0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2,
-                       0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38,
-                       0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a,
-                       0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae,
-                       0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea,
-                       0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda,
-                       0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde,
-                       0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3,
-                       0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6,
-                       0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74,
-                       0xe3,0x55,0xa5,
-               ];
-
-               let expected = [
-                       0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5,
-                       0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9,
-               ];
-
-               let mut mac = [0u8; 16];
-               poly1305(&key, &msg, &mut mac);
-               assert_eq!(&mac[..], &expected[..]);
-
-               let mut poly = Poly1305::new(&key);
-               poly.input(&msg[0..32]);
-               poly.input(&msg[32..96]);
-               poly.input(&msg[96..112]);
-               poly.input(&msg[112..120]);
-               poly.input(&msg[120..124]);
-               poly.input(&msg[124..126]);
-               poly.input(&msg[126..127]);
-               poly.input(&msg[127..128]);
-               poly.input(&msg[128..129]);
-               poly.input(&msg[129..130]);
-               poly.input(&msg[130..131]);
-               poly.raw_result(&mut mac);
-               assert_eq!(&mac[..], &expected[..]);
-       }
-
-       #[test]
-       fn donna_self_test() {
-               let wrap_key = [
-                       0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-               ];
-
-               let wrap_msg = [
-                       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-               ];
-
-               let wrap_mac = [
-                       0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-               ];
-
-               let mut mac = [0u8; 16];
-               poly1305(&wrap_key, &wrap_msg, &mut mac);
-               assert_eq!(&mac[..], &wrap_mac[..]);
-
-               let total_key = [
-                       0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xff,
-                       0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xff, 0xff,
-                       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                       0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
-               ];
-
-               let total_mac = [
-                       0x64, 0xaf, 0xe2, 0xe8, 0xd6, 0xad, 0x7b, 0xbd,
-                       0xd2, 0x87, 0xf9, 0x7c, 0x44, 0x62, 0x3d, 0x39,
-               ];
-
-               let mut tpoly = Poly1305::new(&total_key);
-               for i in 0..256 {
-                       let key: Vec<u8> = repeat(i as u8).take(32).collect();
-                       let msg: Vec<u8> = repeat(i as u8).take(256).collect();
-                       let mut mac = [0u8; 16];
-                       poly1305(&key[..], &msg[0..i], &mut mac);
-                       tpoly.input(&mac);
-               }
-               tpoly.raw_result(&mut mac);
-               assert_eq!(&mac[..], &total_mac[..]);
-       }
-
-       #[test]
-       fn test_tls_vectors() {
-               // from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
-               let key = b"this is 32-byte key for Poly1305";
-               let msg = [0u8; 32];
-               let expected = [
-                       0x49, 0xec, 0x78, 0x09, 0x0e, 0x48, 0x1e, 0xc6,
-                       0xc2, 0x6b, 0x33, 0xb9, 0x1c, 0xcc, 0x03, 0x07,
-               ];
-               let mut mac = [0u8; 16];
-               poly1305(key, &msg, &mut mac);
-               assert_eq!(&mac[..], &expected[..]);
-
-               let msg = b"Hello world!";
-               let expected= [
-                       0xa6, 0xf7, 0x45, 0x00, 0x8f, 0x81, 0xc9, 0x16,
-                       0xa2, 0x0d, 0xcc, 0x74, 0xee, 0xf2, 0xb2, 0xf0,
-               ];
-               poly1305(key, msg, &mut mac);
-               assert_eq!(&mac[..], &expected[..]);
-       }
-}
index fbbcc69a133e0966e8bd937d1838ac8dc4fd5c17..45b24fd14b042e563e7d64f9dc978684f21eab3a 100644 (file)
@@ -69,7 +69,7 @@ pub(crate) mod fake_scid {
        use bitcoin::blockdata::constants::ChainHash;
        use bitcoin::network::constants::Network;
        use crate::sign::EntropySource;
-       use crate::util::chacha20::ChaCha20;
+       use crate::crypto::chacha20::ChaCha20;
        use crate::util::scid_utils;
 
        use core::convert::TryInto;