Skip to content

Commit 5c4cda7

Browse files
committed
fix: Don't panic during valid decryption states
introduced: 6185a28 The decryption path uses a read buffer to concatenate partial encrypted message payloads. The read buffer size can grow larger than LN_MAX_PACKET_LENGTH momentarily as the new bytes are added to the read buffer, but before decryption starts. Fix the invalid panic() and add a test
1 parent 8ce13c2 commit 5c4cda7

File tree

1 file changed

+33
-13
lines changed

1 file changed

+33
-13
lines changed

lightning/src/ln/peers/encryption.rs

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ pub(super) type SymmetricKey = [u8; 32];
99
/// Maximum Lightning message data length according to
1010
/// [BOLT-8](https://github.com/lightningnetwork/lightning-rfc/blob/v1.0/08-transport.md#lightning-message-specification)
1111
/// and [BOLT-1](https://github.com/lightningnetwork/lightning-rfc/blob/master/01-messaging.md#lightning-message-format):
12-
const LN_MAX_MSG_LEN: usize = ::std::u16::MAX as usize; // Must be equal to 65535
12+
const LN_MAX_MSG_LEN: usize = 65535;
13+
const LN_MAX_PACKET_LENGTH: usize = MESSAGE_LENGTH_HEADER_SIZE + chacha::TAG_SIZE + LN_MAX_MSG_LEN + chacha::TAG_SIZE;
1314

1415
const MESSAGE_LENGTH_HEADER_SIZE: usize = 2;
1516
const TAGGED_MESSAGE_LENGTH_HEADER_SIZE: usize = MESSAGE_LENGTH_HEADER_SIZE + chacha::TAG_SIZE;
@@ -76,7 +77,7 @@ impl Iterator for Decryptor {
7677
impl Encryptor {
7778
pub fn encrypt(&mut self, buffer: &[u8]) -> Vec<u8> {
7879
if buffer.len() > LN_MAX_MSG_LEN {
79-
panic!("Attempted to encrypt message longer than 65535 bytes!");
80+
panic!("Attempted to encrypt message longer than {} bytes!", LN_MAX_MSG_LEN);
8081
}
8182

8283
let length = buffer.len() as u16;
@@ -131,16 +132,19 @@ impl Decryptor {
131132
}
132133
}
133134

135+
// If we ever get to the end of the decryption phase and have more data in the read buffer
136+
// than is possible for a valid message something has gone wrong. An error with a mismatched
137+
// length and payload should result an error from the decryption code before we get here.
138+
if self.read_buffer.as_ref().unwrap().len() > LN_MAX_PACKET_LENGTH {
139+
panic!("Encrypted message data longer than {}", LN_MAX_PACKET_LENGTH);
140+
}
141+
134142
Ok(())
135143
}
136144

137145
// Decrypt the next payload from the slice returning the number of bytes consumed during the
138146
// operation. This will always be (None, 0) if no payload could be decrypted.
139147
fn decrypt_next(&mut self, buffer: &[u8]) -> Result<(Option<Vec<u8>>, usize), String> {
140-
if buffer.len() > LN_MAX_MSG_LEN + 16 {
141-
panic!("Attempted to decrypt message longer than 65535 + 16 bytes!");
142-
}
143-
144148
let message_length = if let Some(length) = self.pending_message_length {
145149
// we have already decrypted the header
146150
length
@@ -360,9 +364,10 @@ mod tests {
360364
}
361365

362366
#[test]
367+
// https://github.com/lightningnetwork/lightning-rfc/blob/v1.0/08-transport.md#lightning-message-specification
363368
fn max_msg_len_limit_value() {
364369
assert_eq!(LN_MAX_MSG_LEN, 65535);
365-
assert_eq!(LN_MAX_MSG_LEN, ::std::u16::MAX as usize);
370+
assert_eq!(LN_MAX_PACKET_LENGTH, 65569);
366371
}
367372

368373
#[test]
@@ -373,13 +378,28 @@ mod tests {
373378
let _should_panic = connected_encryptor.encrypt(&msg);
374379
}
375380

381+
// Test that the decryptor can handle multiple partial reads() that result in a total size
382+
// larger than LN_MAX_PACKET_LENGTH and still decrypt the messages.
376383
#[test]
377-
#[should_panic(expected = "Attempted to decrypt message longer than 65535 + 16 bytes!")]
378-
fn max_message_len_decryption() {
379-
let (_, (_, mut remote_decryptor)) = setup_peers();
384+
fn read_buffer_can_grow_over_max_payload_len() {
385+
let ((mut connected_encryptor, _), ( _, mut remote_decryptor)) = setup_peers();
386+
let msg1 = [1u8; LN_MAX_MSG_LEN];
387+
let msg2 = [2u8; LN_MAX_MSG_LEN];
388+
389+
let encrypted1 = connected_encryptor.encrypt(&msg1);
390+
let encrypted2 = connected_encryptor.encrypt(&msg2);
391+
392+
let read1 = &encrypted1[..1];
393+
let mut read2 = vec![];
394+
read2.extend_from_slice(&encrypted1[1..]);
395+
read2.extend_from_slice(&encrypted2);
396+
397+
remote_decryptor.read(read1).unwrap();
398+
assert_eq!(remote_decryptor.next(), None);
399+
400+
remote_decryptor.read(&read2[..]).unwrap();
380401

381-
// MSG should not exceed LN_MAX_MSG_LEN + 16
382-
let msg = [4u8; LN_MAX_MSG_LEN + 17];
383-
remote_decryptor.read(&msg).unwrap();
402+
assert_eq!(remote_decryptor.next(), Some(msg1.to_vec()));
403+
assert_eq!(remote_decryptor.next(), Some(msg2.to_vec()));
384404
}
385405
}

0 commit comments

Comments
 (0)