From 42988b23465ab938acee3895aa5a117644663040 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 15 Jan 2024 01:25:10 +0000 Subject: [PATCH] Move cryptographic algorithms and utilities to a new `crypto` mod As we'd generally like the `lightning` crate to, over time, have more modules rather than being very monolithic, we should move the cryptographic things into their own module, which we do here. We also take this opportunity to move stream adapters into their own module and make clear that the ChaChaPoly `decrypt` method is variable time. --- lightning/src/blinded_path/message.rs | 2 +- lightning/src/blinded_path/utils.rs | 2 +- lightning/src/chain/channelmonitor.rs | 2 +- lightning/src/{util => crypto}/chacha20.rs | 21 +- lightning/src/crypto/chacha20poly1305rfc.rs | 237 ++++++++++ lightning/src/crypto/mod.rs | 8 + lightning/src/{util => crypto}/poly1305.rs | 5 +- lightning/src/crypto/streams.rs | 211 +++++++++ .../src/{util/crypto.rs => crypto/utils.rs} | 0 lightning/src/lib.rs | 2 + lightning/src/ln/chan_utils.rs | 2 +- lightning/src/ln/inbound_payment.rs | 4 +- lightning/src/ln/monitor_tests.rs | 2 +- lightning/src/ln/msgs.rs | 2 +- lightning/src/ln/onion_utils.rs | 3 +- lightning/src/ln/peer_channel_encryptor.rs | 6 +- lightning/src/onion_message/packet.rs | 2 +- lightning/src/routing/router.rs | 4 +- lightning/src/sign/mod.rs | 4 +- lightning/src/util/chacha20poly1305rfc.rs | 427 ------------------ lightning/src/util/mod.rs | 7 - lightning/src/util/scid_utils.rs | 2 +- 22 files changed, 482 insertions(+), 473 deletions(-) rename lightning/src/{util => crypto}/chacha20.rs (98%) create mode 100644 lightning/src/crypto/chacha20poly1305rfc.rs create mode 100644 lightning/src/crypto/mod.rs rename lightning/src/{util => crypto}/poly1305.rs (99%) create mode 100644 lightning/src/crypto/streams.rs rename lightning/src/{util/crypto.rs => crypto/utils.rs} (100%) delete mode 100644 lightning/src/util/chacha20poly1305rfc.rs diff --git a/lightning/src/blinded_path/message.rs b/lightning/src/blinded_path/message.rs index 2631a05f660..3a5541fa146 100644 --- a/lightning/src/blinded_path/message.rs +++ b/lightning/src/blinded_path/message.rs @@ -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; diff --git a/lightning/src/blinded_path/utils.rs b/lightning/src/blinded_path/utils.rs index 7ddb39c1b68..d4894a86aa1 100644 --- a/lightning/src/blinded_path/utils.rs +++ b/lightning/src/blinded_path/utils.rs @@ -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; diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs index bcc324a5582..c81a48b78ac 100644 --- a/lightning/src/chain/channelmonitor.rs +++ b/lightning/src/chain/channelmonitor.rs @@ -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/util/chacha20.rs b/lightning/src/crypto/chacha20.rs similarity index 98% rename from lightning/src/util/chacha20.rs rename to lightning/src/crypto/chacha20.rs index 865a09fa040..d6fd3a7dee0 100644 --- a/lightning/src/util/chacha20.rs +++ b/lightning/src/crypto/chacha20.rs @@ -9,8 +9,6 @@ // 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; @@ -335,27 +333,14 @@ mod fuzzy_chacha { #[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 { - 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 alloc::vec; + use alloc::vec::{Vec}; + use core::convert::TryInto; use core::iter::repeat; use super::ChaCha20; - use std::convert::TryInto; #[test] fn test_chacha20_256_tls_vectors() { diff --git a/lightning/src/crypto/chacha20poly1305rfc.rs b/lightning/src/crypto/chacha20poly1305rfc.rs new file mode 100644 index 00000000000..74fc393bf28 --- /dev/null +++ b/lightning/src/crypto/chacha20poly1305rfc.rs @@ -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 or the MIT license +// , 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(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; diff --git a/lightning/src/crypto/mod.rs b/lightning/src/crypto/mod.rs new file mode 100644 index 00000000000..6efd120667c --- /dev/null +++ b/lightning/src/crypto/mod.rs @@ -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/util/poly1305.rs b/lightning/src/crypto/poly1305.rs similarity index 99% rename from lightning/src/util/poly1305.rs rename to lightning/src/crypto/poly1305.rs index 1abda74b6c2..9eec9b545ed 100644 --- a/lightning/src/util/poly1305.rs +++ b/lightning/src/crypto/poly1305.rs @@ -192,7 +192,6 @@ impl Poly1305 { } pub fn raw_result(&mut self, output: &mut [u8]) { - assert!(output.len() >= 16); if !self.finalized{ self.finish(); } @@ -205,10 +204,10 @@ impl Poly1305 { #[cfg(test)] mod test { - use crate::prelude::*; use core::iter::repeat; + use alloc::vec::Vec; - use crate::util::poly1305::Poly1305; + use super::Poly1305; fn poly1305(key: &[u8], msg: &[u8], mac: &mut [u8]) { let mut poly = Poly1305::new(key); diff --git a/lightning/src/crypto/streams.rs b/lightning/src/crypto/streams.rs new file mode 100644 index 00000000000..14921a38612 --- /dev/null +++ b/lightning/src/crypto/streams.rs @@ -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 { + 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(&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 { + pub readable: R, +} + +impl LengthReadableArgs<[u8; 32]> for ChaChaPolyReadAdapter { + // 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(mut r: &mut R, secret: [u8; 32]) -> Result { + 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 { + 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, + field2: Vec, + field3: Vec, + } + 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 = >::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> = 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/crypto/utils.rs similarity index 100% rename from lightning/src/util/crypto.rs rename to lightning/src/crypto/utils.rs diff --git a/lightning/src/lib.rs b/lightning/src/lib.rs index 6eefb3983cc..160f632415b 100644 --- a/lightning/src/lib.rs +++ b/lightning/src/lib.rs @@ -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; diff --git a/lightning/src/ln/chan_utils.rs b/lightning/src/ln/chan_utils.rs index 672e3aa862e..18c4d83406c 100644 --- a/lightning/src/ln/chan_utils.rs +++ b/lightning/src/ln/chan_utils.rs @@ -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). diff --git a/lightning/src/ln/inbound_payment.rs b/lightning/src/ln/inbound_payment.rs index 2ee93a6c46e..eeae514fdf3 100644 --- a/lightning/src/ln/inbound_payment.rs +++ b/lightning/src/ln/inbound_payment.rs @@ -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; diff --git a/lightning/src/ln/monitor_tests.rs b/lightning/src/ln/monitor_tests.rs index 74740a6f227..b6270181439 100644 --- a/lightning/src/ln/monitor_tests.rs +++ b/lightning/src/ln/monitor_tests.rs @@ -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; diff --git a/lightning/src/ln/msgs.rs b/lightning/src/ln/msgs.rs index 1794aefe7ef..efd04d143d9 100644 --- a/lightning/src/ln/msgs.rs +++ b/lightning/src/ln/msgs.rs @@ -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; diff --git a/lightning/src/ln/onion_utils.rs b/lightning/src/ln/onion_utils.rs index ac0bb6189c6..d9455fc1de2 100644 --- a/lightning/src/ln/onion_utils.rs +++ b/lightning/src/ln/onion_utils.rs @@ -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; diff --git a/lightning/src/ln/peer_channel_encryptor.rs b/lightning/src/ln/peer_channel_encryptor.rs index c9e1ac47886..51e34bdb969 100644 --- a/lightning/src/ln/peer_channel_encryptor.rs +++ b/lightning/src/ln/peer_channel_encryptor.rs @@ -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(()) diff --git a/lightning/src/onion_message/packet.rs b/lightning/src/onion_message/packet.rs index 5ce02c54d08..d9349fdadbf 100644 --- a/lightning/src/onion_message/packet.rs +++ b/lightning/src/onion_message/packet.rs @@ -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}; diff --git a/lightning/src/routing/router.rs b/lightning/src/routing/router.rs index 277661862e3..0b19369a4aa 100644 --- a/lightning/src/routing/router.rs +++ b/lightning/src/routing/router.rs @@ -26,7 +26,7 @@ use crate::routing::scoring::{ChannelUsage, LockableScore, ScoreLookUp}; use crate::sign::EntropySource; use crate::util::ser::{Writeable, Readable, ReadableArgs, Writer}; use crate::util::logger::{Level, Logger}; -use crate::util::chacha20::ChaCha20; +use crate::crypto::chacha20::ChaCha20; use crate::io; use crate::prelude::*; @@ -3195,7 +3195,7 @@ mod tests { use crate::offers::invoice::BlindedPayInfo; use crate::util::config::UserConfig; use crate::util::test_utils as ln_test_utils; - use crate::util::chacha20::ChaCha20; + use crate::crypto::chacha20::ChaCha20; use crate::util::ser::{Readable, Writeable}; #[cfg(c_bindings)] use crate::util::ser::Writer; diff --git a/lightning/src/sign/mod.rs b/lightning/src/sign/mod.rs index 4e418f049bb..c4bb6fb8020 100644 --- a/lightning/src/sign/mod.rs +++ b/lightning/src/sign/mod.rs @@ -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/chacha20poly1305rfc.rs b/lightning/src/util/chacha20poly1305rfc.rs deleted file mode 100644 index d5792e0ac2b..00000000000 --- a/lightning/src/util/chacha20poly1305rfc.rs +++ /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 or the MIT license -// , 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 { - 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(&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 { - pub readable: R, -} - -impl LengthReadableArgs<[u8; 32]> for ChaChaPolyReadAdapter { - // 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(mut r: &mut R, secret: [u8; 32]) -> Result { - 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, - field2: Vec, - field3: Vec, - } - 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 = >::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> = 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/mod.rs b/lightning/src/util/mod.rs index e86885a83db..f2116032786 100644 --- a/lightning/src/util/mod.rs +++ b/lightning/src/util/mod.rs @@ -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/scid_utils.rs b/lightning/src/util/scid_utils.rs index fbbcc69a133..45b24fd14b0 100644 --- a/lightning/src/util/scid_utils.rs +++ b/lightning/src/util/scid_utils.rs @@ -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;