Merge pull request #2828 from TheBlueMatt/2024-01-crypto-module
authorvalentinewallace <valentinewallace@users.noreply.github.com>
Wed, 17 Jan 2024 17:53:02 +0000 (12:53 -0500)
committerGitHub <noreply@github.com>
Wed, 17 Jan 2024 17:53:02 +0000 (12:53 -0500)
Move cryptographic algorithms and utilities to a new `crypto` mod

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 bc914ce49756ee0933dd7cbcf8ace51f137375be..d39f1a6084274762331b456d28494b725999d69e 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 137699521f482b6b186a4375477284a010bc897b..1ea6fd83aa237f08e9f911dc052c42b06a042b01 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 524bb1bc4c708baa983b65064a76d17ade17ae80..9a5c2dfbf215d5a21a3cab0fe2d2689a8453c496 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::*;
@@ -3190,7 +3190,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;