Skip to content

Commit a2c59c3

Browse files
Add BlindedRoute Control Tlvs Padding
1 parent 6772609 commit a2c59c3

File tree

5 files changed

+151
-28
lines changed

5 files changed

+151
-28
lines changed

lightning/src/onion_message/blinded_route.rs

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@ use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey};
1313

1414
use chain::keysinterface::KeysInterface;
1515
use super::utils;
16+
use ::get_control_tlv_length;
1617
use ln::msgs::DecodeError;
1718
use util::chacha20poly1305rfc::ChaChaPolyWriteAdapter;
1819
use util::ser::{Readable, VecWriter, Writeable, Writer};
20+
use super::packet::{ControlTlvs, Padding};
1921

2022
use io;
2123
use prelude::*;
@@ -54,10 +56,11 @@ impl BlindedRoute {
5456
/// will be the destination node.
5557
///
5658
/// Errors if less than two hops are provided or if `node_pk`(s) are invalid.
57-
// TODO: make all payloads the same size with padding + add dummy hops
58-
pub fn new<K: KeysInterface, T: secp256k1::Signing + secp256k1::Verification>
59-
(node_pks: &[PublicKey], keys_manager: &K, secp_ctx: &Secp256k1<T>) -> Result<Self, ()>
60-
{
59+
// TODO: Add dummy hops
60+
pub fn new<K: KeysInterface, T: secp256k1::Signing + secp256k1::Verification> (
61+
node_pks: &[PublicKey], keys_manager: &K, secp_ctx: &Secp256k1<T>,
62+
include_next_blinding_override_padding: bool
63+
) -> Result<Self, ()> {
6164
if node_pks.len() < 2 { return Err(()) }
6265
let blinding_secret_bytes = keys_manager.get_secure_random_bytes();
6366
let blinding_secret = SecretKey::from_slice(&blinding_secret_bytes[..]).expect("RNG is busted");
@@ -66,16 +69,18 @@ impl BlindedRoute {
6669
Ok(BlindedRoute {
6770
introduction_node_id,
6871
blinding_point: PublicKey::from_secret_key(secp_ctx, &blinding_secret),
69-
blinded_hops: blinded_hops(secp_ctx, node_pks, &blinding_secret).map_err(|_| ())?,
72+
blinded_hops: blinded_hops(secp_ctx, node_pks, &blinding_secret, include_next_blinding_override_padding).map_err(|_| ())?,
7073
})
7174
}
7275
}
7376

7477
/// Construct blinded hops for the given `unblinded_path`.
7578
fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
76-
secp_ctx: &Secp256k1<T>, unblinded_path: &[PublicKey], session_priv: &SecretKey
79+
secp_ctx: &Secp256k1<T>, unblinded_path: &[PublicKey], session_priv: &SecretKey,
80+
include_next_blinding_override_padding: bool
7781
) -> Result<Vec<BlindedHop>, secp256k1::Error> {
7882
let mut blinded_hops = Vec::with_capacity(unblinded_path.len());
83+
let max_length = get_control_tlv_length!(true, include_next_blinding_override_padding);
7984

8085
let mut prev_ss_and_blinded_node_id = None;
8186
utils::construct_keys_callback(secp_ctx, unblinded_path, None, session_priv, |blinded_node_id, _, _, encrypted_payload_ss, unblinded_pk, _| {
@@ -84,6 +89,7 @@ fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
8489
let payload = ForwardTlvs {
8590
next_node_id: pk,
8691
next_blinding_override: None,
92+
total_length: max_length,
8793
};
8894
blinded_hops.push(BlindedHop {
8995
blinded_node_id: prev_blinded_node_id,
@@ -95,7 +101,7 @@ fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
95101
})?;
96102

97103
if let Some((final_ss, final_blinded_node_id)) = prev_ss_and_blinded_node_id {
98-
let final_payload = ReceiveTlvs { path_id: None };
104+
let final_payload = ReceiveTlvs { path_id: None, total_length: max_length, };
99105
blinded_hops.push(BlindedHop {
100106
blinded_node_id: final_blinded_node_id,
101107
encrypted_payload: encrypt_payload(final_payload, final_ss),
@@ -150,37 +156,45 @@ impl_writeable!(BlindedHop, {
150156

151157
/// TLVs to encode in an intermediate onion message packet's hop data. When provided in a blinded
152158
/// route, they are encoded into [`BlindedHop::encrypted_payload`].
159+
#[derive(Clone, Copy)]
153160
pub(crate) struct ForwardTlvs {
154161
/// The node id of the next hop in the onion message's path.
155162
pub(super) next_node_id: PublicKey,
156163
/// Senders to a blinded route use this value to concatenate the route they find to the
157164
/// introduction node with the blinded route.
158165
pub(super) next_blinding_override: Option<PublicKey>,
166+
/// The length the tlv should have when it's serialized, with padding included if needed.
167+
/// Used to ensure that all control tlvs in a blinded route have the same length.
168+
pub(super) total_length: u16,
159169
}
160170

161171
/// Similar to [`ForwardTlvs`], but these TLVs are for the final node.
172+
#[derive(Clone, Copy)]
162173
pub(crate) struct ReceiveTlvs {
163174
/// If `path_id` is `Some`, it is used to identify the blinded route that this onion message is
164175
/// sending to. This is useful for receivers to check that said blinded route is being used in
165176
/// the right context.
166177
pub(super) path_id: Option<[u8; 32]>,
178+
/// The length the tlv should have when it's serialized, with padding included if needed.
179+
/// Used to ensure that all control tlvs in a blinded route have the same length.
180+
pub(super) total_length: u16,
167181
}
168182

169183
impl Writeable for ForwardTlvs {
170184
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
171-
// TODO: write padding
172185
encode_tlv_stream!(writer, {
186+
(1, Padding::new_from_tlv(ControlTlvs::Forward(*self)), option),
173187
(4, self.next_node_id, required),
174-
(8, self.next_blinding_override, option)
188+
(8, self.next_blinding_override, option),
175189
});
176190
Ok(())
177191
}
178192
}
179193

180194
impl Writeable for ReceiveTlvs {
181195
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
182-
// TODO: write padding
183196
encode_tlv_stream!(writer, {
197+
(1, Padding::new_from_tlv(ControlTlvs::Receive(*self)), option),
184198
(6, self.path_id, option),
185199
});
186200
Ok(())

lightning/src/onion_message/functional_tests.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ fn two_unblinded_two_blinded() {
9898
let nodes = create_nodes(5);
9999

100100
let secp_ctx = Secp256k1::new();
101-
let blinded_route = BlindedRoute::new(&[nodes[3].get_node_pk(), nodes[4].get_node_pk()], &*nodes[4].keys_manager, &secp_ctx).unwrap();
101+
let blinded_route = BlindedRoute::new(&[nodes[3].get_node_pk(), nodes[4].get_node_pk()], &*nodes[4].keys_manager, &secp_ctx, true).unwrap();
102102

103103
nodes[0].messenger.send_onion_message(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], Destination::BlindedRoute(blinded_route), None).unwrap();
104104
pass_along_path(&nodes, None);
@@ -109,7 +109,7 @@ fn three_blinded_hops() {
109109
let nodes = create_nodes(4);
110110

111111
let secp_ctx = Secp256k1::new();
112-
let blinded_route = BlindedRoute::new(&[nodes[1].get_node_pk(), nodes[2].get_node_pk(), nodes[3].get_node_pk()], &*nodes[3].keys_manager, &secp_ctx).unwrap();
112+
let blinded_route = BlindedRoute::new(&[nodes[1].get_node_pk(), nodes[2].get_node_pk(), nodes[3].get_node_pk()], &*nodes[3].keys_manager, &secp_ctx, true).unwrap();
113113

114114
nodes[0].messenger.send_onion_message(&[], Destination::BlindedRoute(blinded_route), None).unwrap();
115115
pass_along_path(&nodes, None);
@@ -133,13 +133,13 @@ fn invalid_blinded_route_error() {
133133

134134
// 0 hops
135135
let secp_ctx = Secp256k1::new();
136-
let mut blinded_route = BlindedRoute::new(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], &*nodes[2].keys_manager, &secp_ctx).unwrap();
136+
let mut blinded_route = BlindedRoute::new(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], &*nodes[2].keys_manager, &secp_ctx, true).unwrap();
137137
blinded_route.blinded_hops.clear();
138138
let err = nodes[0].messenger.send_onion_message(&[], Destination::BlindedRoute(blinded_route), None).unwrap_err();
139139
assert_eq!(err, SendError::TooFewBlindedHops);
140140

141141
// 1 hop
142-
let mut blinded_route = BlindedRoute::new(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], &*nodes[2].keys_manager, &secp_ctx).unwrap();
142+
let mut blinded_route = BlindedRoute::new(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], &*nodes[2].keys_manager, &secp_ctx, true).unwrap();
143143
blinded_route.blinded_hops.remove(0);
144144
assert_eq!(blinded_route.blinded_hops.len(), 1);
145145
let err = nodes[0].messenger.send_onion_message(&[], Destination::BlindedRoute(blinded_route), None).unwrap_err();
@@ -152,7 +152,7 @@ fn reply_path() {
152152
let secp_ctx = Secp256k1::new();
153153

154154
// Destination::Node
155-
let reply_path = BlindedRoute::new(&[nodes[2].get_node_pk(), nodes[1].get_node_pk(), nodes[0].get_node_pk()], &*nodes[0].keys_manager, &secp_ctx).unwrap();
155+
let reply_path = BlindedRoute::new(&[nodes[2].get_node_pk(), nodes[1].get_node_pk(), nodes[0].get_node_pk()], &*nodes[0].keys_manager, &secp_ctx, false).unwrap();
156156
nodes[0].messenger.send_onion_message(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], Destination::Node(nodes[3].get_node_pk()), Some(reply_path)).unwrap();
157157
pass_along_path(&nodes, None);
158158
// Make sure the last node successfully decoded the reply path.
@@ -161,8 +161,8 @@ fn reply_path() {
161161
format!("Received an onion message with path_id: None and reply_path").to_string(), 1);
162162

163163
// Destination::BlindedRoute
164-
let blinded_route = BlindedRoute::new(&[nodes[1].get_node_pk(), nodes[2].get_node_pk(), nodes[3].get_node_pk()], &*nodes[3].keys_manager, &secp_ctx).unwrap();
165-
let reply_path = BlindedRoute::new(&[nodes[2].get_node_pk(), nodes[1].get_node_pk(), nodes[0].get_node_pk()], &*nodes[0].keys_manager, &secp_ctx).unwrap();
164+
let blinded_route = BlindedRoute::new(&[nodes[1].get_node_pk(), nodes[2].get_node_pk(), nodes[3].get_node_pk()], &*nodes[3].keys_manager, &secp_ctx, true).unwrap();
165+
let reply_path = BlindedRoute::new(&[nodes[2].get_node_pk(), nodes[1].get_node_pk(), nodes[0].get_node_pk()], &*nodes[0].keys_manager, &secp_ctx, false).unwrap();
166166

167167
nodes[0].messenger.send_onion_message(&[], Destination::BlindedRoute(blinded_route), Some(reply_path)).unwrap();
168168
pass_along_path(&nodes, None);

lightning/src/onion_message/messenger.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use ln::onion_utils;
2222
use super::blinded_route::{BlindedRoute, ForwardTlvs, ReceiveTlvs};
2323
use super::packet::{BIG_PACKET_HOP_DATA_LEN, ForwardControlTlvs, Packet, Payload, ReceiveControlTlvs, SMALL_PACKET_HOP_DATA_LEN};
2424
use super::utils;
25+
use ::get_control_tlv_length;
2526
use util::events::OnionMessageProvider;
2627
use util::logger::Logger;
2728
use util::ser::Writeable;
@@ -71,7 +72,7 @@ use prelude::*;
7172
/// // Create a blinded route to yourself, for someone to send an onion message to.
7273
/// # let your_node_id = hop_node_id1;
7374
/// let hops = [hop_node_id3, hop_node_id4, your_node_id];
74-
/// let blinded_route = BlindedRoute::new(&hops, &keys_manager, &secp_ctx).unwrap();
75+
/// let blinded_route = BlindedRoute::new(&hops, &keys_manager, &secp_ctx, true).unwrap();
7576
///
7677
/// // Send an empty onion message to a blinded route.
7778
/// # let intermediate_hops = [hop_node_id1, hop_node_id2];
@@ -256,14 +257,14 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessageHandler for OnionMessenger<Si
256257
msg.onion_routing_packet.hmac, control_tlvs_ss)
257258
{
258259
Ok((Payload::Receive {
259-
control_tlvs: ReceiveControlTlvs::Unblinded(ReceiveTlvs { path_id }), reply_path,
260+
control_tlvs: ReceiveControlTlvs::Unblinded(ReceiveTlvs { path_id, .. }), reply_path,
260261
}, None)) => {
261262
log_info!(self.logger,
262263
"Received an onion message with path_id: {:02x?} and {}reply_path",
263264
path_id, if reply_path.is_some() { "" } else { "no " });
264265
},
265266
Ok((Payload::Forward(ForwardControlTlvs::Unblinded(ForwardTlvs {
266-
next_node_id, next_blinding_override
267+
next_node_id, next_blinding_override, ..
267268
})), Some((next_hop_hmac, new_packet_bytes)))) => {
268269
// TODO: we need to check whether `next_node_id` is our node, in which case this is a dummy
269270
// blinded hop and this onion message is destined for us. In this situation, we should keep
@@ -418,6 +419,7 @@ fn packet_payloads_and_keys<T: secp256k1::Signing + secp256k1::Verification>(
418419
ForwardTlvs {
419420
next_node_id: unblinded_pk_opt.unwrap(),
420421
next_blinding_override: None,
422+
total_length: get_control_tlv_length!(true, false),
421423
}
422424
)), ss));
423425
}
@@ -428,6 +430,7 @@ fn packet_payloads_and_keys<T: secp256k1::Signing + secp256k1::Verification>(
428430
payloads.push((Payload::Forward(ForwardControlTlvs::Unblinded(ForwardTlvs {
429431
next_node_id: intro_node_id,
430432
next_blinding_override: Some(blinding_pt),
433+
total_length: get_control_tlv_length!(true, true),
431434
})), control_tlvs_ss));
432435
}
433436
if let Some(encrypted_payload) = enc_payload_opt {
@@ -460,7 +463,7 @@ fn packet_payloads_and_keys<T: secp256k1::Signing + secp256k1::Verification>(
460463

461464
if let Some(control_tlvs_ss) = prev_control_tlvs_ss {
462465
payloads.push((Payload::Receive {
463-
control_tlvs: ReceiveControlTlvs::Unblinded(ReceiveTlvs { path_id: None, }),
466+
control_tlvs: ReceiveControlTlvs::Unblinded(ReceiveTlvs { path_id: None, total_length: get_control_tlv_length!(false), }),
464467
reply_path: reply_path.take(),
465468
}, control_tlvs_ss));
466469
}

lightning/src/onion_message/packet.rs

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use bitcoin::secp256k1::ecdh::SharedSecret;
1414

1515
use ln::msgs::DecodeError;
1616
use ln::onion_utils;
17+
use ::get_control_tlv_length;
1718
use super::blinded_route::{BlindedRoute, ForwardTlvs, ReceiveTlvs};
1819
use util::chacha20poly1305rfc::{ChaChaPolyReadAdapter, ChaChaPolyWriteAdapter};
1920
use util::ser::{BigSize, FixedLengthReader, LengthRead, LengthReadable, LengthReadableArgs, Readable, ReadableArgs, Writeable, Writer};
@@ -197,7 +198,7 @@ impl ReadableArgs<SharedSecret> for Payload {
197198
/// When reading a packet off the wire, we don't know a priori whether the packet is to be forwarded
198199
/// or received. Thus we read a ControlTlvs rather than reading a ForwardControlTlvs or
199200
/// ReceiveControlTlvs directly.
200-
pub(super) enum ControlTlvs {
201+
pub(crate) enum ControlTlvs {
201202
/// This onion message is intended to be forwarded.
202203
Forward(ForwardTlvs),
203204
/// This onion message is intended to be received.
@@ -206,13 +207,13 @@ pub(super) enum ControlTlvs {
206207

207208
impl Readable for ControlTlvs {
208209
fn read<R: Read>(mut r: &mut R) -> Result<Self, DecodeError> {
209-
let mut _padding: Option<Padding> = None;
210+
let mut padding: Option<Padding> = None;
210211
let mut _short_channel_id: Option<u64> = None;
211212
let mut next_node_id: Option<PublicKey> = None;
212213
let mut path_id: Option<[u8; 32]> = None;
213214
let mut next_blinding_override: Option<PublicKey> = None;
214215
decode_tlv_stream!(&mut r, {
215-
(1, _padding, option),
216+
(1, padding, option),
216217
(2, _short_channel_id, option),
217218
(4, next_node_id, option),
218219
(6, path_id, option),
@@ -222,13 +223,20 @@ impl Readable for ControlTlvs {
222223
let valid_fwd_fmt = next_node_id.is_some() && path_id.is_none();
223224
let valid_recv_fmt = next_node_id.is_none() && next_blinding_override.is_none();
224225

226+
let mut total_length = get_control_tlv_length!(next_node_id.is_some(), next_blinding_override.is_some(), path_id.is_some(), 0, 0);
227+
if padding.is_some() {
228+
total_length += padding.unwrap().padding_length + 2 // 2 extra prefix bytes
229+
}
230+
225231
let payload_fmt = if valid_fwd_fmt {
226232
ControlTlvs::Forward(ForwardTlvs {
233+
total_length,
227234
next_node_id: next_node_id.unwrap(),
228235
next_blinding_override,
229236
})
230237
} else if valid_recv_fmt {
231238
ControlTlvs::Receive(ReceiveTlvs {
239+
total_length,
232240
path_id,
233241
})
234242
} else {
@@ -239,15 +247,57 @@ impl Readable for ControlTlvs {
239247
}
240248
}
241249

242-
/// Reads padding to the end, ignoring what's read.
243-
pub(crate) struct Padding {}
250+
pub(crate) struct Padding {
251+
padding_length: u16,
252+
}
253+
254+
/// Reads padding to the end, and validates that the read bytes' content are 0s.
244255
impl Readable for Padding {
245256
#[inline]
246257
fn read<R: Read>(reader: &mut R) -> Result<Self, DecodeError> {
258+
let mut padding_length = 0;
247259
loop {
248260
let mut buf = [0; 8192];
249-
if reader.read(&mut buf[..])? == 0 { break; }
261+
let read_bytes_len = reader.read(&mut buf[..])?;
262+
if read_bytes_len == 0 { break; }
263+
for n in 0..read_bytes_len {
264+
if buf[n] != 0 as u8 { return Err(DecodeError::InvalidValue); }
265+
}
266+
padding_length += read_bytes_len as u16;
267+
}
268+
Ok(Self { padding_length })
269+
}
270+
}
271+
272+
impl Writeable for Padding {
273+
#[inline]
274+
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
275+
for _ in 0..self.padding_length {
276+
(0 as u8).write(writer)?;
277+
}
278+
Ok(())
279+
}
280+
}
281+
282+
impl Padding {
283+
pub fn new_from_tlv(tlv: ControlTlvs) -> Option<Padding> {
284+
let (data_length, tlv_total_length) = match tlv {
285+
ControlTlvs::Forward(forward_tlvs) => {
286+
let data_length = get_control_tlv_length!(true, forward_tlvs.next_blinding_override.is_some());
287+
(data_length, forward_tlvs.total_length as u16)
288+
},
289+
ControlTlvs::Receive(receive_tlvs) => {
290+
let data_length = get_control_tlv_length!(receive_tlvs.path_id.is_some());
291+
(data_length, receive_tlvs.total_length as u16)
292+
}
293+
};
294+
295+
let extra_bytes_needed = tlv_total_length - data_length;
296+
if extra_bytes_needed >= 2 {
297+
let padding_length = extra_bytes_needed - 2; // 2 bytes of prefix removed
298+
Some(Padding { padding_length })
299+
} else {
300+
None
250301
}
251-
Ok(Self {})
252302
}
253303
}

0 commit comments

Comments
 (0)