Skip to content

Commit

Permalink
Error if onion payloads exceed max length on packet construction.
Browse files Browse the repository at this point in the history
Ensure that if we call construct_onion_packet and friends where payloads are
too large for the allotted packet length, we'll fail to construct. Previously,
senders would happily construct invalid packets by array-shifting the final
node's HMAC out of the packet when adding an intermediate onion layer, causing
the receiver to error with "final payload provided for us as an intermediate
node."
  • Loading branch information
valentinewallace committed Dec 8, 2023
1 parent e9bd893 commit 80ba9ac
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 3 deletions.
34 changes: 33 additions & 1 deletion lightning/src/ln/onion_payment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ pub(super) fn check_incoming_htlc_cltv(
mod tests {
use bitcoin::hashes::Hash;
use bitcoin::hashes::sha256::Hash as Sha256;
use bitcoin::secp256k1::{PublicKey, SecretKey};
use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
use crate::ln::{PaymentPreimage, PaymentHash, PaymentSecret};
use crate::ln::ChannelId;
use crate::ln::channelmanager::RecipientOnionFields;
Expand All @@ -459,6 +459,38 @@ mod tests {
use crate::routing::router::{Path, RouteHop};
use crate::util::test_utils;

#[test]
fn fail_construct_onion_on_too_big_payloads() {
// Ensure that if we call `construct_onion_packet` and friends where payloads are too large for
// the allotted packet length, we'll fail to construct. Previously, senders would happily
// construct invalid packets by array-shifting the final node's HMAC out of the packet when
// adding an intermediate onion layer, causing the receiver to error with "final payload
// provided for us as an intermediate node."
let secp_ctx = Secp256k1::new();
let bob = crate::sign::KeysManager::new(&[2; 32], 42, 42);
let bob_pk = PublicKey::from_secret_key(&secp_ctx, &bob.get_node_secret_key());
let charlie = crate::sign::KeysManager::new(&[3; 32], 42, 42);
let charlie_pk = PublicKey::from_secret_key(&secp_ctx, &charlie.get_node_secret_key());

let (
session_priv, total_amt_msat, cur_height, mut recipient_onion, keysend_preimage, payment_hash,
prng_seed, hops, ..
) = payment_onion_args(bob_pk, charlie_pk);

// Ensure the onion will not fit all the payloads by adding a large custom TLV.
recipient_onion.custom_tlvs.push((13377331, vec![0; 1156]));

let path = Path { hops, blinded_tail: None, };
let onion_keys = super::onion_utils::construct_onion_keys(&secp_ctx, &path, &session_priv).unwrap();
let (onion_payloads, ..) = super::onion_utils::build_onion_payloads(
&path, total_amt_msat, recipient_onion, cur_height + 1, &Some(keysend_preimage)
).unwrap();

assert!(super::onion_utils::construct_onion_packet(
onion_payloads, onion_keys, prng_seed, &payment_hash
).is_err());
}

#[test]
fn test_peel_payment_onion() {
use super::*;
Expand Down
4 changes: 2 additions & 2 deletions lightning/src/ln/onion_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,8 +323,6 @@ fn construct_onion_packet_with_init_noise<HD: Writeable, P: Packet>(

let mut pos = 0;
for (i, (payload, keys)) in payloads.iter().zip(onion_keys.iter()).enumerate() {
if i == payloads.len() - 1 { break; }

let mut chacha = ChaCha20::new(&keys.rho, &[0u8; 8]);
for _ in 0..(packet_data.len() - pos) { // TODO: Batch this.
let mut dummy = [0; 1];
Expand All @@ -338,6 +336,8 @@ fn construct_onion_packet_with_init_noise<HD: Writeable, P: Packet>(
return Err(());
}

if i == payloads.len() - 1 { break; }

res.resize(pos, 0u8);
chacha.process_in_place(&mut res);
}
Expand Down

0 comments on commit 80ba9ac

Please sign in to comment.