Skip to content

Commit 62820fe

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 f4c76a9 commit 62820fe

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
@@ -18,7 +18,8 @@ pub(super) type SymmetricKey = [u8; 32];
1818
/// Maximum Lightning message data length according to
1919
/// [BOLT-8](https://github.com/lightningnetwork/lightning-rfc/blob/v1.0/08-transport.md#lightning-message-specification)
2020
/// and [BOLT-1](https://github.com/lightningnetwork/lightning-rfc/blob/master/01-messaging.md#lightning-message-format):
21-
const LN_MAX_MSG_LEN: usize = ::std::u16::MAX as usize; // Must be equal to 65535
21+
const LN_MAX_MSG_LEN: usize = 65535;
22+
const LN_MAX_PACKET_LENGTH: usize = MESSAGE_LENGTH_HEADER_SIZE + chacha::TAG_SIZE + LN_MAX_MSG_LEN + chacha::TAG_SIZE;
2223

2324
const MESSAGE_LENGTH_HEADER_SIZE: usize = 2;
2425
const TAGGED_MESSAGE_LENGTH_HEADER_SIZE: usize = MESSAGE_LENGTH_HEADER_SIZE + chacha::TAG_SIZE;
@@ -85,7 +86,7 @@ impl Iterator for Decryptor {
8586
impl Encryptor {
8687
pub fn encrypt(&mut self, buffer: &[u8]) -> Vec<u8> {
8788
if buffer.len() > LN_MAX_MSG_LEN {
88-
panic!("Attempted to encrypt message longer than 65535 bytes!");
89+
panic!("Attempted to encrypt message longer than {} bytes!", LN_MAX_MSG_LEN);
8990
}
9091

9192
let length = buffer.len() as u16;
@@ -140,16 +141,19 @@ impl Decryptor {
140141
}
141142
}
142143

144+
// If we ever get to the end of the decryption phase and have more data in the read buffer
145+
// than is possible for a valid message something has gone wrong. An error with a mismatched
146+
// length and payload should result an error from the decryption code before we get here.
147+
if self.read_buffer.as_ref().unwrap().len() > LN_MAX_PACKET_LENGTH {
148+
panic!("Encrypted message data longer than {}", LN_MAX_PACKET_LENGTH);
149+
}
150+
143151
Ok(())
144152
}
145153

146154
// Decrypt the next payload from the slice returning the number of bytes consumed during the
147155
// operation. This will always be (None, 0) if no payload could be decrypted.
148156
fn decrypt_next(&mut self, buffer: &[u8]) -> Result<(Option<Vec<u8>>, usize), String> {
149-
if buffer.len() > LN_MAX_MSG_LEN + 16 {
150-
panic!("Attempted to decrypt message longer than 65535 + 16 bytes!");
151-
}
152-
153157
let message_length = if let Some(length) = self.pending_message_length {
154158
// we have already decrypted the header
155159
length
@@ -369,9 +373,10 @@ mod tests {
369373
}
370374

371375
#[test]
376+
// https://github.com/lightningnetwork/lightning-rfc/blob/v1.0/08-transport.md#lightning-message-specification
372377
fn max_msg_len_limit_value() {
373378
assert_eq!(LN_MAX_MSG_LEN, 65535);
374-
assert_eq!(LN_MAX_MSG_LEN, ::std::u16::MAX as usize);
379+
assert_eq!(LN_MAX_PACKET_LENGTH, 65569);
375380
}
376381

377382
#[test]
@@ -382,13 +387,28 @@ mod tests {
382387
let _should_panic = connected_encryptor.encrypt(&msg);
383388
}
384389

390+
// Test that the decryptor can handle multiple partial reads() that result in a total size
391+
// larger than LN_MAX_PACKET_LENGTH and still decrypt the messages.
385392
#[test]
386-
#[should_panic(expected = "Attempted to decrypt message longer than 65535 + 16 bytes!")]
387-
fn max_message_len_decryption() {
388-
let (_, (_, mut remote_decryptor)) = setup_peers();
393+
fn read_buffer_can_grow_over_max_payload_len() {
394+
let ((mut connected_encryptor, _), ( _, mut remote_decryptor)) = setup_peers();
395+
let msg1 = [1u8; LN_MAX_MSG_LEN];
396+
let msg2 = [2u8; LN_MAX_MSG_LEN];
397+
398+
let encrypted1 = connected_encryptor.encrypt(&msg1);
399+
let encrypted2 = connected_encryptor.encrypt(&msg2);
400+
401+
let read1 = &encrypted1[..1];
402+
let mut read2 = vec![];
403+
read2.extend_from_slice(&encrypted1[1..]);
404+
read2.extend_from_slice(&encrypted2);
405+
406+
remote_decryptor.read(read1).unwrap();
407+
assert_eq!(remote_decryptor.next(), None);
408+
409+
remote_decryptor.read(&read2[..]).unwrap();
389410

390-
// MSG should not exceed LN_MAX_MSG_LEN + 16
391-
let msg = [4u8; LN_MAX_MSG_LEN + 17];
392-
remote_decryptor.read(&msg).unwrap();
411+
assert_eq!(remote_decryptor.next(), Some(msg1.to_vec()));
412+
assert_eq!(remote_decryptor.next(), Some(msg2.to_vec()));
393413
}
394414
}

0 commit comments

Comments
 (0)