]> git.bitcoin.ninja Git - rust-lightning/blob - fuzz/src/onion_message.rs
Merge pull request #1810 from TheBlueMatt/2022-10-112-bindings-base
[rust-lightning] / fuzz / src / onion_message.rs
1 // Imports that need to be added manually
2 use bitcoin::bech32::u5;
3 use bitcoin::blockdata::script::Script;
4 use bitcoin::secp256k1::{PublicKey, Scalar, SecretKey};
5 use bitcoin::secp256k1::ecdh::SharedSecret;
6 use bitcoin::secp256k1::ecdsa::RecoverableSignature;
7
8 use lightning::chain::keysinterface::{Recipient, KeyMaterial, KeysInterface};
9 use lightning::ln::msgs::{self, DecodeError, OnionMessageHandler};
10 use lightning::ln::script::ShutdownScript;
11 use lightning::util::enforcing_trait_impls::EnforcingSigner;
12 use lightning::util::logger::Logger;
13 use lightning::util::ser::{Readable, Writeable, Writer};
14 use lightning::onion_message::packet::CustomOnionMessageContents;
15 use lightning::onion_message::messenger::{OnionMessenger, CustomOnionMessageHandler};
16
17 use crate::utils::test_logger;
18
19 use std::io::{self, Cursor};
20 use std::sync::atomic::{AtomicU64, Ordering};
21
22 #[inline]
23 /// Actual fuzz test, method signature and name are fixed
24 pub fn do_test<L: Logger>(data: &[u8], logger: &L) {
25         if let Ok(msg) = <msgs::OnionMessage as Readable>::read(&mut Cursor::new(data)) {
26                 let mut secret_bytes = [0; 32];
27                 secret_bytes[31] = 2;
28                 let secret = SecretKey::from_slice(&secret_bytes).unwrap();
29                 let keys_manager = KeyProvider {
30                         node_secret: secret,
31                         counter: AtomicU64::new(0),
32                 };
33                 let custom_msg_handler = TestCustomMessageHandler {};
34                 let onion_messenger = OnionMessenger::new(&keys_manager, logger, &custom_msg_handler);
35                 let mut pk = [2; 33]; pk[1] = 0xff;
36                 let peer_node_id_not_used = PublicKey::from_slice(&pk).unwrap();
37                 onion_messenger.handle_onion_message(&peer_node_id_not_used, &msg);
38         }
39 }
40
41 /// Method that needs to be added manually, {name}_test
42 pub fn onion_message_test<Out: test_logger::Output>(data: &[u8], out: Out) {
43         let logger = test_logger::TestLogger::new("".to_owned(), out);
44         do_test(data, &logger);
45 }
46
47 /// Method that needs to be added manually, {name}_run
48 #[no_mangle]
49 pub extern "C" fn onion_message_run(data: *const u8, datalen: usize) {
50         let logger = test_logger::TestLogger::new("".to_owned(), test_logger::DevNull {});
51         do_test(unsafe { std::slice::from_raw_parts(data, datalen) }, &logger);
52 }
53
54 struct TestCustomMessage {}
55
56 const CUSTOM_MESSAGE_TYPE: u64 = 4242;
57 const CUSTOM_MESSAGE_CONTENTS: [u8; 32] = [42; 32];
58
59 impl CustomOnionMessageContents for TestCustomMessage {
60         fn tlv_type(&self) -> u64 {
61                 CUSTOM_MESSAGE_TYPE
62         }
63 }
64
65 impl Writeable for TestCustomMessage {
66         fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
67                 Ok(CUSTOM_MESSAGE_CONTENTS.write(w)?)
68         }
69 }
70
71 struct TestCustomMessageHandler {}
72
73 impl CustomOnionMessageHandler for TestCustomMessageHandler {
74         type CustomMessage = TestCustomMessage;
75         fn handle_custom_message(&self, _msg: Self::CustomMessage) {}
76         fn read_custom_message<R: io::Read>(&self, _message_type: u64, buffer: &mut R) -> Result<Option<Self::CustomMessage>, msgs::DecodeError> {
77                 let mut buf = Vec::new();
78                 buffer.read_to_end(&mut buf)?;
79                 return Ok(Some(TestCustomMessage {}))
80         }
81 }
82
83 pub struct VecWriter(pub Vec<u8>);
84 impl Writer for VecWriter {
85         fn write_all(&mut self, buf: &[u8]) -> Result<(), ::std::io::Error> {
86                 self.0.extend_from_slice(buf);
87                 Ok(())
88         }
89 }
90 struct KeyProvider {
91         node_secret: SecretKey,
92         counter: AtomicU64,
93 }
94 impl KeysInterface for KeyProvider {
95         type Signer = EnforcingSigner;
96
97         fn get_node_secret(&self, _recipient: Recipient) -> Result<SecretKey, ()> {
98                 Ok(self.node_secret.clone())
99         }
100
101         fn ecdh(&self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>) -> Result<SharedSecret, ()> {
102                 let mut node_secret = self.get_node_secret(recipient)?;
103                 if let Some(tweak) = tweak {
104                         node_secret = node_secret.mul_tweak(tweak).map_err(|_| ())?;
105                 }
106                 Ok(SharedSecret::new(other_key, &node_secret))
107         }
108
109         fn get_inbound_payment_key_material(&self) -> KeyMaterial { unreachable!() }
110
111         fn get_destination_script(&self) -> Script { unreachable!() }
112
113         fn get_shutdown_scriptpubkey(&self) -> ShutdownScript { unreachable!() }
114
115         fn get_channel_signer(&self, _inbound: bool, _channel_value_satoshis: u64) -> EnforcingSigner {
116                 unreachable!()
117         }
118
119         fn get_secure_random_bytes(&self) -> [u8; 32] {
120                 let ctr = self.counter.fetch_add(1, Ordering::Relaxed);
121                 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
122                 (ctr >> 8*7) as u8, (ctr >> 8*6) as u8, (ctr >> 8*5) as u8, (ctr >> 8*4) as u8, (ctr >> 8*3) as u8, (ctr >> 8*2) as u8, (ctr >> 8*1) as u8, 14, (ctr >> 8*0) as u8]
123         }
124
125         fn read_chan_signer(&self, _data: &[u8]) -> Result<EnforcingSigner, DecodeError> { unreachable!() }
126
127         fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result<RecoverableSignature, ()> {
128                 unreachable!()
129         }
130 }
131
132 #[cfg(test)]
133 mod tests {
134         use lightning::util::logger::{Logger, Record};
135         use std::collections::HashMap;
136         use std::sync::Mutex;
137
138         struct TrackingLogger {
139                 /// (module, message) -> count
140                 pub lines: Mutex<HashMap<(String, String), usize>>,
141         }
142         impl Logger for TrackingLogger {
143                 fn log(&self, record: &Record) {
144                         *self.lines.lock().unwrap().entry((record.module_path.to_string(), format!("{}", record.args))).or_insert(0) += 1;
145                         println!("{:<5} [{} : {}, {}] {}", record.level.to_string(), record.module_path, record.file, record.line, record.args);
146                 }
147         }
148
149         #[test]
150         fn test_no_onion_message_breakage() {
151                 let one_hop_om = "020000000000000000000000000000000000000000000000000000000000000e01055600020000000000000000000000000000000000000000000000000000000000000e0136041095000000000000000000000000000000fd1092202a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e800000000000000000000000000000000000000000000000000000000000000";
152                 let logger = TrackingLogger { lines: Mutex::new(HashMap::new()) };
153                 super::do_test(&::hex::decode(one_hop_om).unwrap(), &logger);
154                 {
155                         let log_entries = logger.lines.lock().unwrap();
156                         assert_eq!(log_entries.get(&("lightning::onion_message::messenger".to_string(),
157                                                 "Received an onion message with path_id None and no reply_path".to_string())), Some(&1));
158                 }
159
160                 let two_unblinded_hops_om = "020000000000000000000000000000000000000000000000000000000000000e01055600020000000000000000000000000000000000000000000000000000000000000e0135043304210200000000000000000000000000000000000000000000000000000000000000029500000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000003604104b000000000000000000000000000000fd1092202a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b200000000000000000000000000000000000000000000000000000000000000";
161                 let logger = TrackingLogger { lines: Mutex::new(HashMap::new()) };
162                 super::do_test(&::hex::decode(two_unblinded_hops_om).unwrap(), &logger);
163                 {
164                         let log_entries = logger.lines.lock().unwrap();
165                         assert_eq!(log_entries.get(&("lightning::onion_message::messenger".to_string(), "Forwarding an onion message to peer 020000000000000000000000000000000000000000000000000000000000000002".to_string())), Some(&1));
166                 }
167
168                 let two_unblinded_two_blinded_om = "020000000000000000000000000000000000000000000000000000000000000e01055600020000000000000000000000000000000000000000000000000000000000000e01350433042102000000000000000000000000000000000000000000000000000000000000000295000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000058045604210200000000000000000000000000000000000000000000000000000000000000020821020000000000000000000000000000000000000000000000000000000000000e014b000000000000000000000000000000b20000000000000000000000000000000000000000000000000000000000000035043304210200000000000000000000000000000000000000000000000000000000000000029500000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000003604104b000000000000000000000000000000fd1092202a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b200000000000000000000000000000000000000000000000000000000000000";
169                 let logger = TrackingLogger { lines: Mutex::new(HashMap::new()) };
170                 super::do_test(&::hex::decode(two_unblinded_two_blinded_om).unwrap(), &logger);
171                 {
172                         let log_entries = logger.lines.lock().unwrap();
173                         assert_eq!(log_entries.get(&("lightning::onion_message::messenger".to_string(), "Forwarding an onion message to peer 020000000000000000000000000000000000000000000000000000000000000002".to_string())), Some(&1));
174                 }
175
176                 let three_blinded_om = "020000000000000000000000000000000000000000000000000000000000000e01055600020000000000000000000000000000000000000000000000000000000000000e013504330421020000000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000035043304210200000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000ac00000000000000000000000000000000000000000000000000000000000000360410d1000000000000000000000000000000fd1092202a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b200000000000000000000000000000000000000000000000000000000000000";
177                 let logger = TrackingLogger { lines: Mutex::new(HashMap::new()) };
178                 super::do_test(&::hex::decode(three_blinded_om).unwrap(), &logger);
179                 {
180                         let log_entries = logger.lines.lock().unwrap();
181                         assert_eq!(log_entries.get(&("lightning::onion_message::messenger".to_string(), "Forwarding an onion message to peer 020000000000000000000000000000000000000000000000000000000000000002".to_string())), Some(&1));
182                 }
183         }
184 }