diff --git a/fuzz/src/full_stack.rs b/fuzz/src/full_stack.rs index 1ed17b9ea3f..f6a07f351a4 100644 --- a/fuzz/src/full_stack.rs +++ b/fuzz/src/full_stack.rs @@ -31,7 +31,7 @@ use lightning::chain::chainmonitor; use lightning::chain::transaction::OutPoint; use lightning::chain::keysinterface::{InMemoryChannelKeys, KeysInterface}; use lightning::ln::channelmanager::{ChannelManager, PaymentHash, PaymentPreimage, PaymentSecret}; -use lightning::ln::peer_handler::{MessageHandler,PeerManager,SocketDescriptor}; +use lightning::ln::peers::handler::{MessageHandler,PeerManager,SocketDescriptor}; use lightning::routing::router::get_route; use lightning::routing::network_graph::NetGraphMsgHandler; use lightning::util::events::{EventsProvider,Event}; @@ -891,15 +891,15 @@ mod tests { super::do_test(&::hex::decode("00000000000000000000000000000000000000000000000000000000000000000000000001000300000000000000000000000000000000000000000000000000000000000000000300320003000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000030012000a0300000000000000000000000000000003001a00100002200000022000030000000000000000000000000000000300120141030000000000000000000000000000000300fe00207500000000000000000000000000000000000000000000000000000000000000ff4f00f805273c1b203bb5ebf8436bfde57b3be8c2f5e95d9491dbb181909679000000000000c35000000000000000000000000000000222ffffffffffffffff00000000000002220000000000000000000000fd000601e3030000000000000000000000000000000000000000000000000000000000000001030000000000000000000000000000000000000000000000000000000000000002030000000000000000000000000000000000000000000000000000000000000003030000000000000000000000000000000000000000000000000000000000000004030053030000000000000000000000000000000000000000000000000000000000000005030000000000000000000000000000000000000000000000000000000000000000010300000000000000000000000000000000fd00fd00fd0300120084030000000000000000000000000000000300940022ff4f00f805273c1b203bb5ebf8436bfde57b3be8c2f5e95d9491dbb1819096793d00000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001030000000000000000000000000000000c005e020000000100000000000000000000000000000000000000000000000000000000000000000000000000ffffffff0150c3000000000000220020ae00000000000000000000000000000000000000000000000000000000000000000000000c00000c00000c00000c00000c00000c00000c00000c00000c00000c00000c00000c000003001200430300000000000000000000000000000003005300243d0000000000000000000000000000000000000000000000000000000000000003010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000010301320003000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000030142000302000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000003000000000000000000000000000000030112000a0100000000000000000000000000000003011a0010000220000002200001000000000000000000000000000000050103020000000000000000000000000000000000000000000000000000000000000000c3500003e800fd00fd0301120110010000000000000000000000000000000301ff00210000000000000000000000000000000000000000000000000000000000000e02000000000000001a00000000004c4b4000000000000003e800000000000003e80000000203f00005030000000000000000000000000000000000000000000000000000000000000100030000000000000000000000000000000000000000000000000000000000000200030000000000000000000000000000000000000000000000000000000000000300030000000000000000000000000000000000000000000000000000000000000400030000000000000000000000000000000000000000000000000000000000000500030000000000000000000000000000000301210000000000000000000000000000000000010000000000000000000000000000000a03011200620100000000000000000000000000000003017200233900000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100010000000000000000000000000000000b030112004301000000000000000000000000000000030153002439000000000000000000000000000000000000000000000000000000000000000301000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000003001205ac030000000000000000000000000000000300ff00803d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e80ff0000000000000000000000000000000000000000000000000000000000000000000121000300000000000000000000000000000000000000000000000000000000000005550000000e000001000000000000000003e80000007b0000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300c1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff95000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000fd03001200640300000000000000000000000000000003007400843d000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000300000000000000000000000000000003001200630300000000000000000000000000000003007300853d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000703011200640100000000000000000000000000000003017400843900000000000000000000000000000000000000000000000000000000000000f100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000100000000000000000000000000000003011200630100000000000000000000000000000003017300853900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000030112004a0100000000000000000000000000000003015a008239000000000000000000000000000000000000000000000000000000000000000000000000000000ff008888888888888888888888888888888888888888888888888888888888880100000000000000000000000000000003011200640100000000000000000000000000000003017400843900000000000000000000000000000000000000000000000000000000000000fd0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000010000000000000000000000000000000301120063010000000000000000000000000000000301730085390000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000003001205ac030000000000000000000000000000000300ff00803d0000000000000000000000000000000000000000000000000000000000000000000000000000010000000000003e80ff0000000000000000000000000000000000000000000000000000000000000000000121000300000000000000000000000000000000000000000000000000000000000005550000000e000001000000000000000003e80000007b0000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300c1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff95000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000fd03001200630300000000000000000000000000000003007300853d0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000003001200640300000000000000000000000000000003007400843d00000000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000300000000000000000000000000000003001200630300000000000000000000000000000003007300853d000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000703011200640100000000000000000000000000000003017400843900000000000000000000000000000000000000000000000000000000000000fc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000100000000000000000000000000000003011200630100000000000000000000000000000003017300853900000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003040000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000030112002c0100000000000000000000000000000003013c00833900000000000000000000000000000000000000000000000000000000000000000000000000000100000100000000000000000000000000000003011200640100000000000000000000000000000003017400843900000000000000000000000000000000000000000000000000000000000000fb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000001000000000000000000000000000000030112006301000000000000000000000000000000030173008539000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000703001200630300000000000000000000000000000003007300853d0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000305000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000003001200640300000000000000000000000000000003007400843d000000000000000000000000000000000000000000000000000000000000003300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000300000000000000000000000000000003001205ac030000000000000000000000000000000300ff00803d00000000000000000000000000000000000000000000000000000000000000000000000000000200000000000b0838ff0000000000000000000000000000000000000000000000000000000000000000000121000300000000000000000000000000000000000000000000000000000000000005550000000e0000010000000000000003e8000000007b0000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300c1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff95000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000fd03001200a4030000000000000000000000000000000300b400843d000000000000000000000000000000000000000000000000000000000000007b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001c8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007f000000000000000300000000000000000000000000000003001200630300000000000000000000000000000003007300853d00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000003060000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000070c007d02000000013900000000000000000000000000000000000000000000000000000000000000000000000000000080020001000000000000220020bb000000000000000000000000000000000000000000000000000000000000006cc10000000000001600142b000000000000000000000000000000000000000500002000fd00fd0c005e0200000001a100000000000000000000000000000000000000000000000000000000000000000000000000000000014f00000000000000220020f600000000000000000000000000000000000000000000000000000000000000000000000c00000c000000fd0c00000c00000c000007").unwrap(), &(Arc::clone(&logger) as Arc)); let log_entries = logger.lines.lock().unwrap(); - assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling SendAcceptChannel event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 for channel ff4f00f805273c1b203bb5ebf8436bfde57b3be8c2f5e95d9491dbb181909679".to_string())), Some(&1)); // 1 - assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling SendFundingSigned event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&1)); // 2 - assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling SendFundingLocked event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&1)); // 3 - assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling SendFundingLocked event in peer_handler for node 030200000000000000000000000000000000000000000000000000000000000000 for channel 3900000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&1)); // 4 - assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling SendRevokeAndACK event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&4)); // 5 - assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling UpdateHTLCs event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 with 0 adds, 0 fulfills, 0 fails for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&3)); // 6 - assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling UpdateHTLCs event in peer_handler for node 030200000000000000000000000000000000000000000000000000000000000000 with 1 adds, 0 fulfills, 0 fails for channel 3900000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&3)); // 7 - assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling UpdateHTLCs event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 with 0 adds, 1 fulfills, 0 fails for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&1)); // 8 - assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling UpdateHTLCs event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 with 0 adds, 0 fulfills, 1 fails for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&2)); // 9 + assert_eq!(log_entries.get(&("lightning::ln::peers::handler".to_string(), "Handling SendAcceptChannel event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 for channel ff4f00f805273c1b203bb5ebf8436bfde57b3be8c2f5e95d9491dbb181909679".to_string())), Some(&1)); // 1 + assert_eq!(log_entries.get(&("lightning::ln::peers::handler".to_string(), "Handling SendFundingSigned event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&1)); // 2 + assert_eq!(log_entries.get(&("lightning::ln::peers::handler".to_string(), "Handling SendFundingLocked event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&1)); // 3 + assert_eq!(log_entries.get(&("lightning::ln::peers::handler".to_string(), "Handling SendFundingLocked event in peer_handler for node 030200000000000000000000000000000000000000000000000000000000000000 for channel 3900000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&1)); // 4 + assert_eq!(log_entries.get(&("lightning::ln::peers::handler".to_string(), "Handling SendRevokeAndACK event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&4)); // 5 + assert_eq!(log_entries.get(&("lightning::ln::peers::handler".to_string(), "Handling UpdateHTLCs event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 with 0 adds, 0 fulfills, 0 fails for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&3)); // 6 + assert_eq!(log_entries.get(&("lightning::ln::peers::handler".to_string(), "Handling UpdateHTLCs event in peer_handler for node 030200000000000000000000000000000000000000000000000000000000000000 with 1 adds, 0 fulfills, 0 fails for channel 3900000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&3)); // 7 + assert_eq!(log_entries.get(&("lightning::ln::peers::handler".to_string(), "Handling UpdateHTLCs event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 with 0 adds, 1 fulfills, 0 fails for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&1)); // 8 + assert_eq!(log_entries.get(&("lightning::ln::peers::handler".to_string(), "Handling UpdateHTLCs event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000000 with 0 adds, 0 fulfills, 1 fails for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&2)); // 9 assert_eq!(log_entries.get(&("lightning::chain::channelmonitor".to_string(), "Input spending counterparty commitment tx (00000000000000000000000000000000000000000000000000000000000000a1:0) in 0000000000000000000000000000000000000000000000000000000000000018 resolves outbound HTLC with payment hash ff00000000000000000000000000000000000000000000000000000000000000 with timeout".to_string())), Some(&1)); // 10 } } diff --git a/fuzz/src/peer_crypt.rs b/fuzz/src/peer_crypt.rs index f41137fc828..7d832122584 100644 --- a/fuzz/src/peer_crypt.rs +++ b/fuzz/src/peer_crypt.rs @@ -7,81 +7,360 @@ // You may not use this file except in accordance with one or both of these // licenses. -use lightning::ln::peer_channel_encryptor::PeerChannelEncryptor; +use std::cmp; +use std::{error, fmt}; -use bitcoin::secp256k1::key::{PublicKey,SecretKey}; +use bitcoin::secp256k1; +use bitcoin::secp256k1::key::{PublicKey,SecretKey}; +use lightning::ln::peers::conduit::Conduit; +use lightning::ln::peers::handshake::PeerHandshake; use utils::test_logger; -#[inline] -fn slice_to_be16(v: &[u8]) -> u16 { - ((v[0] as u16) << 8*1) | - ((v[1] as u16) << 8*0) +// Test structure used to generate "random" values based on input data. It is used throughout +// the various test cases to send random messages between nodes and to ensure the code does not fail +// unexpectedly. +pub struct FuzzGen<'a> { + read_pos: usize, + data: &'a [u8], } -#[inline] -pub fn do_test(data: &[u8]) { - let mut read_pos = 0; - macro_rules! get_slice { - ($len: expr) => { - { - let slice_len = $len as usize; - if data.len() < read_pos + slice_len { - return; - } - read_pos += slice_len; - &data[read_pos - slice_len..read_pos] +impl<'a> FuzzGen<'a> { + fn new(data: &'a [u8]) -> Self { + Self { + read_pos: 0, + data + } + } + + fn generate_bytes(&mut self, num: usize) -> Result<&'a [u8], GeneratorFinishedError> { + if self.data.len() < self.read_pos + num { + return Err(GeneratorFinishedError { }); + } + + self.read_pos += num; + Ok(&self.data[self.read_pos - num..self.read_pos]) + } + + fn generate_secret_key(&mut self) -> Result { + // Loop through the input 32 bytes at a time until a valid + // secret key can be created or we run out of bytes + loop { + match SecretKey::from_slice(self.generate_bytes(32)?) { + Ok(key) => { return Ok(key) }, + _ => { } } } } - let our_network_key = match SecretKey::from_slice(get_slice!(32)) { - Ok(key) => key, - Err(_) => return, - }; - let ephemeral_key = match SecretKey::from_slice(get_slice!(32)) { - Ok(key) => key, - Err(_) => return, - }; + fn generate_bool(&mut self) -> Result { + let next_byte = self.generate_bytes(1)?; + Ok(next_byte[0] & 1 == 1) + } +} + +#[derive(PartialEq)] +struct GeneratorFinishedError { } + +impl fmt::Debug for GeneratorFinishedError { + fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { + formatter.write_str("Generator out of bytes") + } +} +impl fmt::Display for GeneratorFinishedError { + fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { + formatter.write_str("Generator out of bytes") + } +} +impl error::Error for GeneratorFinishedError { + fn description(&self) -> &str { "Generator out of bytes" } +} + +struct TestCtx { + initiator_static_public_key: PublicKey, + initiator_handshake: PeerHandshake, + responder_static_public_key: PublicKey, + responder_handshake: PeerHandshake, + act1: Vec +} + +impl TestCtx { + // At the completion of this call each handshake has the following state: + // initiator_handshake: HandshakeState::InitiatorStarting + // responder_handshake: HandshakeState::ResponderAwaitingActOne + fn make(generator: &mut FuzzGen) -> Result { + let curve = secp256k1::Secp256k1::new(); + + // Generate needed keys for successful handshake + let initiator_static_private_key = generator.generate_secret_key()?; + let initiator_static_public_key = PublicKey::from_secret_key(&curve, &initiator_static_private_key); + let initiator_ephemeral_private_key = generator.generate_secret_key()?; + let responder_static_private_key = generator.generate_secret_key()?; + let responder_static_public_key = PublicKey::from_secret_key(&curve, &responder_static_private_key); + let responder_ephemeral_private_key = generator.generate_secret_key()?; + + let mut initiator_handshake = PeerHandshake::new_outbound(&initiator_static_private_key, &responder_static_public_key, &initiator_ephemeral_private_key); + let act1 = initiator_handshake.set_up_outbound(); + + // Sanity checks around initialization to catch errors before we get to the fuzzing + + // act 1 is the correct size + assert_eq!(act1.len(), 50); + + // act 1 has the correct version + assert_eq!(act1[0], 0); + let responder_handshake = PeerHandshake::new_inbound(&responder_static_private_key, &responder_ephemeral_private_key); + + Ok(TestCtx { + initiator_static_public_key, + initiator_handshake, + responder_static_public_key, + responder_handshake, + act1 + }) + } +} + +// Common test function that sends encrypted messages between two conduits until the source data +// runs out. +#[inline] +fn do_conduit_tests(generator: &mut FuzzGen, initiator_conduit: &mut Conduit, responder_conduit: &mut Conduit, failures_expected: bool) -> Result<(), GeneratorFinishedError> { + // Keep sending messages back and forth until the input data is consumed + loop { + // Randomly generate message length + let msg_len_raw = generator.generate_bytes(1)?; + let msg_len = msg_len_raw[0] as usize; - let mut crypter = if get_slice!(1)[0] != 0 { - let their_pubkey = match PublicKey::from_slice(get_slice!(33)) { - Ok(key) => key, - Err(_) => return, + // Randomly generate message + let sender_unencrypted_msg = generator.generate_bytes(msg_len)?; + + // randomly choose sender of message + let receiver_unencrypted_msg = if generator.generate_bool()? { + let encrypted_msg = initiator_conduit.encrypt(sender_unencrypted_msg); + if let Ok(msg) = responder_conduit.decrypt_single_message(Some(&encrypted_msg)) { + msg + } else { + assert!(failures_expected); + return Ok(()); + } + } else { + let encrypted_msg = responder_conduit.encrypt(sender_unencrypted_msg); + if let Ok(msg) = initiator_conduit.decrypt_single_message(Some(&encrypted_msg)) { + msg + } else { + assert!(failures_expected); + return Ok(()); + } }; - let mut crypter = PeerChannelEncryptor::new_outbound(their_pubkey, ephemeral_key); - crypter.get_act_one(); - match crypter.process_act_two(get_slice!(50), &our_network_key) { - Ok(_) => {}, - Err(_) => return, - } - assert!(crypter.is_ready_for_encryption()); - crypter - } else { - let mut crypter = PeerChannelEncryptor::new_inbound(&our_network_key); - match crypter.process_act_one_with_keys(get_slice!(50), &our_network_key, ephemeral_key) { - Ok(_) => {}, - Err(_) => return, + + assert_eq!(sender_unencrypted_msg, receiver_unencrypted_msg.unwrap().as_slice()); + } +} + +// This test completes a valid handshake based on fuzzer-provided private keys and then sends +// variable length encrypted messages between two conduits to validate that they can communicate. +#[inline] +fn do_completed_handshake_test(generator: &mut FuzzGen) -> Result<(), GeneratorFinishedError> { + let mut test_ctx = TestCtx::make(generator)?; + + // The handshake should complete with any valid private keys + let act2 = test_ctx.responder_handshake.process_act(&test_ctx.act1).unwrap().0.unwrap(); + let (act3, (mut initiator_conduit, responder_pubkey)) = match test_ctx.initiator_handshake.process_act(&act2) { + Ok((Some(act3), Some((conduit, remote_pubkey)))) => { + (act3, (conduit, remote_pubkey)) } - match crypter.process_act_three(get_slice!(66)) { - Ok(_) => {}, - Err(_) => return, + _ => panic!("handshake failed") + }; + + let (mut responder_conduit, initiator_pubkey) = match test_ctx.responder_handshake.process_act(&act3) { + Ok((None, Some((conduit, remote_pubkey)))) => { + (conduit, remote_pubkey) } - assert!(crypter.is_ready_for_encryption()); - crypter + _ => panic!("handshake failed") }; - loop { - if get_slice!(1)[0] == 0 { - crypter.encrypt_message(get_slice!(slice_to_be16(get_slice!(2)))); - } else { - let len = match crypter.decrypt_length_header(get_slice!(16+2)) { - Ok(len) => len, - Err(_) => return, - }; - match crypter.decrypt_message(get_slice!(len as usize + 16)) { - Ok(_) => {}, - Err(_) => return, + + // The handshake should complete with each peer knowing the static_public_key of the remote peer + assert_eq!(initiator_pubkey, test_ctx.initiator_static_public_key); + assert_eq!(responder_pubkey, test_ctx.responder_static_public_key); + + // The nodes should be able to communicate over the conduit. + do_conduit_tests(generator, &mut initiator_conduit, &mut responder_conduit, false) +} + +// Either returns (act, false) or (random_bytes, true) where random_bytes is the same len as act +fn maybe_generate_bad_act(generator: &mut FuzzGen, act: Vec) -> Result<(Vec, bool), GeneratorFinishedError> { + if generator.generate_bool()? { + Ok(((generator.generate_bytes(act.len())?).to_vec(), true)) + } else { + Ok((act, false)) + } +} + +// Add between 0..15 bytes of garbage to a vec and returns whether or not it added bytes +fn maybe_add_garbage(generator: &mut FuzzGen, input: &mut Vec) -> Result { + let garbage_amount = (generator.generate_bytes(1)?)[0] >> 4; + + if garbage_amount != 0 { + input.extend(generator.generate_bytes(garbage_amount as usize)?); + Ok(true) + } else { + Ok(false) + } +} + +// Splits a Vec into between 1..7 chunks returning a Vec of slices into the original data +fn split_vec<'a>(generator: &mut FuzzGen, input: &'a Vec) -> Result, GeneratorFinishedError> { + let num_chunks = cmp::max(1, ((generator.generate_bytes(1)?)[0] as u8) >> 5) as usize; + let chunk_size = input.len() / num_chunks; + + Ok(input.chunks(chunk_size).collect()) +} + +// This test variant goes through the peer handshake between the initiator and responder with +// "random" failures to verify that nothing panics. +// In the event of an error from process_act() we validate that the input data was generated +// randomly to ensure real act generation still produces valid transitions. +#[inline] +fn do_handshake_test(generator: &mut FuzzGen) -> Result<(), GeneratorFinishedError> { + let mut test_ctx = TestCtx::make(generator)?; + + // Possibly generate bad data for act1 + let (mut act1, mut used_generated_data) = maybe_generate_bad_act(generator, test_ctx.act1)?; + + // Optionally, add garbage data to the end + used_generated_data |= maybe_add_garbage(generator, &mut act1)?; + + // Split act1 into between 1..7 chunks + let act1_chunks = split_vec(generator, &act1)?; + + let mut act2_option = None; + for partial_act1 in act1_chunks { + match test_ctx.responder_handshake.process_act(&partial_act1) { + // Save valid act2 for initiator + Ok((Some(act2_option_inner), None)) => { + act2_option = Some(act2_option_inner); + }, + // Partial act + Ok((None, None)) => { } + // errors are fine as long as they happened due to using bad data + Err(_) => { + assert!(used_generated_data); + return Ok(()); + } + _ => panic!("responder required to output act bytes and no conduit/pubkey") + }; + } + let act2 = act2_option.unwrap(); + + // Possibly generate bad data for act2 + let (mut act2, is_bad_data) = maybe_generate_bad_act(generator, act2)?; + + // Optionally, add garbage data to the end + let did_add_garbage = maybe_add_garbage(generator, &mut act2)?; + + // Keep track of whether or not we have generated bad data up to this point + used_generated_data |= is_bad_data | did_add_garbage; + + // Split act2 into between 1..7 chunks + let act2_chunks = split_vec(generator, &act2)?; + + let mut act3_option = None; + let mut conduit_and_remote_pubkey_option = None; + for partial_act2 in act2_chunks { + match test_ctx.initiator_handshake.process_act(&partial_act2) { + Ok((Some(act3), Some(conduit_and_remote_pubkey_option_inner))) => { + act3_option = Some(act3); + conduit_and_remote_pubkey_option = Some(conduit_and_remote_pubkey_option_inner); + + // Valid conduit and pubkey indicates handshake is over + break; + } + // Partial act + Ok((None, None)) => { }, + // errors are fine as long as they happened due to using bad data + Err(_) => { + assert!(used_generated_data); + return Ok(()); } + _ => panic!("initiator required to output act bytes, conduit, and pubkey") + }; + } + + // Ensure we actually received act3 bytes, conduit, and remote pubkey from process_act() + let act3 = act3_option.unwrap(); + let (mut initiator_conduit, responder_pubkey) = conduit_and_remote_pubkey_option.unwrap(); + + // Possibly generate bad data for act3 + let (mut act3, is_bad_data) = maybe_generate_bad_act(generator, act3)?; + + // Optionally, add garbage data to the end + let did_add_garbage = maybe_add_garbage(generator, &mut act3)?; + + // Keep track of whether or not we have generated bad data up to this point + used_generated_data |= is_bad_data | did_add_garbage; + + // Split act3 into between 1..7 chunks + let act3_chunks = split_vec(generator, &act3)?; + + let mut conduit_and_remote_pubkey_option = None; + for partial_act3 in act3_chunks { + match test_ctx.responder_handshake.process_act(&partial_act3) { + Ok((None, Some(conduit_and_remote_pubkey_option_inner))) => { + conduit_and_remote_pubkey_option = Some(conduit_and_remote_pubkey_option_inner); + + // Valid conduit and pubkey indicates handshake is over + break; + }, + // partial act + Ok((None, None)) => { }, + // errors are fine as long as they happened due to using bad data + Err(_) => { + assert!(used_generated_data); + return Ok(()); + }, + _ => panic!("responder required to output conduit, and pubkey") + }; + } + // Ensure we actually received conduit and remote pubkey from process_act() + let (mut responder_conduit, initiator_pubkey) = conduit_and_remote_pubkey_option.unwrap(); + + // The handshake should complete with each peer knowing the static_public_key of the remote peer + if initiator_pubkey != test_ctx.initiator_static_public_key { + assert!(used_generated_data); + return Ok(()); + } + if responder_pubkey != test_ctx.responder_static_public_key { + assert!(used_generated_data); + return Ok(()); + } + + // The nodes should be able to communicate over the conduit + do_conduit_tests(generator, &mut initiator_conduit, &mut responder_conduit, used_generated_data) +} + +#[inline] +fn do_test(data: &[u8]) { + let mut generator = FuzzGen::new(data); + + // Based on a "random" bool, decide which test variant to run + let do_valid_handshake = match generator.generate_bool() { + Ok(value) => { value }, + _ => { return } + }; + + // The only valid error that can leak here is the FuzzGen error to indicate + // the input bytes have been exhausted and the test can't proceed. Everything + // else should be caught and handled by the individual tests to validate any + // errors. + if do_valid_handshake { + match do_completed_handshake_test(&mut generator) { + Err(_) => { } + _ => { } + } + } else { + match do_handshake_test(&mut generator) { + Err(_) => { } + _ => { } } } } @@ -94,3 +373,145 @@ pub fn peer_crypt_test(data: &[u8], _out: Out) { pub extern "C" fn peer_crypt_run(data: *const u8, datalen: usize) { do_test(unsafe { std::slice::from_raw_parts(data, datalen) }); } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn data_generator_empty() { + let mut generator = FuzzGen::new(&[]); + assert_eq!(generator.generate_bool(), Err(GeneratorFinishedError { })); + } + + #[test] + fn data_generator_bool_true() { + let mut generator = FuzzGen::new(&[1]); + assert!(generator.generate_bool().unwrap()); + } + + #[test] + fn data_generator_bool_false() { + let mut generator = FuzzGen::new(&[0]); + assert!(!generator.generate_bool().unwrap()); + } + + #[test] + fn data_generator_bool_then_error() { + let mut generator = FuzzGen::new(&[1]); + assert!(generator.generate_bool().unwrap()); + assert_eq!(generator.generate_bool(), Err(GeneratorFinishedError { })); + } + + #[test] + fn data_generator_bytes_too_many() { + let mut generator = FuzzGen::new(&[1, 2, 3, 4]); + assert_eq!(generator.generate_bytes(5), Err(GeneratorFinishedError { })); + } + + #[test] + fn data_generator_bytes() { + let input = [1, 2, 3, 4]; + let mut generator = FuzzGen::new(&input); + let result = generator.generate_bytes(4).unwrap(); + assert_eq!(result, input); + } + + #[test] + fn data_generator_bytes_sequential() { + let input = [1, 2, 3, 4]; + let mut generator = FuzzGen::new(&input); + let result = generator.generate_bytes(2).unwrap(); + assert_eq!(result, &input[..2]); + let result = generator.generate_bytes(2).unwrap(); + assert_eq!(result, &input[2..]); + assert_eq!(generator.generate_bytes(1), Err(GeneratorFinishedError { })); + } + + #[test] + fn maybe_generate_bad_act_gen_bad() { + // 1 is used to take bad branch and 2 is used to generate bad act + let input = [1, 2]; + let mut generator = FuzzGen::new(&input); + + let original_act = &[5]; + + let (act, is_bad) = maybe_generate_bad_act(&mut generator, original_act.to_vec()).unwrap(); + assert!(is_bad); + assert_eq!(act, &[2]); + } + + #[test] + fn maybe_generate_bad_act_gen_good() { + // 0 is used to take good branch + let input = [0]; + let mut generator = FuzzGen::new(&input); + let original_act = &[5]; + + let (act, is_bad) = maybe_generate_bad_act(&mut generator, original_act.to_vec()).unwrap(); + assert!(!is_bad); + assert_eq!(act, &[5]); + } + + #[test] + fn maybe_add_garbage_did_add() { + // 0x10 consumed to specify amount of garbage (1 byte) and 2 is consumed to add garbage + let input = [0x10, 2]; + let mut generator = FuzzGen::new(&input); + let mut act = vec![5]; + + let did_add_garbage = maybe_add_garbage(&mut generator, &mut act).unwrap(); + assert!(did_add_garbage); + assert_eq!(act, &[5, 2]); + } + + #[test] + fn maybe_add_garbage_no_add() { + // 0x10 consumed to specify amount of garbage (1 byte) and 2 is consumed to add garbage + let input = [0]; + let mut generator = FuzzGen::new(&input); + let mut act = vec![5]; + + let did_add_garbage = maybe_add_garbage(&mut generator, &mut act).unwrap(); + assert!(!did_add_garbage); + assert_eq!(act, &[5]); + } + + #[test] + fn split_vec_1_chunk() { + // 0 consumed for number of chunks (1 is min) + let input = [0]; + let mut generator = FuzzGen::new(&input); + let act = vec![5, 6]; + + let act_parts = split_vec(&mut generator, &act).unwrap(); + assert_eq!(act_parts.len(), 1); + assert_eq!(act_parts[0], &[5, 6]); + } + + #[test] + fn split_vec_2_chunks() { + // 40 consumed for number of chunks. Chunk size is equal to the high three bits (2) + let input = [0x40]; + let mut generator = FuzzGen::new(&input); + let act = vec![5, 6]; + + let act_parts = split_vec(&mut generator, &act).unwrap(); + assert_eq!(act_parts.len(), 2); + assert_eq!(act_parts[0], &[5]); + assert_eq!(act_parts[1], &[6]); + } + #[test] + fn split_vec_2_chunks_odd() { + // 40 consumed for number of chunks. Chunk size is equal to the high three bits (2) + let input = [0x40]; + let mut generator = FuzzGen::new(&input); + let act = vec![5, 6, 7, 8, 9]; + + let act_parts = split_vec(&mut generator, &act).unwrap(); + assert_eq!(act_parts.len(), 3); + assert_eq!(act_parts[0], &[5, 6]); + assert_eq!(act_parts[1], &[7, 8]); + assert_eq!(act_parts[2], &[9]); + } +} \ No newline at end of file diff --git a/lightning-net-tokio/src/lib.rs b/lightning-net-tokio/src/lib.rs index e84ee76229f..8e02b11e719 100644 --- a/lightning-net-tokio/src/lib.rs +++ b/lightning-net-tokio/src/lib.rs @@ -38,7 +38,7 @@ //! type ChainFilter = dyn lightning::chain::Filter; //! type ChainMonitor = lightning::chain::chainmonitor::ChainMonitor, Arc, Arc, Arc>; //! type ChannelManager = lightning::ln::channelmanager::SimpleArcChannelManager; -//! type PeerManager = lightning::ln::peer_handler::SimpleArcPeerManager; +//! type PeerManager = lightning::ln::peers::handler::SimpleArcPeerManager; //! //! // Connect to node with pubkey their_node_id at addr: //! async fn connect_to_node(peer_manager: PeerManager, chain_monitor: Arc, channel_manager: ChannelManager, their_node_id: PublicKey, addr: SocketAddr) { @@ -78,8 +78,8 @@ use tokio::{io, time}; use tokio::sync::mpsc; use tokio::io::{AsyncReadExt, AsyncWrite, AsyncWriteExt}; -use lightning::ln::peer_handler; -use lightning::ln::peer_handler::SocketDescriptor as LnSocketTrait; +use lightning::ln::peers::handler; +use lightning::ln::peers::handler::SocketDescriptor as LnSocketTrait; use lightning::ln::msgs::{ChannelMessageHandler, RoutingMessageHandler}; use lightning::util::logger::Logger; @@ -134,7 +134,7 @@ impl Connection { _ => panic!() } } - async fn schedule_read(peer_manager: Arc, Arc, Arc>>, us: Arc>, mut reader: io::ReadHalf, mut read_wake_receiver: mpsc::Receiver<()>, mut write_avail_receiver: mpsc::Receiver<()>) where + async fn schedule_read(peer_manager: Arc, Arc, Arc>>, us: Arc>, mut reader: io::ReadHalf, mut read_wake_receiver: mpsc::Receiver<()>, mut write_avail_receiver: mpsc::Receiver<()>) where CMH: ChannelMessageHandler + 'static, RMH: RoutingMessageHandler + 'static, L: Logger + 'static + ?Sized { @@ -247,7 +247,7 @@ impl Connection { /// not need to poll the provided future in order to make progress. /// /// See the module-level documentation for how to handle the event_notify mpsc::Sender. -pub fn setup_inbound(peer_manager: Arc, Arc, Arc>>, event_notify: mpsc::Sender<()>, stream: TcpStream) -> impl std::future::Future where +pub fn setup_inbound(peer_manager: Arc, Arc, Arc>>, event_notify: mpsc::Sender<()>, stream: TcpStream) -> impl std::future::Future where CMH: ChannelMessageHandler + 'static, RMH: RoutingMessageHandler + 'static, L: Logger + 'static + ?Sized { @@ -289,7 +289,7 @@ pub fn setup_inbound(peer_manager: Arc(peer_manager: Arc, Arc, Arc>>, event_notify: mpsc::Sender<()>, their_node_id: PublicKey, stream: TcpStream) -> impl std::future::Future where +pub fn setup_outbound(peer_manager: Arc, Arc, Arc>>, event_notify: mpsc::Sender<()>, their_node_id: PublicKey, stream: TcpStream) -> impl std::future::Future where CMH: ChannelMessageHandler + 'static, RMH: RoutingMessageHandler + 'static, L: Logger + 'static + ?Sized { @@ -361,7 +361,7 @@ pub fn setup_outbound(peer_manager: Arc(peer_manager: Arc, Arc, Arc>>, event_notify: mpsc::Sender<()>, their_node_id: PublicKey, addr: SocketAddr) -> Option> where +pub async fn connect_outbound(peer_manager: Arc, Arc, Arc>>, event_notify: mpsc::Sender<()>, their_node_id: PublicKey, addr: SocketAddr) -> Option> where CMH: ChannelMessageHandler + 'static, RMH: RoutingMessageHandler + 'static, L: Logger + 'static + ?Sized { @@ -412,7 +412,7 @@ impl SocketDescriptor { Self { conn, id } } } -impl peer_handler::SocketDescriptor for SocketDescriptor { +impl handler::SocketDescriptor for SocketDescriptor { fn send_data(&mut self, data: &[u8], resume_read: bool) -> usize { // To send data, we take a lock on our Connection to access the WriteHalf of the TcpStream, // writing to it if there's room in the kernel buffer, or otherwise create a new Waker with @@ -504,7 +504,7 @@ impl Hash for SocketDescriptor { mod tests { use lightning::ln::features::*; use lightning::ln::msgs::*; - use lightning::ln::peer_handler::{MessageHandler, PeerManager}; + use lightning::ln::peers::handler::{MessageHandler, PeerManager}; use lightning::util::events::*; use bitcoin::secp256k1::{Secp256k1, SecretKey, PublicKey}; diff --git a/lightning/src/ln/mod.rs b/lightning/src/ln/mod.rs index cd959a74dc5..5f0f1f59f6a 100644 --- a/lightning/src/ln/mod.rs +++ b/lightning/src/ln/mod.rs @@ -20,16 +20,11 @@ pub mod channelmanager; pub mod msgs; -pub mod peer_handler; +pub mod peers; pub mod chan_utils; pub mod features; pub(crate) mod onchaintx; -#[cfg(feature = "fuzztarget")] -pub mod peer_channel_encryptor; -#[cfg(not(feature = "fuzztarget"))] -pub(crate) mod peer_channel_encryptor; - mod channel; mod onion_utils; mod wire; @@ -53,4 +48,3 @@ mod reorg_tests; #[allow(unused_mut)] mod onion_route_tests; -pub use self::peer_channel_encryptor::LN_MAX_MSG_LEN; diff --git a/lightning/src/ln/peer_channel_encryptor.rs b/lightning/src/ln/peer_channel_encryptor.rs deleted file mode 100644 index 8310edb64e2..00000000000 --- a/lightning/src/ln/peer_channel_encryptor.rs +++ /dev/null @@ -1,738 +0,0 @@ -// This file is Copyright its original authors, visible in version control -// history. -// -// 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. - -use ln::msgs::LightningError; -use ln::msgs; - -use bitcoin::hashes::{Hash, HashEngine, Hmac, HmacEngine}; -use bitcoin::hashes::sha256::Hash as Sha256; - -use bitcoin::secp256k1::Secp256k1; -use bitcoin::secp256k1::key::{PublicKey,SecretKey}; -use bitcoin::secp256k1::ecdh::SharedSecret; -use bitcoin::secp256k1; - -use util::chacha20poly1305rfc::ChaCha20Poly1305RFC; -use util::byte_utils; -use bitcoin::hashes::hex::ToHex; - -/// Maximum Lightning message data length according to -/// [BOLT-8](https://github.com/lightningnetwork/lightning-rfc/blob/v1.0/08-transport.md#lightning-message-specification) -/// and [BOLT-1](https://github.com/lightningnetwork/lightning-rfc/blob/master/01-messaging.md#lightning-message-format): -pub const LN_MAX_MSG_LEN: usize = ::std::u16::MAX as usize; // Must be equal to 65535 - -// Sha256("Noise_XK_secp256k1_ChaChaPoly_SHA256") -const NOISE_CK: [u8; 32] = [0x26, 0x40, 0xf5, 0x2e, 0xeb, 0xcd, 0x9e, 0x88, 0x29, 0x58, 0x95, 0x1c, 0x79, 0x42, 0x50, 0xee, 0xdb, 0x28, 0x00, 0x2c, 0x05, 0xd7, 0xdc, 0x2e, 0xa0, 0xf1, 0x95, 0x40, 0x60, 0x42, 0xca, 0xf1]; -// Sha256(NOISE_CK || "lightning") -const NOISE_H: [u8; 32] = [0xd1, 0xfb, 0xf6, 0xde, 0xe4, 0xf6, 0x86, 0xf1, 0x32, 0xfd, 0x70, 0x2c, 0x4a, 0xbf, 0x8f, 0xba, 0x4b, 0xb4, 0x20, 0xd8, 0x9d, 0x2a, 0x04, 0x8a, 0x3c, 0x4f, 0x4c, 0x09, 0x2e, 0x37, 0xb6, 0x76]; - -pub enum NextNoiseStep { - ActOne, - ActTwo, - ActThree, - NoiseComplete, -} - -#[derive(PartialEq)] -enum NoiseStep { - PreActOne, - PostActOne, - PostActTwo, - // When done swap noise_state for NoiseState::Finished -} - -struct BidirectionalNoiseState { - h: [u8; 32], - ck: [u8; 32], -} -enum DirectionalNoiseState { - Outbound { - ie: SecretKey, - }, - Inbound { - ie: Option, // filled in if state >= PostActOne - re: Option, // filled in if state >= PostActTwo - temp_k2: Option<[u8; 32]>, // filled in if state >= PostActTwo - } -} -enum NoiseState { - InProgress { - state: NoiseStep, - directional_state: DirectionalNoiseState, - bidirectional_state: BidirectionalNoiseState, - }, - Finished { - sk: [u8; 32], - sn: u64, - sck: [u8; 32], - rk: [u8; 32], - rn: u64, - rck: [u8; 32], - } -} - -pub struct PeerChannelEncryptor { - secp_ctx: Secp256k1, - their_node_id: Option, // filled in for outbound, or inbound after noise_state is Finished - - noise_state: NoiseState, -} - -impl PeerChannelEncryptor { - pub fn new_outbound(their_node_id: PublicKey, ephemeral_key: SecretKey) -> PeerChannelEncryptor { - let secp_ctx = Secp256k1::signing_only(); - - let mut sha = Sha256::engine(); - sha.input(&NOISE_H); - sha.input(&their_node_id.serialize()[..]); - let h = Sha256::from_engine(sha).into_inner(); - - PeerChannelEncryptor { - their_node_id: Some(their_node_id), - secp_ctx: secp_ctx, - noise_state: NoiseState::InProgress { - state: NoiseStep::PreActOne, - directional_state: DirectionalNoiseState::Outbound { - ie: ephemeral_key, - }, - bidirectional_state: BidirectionalNoiseState { - h: h, - ck: NOISE_CK, - }, - } - } - } - - pub fn new_inbound(our_node_secret: &SecretKey) -> PeerChannelEncryptor { - let secp_ctx = Secp256k1::signing_only(); - - let mut sha = Sha256::engine(); - sha.input(&NOISE_H); - let our_node_id = PublicKey::from_secret_key(&secp_ctx, our_node_secret); - sha.input(&our_node_id.serialize()[..]); - let h = Sha256::from_engine(sha).into_inner(); - - PeerChannelEncryptor { - their_node_id: None, - secp_ctx: secp_ctx, - noise_state: NoiseState::InProgress { - state: NoiseStep::PreActOne, - directional_state: DirectionalNoiseState::Inbound { - ie: None, - re: None, - temp_k2: None, - }, - bidirectional_state: BidirectionalNoiseState { - h: h, - ck: NOISE_CK, - }, - } - } - } - - #[inline] - fn encrypt_with_ad(res: &mut[u8], n: u64, key: &[u8; 32], h: &[u8], plaintext: &[u8]) { - let mut nonce = [0; 12]; - nonce[4..].copy_from_slice(&byte_utils::le64_to_array(n)); - - let mut chacha = ChaCha20Poly1305RFC::new(key, &nonce, h); - let mut tag = [0; 16]; - chacha.encrypt(plaintext, &mut res[0..plaintext.len()], &mut tag); - res[plaintext.len()..].copy_from_slice(&tag); - } - - #[inline] - fn decrypt_with_ad(res: &mut[u8], n: u64, key: &[u8; 32], h: &[u8], cyphertext: &[u8]) -> Result<(), LightningError> { - let mut nonce = [0; 12]; - nonce[4..].copy_from_slice(&byte_utils::le64_to_array(n)); - - let mut chacha = ChaCha20Poly1305RFC::new(key, &nonce, h); - if !chacha.decrypt(&cyphertext[0..cyphertext.len() - 16], res, &cyphertext[cyphertext.len() - 16..]) { - return Err(LightningError{err: "Bad MAC".to_owned(), action: msgs::ErrorAction::DisconnectPeer{ msg: None }}); - } - Ok(()) - } - - fn hkdf_extract_expand(salt: &[u8], ikm: &[u8]) -> ([u8; 32], [u8; 32]) { - let mut hmac = HmacEngine::::new(salt); - hmac.input(ikm); - let prk = Hmac::from_engine(hmac).into_inner(); - let mut hmac = HmacEngine::::new(&prk[..]); - hmac.input(&[1; 1]); - let t1 = Hmac::from_engine(hmac).into_inner(); - let mut hmac = HmacEngine::::new(&prk[..]); - hmac.input(&t1); - hmac.input(&[2; 1]); - (t1, Hmac::from_engine(hmac).into_inner()) - } - - #[inline] - fn hkdf(state: &mut BidirectionalNoiseState, ss: SharedSecret) -> [u8; 32] { - let (t1, t2) = Self::hkdf_extract_expand(&state.ck, &ss[..]); - state.ck = t1; - t2 - } - - #[inline] - fn outbound_noise_act(secp_ctx: &Secp256k1, state: &mut BidirectionalNoiseState, our_key: &SecretKey, their_key: &PublicKey) -> ([u8; 50], [u8; 32]) { - let our_pub = PublicKey::from_secret_key(secp_ctx, &our_key); - - let mut sha = Sha256::engine(); - sha.input(&state.h); - sha.input(&our_pub.serialize()[..]); - state.h = Sha256::from_engine(sha).into_inner(); - - let ss = SharedSecret::new(&their_key, &our_key); - let temp_k = PeerChannelEncryptor::hkdf(state, ss); - - let mut res = [0; 50]; - res[1..34].copy_from_slice(&our_pub.serialize()[..]); - PeerChannelEncryptor::encrypt_with_ad(&mut res[34..], 0, &temp_k, &state.h, &[0; 0]); - - let mut sha = Sha256::engine(); - sha.input(&state.h); - sha.input(&res[34..]); - state.h = Sha256::from_engine(sha).into_inner(); - - (res, temp_k) - } - - #[inline] - fn inbound_noise_act(state: &mut BidirectionalNoiseState, act: &[u8], our_key: &SecretKey) -> Result<(PublicKey, [u8; 32]), LightningError> { - assert_eq!(act.len(), 50); - - if act[0] != 0 { - return Err(LightningError{err: format!("Unknown handshake version number {}", act[0]), action: msgs::ErrorAction::DisconnectPeer{ msg: None }}); - } - - let their_pub = match PublicKey::from_slice(&act[1..34]) { - Err(_) => return Err(LightningError{err: format!("Invalid public key {}", &act[1..34].to_hex()), action: msgs::ErrorAction::DisconnectPeer{ msg: None }}), - Ok(key) => key, - }; - - let mut sha = Sha256::engine(); - sha.input(&state.h); - sha.input(&their_pub.serialize()[..]); - state.h = Sha256::from_engine(sha).into_inner(); - - let ss = SharedSecret::new(&their_pub, &our_key); - let temp_k = PeerChannelEncryptor::hkdf(state, ss); - - let mut dec = [0; 0]; - PeerChannelEncryptor::decrypt_with_ad(&mut dec, 0, &temp_k, &state.h, &act[34..])?; - - let mut sha = Sha256::engine(); - sha.input(&state.h); - sha.input(&act[34..]); - state.h = Sha256::from_engine(sha).into_inner(); - - Ok((their_pub, temp_k)) - } - - pub fn get_act_one(&mut self) -> [u8; 50] { - match self.noise_state { - NoiseState::InProgress { ref mut state, ref directional_state, ref mut bidirectional_state } => - match directional_state { - &DirectionalNoiseState::Outbound { ref ie } => { - if *state != NoiseStep::PreActOne { - panic!("Requested act at wrong step"); - } - - let (res, _) = PeerChannelEncryptor::outbound_noise_act(&self.secp_ctx, bidirectional_state, &ie, &self.their_node_id.unwrap()); - *state = NoiseStep::PostActOne; - res - }, - _ => panic!("Wrong direction for act"), - }, - _ => panic!("Cannot get act one after noise handshake completes"), - } - } - - pub fn process_act_one_with_keys(&mut self, act_one: &[u8], our_node_secret: &SecretKey, our_ephemeral: SecretKey) -> Result<[u8; 50], LightningError> { - assert_eq!(act_one.len(), 50); - - match self.noise_state { - NoiseState::InProgress { ref mut state, ref mut directional_state, ref mut bidirectional_state } => - match directional_state { - &mut DirectionalNoiseState::Inbound { ref mut ie, ref mut re, ref mut temp_k2 } => { - if *state != NoiseStep::PreActOne { - panic!("Requested act at wrong step"); - } - - let (their_pub, _) = PeerChannelEncryptor::inbound_noise_act(bidirectional_state, act_one, &our_node_secret)?; - ie.get_or_insert(their_pub); - - re.get_or_insert(our_ephemeral); - - let (res, temp_k) = PeerChannelEncryptor::outbound_noise_act(&self.secp_ctx, bidirectional_state, &re.unwrap(), &ie.unwrap()); - *temp_k2 = Some(temp_k); - *state = NoiseStep::PostActTwo; - Ok(res) - }, - _ => panic!("Wrong direction for act"), - }, - _ => panic!("Cannot get act one after noise handshake completes"), - } - } - - pub fn process_act_two(&mut self, act_two: &[u8], our_node_secret: &SecretKey) -> Result<([u8; 66], PublicKey), LightningError> { - assert_eq!(act_two.len(), 50); - - let final_hkdf; - let ck; - let res: [u8; 66] = match self.noise_state { - NoiseState::InProgress { ref state, ref directional_state, ref mut bidirectional_state } => - match directional_state { - &DirectionalNoiseState::Outbound { ref ie } => { - if *state != NoiseStep::PostActOne { - panic!("Requested act at wrong step"); - } - - let (re, temp_k2) = PeerChannelEncryptor::inbound_noise_act(bidirectional_state, act_two, &ie)?; - - let mut res = [0; 66]; - let our_node_id = PublicKey::from_secret_key(&self.secp_ctx, &our_node_secret); - - PeerChannelEncryptor::encrypt_with_ad(&mut res[1..50], 1, &temp_k2, &bidirectional_state.h, &our_node_id.serialize()[..]); - - let mut sha = Sha256::engine(); - sha.input(&bidirectional_state.h); - sha.input(&res[1..50]); - bidirectional_state.h = Sha256::from_engine(sha).into_inner(); - - let ss = SharedSecret::new(&re, our_node_secret); - let temp_k = PeerChannelEncryptor::hkdf(bidirectional_state, ss); - - PeerChannelEncryptor::encrypt_with_ad(&mut res[50..], 0, &temp_k, &bidirectional_state.h, &[0; 0]); - final_hkdf = Self::hkdf_extract_expand(&bidirectional_state.ck, &[0; 0]); - ck = bidirectional_state.ck.clone(); - res - }, - _ => panic!("Wrong direction for act"), - }, - _ => panic!("Cannot get act one after noise handshake completes"), - }; - - let (sk, rk) = final_hkdf; - self.noise_state = NoiseState::Finished { - sk: sk, - sn: 0, - sck: ck.clone(), - rk: rk, - rn: 0, - rck: ck, - }; - - Ok((res, self.their_node_id.unwrap().clone())) - } - - pub fn process_act_three(&mut self, act_three: &[u8]) -> Result { - assert_eq!(act_three.len(), 66); - - let final_hkdf; - let ck; - match self.noise_state { - NoiseState::InProgress { ref state, ref directional_state, ref mut bidirectional_state } => - match directional_state { - &DirectionalNoiseState::Inbound { ie: _, ref re, ref temp_k2 } => { - if *state != NoiseStep::PostActTwo { - panic!("Requested act at wrong step"); - } - if act_three[0] != 0 { - return Err(LightningError{err: format!("Unknown handshake version number {}", act_three[0]), action: msgs::ErrorAction::DisconnectPeer{ msg: None }}); - } - - let mut their_node_id = [0; 33]; - PeerChannelEncryptor::decrypt_with_ad(&mut their_node_id, 1, &temp_k2.unwrap(), &bidirectional_state.h, &act_three[1..50])?; - self.their_node_id = Some(match PublicKey::from_slice(&their_node_id) { - Ok(key) => key, - Err(_) => return Err(LightningError{err: format!("Bad node_id from peer, {}", &their_node_id.to_hex()), action: msgs::ErrorAction::DisconnectPeer{ msg: None }}), - }); - - let mut sha = Sha256::engine(); - sha.input(&bidirectional_state.h); - sha.input(&act_three[1..50]); - bidirectional_state.h = Sha256::from_engine(sha).into_inner(); - - let ss = SharedSecret::new(&self.their_node_id.unwrap(), &re.unwrap()); - let temp_k = PeerChannelEncryptor::hkdf(bidirectional_state, ss); - - PeerChannelEncryptor::decrypt_with_ad(&mut [0; 0], 0, &temp_k, &bidirectional_state.h, &act_three[50..])?; - final_hkdf = Self::hkdf_extract_expand(&bidirectional_state.ck, &[0; 0]); - ck = bidirectional_state.ck.clone(); - }, - _ => panic!("Wrong direction for act"), - }, - _ => panic!("Cannot get act one after noise handshake completes"), - } - - let (rk, sk) = final_hkdf; - self.noise_state = NoiseState::Finished { - sk: sk, - sn: 0, - sck: ck.clone(), - rk: rk, - rn: 0, - rck: ck, - }; - - Ok(self.their_node_id.unwrap().clone()) - } - - /// Encrypts the given message, returning the encrypted version - /// panics if msg.len() > 65535 or Noise handshake has not finished. - pub fn encrypt_message(&mut self, msg: &[u8]) -> Vec { - if msg.len() > LN_MAX_MSG_LEN { - panic!("Attempted to encrypt message longer than 65535 bytes!"); - } - - let mut res = Vec::with_capacity(msg.len() + 16*2 + 2); - res.resize(msg.len() + 16*2 + 2, 0); - - match self.noise_state { - NoiseState::Finished { ref mut sk, ref mut sn, ref mut sck, rk: _, rn: _, rck: _ } => { - if *sn >= 1000 { - let (new_sck, new_sk) = Self::hkdf_extract_expand(sck, sk); - *sck = new_sck; - *sk = new_sk; - *sn = 0; - } - - Self::encrypt_with_ad(&mut res[0..16+2], *sn, sk, &[0; 0], &byte_utils::be16_to_array(msg.len() as u16)); - *sn += 1; - - Self::encrypt_with_ad(&mut res[16+2..], *sn, sk, &[0; 0], msg); - *sn += 1; - }, - _ => panic!("Tried to encrypt a message prior to noise handshake completion"), - } - - res - } - - /// Decrypts a message length header from the remote peer. - /// panics if noise handshake has not yet finished or msg.len() != 18 - pub fn decrypt_length_header(&mut self, msg: &[u8]) -> Result { - assert_eq!(msg.len(), 16+2); - - match self.noise_state { - NoiseState::Finished { sk: _, sn: _, sck: _, ref mut rk, ref mut rn, ref mut rck } => { - if *rn >= 1000 { - let (new_rck, new_rk) = Self::hkdf_extract_expand(rck, rk); - *rck = new_rck; - *rk = new_rk; - *rn = 0; - } - - let mut res = [0; 2]; - Self::decrypt_with_ad(&mut res, *rn, rk, &[0; 0], msg)?; - *rn += 1; - Ok(byte_utils::slice_to_be16(&res)) - }, - _ => panic!("Tried to decrypt a message prior to noise handshake completion"), - } - } - - /// Decrypts the given message. - /// panics if msg.len() > 65535 + 16 - pub fn decrypt_message(&mut self, msg: &[u8]) -> Result, LightningError> { - if msg.len() > LN_MAX_MSG_LEN + 16 { - panic!("Attempted to decrypt message longer than 65535 + 16 bytes!"); - } - - match self.noise_state { - NoiseState::Finished { sk: _, sn: _, sck: _, ref rk, ref mut rn, rck: _ } => { - let mut res = Vec::with_capacity(msg.len() - 16); - res.resize(msg.len() - 16, 0); - Self::decrypt_with_ad(&mut res[..], *rn, rk, &[0; 0], msg)?; - *rn += 1; - - Ok(res) - }, - _ => panic!("Tried to decrypt a message prior to noise handshake completion"), - } - } - - pub fn get_noise_step(&self) -> NextNoiseStep { - match self.noise_state { - NoiseState::InProgress {ref state, ..} => { - match state { - &NoiseStep::PreActOne => NextNoiseStep::ActOne, - &NoiseStep::PostActOne => NextNoiseStep::ActTwo, - &NoiseStep::PostActTwo => NextNoiseStep::ActThree, - } - }, - NoiseState::Finished {..} => NextNoiseStep::NoiseComplete, - } - } - - pub fn is_ready_for_encryption(&self) -> bool { - match self.noise_state { - NoiseState::InProgress {..} => { false }, - NoiseState::Finished {..} => { true } - } - } -} - -#[cfg(test)] -mod tests { - use super::LN_MAX_MSG_LEN; - - use bitcoin::secp256k1::key::{PublicKey,SecretKey}; - - use hex; - - use ln::peer_channel_encryptor::{PeerChannelEncryptor,NoiseState}; - - fn get_outbound_peer_for_initiator_test_vectors() -> PeerChannelEncryptor { - let their_node_id = PublicKey::from_slice(&hex::decode("028d7500dd4c12685d1f568b4c2b5048e8534b873319f3a8daa612b469132ec7f7").unwrap()[..]).unwrap(); - - let mut outbound_peer = PeerChannelEncryptor::new_outbound(their_node_id, SecretKey::from_slice(&hex::decode("1212121212121212121212121212121212121212121212121212121212121212").unwrap()[..]).unwrap()); - assert_eq!(outbound_peer.get_act_one()[..], hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap()[..]); - outbound_peer - } - - fn get_inbound_peer_for_test_vectors() -> PeerChannelEncryptor { - // transport-responder successful handshake - let our_node_id = SecretKey::from_slice(&hex::decode("2121212121212121212121212121212121212121212121212121212121212121").unwrap()[..]).unwrap(); - let our_ephemeral = SecretKey::from_slice(&hex::decode("2222222222222222222222222222222222222222222222222222222222222222").unwrap()[..]).unwrap(); - - let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id); - - let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone()).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); - - let act_three = hex::decode("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap().to_vec(); - // test vector doesn't specify the initiator static key, but it's the same as the one - // from transport-initiator successful handshake - assert_eq!(inbound_peer.process_act_three(&act_three[..]).unwrap().serialize()[..], hex::decode("034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa").unwrap()[..]); - - match inbound_peer.noise_state { - NoiseState::Finished { sk, sn, sck, rk, rn, rck } => { - assert_eq!(sk, hex::decode("bb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442").unwrap()[..]); - assert_eq!(sn, 0); - assert_eq!(sck, hex::decode("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap()[..]); - assert_eq!(rk, hex::decode("969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9").unwrap()[..]); - assert_eq!(rn, 0); - assert_eq!(rck, hex::decode("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap()[..]); - }, - _ => panic!() - } - - inbound_peer - } - - #[test] - fn noise_initiator_test_vectors() { - let our_node_id = SecretKey::from_slice(&hex::decode("1111111111111111111111111111111111111111111111111111111111111111").unwrap()[..]).unwrap(); - - { - // transport-initiator successful handshake - let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors(); - - let act_two = hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap().to_vec(); - assert_eq!(outbound_peer.process_act_two(&act_two[..], &our_node_id).unwrap().0[..], hex::decode("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap()[..]); - - match outbound_peer.noise_state { - NoiseState::Finished { sk, sn, sck, rk, rn, rck } => { - assert_eq!(sk, hex::decode("969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9").unwrap()[..]); - assert_eq!(sn, 0); - assert_eq!(sck, hex::decode("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap()[..]); - assert_eq!(rk, hex::decode("bb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442").unwrap()[..]); - assert_eq!(rn, 0); - assert_eq!(rck, hex::decode("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap()[..]); - }, - _ => panic!() - } - } - { - // transport-initiator act2 short read test - // Can't actually test this cause process_act_two requires you pass the right length! - } - { - // transport-initiator act2 bad version test - let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors(); - - let act_two = hex::decode("0102466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap().to_vec(); - assert!(outbound_peer.process_act_two(&act_two[..], &our_node_id).is_err()); - } - - { - // transport-initiator act2 bad key serialization test - let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors(); - - let act_two = hex::decode("0004466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap().to_vec(); - assert!(outbound_peer.process_act_two(&act_two[..], &our_node_id).is_err()); - } - - { - // transport-initiator act2 bad MAC test - let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors(); - - let act_two = hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730af").unwrap().to_vec(); - assert!(outbound_peer.process_act_two(&act_two[..], &our_node_id).is_err()); - } - } - - #[test] - fn noise_responder_test_vectors() { - let our_node_id = SecretKey::from_slice(&hex::decode("2121212121212121212121212121212121212121212121212121212121212121").unwrap()[..]).unwrap(); - let our_ephemeral = SecretKey::from_slice(&hex::decode("2222222222222222222222222222222222222222222222222222222222222222").unwrap()[..]).unwrap(); - - { - let _ = get_inbound_peer_for_test_vectors(); - } - { - // transport-responder act1 short read test - // Can't actually test this cause process_act_one requires you pass the right length! - } - { - // transport-responder act1 bad version test - let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id); - - let act_one = hex::decode("01036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone()).is_err()); - } - { - // transport-responder act1 bad key serialization test - let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id); - - let act_one =hex::decode("00046360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone()).is_err()); - } - { - // transport-responder act1 bad MAC test - let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id); - - let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6b").unwrap().to_vec(); - assert!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone()).is_err()); - } - { - // transport-responder act3 bad version test - let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id); - - let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone()).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); - - let act_three = hex::decode("01b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap().to_vec(); - assert!(inbound_peer.process_act_three(&act_three[..]).is_err()); - } - { - // transport-responder act3 short read test - // Can't actually test this cause process_act_three requires you pass the right length! - } - { - // transport-responder act3 bad MAC for ciphertext test - let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id); - - let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone()).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); - - let act_three = hex::decode("00c9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap().to_vec(); - assert!(inbound_peer.process_act_three(&act_three[..]).is_err()); - } - { - // transport-responder act3 bad rs test - let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id); - - let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone()).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); - - let act_three = hex::decode("00bfe3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa2235536ad09a8ee351870c2bb7f78b754a26c6cef79a98d25139c856d7efd252c2ae73c").unwrap().to_vec(); - assert!(inbound_peer.process_act_three(&act_three[..]).is_err()); - } - { - // transport-responder act3 bad MAC test - let mut inbound_peer = PeerChannelEncryptor::new_inbound(&our_node_id); - - let act_one = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap().to_vec(); - assert_eq!(inbound_peer.process_act_one_with_keys(&act_one[..], &our_node_id, our_ephemeral.clone()).unwrap()[..], hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap()[..]); - - let act_three = hex::decode("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139bb").unwrap().to_vec(); - assert!(inbound_peer.process_act_three(&act_three[..]).is_err()); - } - } - - - #[test] - fn message_encryption_decryption_test_vectors() { - // We use the same keys as the initiator and responder test vectors, so we copy those tests - // here and use them to encrypt. - let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors(); - - { - let our_node_id = SecretKey::from_slice(&hex::decode("1111111111111111111111111111111111111111111111111111111111111111").unwrap()[..]).unwrap(); - - let act_two = hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap().to_vec(); - assert_eq!(outbound_peer.process_act_two(&act_two[..], &our_node_id).unwrap().0[..], hex::decode("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap()[..]); - - match outbound_peer.noise_state { - NoiseState::Finished { sk, sn, sck, rk, rn, rck } => { - assert_eq!(sk, hex::decode("969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9").unwrap()[..]); - assert_eq!(sn, 0); - assert_eq!(sck, hex::decode("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap()[..]); - assert_eq!(rk, hex::decode("bb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442").unwrap()[..]); - assert_eq!(rn, 0); - assert_eq!(rck, hex::decode("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap()[..]); - }, - _ => panic!() - } - } - - let mut inbound_peer = get_inbound_peer_for_test_vectors(); - - for i in 0..1005 { - let msg = [0x68, 0x65, 0x6c, 0x6c, 0x6f]; - let res = outbound_peer.encrypt_message(&msg); - assert_eq!(res.len(), 5 + 2*16 + 2); - - let len_header = res[0..2+16].to_vec(); - assert_eq!(inbound_peer.decrypt_length_header(&len_header[..]).unwrap() as usize, msg.len()); - assert_eq!(inbound_peer.decrypt_message(&res[2+16..]).unwrap()[..], msg[..]); - - if i == 0 { - assert_eq!(res, hex::decode("cf2b30ddf0cf3f80e7c35a6e6730b59fe802473180f396d88a8fb0db8cbcf25d2f214cf9ea1d95").unwrap()); - } else if i == 1 { - assert_eq!(res, hex::decode("72887022101f0b6753e0c7de21657d35a4cb2a1f5cde2650528bbc8f837d0f0d7ad833b1a256a1").unwrap()); - } else if i == 500 { - assert_eq!(res, hex::decode("178cb9d7387190fa34db9c2d50027d21793c9bc2d40b1e14dcf30ebeeeb220f48364f7a4c68bf8").unwrap()); - } else if i == 501 { - assert_eq!(res, hex::decode("1b186c57d44eb6de4c057c49940d79bb838a145cb528d6e8fd26dbe50a60ca2c104b56b60e45bd").unwrap()); - } else if i == 1000 { - assert_eq!(res, hex::decode("4a2f3cc3b5e78ddb83dcb426d9863d9d9a723b0337c89dd0b005d89f8d3c05c52b76b29b740f09").unwrap()); - } else if i == 1001 { - assert_eq!(res, hex::decode("2ecd8c8a5629d0d02ab457a0fdd0f7b90a192cd46be5ecb6ca570bfc5e268338b1a16cf4ef2d36").unwrap()); - } - } - } - - #[test] - fn max_msg_len_limit_value() { - assert_eq!(LN_MAX_MSG_LEN, 65535); - assert_eq!(LN_MAX_MSG_LEN, ::std::u16::MAX as usize); - } - - #[test] - #[should_panic(expected = "Attempted to encrypt message longer than 65535 bytes!")] - fn max_message_len_encryption() { - let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors(); - let msg = [4u8; LN_MAX_MSG_LEN + 1]; - outbound_peer.encrypt_message(&msg); - } - - #[test] - #[should_panic(expected = "Attempted to decrypt message longer than 65535 + 16 bytes!")] - fn max_message_len_decryption() { - let mut inbound_peer = get_inbound_peer_for_test_vectors(); - - // MSG should not exceed LN_MAX_MSG_LEN + 16 - let msg = [4u8; LN_MAX_MSG_LEN + 17]; - inbound_peer.decrypt_message(&msg).unwrap(); - } -} diff --git a/lightning/src/ln/peers/chacha.rs b/lightning/src/ln/peers/chacha.rs new file mode 100644 index 00000000000..7d5ab45c50c --- /dev/null +++ b/lightning/src/ln/peers/chacha.rs @@ -0,0 +1,46 @@ +// This file is Copyright its original authors, visible in version control +// history. +// +// 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. + +use util::byte_utils; +use util::chacha20poly1305rfc::ChaCha20Poly1305RFC; + +pub const TAG_SIZE: usize = 16; + +pub fn encrypt(key: &[u8], nonce: u64, associated_data: &[u8], plaintext: &[u8], ciphertext_out: &mut [u8]) { + let mut nonce_bytes = [0; 12]; + nonce_bytes[4..].copy_from_slice(&byte_utils::le64_to_array(nonce)); + + let mut chacha = ChaCha20Poly1305RFC::new(key, &nonce_bytes, associated_data); + let mut authentication_tag = [0u8; 16]; + chacha.encrypt(plaintext, &mut ciphertext_out[..plaintext.len()], &mut authentication_tag); + + ciphertext_out[plaintext.len()..].copy_from_slice(&authentication_tag); +} + +pub fn decrypt(key: &[u8], nonce: u64, associated_data: &[u8], tagged_ciphertext: &[u8], plaintext_out: &mut [u8]) -> Result<(), String> { + let mut nonce_bytes = [0; 12]; + nonce_bytes[4..].copy_from_slice(&byte_utils::le64_to_array(nonce)); + + let length = tagged_ciphertext.len(); + if length < 16 { + return Err("ciphertext cannot be shorter than tag length of 16 bytes".to_string()); + } + let end_index = length - 16; + let ciphertext = &tagged_ciphertext[0..end_index]; + let authentication_tag = &tagged_ciphertext[end_index..]; + + let mut chacha = ChaCha20Poly1305RFC::new(key, &nonce_bytes, associated_data); + let success = chacha.decrypt(ciphertext, plaintext_out, authentication_tag); + + if !success { + Err("invalid hmac".to_string()) + } else { + Ok(()) + } +} diff --git a/lightning/src/ln/peers/conduit.rs b/lightning/src/ln/peers/conduit.rs new file mode 100644 index 00000000000..aa9ad87bc58 --- /dev/null +++ b/lightning/src/ln/peers/conduit.rs @@ -0,0 +1,466 @@ +// This file is Copyright its original authors, visible in version control +// history. +// +// 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. + +//! Handles all over the wire message encryption and decryption upon handshake completion. + +use ln::peers::{chacha, hkdf5869rfc}; +use util::byte_utils; + +pub(super) type SymmetricKey = [u8; 32]; + +/// Maximum Lightning message data length according to +/// [BOLT-8](https://github.com/lightningnetwork/lightning-rfc/blob/v1.0/08-transport.md#lightning-message-specification) +/// and [BOLT-1](https://github.com/lightningnetwork/lightning-rfc/blob/master/01-messaging.md#lightning-message-format): +const LN_MAX_MSG_LEN: usize = ::std::u16::MAX as usize; // Must be equal to 65535 + +const MESSAGE_LENGTH_HEADER_SIZE: usize = 2; +const TAGGED_MESSAGE_LENGTH_HEADER_SIZE: usize = MESSAGE_LENGTH_HEADER_SIZE + chacha::TAG_SIZE; + +const KEY_ROTATION_INDEX: u32 = 1000; + +/// Returned after a successful handshake to encrypt and decrypt communication with peer nodes. +/// It should not normally be manually instantiated. +/// Automatically handles key rotation. +/// For decryption, it is recommended to call `decrypt_message_stream` for automatic buffering. +pub struct Conduit { + pub(super) encryptor: Encryptor, + pub(super) decryptor: Decryptor + +} + +pub(super) struct Encryptor { + sending_key: SymmetricKey, + sending_chaining_key: SymmetricKey, + sending_nonce: u32, +} + +pub(super) struct Decryptor { + receiving_key: SymmetricKey, + receiving_chaining_key: SymmetricKey, + receiving_nonce: u32, + + pending_message_length: Option, + read_buffer: Option>, + poisoned: bool, // signal an error has occurred so None is returned on iteration after failure +} + +impl Iterator for Decryptor { + type Item = Result>, String>; + + fn next(&mut self) -> Option { + if self.poisoned { + return None; + } + + match self.decrypt_single_message(None) { + Ok(Some(result)) => { + Some(Ok(Some(result))) + }, + Ok(None) => { + None + } + Err(e) => { + self.poisoned = true; + Some(Err(e)) + } + } + } +} + +impl Conduit { + /// Instantiate a new Conduit with specified sending and receiving keys + pub fn new(sending_key: SymmetricKey, receiving_key: SymmetricKey, chaining_key: SymmetricKey) -> Self { + Conduit { + encryptor: Encryptor { + sending_key, + sending_chaining_key: chaining_key, + sending_nonce: 0 + }, + decryptor: Decryptor { + receiving_key, + receiving_chaining_key: chaining_key, + receiving_nonce: 0, + read_buffer: None, + pending_message_length: None, + poisoned: false + } + } + } + + /// Encrypt data to be sent to peer + pub fn encrypt(&mut self, buffer: &[u8]) -> Vec { + self.encryptor.encrypt(buffer) + } + + pub(super) fn read(&mut self, data: &[u8]) { + self.decryptor.read(data) + } + + /// Decrypt a single message. If data containing more than one message has been received, + /// only the first message will be returned, and the rest stored in the internal buffer. + /// If a message pending in the buffer still hasn't been decrypted, that message will be + /// returned in lieu of anything new, even if new data is provided. + #[cfg(any(test, feature = "fuzztarget"))] + pub fn decrypt_single_message(&mut self, new_data: Option<&[u8]>) -> Result>, String> { + Ok(self.decryptor.decrypt_single_message(new_data)?) + } + + fn increment_nonce(nonce: &mut u32, chaining_key: &mut SymmetricKey, key: &mut SymmetricKey) { + *nonce += 1; + if *nonce == KEY_ROTATION_INDEX { + Self::rotate_key(chaining_key, key); + *nonce = 0; + } + } + + fn rotate_key(chaining_key: &mut SymmetricKey, key: &mut SymmetricKey) { + let (new_chaining_key, new_key) = hkdf5869rfc::derive(chaining_key, key); + chaining_key.copy_from_slice(&new_chaining_key); + key.copy_from_slice(&new_key); + } +} + +impl Encryptor { + pub(super) fn encrypt(&mut self, buffer: &[u8]) -> Vec { + if buffer.len() > LN_MAX_MSG_LEN { + panic!("Attempted to encrypt message longer than 65535 bytes!"); + } + + let length = buffer.len() as u16; + let length_bytes = byte_utils::be16_to_array(length); + + let mut ciphertext = vec![0u8; TAGGED_MESSAGE_LENGTH_HEADER_SIZE + length as usize + chacha::TAG_SIZE]; + + chacha::encrypt(&self.sending_key, self.sending_nonce as u64, &[0; 0], &length_bytes, &mut ciphertext[..TAGGED_MESSAGE_LENGTH_HEADER_SIZE]); + self.increment_nonce(); + + &chacha::encrypt(&self.sending_key, self.sending_nonce as u64, &[0; 0], buffer, &mut ciphertext[TAGGED_MESSAGE_LENGTH_HEADER_SIZE..]); + self.increment_nonce(); + + ciphertext + } + + fn increment_nonce(&mut self) { + Conduit::increment_nonce(&mut self.sending_nonce, &mut self.sending_chaining_key, &mut self.sending_key); + } +} + +impl Decryptor { + pub(super) fn read(&mut self, data: &[u8]) { + let read_buffer = self.read_buffer.get_or_insert(Vec::new()); + read_buffer.extend_from_slice(data); + } + + /// Decrypt a single message. If data containing more than one message has been received, + /// only the first message will be returned, and the rest stored in the internal buffer. + /// If a message pending in the buffer still hasn't been decrypted, that message will be + /// returned in lieu of anything new, even if new data is provided. + pub fn decrypt_single_message(&mut self, new_data: Option<&[u8]>) -> Result>, String> { + let mut read_buffer = if let Some(buffer) = self.read_buffer.take() { + buffer + } else { + Vec::new() + }; + + if let Some(data) = new_data { + read_buffer.extend_from_slice(data); + } + + if read_buffer.len() > LN_MAX_MSG_LEN + 16 { + panic!("Attempted to decrypt message longer than 65535 + 16 bytes!"); + } + + let (current_message, offset) = self.decrypt(&read_buffer[..])?; + read_buffer.drain(..offset); // drain the read buffer + self.read_buffer = Some(read_buffer); // assign the new value to the built-in buffer + Ok(current_message) + } + + fn decrypt(&mut self, buffer: &[u8]) -> Result<(Option>, usize), String> { + let message_length = if let Some(length) = self.pending_message_length { + // we have already decrypted the header + length + } else { + if buffer.len() < TAGGED_MESSAGE_LENGTH_HEADER_SIZE { + // A message must be at least 18 bytes (2 for encrypted length, 16 for the tag) + return Ok((None, 0)); + } + + let encrypted_length = &buffer[0..TAGGED_MESSAGE_LENGTH_HEADER_SIZE]; + let mut length_bytes = [0u8; MESSAGE_LENGTH_HEADER_SIZE]; + chacha::decrypt(&self.receiving_key, self.receiving_nonce as u64, &[0; 0], encrypted_length, &mut length_bytes)?; + + self.increment_nonce(); + + // the message length + byte_utils::slice_to_be16(&length_bytes) as usize + }; + + let message_end_index = TAGGED_MESSAGE_LENGTH_HEADER_SIZE + message_length + chacha::TAG_SIZE; + + if buffer.len() < message_end_index { + self.pending_message_length = Some(message_length); + return Ok((None, 0)); + } + + self.pending_message_length = None; + + let encrypted_message = &buffer[TAGGED_MESSAGE_LENGTH_HEADER_SIZE..message_end_index]; + let mut message = vec![0u8; message_length]; + + chacha::decrypt(&self.receiving_key, self.receiving_nonce as u64, &[0; 0], encrypted_message, &mut message)?; + + self.increment_nonce(); + + Ok((Some(message), message_end_index)) + } + + fn increment_nonce(&mut self) { + Conduit::increment_nonce(&mut self.receiving_nonce, &mut self.receiving_chaining_key, &mut self.receiving_key); + } + + // Used in tests to determine whether or not excess bytes entered the conduit without needing to bring up + // infrastructure to properly encode it + #[cfg(test)] + pub fn read_buffer_length(&self) -> usize { + match &self.read_buffer { + &Some(ref vec) => { vec.len() } + &None => 0 + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use hex; + + use ln::peers::conduit::Conduit; + + fn setup_peers() -> (Conduit, Conduit) { + let chaining_key_vec = hex::decode("919219dbb2920afa8db80f9a51787a840bcf111ed8d588caf9ab4be716e42b01").unwrap(); + let mut chaining_key = [0u8; 32]; + chaining_key.copy_from_slice(&chaining_key_vec); + + let sending_key_vec = hex::decode("969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9").unwrap(); + let mut sending_key = [0u8; 32]; + sending_key.copy_from_slice(&sending_key_vec); + + let receiving_key_vec = hex::decode("bb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442").unwrap(); + let mut receiving_key = [0u8; 32]; + receiving_key.copy_from_slice(&receiving_key_vec); + + let connected_peer = Conduit::new(sending_key, receiving_key, chaining_key); + let remote_peer = Conduit::new(receiving_key, sending_key, chaining_key); + + (connected_peer, remote_peer) + } + + #[test] + fn test_empty_message() { + let (mut connected_peer, mut remote_peer) = setup_peers(); + + let message: Vec = vec![]; + let encrypted_message = connected_peer.encrypt(&message); + assert_eq!(encrypted_message.len(), 2 + 16 + 16); + + let decrypted_message = remote_peer.decrypt_single_message(Some(&encrypted_message)).unwrap().unwrap(); + assert_eq!(decrypted_message, Vec::::new()); + } + + #[test] + fn test_nonce_chaining() { + let (mut connected_peer, _remote_peer) = setup_peers(); + let message = hex::decode("68656c6c6f").unwrap(); + + let encrypted_message = connected_peer.encrypt(&message); + assert_eq!(encrypted_message, hex::decode("cf2b30ddf0cf3f80e7c35a6e6730b59fe802473180f396d88a8fb0db8cbcf25d2f214cf9ea1d95").unwrap()); + + // the second time the same message is encrypted, the ciphertext should be different + let encrypted_message = connected_peer.encrypt(&message); + assert_eq!(encrypted_message, hex::decode("72887022101f0b6753e0c7de21657d35a4cb2a1f5cde2650528bbc8f837d0f0d7ad833b1a256a1").unwrap()); + } + + #[test] + /// Based on RFC test vectors: https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#message-encryption-tests + fn test_key_rotation() { + let (mut connected_peer, _remote_peer) = setup_peers(); + + let message = hex::decode("68656c6c6f").unwrap(); + let mut encrypted_messages: Vec> = Vec::new(); + + for _ in 0..1002 { + let encrypted_message = connected_peer.encrypt(&message); + encrypted_messages.push(encrypted_message); + } + + assert_eq!(encrypted_messages[500], hex::decode("178cb9d7387190fa34db9c2d50027d21793c9bc2d40b1e14dcf30ebeeeb220f48364f7a4c68bf8").unwrap()); + assert_eq!(encrypted_messages[501], hex::decode("1b186c57d44eb6de4c057c49940d79bb838a145cb528d6e8fd26dbe50a60ca2c104b56b60e45bd").unwrap()); + assert_eq!(encrypted_messages[1000], hex::decode("4a2f3cc3b5e78ddb83dcb426d9863d9d9a723b0337c89dd0b005d89f8d3c05c52b76b29b740f09").unwrap()); + assert_eq!(encrypted_messages[1001], hex::decode("2ecd8c8a5629d0d02ab457a0fdd0f7b90a192cd46be5ecb6ca570bfc5e268338b1a16cf4ef2d36").unwrap()); + } + + #[test] + fn test_decryption_buffering() { + let (mut connected_peer, mut remote_peer) = setup_peers(); + + let message = hex::decode("68656c6c6f").unwrap(); + let mut encrypted_messages: Vec> = Vec::new(); + + for _ in 0..1002 { + let encrypted_message = connected_peer.encrypt(&message); + encrypted_messages.push(encrypted_message); + } + + for _ in 0..501 { + // read two messages at once, filling buffer + let mut current_encrypted_message = encrypted_messages.remove(0); + let next_encrypted_message = encrypted_messages.remove(0); + current_encrypted_message.extend_from_slice(&next_encrypted_message); + let decrypted_message = remote_peer.decrypt_single_message(Some(¤t_encrypted_message)).unwrap().unwrap(); + assert_eq!(decrypted_message, message); + } + + for _ in 0..501 { + // decrypt messages directly from buffer without adding to it + let decrypted_message = remote_peer.decrypt_single_message(None).unwrap().unwrap(); + assert_eq!(decrypted_message, message); + } + } + + // Decryption errors should result in Err + #[test] + fn decryption_failure_errors() { + let (mut connected_peer, mut remote_peer) = setup_peers(); + let encrypted = remote_peer.encrypt(&[1]); + + connected_peer.decryptor.receiving_key = [0; 32]; + assert_eq!(connected_peer.decrypt_single_message(Some(&encrypted)), Err("invalid hmac".to_string())); + } + + // Test next()::None + #[test] + fn decryptor_iterator_empty() { + let (mut connected_peer, _) = setup_peers(); + + assert_eq!(connected_peer.decryptor.next(), None); + } + + // Test next() -> next()::None + #[test] + fn decryptor_iterator_one_item_valid() { + let (mut connected_peer, mut remote_peer) = setup_peers(); + let encrypted = remote_peer.encrypt(&[1]); + connected_peer.read(&encrypted); + + assert_eq!(connected_peer.decryptor.next(), Some(Ok(Some(vec![1])))); + assert_eq!(connected_peer.decryptor.next(), None); + } + + // Test next()::err -> next()::None + #[test] + fn decryptor_iterator_error() { + let (mut connected_peer, mut remote_peer) = setup_peers(); + let encrypted = remote_peer.encrypt(&[1]); + connected_peer.read(&encrypted); + + connected_peer.decryptor.receiving_key = [0; 32]; + assert_eq!(connected_peer.decryptor.next(), Some(Err("invalid hmac".to_string()))); + assert_eq!(connected_peer.decryptor.next(), None); + } + + // Test next()::Some -> next()::err -> next()::None + #[test] + fn decryptor_iterator_error_after_success() { + let (mut connected_peer, mut remote_peer) = setup_peers(); + let encrypted = remote_peer.encrypt(&[1]); + connected_peer.read(&encrypted); + let encrypted = remote_peer.encrypt(&[2]); + connected_peer.read(&encrypted); + + assert_eq!(connected_peer.decryptor.next(), Some(Ok(Some(vec![1])))); + connected_peer.decryptor.receiving_key = [0; 32]; + assert_eq!(connected_peer.decryptor.next(), Some(Err("invalid hmac".to_string()))); + assert_eq!(connected_peer.decryptor.next(), None); + } + + // Test that next()::Some -> next()::err -> next()::None + // Error should poison decryptor + #[test] + fn decryptor_iterator_next_after_error_returns_none() { + let (mut connected_peer, mut remote_peer) = setup_peers(); + let encrypted = remote_peer.encrypt(&[1]); + connected_peer.read(&encrypted); + let encrypted = remote_peer.encrypt(&[2]); + connected_peer.read(&encrypted); + let encrypted = remote_peer.encrypt(&[3]); + connected_peer.read(&encrypted); + + // Get one valid value + assert_eq!(connected_peer.decryptor.next(), Some(Ok(Some(vec![1])))); + let valid_receiving_key = connected_peer.decryptor.receiving_key; + + // Corrupt the receiving key and ensure we get a failure + connected_peer.decryptor.receiving_key = [0; 32]; + assert_eq!(connected_peer.decryptor.next(), Some(Err("invalid hmac".to_string()))); + + // Restore the receiving key, do a read and ensure None is returned (poisoned) + connected_peer.decryptor.receiving_key = valid_receiving_key; + assert_eq!(connected_peer.decryptor.next(), None); + } + + // Test next()::Some -> next()::err -> read() -> next()::None + // Error should poison decryptor even after future reads + #[test] + fn decryptor_iterator_read_next_after_error_returns_none() { + let (mut connected_peer, mut remote_peer) = setup_peers(); + let encrypted = remote_peer.encrypt(&[1]); + connected_peer.read(&encrypted); + let encrypted = remote_peer.encrypt(&[2]); + connected_peer.read(&encrypted); + + // Get one valid value + assert_eq!(connected_peer.decryptor.next(), Some(Ok(Some(vec![1])))); + let valid_receiving_key = connected_peer.decryptor.receiving_key; + + // Corrupt the receiving key and ensure we get a failure + connected_peer.decryptor.receiving_key = [0; 32]; + assert_eq!(connected_peer.decryptor.next(), Some(Err("invalid hmac".to_string()))); + + // Restore the receiving key, do a read and ensure None is returned (poisoned) + let encrypted = remote_peer.encrypt(&[3]); + connected_peer.read(&encrypted); + connected_peer.decryptor.receiving_key = valid_receiving_key; + assert_eq!(connected_peer.decryptor.next(), None); + } + + #[test] + fn max_msg_len_limit_value() { + assert_eq!(LN_MAX_MSG_LEN, 65535); + assert_eq!(LN_MAX_MSG_LEN, ::std::u16::MAX as usize); + } + + #[test] + #[should_panic(expected = "Attempted to encrypt message longer than 65535 bytes!")] + fn max_message_len_encryption() { + let (mut connected_peer, _) = setup_peers(); + let msg = [4u8; LN_MAX_MSG_LEN + 1]; + connected_peer.encrypt(&msg); + } + + #[test] + #[should_panic(expected = "Attempted to decrypt message longer than 65535 + 16 bytes!")] + fn max_message_len_decryption() { + let (mut connected_peer, _) = setup_peers(); + + // MSG should not exceed LN_MAX_MSG_LEN + 16 + let msg = [4u8; LN_MAX_MSG_LEN + 17]; + connected_peer.decrypt_single_message(Some(&msg)).unwrap(); + } +} \ No newline at end of file diff --git a/lightning/src/ln/peer_handler.rs b/lightning/src/ln/peers/handler.rs similarity index 80% rename from lightning/src/ln/peer_handler.rs rename to lightning/src/ln/peers/handler.rs index edb2084c716..25ecfcaaadd 100644 --- a/lightning/src/ln/peer_handler.rs +++ b/lightning/src/ln/peers/handler.rs @@ -22,7 +22,6 @@ use ln::msgs; use ln::msgs::{ChannelMessageHandler, LightningError, RoutingMessageHandler}; use ln::channelmanager::{SimpleArcChannelManager, SimpleRefChannelManager}; use util::ser::{VecWriter, Writeable}; -use ln::peer_channel_encryptor::{PeerChannelEncryptor,NextNoiseStep}; use ln::wire; use ln::wire::Encode; use util::byte_utils; @@ -39,6 +38,8 @@ use std::ops::Deref; use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::hashes::sha256::HashEngine as Sha256Engine; use bitcoin::hashes::{HashEngine, Hash}; +use ln::peers::handshake::PeerHandshake; +use ln::peers::conduit::Conduit; /// Provides references to trait impls which handle different types of messages. pub struct MessageHandler where @@ -119,8 +120,68 @@ enum InitSyncTracker{ NodesSyncing(PublicKey), } +enum PeerState { + Authenticating(PeerHandshake), + Connected(Conduit), +} + +enum PeerDataProcessingDecision { + CompleteHandshake(PublicKey), + Continue, + Disconnect(PeerHandleError) +} + +impl PeerState { + fn is_ready_for_encryption(&self) -> bool { + match self { + &PeerState::Connected(_) => true, + _ => false + } + } + + fn process_peer_data(&mut self, data: &[u8], mutable_response_buffer: &mut LinkedList>) -> PeerDataProcessingDecision { + let (new_state_opt, decision) = match self { + &mut PeerState::Authenticating(ref mut handshake) => { + match handshake.process_act(data) { + // Any errors originating from the handshake sequence result in Disconnect + Err(_e) => { + (None, PeerDataProcessingDecision::Disconnect(PeerHandleError { no_connection_possible: false })) + }, + // Otherwise, handshake may or may not be complete depending on whether or not + // we receive a (conduit, pubkey) + Ok((response_vec_option, conduit_and_remote_static_public_key_option)) => { + + // Any response generated by the handshake sequence is put into the response buffer + if let Some(response_vec) = response_vec_option { + mutable_response_buffer.push_back(response_vec); + } + + // if process_act() returns the conduit and remote static public key (node id) + // the handshake is complete + if let Some((conduit, remote_static_public_key)) = conduit_and_remote_static_public_key_option { + (Some(PeerState::Connected(conduit)), PeerDataProcessingDecision::CompleteHandshake(remote_static_public_key)) + } else { + (None, PeerDataProcessingDecision::Continue) + } + } + } + }, + &mut PeerState::Connected(ref mut conduit) => { + conduit.read(data); + (None, PeerDataProcessingDecision::Continue) + } + }; + + if let Some(new_state) = new_state_opt { + *self = new_state; + } + + decision + } +} + struct Peer { - channel_encryptor: PeerChannelEncryptor, + encryptor: PeerState, outbound: bool, their_node_id: Option, their_features: Option, @@ -129,10 +190,6 @@ struct Peer { pending_outbound_buffer_first_msg_offset: usize, awaiting_write_event: bool, - pending_read_buffer: Vec, - pending_read_buffer_pos: usize, - pending_read_is_header: bool, - sync_status: InitSyncTracker, awaiting_pong: bool, @@ -279,7 +336,7 @@ impl PeerManager Vec { let peers = self.peers.lock().unwrap(); peers.peers.values().filter_map(|p| { - if !p.channel_encryptor.is_ready_for_encryption() || p.their_features.is_none() { + if !p.encryptor.is_ready_for_encryption() || p.their_features.is_none() { return None; } p.their_node_id @@ -308,32 +365,27 @@ impl PeerManager Result, PeerHandleError> { - let mut peer_encryptor = PeerChannelEncryptor::new_outbound(their_node_id.clone(), self.get_ephemeral_key()); - let res = peer_encryptor.get_act_one().to_vec(); - let pending_read_buffer = [0; 50].to_vec(); // Noise act two is 50 bytes + let mut handshake = PeerHandshake::new_outbound(&self.our_node_secret, &their_node_id, &self.get_ephemeral_key()); + let initial_bytes = handshake.set_up_outbound(); let mut peers = self.peers.lock().unwrap(); if peers.peers.insert(descriptor, Peer { - channel_encryptor: peer_encryptor, + encryptor: PeerState::Authenticating(handshake), outbound: true, - their_node_id: None, + their_node_id: Some(their_node_id.clone()), their_features: None, pending_outbound_buffer: LinkedList::new(), pending_outbound_buffer_first_msg_offset: 0, awaiting_write_event: false, - pending_read_buffer: pending_read_buffer, - pending_read_buffer_pos: 0, - pending_read_is_header: false, - sync_status: InitSyncTracker::NoSyncRequested, awaiting_pong: false, }).is_some() { panic!("PeerManager driver duplicated descriptors!"); }; - Ok(res) + Ok(initial_bytes) } /// Indicates a new inbound connection has been established. @@ -346,12 +398,11 @@ impl PeerManager Result<(), PeerHandleError> { - let peer_encryptor = PeerChannelEncryptor::new_inbound(&self.our_node_secret); - let pending_read_buffer = [0; 50].to_vec(); // Noise act one is 50 bytes + let handshake = PeerHandshake::new_inbound(&self.our_node_secret, &self.get_ephemeral_key()); let mut peers = self.peers.lock().unwrap(); if peers.peers.insert(descriptor, Peer { - channel_encryptor: peer_encryptor, + encryptor: PeerState::Authenticating(handshake), outbound: false, their_node_id: None, their_features: None, @@ -360,10 +411,6 @@ impl PeerManager PeerManager { { log_trace!(self.logger, "Encoding and sending sync update message of type {} to {}", $msg.type_id(), log_pubkey!(peer.their_node_id.unwrap())); - peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!($msg)[..])); + match peer.encryptor { + PeerState::Connected(ref mut conduit) => peer.pending_outbound_buffer.push_back(conduit.encrypt(&encode_msg!($msg)[..])), + _ => panic!("peer must be connected!") + } } } } @@ -501,7 +551,10 @@ impl PeerManager peer.pending_outbound_buffer.push_back(conduit.encrypt(&encoded_message[..])), + _ => panic!("peer must be connected!") + } peers_needing_send.insert(descriptor); } @@ -512,145 +565,128 @@ impl PeerManager panic!("Descriptor for read_event is not already known to PeerManager"), Some(peer) => { - assert!(peer.pending_read_buffer.len() > 0); - assert!(peer.pending_read_buffer.len() > peer.pending_read_buffer_pos); - let mut read_pos = 0; - while read_pos < data.len() { - { - let data_to_copy = cmp::min(peer.pending_read_buffer.len() - peer.pending_read_buffer_pos, data.len() - read_pos); - peer.pending_read_buffer[peer.pending_read_buffer_pos..peer.pending_read_buffer_pos + data_to_copy].copy_from_slice(&data[read_pos..read_pos + data_to_copy]); - read_pos += data_to_copy; - peer.pending_read_buffer_pos += data_to_copy; + let data_processing_decision = peer.encryptor.process_peer_data(data, &mut peer.pending_outbound_buffer); + match data_processing_decision { + PeerDataProcessingDecision::Disconnect(e) => { + log_trace!(self.logger, "Invalid act message; disconnecting: {}", e); + return Err(e); } - if peer.pending_read_buffer_pos == peer.pending_read_buffer.len() { - peer.pending_read_buffer_pos = 0; + PeerDataProcessingDecision::CompleteHandshake(remote_pubkey) => { + peer.their_node_id = Some(remote_pubkey); + + if peer.outbound { + let mut features = InitFeatures::known(); + if !self.message_handler.route_handler.should_request_full_sync(&peer.their_node_id.unwrap()) { + features.clear_initial_routing_sync(); + } + + let resp = msgs::Init { features }; + self.enqueue_message(&mut peers.peers_needing_send, peer, peer_descriptor.clone(), &resp); + } - macro_rules! try_potential_handleerror { - ($thing: expr) => { - match $thing { + // insert node id + match peers.node_id_to_descriptor.entry(peer.their_node_id.unwrap()) { + hash_map::Entry::Occupied(_) => { + log_trace!(self.logger, "Got second connection with {}, closing", log_pubkey!(peer.their_node_id.unwrap())); + peer.their_node_id = None; // Unset so that we don't generate a peer_disconnected event + return Err(PeerHandleError { no_connection_possible: false }); + } + hash_map::Entry::Vacant(entry) => { + log_trace!(self.logger, "Finished noise handshake for connection with {}", log_pubkey!(peer.their_node_id.unwrap())); + entry.insert(peer_descriptor.clone()) + } + }; + } + _ => { } + }; + + let mut received_messages = vec![]; + if let &mut PeerState::Connected(ref mut conduit) = &mut peer.encryptor { + // Using Iterators that can error requires special handling + // The item returned from next() has type Option, String>> + // The Some wrapper is stripped for each item inside the loop + // There are 3 valid match cases: + // 1) Some(Ok(Some(msg_data))) => Indicates a valid decrypted msg accessed via msg_data + // 2) Some(Err(_)) => Indicates an error during decryption that should be handled + // 3) None -> Indicates there were no messages available to decrypt + // Invalid Cases + // 1) Some(Ok(None)) => Translated to None case above so users of iterators can stop correctly + for msg_data_result in &mut conduit.decryptor { + match msg_data_result { + Ok(Some(msg_data)) => { + let mut reader = ::std::io::Cursor::new(&msg_data[..]); + let message_result = wire::read(&mut reader); + let message = match message_result { Ok(x) => x, Err(e) => { - match e.action { - msgs::ErrorAction::DisconnectPeer { msg: _ } => { - //TODO: Try to push msg - log_trace!(self.logger, "Got Err handling message, disconnecting peer because {}", e.err); - return Err(PeerHandleError{ no_connection_possible: false }); - }, - msgs::ErrorAction::IgnoreError => { - log_trace!(self.logger, "Got Err handling message, ignoring because {}", e.err); - continue; - }, - msgs::ErrorAction::SendErrorMessage { msg } => { - log_trace!(self.logger, "Got Err handling message, sending Error message because {}", e.err); - self.enqueue_message(&mut peers.peers_needing_send, peer, peer_descriptor.clone(), &msg); + match e { + msgs::DecodeError::UnknownVersion => return Err(PeerHandleError { no_connection_possible: false }), + msgs::DecodeError::UnknownRequiredFeature => { + log_debug!(self.logger, "Got a channel/node announcement with an known required feature flag, you may want to update!"); continue; - }, + } + msgs::DecodeError::InvalidValue => { + log_debug!(self.logger, "Got an invalid value while deserializing message"); + return Err(PeerHandleError { no_connection_possible: false }); + } + msgs::DecodeError::ShortRead => { + log_debug!(self.logger, "Deserialization failed due to shortness of message"); + return Err(PeerHandleError { no_connection_possible: false }); + } + msgs::DecodeError::BadLengthDescriptor => return Err(PeerHandleError { no_connection_possible: false }), + msgs::DecodeError::Io(_) => return Err(PeerHandleError { no_connection_possible: false }), } } }; - } - } - macro_rules! insert_node_id { - () => { - match peers.node_id_to_descriptor.entry(peer.their_node_id.unwrap()) { - hash_map::Entry::Occupied(_) => { - log_trace!(self.logger, "Got second connection with {}, closing", log_pubkey!(peer.their_node_id.unwrap())); - peer.their_node_id = None; // Unset so that we don't generate a peer_disconnected event - return Err(PeerHandleError{ no_connection_possible: false }) - }, - hash_map::Entry::Vacant(entry) => { - log_trace!(self.logger, "Finished noise handshake for connection with {}", log_pubkey!(peer.their_node_id.unwrap())); - entry.insert(peer_descriptor.clone()) - }, - }; + received_messages.push(message); + }, + Err(e) => { + log_trace!(self.logger, "Message decryption failed due to: {}", e); + return Err(PeerHandleError { no_connection_possible: false }); + } + Ok(None) => { + panic!("Invalid behavior. Conduit iterator should never return this match.") } } + } + } - let next_step = peer.channel_encryptor.get_noise_step(); - match next_step { - NextNoiseStep::ActOne => { - let act_two = try_potential_handleerror!(peer.channel_encryptor.process_act_one_with_keys(&peer.pending_read_buffer[..], &self.our_node_secret, self.get_ephemeral_key())).to_vec(); - peer.pending_outbound_buffer.push_back(act_two); - peer.pending_read_buffer = [0; 66].to_vec(); // act three is 66 bytes long - }, - NextNoiseStep::ActTwo => { - let (act_three, their_node_id) = try_potential_handleerror!(peer.channel_encryptor.process_act_two(&peer.pending_read_buffer[..], &self.our_node_secret)); - peer.pending_outbound_buffer.push_back(act_three.to_vec()); - peer.pending_read_buffer = [0; 18].to_vec(); // Message length header is 18 bytes - peer.pending_read_is_header = true; - - peer.their_node_id = Some(their_node_id); - insert_node_id!(); - let mut features = InitFeatures::known(); - if !self.message_handler.route_handler.should_request_full_sync(&peer.their_node_id.unwrap()) { - features.clear_initial_routing_sync(); + for message in received_messages { + macro_rules! try_potential_handleerror { + ($thing: expr) => { + match $thing { + Ok(x) => x, + Err(e) => { + match e.action { + msgs::ErrorAction::DisconnectPeer { msg: _ } => { + //TODO: Try to push msg + log_trace!(self.logger, "Got Err handling message, disconnecting peer because {}", e.err); + return Err(PeerHandleError{ no_connection_possible: false }); + }, + msgs::ErrorAction::IgnoreError => { + log_trace!(self.logger, "Got Err handling message, ignoring because {}", e.err); + continue; + }, + msgs::ErrorAction::SendErrorMessage { msg } => { + log_trace!(self.logger, "Got Err handling message, sending Error message because {}", e.err); + self.enqueue_message(&mut peers.peers_needing_send, peer, peer_descriptor.clone(), &msg); + continue; + }, + } } + }; + } + } - let resp = msgs::Init { features }; - self.enqueue_message(&mut peers.peers_needing_send, peer, peer_descriptor.clone(), &resp); + if let Err(handling_error) = self.handle_message(&mut peers.peers_needing_send, peer, peer_descriptor.clone(), message){ + match handling_error { + MessageHandlingError::PeerHandleError(e) => { return Err(e) }, + MessageHandlingError::LightningError(e) => { + try_potential_handleerror!(Err(e)); }, - NextNoiseStep::ActThree => { - let their_node_id = try_potential_handleerror!(peer.channel_encryptor.process_act_three(&peer.pending_read_buffer[..])); - peer.pending_read_buffer = [0; 18].to_vec(); // Message length header is 18 bytes - peer.pending_read_is_header = true; - peer.their_node_id = Some(their_node_id); - insert_node_id!(); - }, - NextNoiseStep::NoiseComplete => { - if peer.pending_read_is_header { - let msg_len = try_potential_handleerror!(peer.channel_encryptor.decrypt_length_header(&peer.pending_read_buffer[..])); - peer.pending_read_buffer = Vec::with_capacity(msg_len as usize + 16); - peer.pending_read_buffer.resize(msg_len as usize + 16, 0); - if msg_len < 2 { // Need at least the message type tag - return Err(PeerHandleError{ no_connection_possible: false }); - } - peer.pending_read_is_header = false; - } else { - let msg_data = try_potential_handleerror!(peer.channel_encryptor.decrypt_message(&peer.pending_read_buffer[..])); - assert!(msg_data.len() >= 2); - - // Reset read buffer - peer.pending_read_buffer = [0; 18].to_vec(); - peer.pending_read_is_header = true; - - let mut reader = ::std::io::Cursor::new(&msg_data[..]); - let message_result = wire::read(&mut reader); - let message = match message_result { - Ok(x) => x, - Err(e) => { - match e { - msgs::DecodeError::UnknownVersion => return Err(PeerHandleError { no_connection_possible: false }), - msgs::DecodeError::UnknownRequiredFeature => { - log_debug!(self.logger, "Got a channel/node announcement with an known required feature flag, you may want to update!"); - continue; - } - msgs::DecodeError::InvalidValue => { - log_debug!(self.logger, "Got an invalid value while deserializing message"); - return Err(PeerHandleError { no_connection_possible: false }); - } - msgs::DecodeError::ShortRead => { - log_debug!(self.logger, "Deserialization failed due to shortness of message"); - return Err(PeerHandleError { no_connection_possible: false }); - } - msgs::DecodeError::BadLengthDescriptor => return Err(PeerHandleError { no_connection_possible: false }), - msgs::DecodeError::Io(_) => return Err(PeerHandleError { no_connection_possible: false }), - } - } - }; - - if let Err(handling_error) = self.handle_message(&mut peers.peers_needing_send, peer, peer_descriptor.clone(), message){ - match handling_error { - MessageHandlingError::PeerHandleError(e) => { return Err(e) }, - MessageHandlingError::LightningError(e) => { - try_potential_handleerror!(Err(e)); - }, - } - } - } - } } } } @@ -898,7 +934,9 @@ impl PeerManager { @@ -908,7 +946,9 @@ impl PeerManager { @@ -920,7 +960,9 @@ impl PeerManager { @@ -931,7 +973,9 @@ impl PeerManager { @@ -941,7 +985,9 @@ impl PeerManager { @@ -952,7 +998,9 @@ impl PeerManager { @@ -965,22 +1013,24 @@ impl PeerManager { @@ -990,7 +1040,9 @@ impl PeerManager { @@ -1000,7 +1052,9 @@ impl PeerManager { @@ -1010,7 +1064,9 @@ impl PeerManager { @@ -1020,7 +1076,9 @@ impl PeerManager { @@ -1030,8 +1088,8 @@ impl PeerManager PeerManager PeerManager PeerManager PeerManager PeerManager PeerManager PeerManager or the MIT license +// , at your option. +// You may not use this file except in accordance with one or both of these +// licenses. + +//! Helper library for working with NOISE handshake Act data. Contains utilities for passing Act +//! objects around and building them from received data. +//! Act objects are thin wrappers about raw arrays for stack-based processing as well as convenient +//! coercion to slices for flexible use by the higher-level modules. + +use std::{cmp, ops}; + +pub const ACT_ONE_LENGTH: usize = 50; +pub const ACT_TWO_LENGTH: usize = 50; +pub const ACT_THREE_LENGTH: usize = 66; +pub const EMPTY_ACT_ONE: ActOne = [0; ACT_ONE_LENGTH]; +pub const EMPTY_ACT_TWO: ActTwo = [0; ACT_TWO_LENGTH]; +pub const EMPTY_ACT_THREE: ActThree = [0; ACT_THREE_LENGTH]; +type ActOne = [u8; ACT_ONE_LENGTH]; +type ActTwo = [u8; ACT_TWO_LENGTH]; +type ActThree = [u8; ACT_THREE_LENGTH]; + +/// Wrapper for any act message +pub(super) enum Act { + One(ActOne), + Two(ActTwo), + Three(ActThree) +} + +impl Act { + /// Returns the size of the underlying array + fn len(&self) -> usize { + self.as_ref().len() + } +} + +impl From for Act { + /// Convert a finished ActBuilder into an Act + fn from(act_builder: ActBuilder) -> Self { + assert!(act_builder.is_finished()); + act_builder.partial_act + } +} + +impl ops::Deref for Act { + type Target = [u8]; + + /// Allows automatic coercion to slices in function calls + /// &Act -> &[u8] + fn deref(&self) -> &Self::Target { + match self { + &Act::One(ref act) => { + act + } + &Act::Two(ref act) => { + act + } + &Act::Three(ref act) => { + act + } + } + } +} + +impl AsRef<[u8]> for Act { + /// Allow convenient exposure of the underlying array through as_ref() + /// Act.as_ref() -> &[u8] + fn as_ref(&self) -> &[u8] { + &self + } +} + +/// Light wrapper around an Act that allows multiple fill() calls before finally +/// converting to an Act via Act::from(act_builder). Handles all of the bookkeeping +/// and edge cases of the array fill +pub(super) struct ActBuilder { + partial_act: Act, + write_pos: usize +} + +impl ActBuilder { + /// Returns a new ActBuilder for Act::One + pub(super) fn new(empty_act: Act) -> Self { + Self { + partial_act: empty_act, + write_pos: 0 + } + } + + /// Fills the Act with bytes from input and returns the number of bytes consumed from input. + pub(super) fn fill(&mut self, input: &[u8]) -> usize { + // Simple fill implementation for both almost-identical structs to deduplicate code + // $act: Act[One|Two|Three], $input: &[u8]; returns &[u8] of remaining input that was not processed + macro_rules! fill_act_content { + ($act:expr, $write_pos:expr, $input:expr) => {{ + let fill_amount = cmp::min($act.len() - $write_pos, $input.len()); + + $act[$write_pos..$write_pos + fill_amount].copy_from_slice(&$input[..fill_amount]); + + $write_pos += fill_amount; + fill_amount + }} + } + + match &mut self.partial_act { + &mut Act::One(ref mut act) => { + fill_act_content!(act, self.write_pos, input) + } + &mut Act::Two(ref mut act) => { + fill_act_content!(act, self.write_pos, input) + } + &mut Act::Three(ref mut act) => { + fill_act_content!(act, self.write_pos, input) + } + } + } + + /// Returns true if the Act is finished building (enough bytes via fill()) + pub(super) fn is_finished(&self) -> bool { + self.write_pos == self.partial_act.len() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + // Test bookkeeping of partial fill + #[test] + fn partial_fill() { + let mut builder = ActBuilder::new(Act::One(EMPTY_ACT_ONE)); + + let input = [1, 2, 3]; + let bytes_read = builder.fill(&input); + assert_eq!(builder.partial_act.len(), ACT_ONE_LENGTH); + assert_eq!(builder.write_pos, 3); + assert!(!builder.is_finished()); + assert_eq!(bytes_read, input.len()); + } + + // Test bookkeeping of exact fill + #[test] + fn exact_fill() { + let mut builder = ActBuilder::new(Act::One(EMPTY_ACT_ONE)); + + let input = [0; ACT_ONE_LENGTH]; + let bytes_read = builder.fill(&input); + assert_eq!(builder.partial_act.len(), ACT_ONE_LENGTH); + assert_eq!(builder.write_pos, ACT_ONE_LENGTH); + assert!(builder.is_finished()); + assert_eq!(Act::from(builder).as_ref(), &input[..]); + assert_eq!(bytes_read, input.len()); + } + + // Test bookkeeping of overfill + #[test] + fn over_fill() { + let mut builder = ActBuilder::new(Act::One(EMPTY_ACT_ONE)); + + let input = [0; ACT_ONE_LENGTH + 1]; + let bytes_read = builder.fill(&input); + + assert_eq!(builder.partial_act.len(), ACT_ONE_LENGTH); + assert_eq!(builder.write_pos, ACT_ONE_LENGTH); + assert!(builder.is_finished()); + assert_eq!(Act::from(builder).as_ref(), &input[..ACT_ONE_LENGTH]); + assert_eq!(bytes_read, ACT_ONE_LENGTH); + } + + // Converting an unfinished ActBuilder panics + #[test] + #[should_panic(expected="assertion failed: act_builder.is_finished()")] + fn convert_not_finished_panics() { + let builder = ActBuilder::new(Act::One(EMPTY_ACT_ONE)); + let _should_panic = Act::from(builder); + } +} + diff --git a/lightning/src/ln/peers/handshake/mod.rs b/lightning/src/ln/peers/handshake/mod.rs new file mode 100644 index 00000000000..f964c245a94 --- /dev/null +++ b/lightning/src/ln/peers/handshake/mod.rs @@ -0,0 +1,246 @@ +// This file is Copyright its original authors, visible in version control +// history. +// +// 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. + +//! Execute handshakes for peer-to-peer connection establishment. +//! Handshake states can be advanced automatically, or by manually calling the appropriate step. +//! Once complete, returns an instance of Conduit. + +use bitcoin::secp256k1::{PublicKey, SecretKey}; + +use ln::peers::conduit::Conduit; +use ln::peers::handshake::states::{HandshakeState, IHandshakeState}; + +mod acts; +mod states; + +/// Object for managing handshakes. +/// Currently requires explicit ephemeral private key specification. +pub struct PeerHandshake { + state: Option, + ready_to_process: bool, +} + +impl PeerHandshake { + /// Instantiate a handshake given the peer's static public key. The ephemeral private key MUST + /// generate a new session with strong cryptographic randomness. + pub fn new_outbound(initiator_static_private_key: &SecretKey, responder_static_public_key: &PublicKey, initiator_ephemeral_private_key: &SecretKey) -> Self { + let state = HandshakeState::new_initiator(initiator_static_private_key, responder_static_public_key, initiator_ephemeral_private_key); + + Self { + state: Some(state), + ready_to_process: false, + } + } + + /// Instantiate a handshake in anticipation of a peer's first handshake act + pub fn new_inbound(responder_static_private_key: &SecretKey, responder_ephemeral_private_key: &SecretKey) -> Self { + Self { + state: Some(HandshakeState::new_responder(responder_static_private_key, responder_ephemeral_private_key)), + ready_to_process: true, + } + } + + /// Initializes the outbound handshake and provides the initial bytes to send to the responder + pub fn set_up_outbound(&mut self) -> Vec { + assert!(!self.ready_to_process); + self.ready_to_process = true; + + // This transition does not have a failure path + let (response_vec_option, conduit_and_remote_static_public_key_option) = self.process_act(&[]).unwrap(); + assert!(conduit_and_remote_static_public_key_option.is_none()); + + response_vec_option.unwrap() + } + + /// Process act dynamically + /// # Arguments + /// `input`: Byte slice received from peer as part of the handshake protocol + /// + /// # Return values + /// Returns a tuple with the following components: + /// `.0`: Byte vector containing the next act to send back to the peer per the handshake protocol + /// `.1`: Some(Conduit, PublicKey) if the handshake was just processed to completion and messages can now be encrypted and decrypted + pub fn process_act(&mut self, input: &[u8]) -> Result<(Option>, Option<(Conduit, PublicKey)>), String> { + assert!(self.ready_to_process); + let cur_state = self.state.take().unwrap(); + + let (act_option, mut next_state) = match cur_state.next(input)? { + (Some(act), next_state) => (Some(act.to_vec()), next_state), + (None, next_state) => (None, next_state) + }; + + let result = match next_state { + HandshakeState::Complete(ref mut conduit_and_pubkey) => { + Ok((act_option, conduit_and_pubkey.take())) + }, + _ => { Ok((act_option, None)) } + }; + + self.state = Some(next_state); + + result + } +} + +#[cfg(test)] +mod test { + use super::*; + + use bitcoin::secp256k1; + use bitcoin::secp256k1::key::{PublicKey, SecretKey}; + + struct TestCtx { + act1: Vec, + outbound_handshake: PeerHandshake, + outbound_static_public_key: PublicKey, + inbound_handshake: PeerHandshake, + inbound_static_public_key: PublicKey + } + + impl TestCtx { + fn new() -> TestCtx { + let curve = secp256k1::Secp256k1::new(); + + let outbound_static_private_key = SecretKey::from_slice(&[0x_11_u8; 32]).unwrap(); + let outbound_static_public_key = PublicKey::from_secret_key(&curve, &outbound_static_private_key); + let outbound_ephemeral_private_key = SecretKey::from_slice(&[0x_12_u8; 32]).unwrap(); + + let inbound_static_private_key = SecretKey::from_slice(&[0x_21_u8; 32]).unwrap(); + let inbound_static_public_key = PublicKey::from_secret_key(&curve, &inbound_static_private_key); + let inbound_ephemeral_private_key = SecretKey::from_slice(&[0x_22_u8; 32]).unwrap(); + + let mut outbound_handshake= PeerHandshake::new_outbound(&outbound_static_private_key, &inbound_static_public_key, &outbound_ephemeral_private_key); + let act1 = outbound_handshake.set_up_outbound(); + let inbound_handshake = PeerHandshake::new_inbound(&inbound_static_private_key, &inbound_ephemeral_private_key); + + TestCtx { + act1, + outbound_handshake, + outbound_static_public_key, + inbound_handshake, + inbound_static_public_key, + } + } + } + + macro_rules! assert_matches { + ($e:expr, $state_match:pat) => { + match $e { + $state_match => (), + _ => panic!() + } + } + } + + macro_rules! do_process_act_or_panic { + ($handshake:expr, $input:expr) => { + $handshake.process_act($input).unwrap().0.unwrap() + } + } + + // Test that the outbound needs to call set_up_outbound() before process_act() + #[test] + #[should_panic(expected = "assertion failed: self.ready_to_process")] + fn new_outbound_no_set_up_panics() { + let curve = secp256k1::Secp256k1::new(); + + let outbound_static_private_key = SecretKey::from_slice(&[0x_11_u8; 32]).unwrap(); + let outbound_ephemeral_private_key = SecretKey::from_slice(&[0x_12_u8; 32]).unwrap(); + let inbound_static_private_key = SecretKey::from_slice(&[0x_21_u8; 32]).unwrap(); + let inbound_static_public_key = PublicKey::from_secret_key(&curve, &inbound_static_private_key); + + let mut outbound_handshake= PeerHandshake::new_outbound(&outbound_static_private_key, &inbound_static_public_key, &outbound_ephemeral_private_key); + outbound_handshake.process_act(&[]).unwrap(); + } + + // Test that calling set_up_outbound() on the inbound panics + #[test] + #[should_panic(expected = "assertion failed: !self.ready_to_process")] + fn new_inbound_calling_set_up_panics() { + let inbound_static_private_key = SecretKey::from_slice(&[0x_21_u8; 32]).unwrap(); + let inbound_ephemeral_private_key = SecretKey::from_slice(&[0x_22_u8; 32]).unwrap(); + + let mut inbound_handshake = PeerHandshake::new_inbound(&inbound_static_private_key, &inbound_ephemeral_private_key); + inbound_handshake.set_up_outbound(); + } + + // Default Outbound::Uninitiated + #[test] + fn new_outbound() { + let test_ctx = TestCtx::new(); + + assert_matches!(test_ctx.outbound_handshake.state, Some(HandshakeState::InitiatorAwaitingActTwo(_))); + } + + // Default Inbound::AwaitingActOne + #[test] + fn new_inbound() { + let test_ctx = TestCtx::new(); + + assert_matches!(test_ctx.inbound_handshake.state, Some(HandshakeState::ResponderAwaitingActOne(_))); + } + + /* + * PeerHandshake::process_act() tests + */ + + // Full sequence from initiator and responder as a sanity test. State machine is tested in states.rs + #[test] + fn full_sequence_sanity_test() { + let mut test_ctx = TestCtx::new(); + let act2 = do_process_act_or_panic!(test_ctx.inbound_handshake, &test_ctx.act1); + + let (act3, inbound_remote_pubkey) = if let (Some(act3), Some((_, remote_pubkey))) = test_ctx.outbound_handshake.process_act(&act2).unwrap() { + (act3, remote_pubkey) + } else { + panic!(); + }; + + let outbound_remote_pubkey = if let (None, Some((_, remote_pubkey))) = test_ctx.inbound_handshake.process_act(&act3).unwrap() { + remote_pubkey + } else { + panic!(); + }; + + assert_eq!(inbound_remote_pubkey, test_ctx.inbound_static_public_key); + assert_eq!(outbound_remote_pubkey, test_ctx.outbound_static_public_key); + } + + // Test that the internal state object matches the return from state_machine.next() + // This could make use of a mocking library to remove the dependency on the state machine. All + // that needs to be tested is that the expected state (returned) from state_machine.next() matchse + // the internal set state. + #[test] + fn process_act_properly_updates_state() { + let mut test_ctx = TestCtx::new(); + do_process_act_or_panic!(test_ctx.inbound_handshake, &test_ctx.act1); + assert_matches!(test_ctx.inbound_handshake.state, Some(HandshakeState::ResponderAwaitingActThree(_))); + } + + // Test that any errors from the state machine are passed back to the caller + // This could make use of a mocking library to remove the dependency on the state machine + // logic. All that needs to be tested is that an error from state_machine.next() + // results in an error in process_act() + #[test] + fn errors_properly_returned() { + let mut test_ctx = TestCtx::new(); + let invalid_act1 = [0; 50]; + assert_matches!(test_ctx.inbound_handshake.process_act(&invalid_act1).err(), Some(_)); + } + + // Test that any use of the PeerHandshake after returning an error panics + #[test] + #[should_panic(expected = "called `Option::unwrap()` on a `None` value")] + fn use_after_error_panics() { + let mut test_ctx = TestCtx::new(); + let invalid_act1 = [0; 50]; + assert_matches!(test_ctx.inbound_handshake.process_act(&invalid_act1).err(), Some(_)); + test_ctx.inbound_handshake.process_act(&[]).unwrap(); + } +} diff --git a/lightning/src/ln/peers/handshake/states.rs b/lightning/src/ln/peers/handshake/states.rs new file mode 100644 index 00000000000..347620cbb8f --- /dev/null +++ b/lightning/src/ln/peers/handshake/states.rs @@ -0,0 +1,906 @@ +// This file is Copyright its original authors, visible in version control +// history. +// +// 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. + +use bitcoin::secp256k1; + +use bitcoin::hashes::{Hash, HashEngine}; +use bitcoin::hashes::sha256::Hash as Sha256; +use bitcoin::secp256k1::{SecretKey, PublicKey}; + +use ln::peers::{chacha, hkdf5869rfc}; +use ln::peers::conduit::{Conduit, SymmetricKey}; +use ln::peers::handshake::acts::{Act, ActBuilder, ACT_ONE_LENGTH, ACT_TWO_LENGTH, ACT_THREE_LENGTH, EMPTY_ACT_ONE, EMPTY_ACT_TWO, EMPTY_ACT_THREE}; + +// Alias type to help differentiate between temporary key and chaining key when passing bytes around +type ChainingKey = [u8; 32]; + +// Generate a SHA-256 hash from one or more elements concatenated together +macro_rules! concat_then_sha256 { + ( $( $x:expr ),+ ) => {{ + let mut sha = Sha256::engine(); + $( + sha.input($x.as_ref()); + )+ + Sha256::from_engine(sha) + }} +} + +pub(super) enum HandshakeState { + InitiatorStarting(InitiatorStartingState), + ResponderAwaitingActOne(ResponderAwaitingActOneState), + InitiatorAwaitingActTwo(InitiatorAwaitingActTwoState), + ResponderAwaitingActThree(ResponderAwaitingActThreeState), + Complete(Option<(Conduit, PublicKey)>), +} + +// Trait for all individual states to implement that ensure HandshakeState::next() can +// delegate to a common function signature. May transition to the same state in the event there are +// not yet enough bytes to move forward with the handshake. +pub(super) trait IHandshakeState { + fn next(self, input: &[u8]) -> Result<(Option, HandshakeState), String>; +} + +// Enum dispatch for state machine. Single public interface can statically dispatch to all states +impl HandshakeState { + pub(super) fn new_initiator(initiator_static_private_key: &SecretKey, responder_static_public_key: &PublicKey, initiator_ephemeral_private_key: &SecretKey) -> Self { + HandshakeState::InitiatorStarting(InitiatorStartingState::new(initiator_static_private_key.clone(), initiator_ephemeral_private_key.clone(), responder_static_public_key.clone())) + } + pub(super) fn new_responder(responder_static_private_key: &SecretKey, responder_ephemeral_private_key: &SecretKey) -> Self { + HandshakeState::ResponderAwaitingActOne(ResponderAwaitingActOneState::new(responder_static_private_key.clone(), responder_ephemeral_private_key.clone())) + } +} + +impl IHandshakeState for HandshakeState { + fn next(self, input: &[u8]) -> Result<(Option, HandshakeState), String> { + match self { + HandshakeState::InitiatorStarting(state) => { state.next(input) }, + HandshakeState::ResponderAwaitingActOne(state) => { state.next(input) }, + HandshakeState::InitiatorAwaitingActTwo(state) => { state.next(input) }, + HandshakeState::ResponderAwaitingActThree(state) => { state.next(input) }, + HandshakeState::Complete(_conduit) => { panic!("no acts left to process") } + } + } +} + +// Handshake state of the Initiator prior to generating Act 1 +pub(super) struct InitiatorStartingState { + initiator_static_private_key: SecretKey, + initiator_static_public_key: PublicKey, + initiator_ephemeral_private_key: SecretKey, + initiator_ephemeral_public_key: PublicKey, + responder_static_public_key: PublicKey, + chaining_key: Sha256, + hash: Sha256 +} + +// Handshake state of the Responder prior to receiving Act 1 +pub(super) struct ResponderAwaitingActOneState { + responder_static_private_key: SecretKey, + responder_ephemeral_private_key: SecretKey, + responder_ephemeral_public_key: PublicKey, + chaining_key: Sha256, + hash: Sha256, + act_one_builder: ActBuilder +} + +// Handshake state of the Initiator prior to receiving Act 2 +pub(super) struct InitiatorAwaitingActTwoState { + initiator_static_private_key: SecretKey, + initiator_static_public_key: PublicKey, + initiator_ephemeral_private_key: SecretKey, + responder_static_public_key: PublicKey, + chaining_key: ChainingKey, + hash: Sha256, + act_two_builder: ActBuilder +} + +// Handshake state of the Responder prior to receiving Act 3 +pub(super) struct ResponderAwaitingActThreeState { + hash: Sha256, + responder_ephemeral_private_key: SecretKey, + chaining_key: ChainingKey, + temporary_key: [u8; 32], + act_three_builder: ActBuilder +} + +impl InitiatorStartingState { + pub(crate) fn new(initiator_static_private_key: SecretKey, initiator_ephemeral_private_key: SecretKey, responder_static_public_key: PublicKey) -> Self { + let initiator_static_public_key = private_key_to_public_key(&initiator_static_private_key); + let (hash, chaining_key) = initialize_handshake_state(&responder_static_public_key); + let initiator_ephemeral_public_key = private_key_to_public_key(&initiator_ephemeral_private_key); + InitiatorStartingState { + initiator_static_private_key, + initiator_static_public_key, + initiator_ephemeral_private_key, + initiator_ephemeral_public_key, + responder_static_public_key, + chaining_key, + hash + } + } +} + +impl IHandshakeState for InitiatorStartingState { + // https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#act-one (sender) + fn next(self, input: &[u8]) -> Result<(Option, HandshakeState), String> { + + if input.len() > 0 { + return Err("first call for initiator must be empty".to_string()); + } + + let initiator_static_private_key = self.initiator_static_private_key; + let initiator_static_public_key = self.initiator_static_public_key; + let initiator_ephemeral_private_key = self.initiator_ephemeral_private_key; + let initiator_ephemeral_public_key = self.initiator_ephemeral_public_key; + let responder_static_public_key = self.responder_static_public_key; + let chaining_key = self.chaining_key; + let hash = self.hash; + + // serialize act one + let mut act_one = EMPTY_ACT_ONE; + let (hash, chaining_key, _) = calculate_act_message( + &initiator_ephemeral_private_key, + &initiator_ephemeral_public_key, + &responder_static_public_key, + chaining_key.into_inner(), + hash, + &mut act_one + ); + + Ok(( + Some(Act::One(act_one)), + HandshakeState::InitiatorAwaitingActTwo(InitiatorAwaitingActTwoState { + initiator_static_private_key, + initiator_static_public_key, + initiator_ephemeral_private_key, + responder_static_public_key, + chaining_key, + hash, + act_two_builder: ActBuilder::new(Act::Two(EMPTY_ACT_TWO)) + }) + )) + } +} + +impl ResponderAwaitingActOneState { + pub(crate) fn new(responder_static_private_key: SecretKey, responder_ephemeral_private_key: SecretKey) -> Self { + let responder_static_public_key = private_key_to_public_key(&responder_static_private_key); + let (hash, chaining_key) = initialize_handshake_state(&responder_static_public_key); + let responder_ephemeral_public_key = private_key_to_public_key(&responder_ephemeral_private_key); + + ResponderAwaitingActOneState { + responder_static_private_key, + responder_ephemeral_private_key, + responder_ephemeral_public_key, + chaining_key, + hash, + act_one_builder: ActBuilder::new(Act::One(EMPTY_ACT_ONE)) + } + } +} + +impl IHandshakeState for ResponderAwaitingActOneState { + // https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#act-one (receiver) + // https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#act-two (sender) + fn next(self, input: &[u8]) -> Result<(Option, HandshakeState), String> { + let mut act_one_builder = self.act_one_builder; + let bytes_read = act_one_builder.fill(input); + + // Any payload that is not fully consumed by the builder indicates a bad peer since responder + // data is required to generate act3 (so it can't come before we transition) + if bytes_read < input.len() { + return Err("Act One too large".to_string()); + } + + // In the event of a partial fill, stay in the same state and wait for more data + if !act_one_builder.is_finished() { + assert_eq!(bytes_read, input.len()); + return Ok(( + None, + HandshakeState::ResponderAwaitingActOne(Self { + responder_static_private_key: self.responder_static_private_key, + responder_ephemeral_private_key: self.responder_ephemeral_private_key, + responder_ephemeral_public_key: self.responder_ephemeral_public_key, + chaining_key: self.chaining_key, + hash: self.hash, + act_one_builder + }) + )); + } + + let hash = self.hash; + let responder_static_private_key = self.responder_static_private_key; + let chaining_key = self.chaining_key; + let responder_ephemeral_private_key = self.responder_ephemeral_private_key; + let responder_ephemeral_public_key = self.responder_ephemeral_public_key; + let act_one = Act::from(act_one_builder); + + let (initiator_ephemeral_public_key, hash, chaining_key, _) = process_act_message( + &act_one, + &responder_static_private_key, + chaining_key.into_inner(), + hash, + )?; + + let mut act_two = EMPTY_ACT_TWO; + let (hash, chaining_key, temporary_key) = calculate_act_message( + &responder_ephemeral_private_key, + &responder_ephemeral_public_key, + &initiator_ephemeral_public_key, + chaining_key, + hash, + &mut act_two + ); + + Ok(( + Some(Act::Two(act_two)), + HandshakeState::ResponderAwaitingActThree(ResponderAwaitingActThreeState { + hash, + responder_ephemeral_private_key, + chaining_key, + temporary_key, + act_three_builder: ActBuilder::new(Act::Three(EMPTY_ACT_THREE)) + }) + )) + } +} + +impl IHandshakeState for InitiatorAwaitingActTwoState { + // https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#act-two (receiver) + // https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#act-three (sender) + fn next(self, input: &[u8]) -> Result<(Option, HandshakeState), String> { + let mut act_two_builder = self.act_two_builder; + let bytes_read = act_two_builder.fill(input); + + // Any payload that is not fully consumed by the builder indicates a bad peer since responder data + // is required to generate post-authentication messages (so it can't come before we transition) + if bytes_read < input.len() { + return Err("Act Two too large".to_string()); + } + + // In the event of a partial fill, stay in the same state and wait for more data + if !act_two_builder.is_finished() { + assert_eq!(bytes_read, input.len()); + return Ok(( + None, + HandshakeState::InitiatorAwaitingActTwo(Self { + initiator_static_private_key: self.initiator_static_private_key, + initiator_static_public_key: self.initiator_static_public_key, + initiator_ephemeral_private_key: self.initiator_ephemeral_private_key, + responder_static_public_key: self.responder_static_public_key, + chaining_key: self.chaining_key, + hash: self.hash, + act_two_builder + }) + )); + } + + let initiator_static_private_key = self.initiator_static_private_key; + let initiator_static_public_key = self.initiator_static_public_key; + let initiator_ephemeral_private_key = self.initiator_ephemeral_private_key; + let responder_static_public_key = self.responder_static_public_key; + let hash = self.hash; + let chaining_key = self.chaining_key; + let act_two = Act::from(act_two_builder); + + let (responder_ephemeral_public_key, hash, chaining_key, temporary_key) = process_act_message( + &act_two, + &initiator_ephemeral_private_key, + chaining_key, + hash, + )?; + + let mut act_three = EMPTY_ACT_THREE; + + // start serializing act three + // 1. c = encryptWithAD(temp_k2, 1, h, s.pub.serializeCompressed()) + chacha::encrypt(&temporary_key, 1, &hash, &initiator_static_public_key.serialize(), &mut act_three[1..50]); + + // 2. h = SHA-256(h || c) + let hash = concat_then_sha256!(hash, act_three[1..50]); + + // 3. se = ECDH(s.priv, re) + let ecdh = ecdh(&initiator_static_private_key, &responder_ephemeral_public_key); + + // 4. ck, temp_k3 = HKDF(ck, se) + let (chaining_key, temporary_key) = hkdf5869rfc::derive(&chaining_key, &ecdh); + + // 5. t = encryptWithAD(temp_k3, 0, h, zero) + chacha::encrypt(&temporary_key, 0, &hash, &[0; 0], &mut act_three[50..]); + + // 6. sk, rk = HKDF(ck, zero) + let (sending_key, receiving_key) = hkdf5869rfc::derive(&chaining_key, &[0; 0]); + + // 7. rn = 0, sn = 0 + // - done by Conduit + let conduit = Conduit::new(sending_key, receiving_key, chaining_key); + + // 8. Send m = 0 || c || t + act_three[0] = 0; + Ok(( + Some(Act::Three(act_three)), + HandshakeState::Complete(Some((conduit, responder_static_public_key))) + )) + } +} + +impl IHandshakeState for ResponderAwaitingActThreeState { + // https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#act-three (receiver) + fn next(self, input: &[u8]) -> Result<(Option, HandshakeState), String> { + let mut act_three_builder = self.act_three_builder; + let bytes_read = act_three_builder.fill(input); + + // In the event of a partial fill, stay in the same state and wait for more data + if !act_three_builder.is_finished() { + assert_eq!(bytes_read, input.len()); + return Ok(( + None, + HandshakeState::ResponderAwaitingActThree(Self { + hash: self.hash, + responder_ephemeral_private_key: self.responder_ephemeral_private_key, + chaining_key: self.chaining_key, + temporary_key: self.temporary_key, + act_three_builder + }) + )); + } + + let hash = self.hash; + let temporary_key = self.temporary_key; + let responder_ephemeral_private_key = self.responder_ephemeral_private_key; + let chaining_key = self.chaining_key; + + // 1. Read exactly 66 bytes from the network buffer + let act_three_bytes = Act::from(act_three_builder); + assert_eq!(act_three_bytes.len(), ACT_THREE_LENGTH); + + // 2. Parse the read message (m) into v, c, and t + let version = act_three_bytes[0]; + let tagged_encrypted_pubkey = &act_three_bytes[1..50]; + let chacha_tag = &act_three_bytes[50..]; + + // 3. If v is an unrecognized handshake version, then the responder MUST abort the connection attempt. + if version != 0 { + // this should not crash the process, hence no panic + return Err("unexpected version".to_string()); + } + + // 4. rs = decryptWithAD(temp_k2, 1, h, c) + let mut remote_pubkey = [0; 33]; + chacha::decrypt(&temporary_key, 1, &hash, &tagged_encrypted_pubkey, &mut remote_pubkey)?; + let initiator_pubkey = if let Ok(public_key) = PublicKey::from_slice(&remote_pubkey) { + public_key + } else { + return Err("invalid remote public key".to_string()); + }; + + // 5. h = SHA-256(h || c) + let hash = concat_then_sha256!(hash, tagged_encrypted_pubkey); + + // 6. se = ECDH(e.priv, rs) + let ecdh = ecdh(&responder_ephemeral_private_key, &initiator_pubkey); + + // 7. ck, temp_k3 = HKDF(ck, se) + let (chaining_key, temporary_key) = hkdf5869rfc::derive(&chaining_key, &ecdh); + + // 8. p = decryptWithAD(temp_k3, 0, h, t) + chacha::decrypt(&temporary_key, 0, &hash, &chacha_tag, &mut [0; 0])?; + + // 9. rk, sk = HKDF(ck, zero) + let (receiving_key, sending_key) = hkdf5869rfc::derive(&chaining_key, &[0; 0]); + + // 10. rn = 0, sn = 0 + // - done by Conduit + let mut conduit = Conduit::new(sending_key, receiving_key, chaining_key); + + // Any remaining data in the read buffer would be encrypted, so transfer ownership + // to the Conduit for future use. + conduit.read(&input[bytes_read..]); + + Ok(( + None, + HandshakeState::Complete(Some((conduit, initiator_pubkey))) + )) + } +} + +// The handshake state always uses the responder's static public key. When running on the initiator, +// the initiator provides the remote's static public key and running on the responder they provide +// their own. +// https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#handshake-state-initialization +fn initialize_handshake_state(responder_static_public_key: &PublicKey) -> (Sha256, Sha256) { + let protocol_name = b"Noise_XK_secp256k1_ChaChaPoly_SHA256"; + let prologue = b"lightning"; + + // 1. h = SHA-256(protocolName) + // 2. ck = h + let chaining_key = concat_then_sha256!(protocol_name); + + // 3. h = SHA-256(h || prologue) + let hash = concat_then_sha256!(chaining_key, prologue); + + // h = SHA-256(h || responderPublicKey) + let hash = concat_then_sha256!(hash, responder_static_public_key.serialize()); + + (hash, chaining_key) +} + +// Due to the very high similarity of acts 1 and 2, this method is used to process both +// https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#act-one (sender) +// https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#act-two (sender) +fn calculate_act_message(local_private_ephemeral_key: &SecretKey, local_public_ephemeral_key: &PublicKey, remote_public_key: &PublicKey, chaining_key: ChainingKey, hash: Sha256, act_out: &mut [u8]) -> (Sha256, SymmetricKey, SymmetricKey) { + // 1. e = generateKey() (passed in) + // 2. h = SHA-256(h || e.pub.serializeCompressed()) + let serialized_local_public_key = local_public_ephemeral_key.serialize(); + let hash = concat_then_sha256!(hash, serialized_local_public_key); + + // 3. ACT1: es = ECDH(e.priv, rs) + // 3. ACT2: es = ECDH(e.priv, re) + let ecdh = ecdh(local_private_ephemeral_key, &remote_public_key); + + // 4. ACT1: ck, temp_k1 = HKDF(ck, es) + // 4. ACT2: ck, temp_k2 = HKDF(ck, ee) + let (chaining_key, temporary_key) = hkdf5869rfc::derive(&chaining_key, &ecdh); + + // 5. ACT1: c = encryptWithAD(temp_k1, 0, h, zero) + // 5. ACT2: c = encryptWithAD(temp_k2, 0, h, zero) + chacha::encrypt(&temporary_key, 0, &hash, &[0; 0], &mut act_out[34..]); + + // 6. h = SHA-256(h || c) + let hash = concat_then_sha256!(hash, &act_out[34..]); + + // Send m = 0 || e.pub.serializeCompressed() || c + act_out[0] = 0; + act_out[1..34].copy_from_slice(&serialized_local_public_key); + + (hash, chaining_key, temporary_key) +} + +// Due to the very high similarity of acts 1 and 2, this method is used to process both +// https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#act-one (receiver) +// https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#act-two (receiver) +fn process_act_message(act_bytes: &[u8], local_private_key: &SecretKey, chaining_key: ChainingKey, hash: Sha256) -> Result<(PublicKey, Sha256, SymmetricKey, SymmetricKey), String> { + // 1. Read exactly 50 bytes from the network buffer + // Partial act messages are handled by the callers. By the time it gets here, it + // must be the correct size. + assert_eq!(act_bytes.len(), ACT_ONE_LENGTH); + assert_eq!(act_bytes.len(), ACT_TWO_LENGTH); + + // 2.Parse the read message (m) into v, re, and c + let version = act_bytes[0]; + let ephemeral_public_key_bytes = &act_bytes[1..34]; + let chacha_tag = &act_bytes[34..]; + + let ephemeral_public_key = if let Ok(public_key) = PublicKey::from_slice(&ephemeral_public_key_bytes) { + public_key + } else { + return Err("invalid remote ephemeral public key".to_string()); + }; + + // 3. If v is an unrecognized handshake version, then the responder MUST abort the connection attempt + if version != 0 { + // this should not crash the process, hence no panic + return Err("unexpected version".to_string()); + } + + // 4. h = SHA-256(h || re.serializeCompressed()) + let hash = concat_then_sha256!(hash, ephemeral_public_key_bytes); + + // 5. Act1: es = ECDH(s.priv, re) + // 5. Act2: ee = ECDH(e.priv, ee) + let ecdh = ecdh(local_private_key, &ephemeral_public_key); + + // 6. Act1: ck, temp_k1 = HKDF(ck, es) + // 6. Act2: ck, temp_k2 = HKDF(ck, ee) + let (chaining_key, temporary_key) = hkdf5869rfc::derive(&chaining_key, &ecdh); + + // 7. Act1: p = decryptWithAD(temp_k1, 0, h, c) + // 7. Act2: p = decryptWithAD(temp_k2, 0, h, c) + chacha::decrypt(&temporary_key, 0, &hash, &chacha_tag, &mut [0; 0])?; + + // 8. h = SHA-256(h || c) + let hash = concat_then_sha256!(hash, chacha_tag); + + Ok((ephemeral_public_key, hash, chaining_key, temporary_key)) +} + +fn private_key_to_public_key(private_key: &SecretKey) -> PublicKey { + let curve = secp256k1::Secp256k1::new(); + let pk_object = PublicKey::from_secret_key(&curve, &private_key); + pk_object +} + +fn ecdh(private_key: &SecretKey, public_key: &PublicKey) -> SymmetricKey { + let curve = secp256k1::Secp256k1::new(); + let mut pk_object = public_key.clone(); + pk_object.mul_assign(&curve, &private_key[..]).expect("invalid multiplication"); + + let preimage = pk_object.serialize(); + concat_then_sha256!(preimage).into_inner() +} + +#[cfg(test)] +// Reference RFC test vectors for hard-coded values +// https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#appendix-a-transport-test-vectors +mod test { + use super::*; + use super::HandshakeState::*; + + use hex; + + use bitcoin::secp256k1; + use bitcoin::secp256k1::{PublicKey, SecretKey}; + + struct TestCtx { + initiator: HandshakeState, + initiator_public_key: PublicKey, + responder: HandshakeState, + responder_static_public_key: PublicKey, + valid_act1: Vec, + valid_act2: Vec, + valid_act3: Vec, + + } + + impl TestCtx { + fn new() -> Self { + let curve = secp256k1::Secp256k1::new(); + let initiator_static_private_key = SecretKey::from_slice(&[0x_11_u8; 32]).unwrap(); + let initiator_public_key = PublicKey::from_secret_key(&curve, &initiator_static_private_key); + let initiator_ephemeral_private_key = SecretKey::from_slice(&[0x_12_u8; 32]).unwrap(); + + let responder_static_private_key = SecretKey::from_slice(&[0x_21_u8; 32]).unwrap(); + let responder_static_public_key = PublicKey::from_secret_key(&curve, &responder_static_private_key); + let responder_ephemeral_private_key = SecretKey::from_slice(&[0x_22_u8; 32]).unwrap(); + + let initiator = InitiatorStartingState::new(initiator_static_private_key, initiator_ephemeral_private_key, responder_static_public_key); + let responder = ResponderAwaitingActOneState::new(responder_static_private_key, responder_ephemeral_private_key); + + TestCtx { + initiator: InitiatorStarting(initiator), + initiator_public_key, + responder: ResponderAwaitingActOne(responder), + responder_static_public_key, + valid_act1: hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap(), + valid_act2: hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap(), + valid_act3: hex::decode("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap() + } + } + } + + macro_rules! do_next_or_panic { + ($state:expr, $input:expr) => { + if let (Some(output_act), next_state) = $state.next($input).unwrap() { + (output_act, next_state) + } else { + panic!(); + } + } + } + + macro_rules! assert_matches { + ($e:expr, $state_match:pat) => { + match $e { + $state_match => (), + _ => panic!() + } + } + } + + // Initiator::Starting -> AwaitingActTwo + #[test] + fn starting_to_awaiting_act_two() { + let test_ctx = TestCtx::new(); + let (act1, awaiting_act_two_state) = do_next_or_panic!(test_ctx.initiator, &[]); + + assert_eq!(act1.as_ref(), test_ctx.valid_act1.as_slice()); + assert_matches!(awaiting_act_two_state, InitiatorAwaitingActTwo(_)); + } + + // Initiator::Starting -> AwaitingActTwo (extra bytes in argument) + #[test] + fn starting_to_awaiting_act_two_extra_bytes() { + let test_ctx = TestCtx::new(); + + assert_eq!(test_ctx.initiator.next(&[1]).err(), Some(String::from("first call for initiator must be empty"))); + } + + // Responder::AwaitingActOne -> AwaitingActThree + // RFC test vector: transport-responder successful handshake + #[test] + fn awaiting_act_one_to_awaiting_act_three() { + let test_ctx = TestCtx::new(); + let (act2, awaiting_act_three_state) = test_ctx.responder.next(&test_ctx.valid_act1).unwrap(); + + assert_eq!(act2.unwrap().as_ref(), test_ctx.valid_act2.as_slice()); + assert_matches!(awaiting_act_three_state, ResponderAwaitingActThree(_)); + } + + // Responder::AwaitingActOne -> AwaitingActThree (bad peer) + // Act2 requires data from the initiator. If we receive a payload for act1 that is larger than + // expected it indicates a bad peer + #[test] + fn awaiting_act_one_to_awaiting_act_three_input_extra_bytes() { + let test_ctx = TestCtx::new(); + let mut act1 = test_ctx.valid_act1; + act1.extend_from_slice(&[1]); + + assert_eq!(test_ctx.responder.next(&act1).err(), Some(String::from("Act One too large"))); + } + + // Responder::AwaitingActOne -> AwaitingActThree (segmented calls) + // RFC test vector: transport-responder act1 short read test + // Divergence from RFC tests due to not reading directly from the socket (partial message OK) + #[test] + fn awaiting_act_one_to_awaiting_act_three_segmented() { + let test_ctx = TestCtx::new(); + let act1_partial1 = &test_ctx.valid_act1[..25]; + let act1_partial2 = &test_ctx.valid_act1[25..]; + + let next_state = test_ctx.responder.next(&act1_partial1).unwrap(); + assert_matches!(next_state, (None, ResponderAwaitingActOne(_))); + assert_matches!(next_state.1.next(&act1_partial2).unwrap(), (Some(_), ResponderAwaitingActThree(_))); + } + + // Responder::AwaitingActOne -> Error (bad version byte) + // RFC test vector: transport-responder act1 bad version test + #[test] + fn awaiting_act_one_to_awaiting_act_three_input_bad_version() { + let test_ctx = TestCtx::new(); + let act1 = hex::decode("01036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap(); + + assert_eq!(test_ctx.responder.next(&act1).err(), Some(String::from("unexpected version"))); + } + + // Responder::AwaitingActOne -> Error (invalid remote ephemeral key) + // RFC test vector: transport-responder act1 bad key serialization test + #[test] + fn awaiting_act_one_to_awaiting_act_three_invalid_remote_ephemeral_key() { + let test_ctx = TestCtx::new(); + let act1 = hex::decode("00046360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a").unwrap(); + + assert_eq!(test_ctx.responder.next(&act1).err(), Some(String::from("invalid remote ephemeral public key"))); + } + + // Responder::AwaitingActOne -> Error (invalid hmac) + // RFC test vector: transport-responder act1 bad MAC test + #[test] + fn awaiting_act_one_to_awaiting_act_three_invalid_hmac() { + let test_ctx = TestCtx::new(); + let act1 = hex::decode("00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6b").unwrap(); + + assert_eq!(test_ctx.responder.next(&act1).err(), Some(String::from("invalid hmac"))); + } + + // Initiator::AwaitingActTwo -> Complete (bad peer) + // Initiator data is required to generate post-authentication messages. This means any extra + // data indicates a bad peer. + #[test] + fn awaiting_act_two_to_complete_extra_bytes() { + let test_ctx = TestCtx::new(); + let (_act1, awaiting_act_two_state) = do_next_or_panic!(test_ctx.initiator, &[]); + let mut act2 = test_ctx.valid_act2; + act2.extend_from_slice(&[1]); + + assert_eq!(awaiting_act_two_state.next(&act2).err(), Some(String::from("Act Two too large"))); + } + + // Initiator::AwaitingActTwo -> Complete + // RFC test vector: transport-initiator successful handshake + #[test] + fn awaiting_act_two_to_complete() { + let test_ctx = TestCtx::new(); + let (_act1, awaiting_act_two_state) = do_next_or_panic!(test_ctx.initiator, &[]); + let (act3, complete_state) = do_next_or_panic!(awaiting_act_two_state, &test_ctx.valid_act2); + + let (conduit, remote_pubkey) = if let Complete(Some((conduit, remote_pubkey))) = complete_state { + (conduit, remote_pubkey) + } else { + panic!(); + }; + + assert_eq!(act3.as_ref(), test_ctx.valid_act3.as_slice()); + assert_eq!(remote_pubkey, test_ctx.responder_static_public_key); + assert_eq!(0, conduit.decryptor.read_buffer_length()); + } + + // Initiator::AwaitingActTwo -> Complete (segmented calls) + // RFC test vector: transport-initiator act2 short read test + // Divergence from RFC tests due to not reading directly from the socket (partial message OK) + #[test] + fn awaiting_act_two_to_complete_segmented() { + let test_ctx = TestCtx::new(); + let (_act1, awaiting_act_two_state) = do_next_or_panic!(test_ctx.initiator, &[]); + + let act2_partial1 = &test_ctx.valid_act2[..25]; + let act2_partial2 = &test_ctx.valid_act2[25..]; + + let next_state = awaiting_act_two_state.next(&act2_partial1).unwrap(); + assert_matches!(next_state, (None, InitiatorAwaitingActTwo(_))); + assert_matches!(next_state.1.next(&act2_partial2).unwrap(), (Some(_), Complete(_))); + } + + // Initiator::AwaitingActTwo -> Error (bad version byte) + // RFC test vector: transport-initiator act2 bad version test + #[test] + fn awaiting_act_two_bad_version_byte() { + let test_ctx = TestCtx::new(); + let (_act1, awaiting_act_two_state) = do_next_or_panic!(test_ctx.initiator, &[]); + let act2 = hex::decode("0102466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap(); + + assert_eq!(awaiting_act_two_state.next(&act2).err(), Some(String::from("unexpected version"))); + } + + // Initiator::AwaitingActTwo -> Error (invalid ephemeral public key) + // RFC test vector: transport-initiator act2 bad key serialization test + #[test] + fn awaiting_act_two_invalid_ephemeral_public_key() { + let test_ctx = TestCtx::new(); + let (_act1, awaiting_act_two_state) = do_next_or_panic!(test_ctx.initiator, &[]); + let act2 = hex::decode("0004466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae").unwrap(); + + assert_eq!(awaiting_act_two_state.next(&act2).err(), Some(String::from("invalid remote ephemeral public key"))); + } + + // Initiator::AwaitingActTwo -> Error (invalid hmac) + // RFC test vector: transport-initiator act2 bad MAC test + #[test] + fn awaiting_act_two_invalid_hmac() { + let test_ctx = TestCtx::new(); + let (_act1, awaiting_act_two_state) = do_next_or_panic!(test_ctx.initiator, &[]); + let act2 = hex::decode("0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730af").unwrap(); + + assert_eq!(awaiting_act_two_state.next(&act2).err(), Some(String::from("invalid hmac"))); + } + + // Responder::AwaitingActThree -> Complete + // RFC test vector: transport-responder successful handshake + #[test] + fn awaiting_act_three_to_complete() { + let test_ctx = TestCtx::new(); + let (_act2, awaiting_act_three_state) = do_next_or_panic!(test_ctx.responder, &test_ctx.valid_act1); + + let (conduit, remote_pubkey) = if let (None, Complete(Some((conduit, remote_pubkey)))) = awaiting_act_three_state.next(&test_ctx.valid_act3).unwrap() { + (conduit, remote_pubkey) + } else { + panic!(); + }; + + assert_eq!(remote_pubkey, test_ctx.initiator_public_key); + assert_eq!(0, conduit.decryptor.read_buffer_length()); + } + + // Responder::AwaitingActThree -> None (with extra bytes) + // Ensures that any remaining data in the read buffer is transferred to the conduit once + // the handshake is complete + #[test] + fn awaiting_act_three_excess_bytes_after_complete_are_in_conduit() { + let test_ctx = TestCtx::new(); + let (_act2, awaiting_act_three_state) = do_next_or_panic!(test_ctx.responder, &test_ctx.valid_act1); + let mut act3 = test_ctx.valid_act3; + act3.extend_from_slice(&[2; 100]); + + let (conduit, remote_pubkey) = if let (None, Complete(Some((conduit, remote_pubkey)))) = awaiting_act_three_state.next(&act3).unwrap() { + (conduit, remote_pubkey) + } else { + panic!(); + }; + + assert_eq!(remote_pubkey, test_ctx.initiator_public_key); + assert_eq!(100, conduit.decryptor.read_buffer_length()); + } + + // Responder::AwaitingActThree -> Error (bad version bytes) + // RFC test vector: transport-responder act3 bad version test + #[test] + fn awaiting_act_three_bad_version_bytes() { + let test_ctx = TestCtx::new(); + let (_act2, awaiting_act_three_state) = do_next_or_panic!(test_ctx.responder, &test_ctx.valid_act1); + let act3 = hex::decode("01b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap(); + + assert_eq!(awaiting_act_three_state.next(&act3).err(), Some(String::from("unexpected version"))); + } + + // Responder::AwaitingActThree -> Complete (segmented calls) + // RFC test vector: transport-responder act3 short read test + // Divergence from RFC tests due to not reading directly from the socket (partial message OK) + #[test] + fn awaiting_act_three_to_complete_segmented() { + let test_ctx = TestCtx::new(); + let (_act2, awaiting_act_three_state) = do_next_or_panic!(test_ctx.responder, &test_ctx.valid_act1); + + let act3_partial1 = &test_ctx.valid_act3[..35]; + let act3_partial2 = &test_ctx.valid_act3[35..]; + + let next_state = awaiting_act_three_state.next(&act3_partial1).unwrap(); + assert_matches!(next_state, (None, ResponderAwaitingActThree(_))); + assert_matches!(next_state.1.next(&act3_partial2), Ok((None, Complete(_)))); + } + + // Responder::AwaitingActThree -> Error (invalid hmac) + // RFC test vector: transport-responder act3 bad MAC for ciphertext test + #[test] + fn awaiting_act_three_invalid_hmac() { + let test_ctx = TestCtx::new(); + let (_act2, awaiting_act_three_state) = do_next_or_panic!(test_ctx.responder, &test_ctx.valid_act1); + let act3 = hex::decode("00c9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba").unwrap(); + + assert_eq!(awaiting_act_three_state.next(&act3).err(), Some(String::from("invalid hmac"))); + } + + // Responder::AwaitingActThree -> Error (invalid remote_static_key) + // RFC test vector: transport-responder act3 bad rs test + #[test] + fn awaiting_act_three_invalid_rs() { + let test_ctx = TestCtx::new(); + let (_act2, awaiting_act_three_state) = do_next_or_panic!(test_ctx.responder, &test_ctx.valid_act1); + let act3 = hex::decode("00bfe3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa2235536ad09a8ee351870c2bb7f78b754a26c6cef79a98d25139c856d7efd252c2ae73c").unwrap(); + + assert_eq!(awaiting_act_three_state.next(&act3).err(), Some(String::from("invalid remote public key"))); + } + + // Responder::AwaitingActThree -> Error (invalid tag hmac) + // RFC test vector: transport-responder act3 bad MAC test + #[test] + fn awaiting_act_three_invalid_tag_hmac() { + let test_ctx = TestCtx::new(); + let (_act2, awaiting_act_three_state) = do_next_or_panic!(test_ctx.responder, &test_ctx.valid_act1); + let act3 = hex::decode("00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139bb").unwrap(); + + assert_eq!(awaiting_act_three_state.next(&act3).err(), Some(String::from("invalid hmac"))); + } + + // Initiator::Complete -> Error + #[test] + #[should_panic(expected = "no acts left to process")] + fn initiator_complete_next_fail() { + let test_ctx = TestCtx::new(); + let (act1, awaiting_act_two_state) = do_next_or_panic!(test_ctx.initiator, &[]); + let (act2, _awaiting_act_three_state) = do_next_or_panic!(test_ctx.responder, &act1); + let (_act3, complete_state) = do_next_or_panic!(awaiting_act_two_state, &act2); + + complete_state.next(&[]).unwrap(); + } + + // Initiator::Complete -> Error + #[test] + #[should_panic(expected = "no acts left to process")] + fn responder_complete_next_fail() { + let test_ctx = TestCtx::new(); + let (act1, awaiting_act_two_state) = do_next_or_panic!(test_ctx.initiator, &[]); + let (act2, awaiting_act_three_state) = do_next_or_panic!(test_ctx.responder, &act1); + let (act3, _complete_state) = do_next_or_panic!(awaiting_act_two_state, &act2); + + let complete_state = if let (None, complete_state) = awaiting_act_three_state.next(&act3).unwrap() { + complete_state + } else { + panic!(); + }; + + complete_state.next(&[]).unwrap(); + } + + // Test the Act byte generation against known good hard-coded values in case the implementation + // changes in a symmetric way that makes the other tests useless + #[test] + fn test_acts_against_reference_bytes() { + let test_ctx = TestCtx::new(); + let (act1, awaiting_act_two_state) = do_next_or_panic!(test_ctx.initiator, &[]); + let (act2, _awaiting_act_three_state) = do_next_or_panic!(test_ctx.responder, &act1); + let (act3, _complete_state) = do_next_or_panic!(awaiting_act_two_state, &act2); + + assert_eq!(hex::encode(&act1), + "00036360e856310ce5d294e8be33fc807077dc56ac80d95d9cd4ddbd21325eff73f70df6086551151f58b8afe6c195782c6a"); + assert_eq!(hex::encode(&act2), + "0002466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f276e2470b93aac583c9ef6eafca3f730ae"); + assert_eq!(hex::encode(&act3), + "00b9e3a702e93e3a9948c2ed6e5fd7590a6e1c3a0344cfc9d5b57357049aa22355361aa02e55a8fc28fef5bd6d71ad0c38228dc68b1c466263b47fdf31e560e139ba"); + } +} + diff --git a/lightning/src/ln/peers/hkdf5869rfc.rs b/lightning/src/ln/peers/hkdf5869rfc.rs new file mode 100644 index 00000000000..1d9f66ab1cb --- /dev/null +++ b/lightning/src/ln/peers/hkdf5869rfc.rs @@ -0,0 +1,80 @@ +// This file is Copyright its original authors, visible in version control +// history. +// +// 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. + +use bitcoin::hashes::{Hash, HashEngine, Hmac, HmacEngine}; +use bitcoin::hashes::sha256::Hash as Sha256; + +// Allows 1 or more inputs and "concatenates" them together using the input() function +// of HmacEngine:: +macro_rules! hmac_sha256 { + ( $salt:expr, ($( $input:expr ),+ )) => {{ + let mut engine = HmacEngine::::new($salt); + $( + engine.input($input); + )+ + Hmac::from_engine(engine).into_inner() + }} +} + +/// Implements HKDF defined in [BOLT #8](https://github.com/lightningnetwork/lightning-rfc/blob/master/08-transport.md#handshake-state) +/// [RFC 5869](https://tools.ietf.org/html/rfc5869pub) +/// Returns the first 64 octets as two 32 byte arrays +pub(super) fn derive(salt: &[u8], ikm: &[u8]) -> ([u8; 32], [u8; 32]) { + // 2.1. Notation + // + // HMAC-Hash denotes the HMAC function [HMAC] instantiated with hash + // function 'Hash'. HMAC always has two arguments: the first is a key + // and the second an input (or message). (Note that in the extract + // step, 'IKM' is used as the HMAC input, not as the HMAC key.) + // + // When the message is composed of several elements we use concatenation + // (denoted |) in the second argument; for example, HMAC(K, elem1 | + // elem2 | elem3). + + // 2.2. Step 1: Extract + // HKDF-Extract(salt, IKM) -> PRK + // PRK = HMAC-Hash(salt, IKM) + let prk = hmac_sha256!(salt, (ikm)); + + // 2.3. Step 2: Expand + // HKDF-Expand(PRK, info, L) -> OKM + // N = ceil(L/HashLen) + // T = T(1) | T(2) | T(3) | ... | T(N) + // OKM = first L octets of T + // + // where: + // T(0) = empty string (zero length) + // T(1) = HMAC-Hash(PRK, T(0) | info | 0x01) + let t1 = hmac_sha256!(&prk, (&[1])); + // T(2) = HMAC-Hash(PRK, T(1) | info | 0x02) + let t2 = hmac_sha256!(&prk, (&t1, &[2])); + + return (t1, t2) +} + +// Appendix A. Test Vectors +#[cfg(test)] +mod test { + use hex; + use ln::peers::hkdf5869rfc::derive; + + // Test with SHA-256 and zero-length salt/info + // Our implementation uses a zero-length info field and returns the first 64 octets. As a result, + // this test will be a prefix match on the vector provided by the RFC which is 42 bytes. + #[test] + fn rfc_5869_test_vector_3() { + let ikm = hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap(); + let (t1, t2) = derive(&[], &ikm); + + let mut calculated_okm = t1.to_vec(); + calculated_okm.extend_from_slice(&t2); + calculated_okm.truncate(42); + assert_eq!(calculated_okm, hex::decode("8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8").unwrap()); + } +} \ No newline at end of file diff --git a/lightning/src/ln/peers/mod.rs b/lightning/src/ln/peers/mod.rs new file mode 100644 index 00000000000..5c10e56657c --- /dev/null +++ b/lightning/src/ln/peers/mod.rs @@ -0,0 +1,27 @@ +// This file is Copyright its original authors, visible in version control +// history. +// +// 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. + +//! Everything that has to do with over-the-wire peer communication. +//! The handshake module exposes mechanisms to conduct inbound and outbound handshakes. +//! When a handshake completes, it returns an instance of Conduit. +//! Conduit enables message encryption and decryption, and automatically handles key rotation. + +mod chacha; +pub mod handler; +mod hkdf5869rfc; + +#[cfg(feature = "fuzztarget")] +pub mod conduit; +#[cfg(not(feature = "fuzztarget"))] +mod conduit; + +#[cfg(feature = "fuzztarget")] +pub mod handshake; +#[cfg(not(feature = "fuzztarget"))] +mod handshake;