Skip to content

Commit 4508a58

Browse files
committed
respond to more of Jeff's comments
1 parent ed6ec4d commit 4508a58

File tree

5 files changed

+59
-38
lines changed

5 files changed

+59
-38
lines changed

lightning/src/ln/peer_handler.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,8 @@ impl<Descriptor: SocketDescriptor, CM: Deref> PeerManager<Descriptor, CM> where
542542
}
543543
}
544544

545-
let message_option = conduit.decrypt_single_message(Some(&peer.pending_read_buffer));
545+
let message_option = conduit.decrypt_single_message(Some(&peer.pending_read_buffer.clone()));
546+
peer.pending_read_buffer = Vec::new(); // empty the pending read buffer
546547
let msg_data = if let Some(message) = message_option {
547548
message
548549
} else {

lightning/src/ln/peers/conduit.rs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use ln::peers::{chacha, hkdf};
44
use util::byte_utils;
55

6-
type SymmetricKey = [u8; 32];
6+
pub(super) type SymmetricKey = [u8; 32];
77
const MESSAGE_LENGTH_HEADER_SIZE: usize = 2;
88
const TAGGED_MESSAGE_LENGTH_HEADER_SIZE: usize = MESSAGE_LENGTH_HEADER_SIZE + chacha::TAG_SIZE;
99

@@ -62,15 +62,17 @@ impl Conduit {
6262
}
6363

6464
let (current_message, offset) = self.decrypt(&read_buffer[..]);
65+
read_buffer.drain(0..offset); // drain the read buffer
66+
self.read_buffer = Some(read_buffer); // assign the new value to the built-in buffer
67+
6568
if offset == 0 {
6669
return None;
6770
}
6871

69-
read_buffer.drain(0..offset);
7072
current_message
7173
}
7274

73-
fn decrypt(&mut self, buffer: &[u8]) -> (Option<Vec<u8>>, usize) { // the response slice should have the same lifetime as the argument. It's the slice data is read from
75+
pub(crate) fn decrypt(&mut self, buffer: &[u8]) -> (Option<Vec<u8>>, usize) { // the response slice should have the same lifetime as the argument. It's the slice data is read from
7476
if buffer.len() < TAGGED_MESSAGE_LENGTH_HEADER_SIZE {
7577
return (None, 0);
7678
}
@@ -81,7 +83,7 @@ impl Conduit {
8183
length_bytes.copy_from_slice(length_vec.as_slice());
8284
let message_length = byte_utils::slice_to_be16(&length_bytes) as usize;
8385

84-
let message_end_index = message_length + TAGGED_MESSAGE_LENGTH_HEADER_SIZE + chacha::TAG_SIZE; // todo: abort if too short
86+
let message_end_index = TAGGED_MESSAGE_LENGTH_HEADER_SIZE + message_length + chacha::TAG_SIZE; // todo: abort if too short
8587
if buffer.len() < message_end_index {
8688
return (None, 0);
8789
}
@@ -175,9 +177,18 @@ mod tests {
175177
assert_eq!(encrypted_messages[1000], hex::decode("4a2f3cc3b5e78ddb83dcb426d9863d9d9a723b0337c89dd0b005d89f8d3c05c52b76b29b740f09").unwrap());
176178
assert_eq!(encrypted_messages[1001], hex::decode("2ecd8c8a5629d0d02ab457a0fdd0f7b90a192cd46be5ecb6ca570bfc5e268338b1a16cf4ef2d36").unwrap());
177179

178-
for _ in 0..1002 {
179-
let encrypted_message = encrypted_messages.remove(0);
180-
let decrypted_message = remote_peer.decrypt_single_message(Some(&encrypted_message)).unwrap();
180+
for _ in 0..501 {
181+
// read two messages at once, filling buffer
182+
let mut current_encrypted_message = encrypted_messages.remove(0);
183+
let mut next_encrypted_message = encrypted_messages.remove(0);
184+
current_encrypted_message.extend_from_slice(&next_encrypted_message);
185+
let decrypted_message = remote_peer.decrypt_single_message(Some(&current_encrypted_message)).unwrap();
186+
assert_eq!(decrypted_message, hex::decode("68656c6c6f").unwrap());
187+
}
188+
189+
for _ in 0..501 {
190+
// decrypt messages directly from buffer without adding to it
191+
let decrypted_message = remote_peer.decrypt_single_message(None).unwrap();
181192
assert_eq!(decrypted_message, hex::decode("68656c6c6f").unwrap());
182193
}
183194
}

lightning/src/ln/peers/handshake/acts.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
1+
pub const ACT_ONE_LENGTH: usize = 50;
2+
pub const ACT_TWO_LENGTH: usize = 50;
3+
pub const ACT_THREE_LENGTH: usize = 66;
4+
15
/// Wrapper for the first act message
26
pub struct ActOne(
3-
pub(super) [u8; 50]
7+
pub(super) [u8; ACT_ONE_LENGTH]
48
);
59

610
/// Wrapper for the second act message
711
pub struct ActTwo(
8-
pub(super) [u8; 50]
12+
pub(super) [u8; ACT_TWO_LENGTH]
913
);
1014

1115
/// Wrapper for the third act message
1216
pub struct ActThree(
13-
pub(super) [u8; 66]
17+
pub(super) [u8; ACT_THREE_LENGTH]
1418
);
1519

1620
/// Wrapper for any act message

lightning/src/ln/peers/handshake/mod.rs

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ use bitcoin_hashes::sha256::Hash as Sha256;
99
use secp256k1::{PublicKey, SecretKey};
1010

1111
use ln::peers::{chacha, hkdf};
12-
use ln::peers::conduit::Conduit;
13-
use ln::peers::handshake::acts::{ActOne, ActThree, ActTwo};
12+
use ln::peers::conduit::{Conduit, SymmetricKey};
13+
use ln::peers::handshake::acts::{ActOne, ActThree, ActTwo, ACT_ONE_LENGTH, ACT_TWO_LENGTH, ACT_THREE_LENGTH};
1414
use ln::peers::handshake::hash::HandshakeHash;
1515
use ln::peers::handshake::states::{ActOneExpectation, ActThreeExpectation, ActTwoExpectation, HandshakeState};
1616

@@ -33,7 +33,7 @@ impl PeerHandshake {
3333
/// Instantiate a new handshake with a node identity secret key and an ephemeral private key
3434
pub fn new(private_key: &SecretKey, ephemeral_private_key: &SecretKey) -> Self {
3535
Self {
36-
state: Some(HandshakeState::Blank),
36+
state: Some(HandshakeState::Uninitiated),
3737
private_key: (*private_key).clone(),
3838
ephemeral_private_key: (*ephemeral_private_key).clone(),
3939
read_buffer: Vec::new(),
@@ -68,7 +68,15 @@ impl PeerHandshake {
6868
}
6969

7070
/// Process act dynamically
71-
/// The role must be set before this method can be called
71+
/// # Arguments
72+
/// `input`: Byte slice received from peer as part of the handshake protocol
73+
/// `remote_public_key`: If outbound, the peer's static identity public key needs is required for the handshake initiation
74+
///
75+
/// # Return values
76+
/// Returns a tuple with the following components:
77+
/// `.0`: Byte vector containing the next act to send back to the peer per the handshake protocol
78+
/// `.1`: Conduit option if the handshake was just processed to completion and messages can now be encrypted and decrypted
79+
/// `.2`: Public key option if the handshake was inbound and the peer's static identity pubkey was just learned
7280
pub fn process_act(&mut self, input: &[u8], remote_public_key: Option<&PublicKey>) -> Result<(Vec<u8>, Option<Conduit>, Option<PublicKey>), String> {
7381
let mut response: Vec<u8> = Vec::new();
7482
let mut connected_peer = None;
@@ -78,7 +86,7 @@ impl PeerHandshake {
7886
let read_buffer_length = self.read_buffer.len();
7987

8088
match &self.state {
81-
&Some(HandshakeState::Blank) => {
89+
&Some(HandshakeState::Uninitiated) => {
8290
let remote_public_key = remote_public_key.ok_or("remote_public_key must be Some for outbound connections")?;
8391
let act_one = self.initiate(&remote_public_key)?;
8492
response = act_one.0.to_vec();
@@ -89,22 +97,21 @@ impl PeerHandshake {
8997
return Err("need at least 50 bytes".to_string());
9098
}
9199

92-
let mut act_one_buffer = [0u8; 50];
93-
act_one_buffer.copy_from_slice(&self.read_buffer[..act_length]);
94-
self.read_buffer.drain(..act_length);
100+
let mut act_one_buffer = [0u8; ACT_ONE_LENGTH];
101+
act_one_buffer.copy_from_slice(&self.read_buffer[..ACT_ONE_LENGTH]);
102+
self.read_buffer.drain(..ACT_ONE_LENGTH);
95103

96104
let act_two = self.process_act_one(ActOne(act_one_buffer))?;
97105
response = act_two.0.to_vec();
98106
}
99107
&Some(HandshakeState::AwaitingActTwo(_)) => {
100-
let act_length = 50;
101-
if read_buffer_length < act_length {
108+
if read_buffer_length < ACT_TWO_LENGTH {
102109
return Err("need at least 50 bytes".to_string());
103110
}
104111

105-
let mut act_two_buffer = [0u8; 50];
106-
act_two_buffer.copy_from_slice(&self.read_buffer[..act_length]);
107-
self.read_buffer.drain(..act_length);
112+
let mut act_two_buffer = [0u8; ACT_TWO_LENGTH];
113+
act_two_buffer.copy_from_slice(&self.read_buffer[..ACT_TWO_LENGTH]);
114+
self.read_buffer.drain(..ACT_TWO_LENGTH);
108115

109116
let (act_three, mut conduit) = self.process_act_two(ActTwo(act_two_buffer))?;
110117

@@ -117,14 +124,13 @@ impl PeerHandshake {
117124
connected_peer = Some(conduit);
118125
}
119126
&Some(HandshakeState::AwaitingActThree(_)) => {
120-
let act_length = 66;
121-
if read_buffer_length < act_length {
122-
return Err("need at least 50 bytes".to_string());
127+
if read_buffer_length < ACT_THREE_LENGTH {
128+
return Err("need at least 66 bytes".to_string());
123129
}
124130

125-
let mut act_three_buffer = [0u8; 66];
126-
act_three_buffer.copy_from_slice(&self.read_buffer[..act_length]);
127-
self.read_buffer.drain(..act_length);
131+
let mut act_three_buffer = [0u8; ACT_THREE_LENGTH];
132+
act_three_buffer.copy_from_slice(&self.read_buffer[..ACT_THREE_LENGTH]);
133+
self.read_buffer.drain(..ACT_THREE_LENGTH);
128134

129135
let (public_key, mut conduit) = self.process_act_three(ActThree(act_three_buffer))?;
130136

@@ -145,7 +151,7 @@ impl PeerHandshake {
145151

146152
/// Initiate the handshake with a peer and return the first act
147153
pub fn initiate(&mut self, remote_public_key: &PublicKey) -> Result<ActOne, String> {
148-
if let &Some(HandshakeState::Blank) = &self.state {} else {
154+
if let &Some(HandshakeState::Uninitiated) = &self.state {} else {
149155
return Err("incorrect state".to_string());
150156
}
151157

@@ -174,9 +180,8 @@ impl PeerHandshake {
174180
let state = self.state.take();
175181
let act_one_expectation = match state {
176182
Some(HandshakeState::AwaitingActOne(act_state)) => act_state,
177-
Some(HandshakeState::Blank) => {
183+
Some(HandshakeState::Uninitiated) => {
178184
// this can also be initiated from a blank state
179-
// public key
180185
let public_key = Self::private_key_to_public_key(&self.private_key);
181186
let (hash, chaining_key) = Self::initialize_state(&public_key);
182187
ActOneExpectation {
@@ -315,7 +320,7 @@ impl PeerHandshake {
315320
Ok((remote_pubkey, connected_peer))
316321
}
317322

318-
fn calculate_act_message(local_private_key: &SecretKey, remote_public_key: &PublicKey, chaining_key: [u8; 32], hash: &mut HandshakeHash) -> ([u8; 50], [u8; 32], [u8; 32]) {
323+
fn calculate_act_message(local_private_key: &SecretKey, remote_public_key: &PublicKey, chaining_key: [u8; 32], hash: &mut HandshakeHash) -> ([u8; 50], SymmetricKey, SymmetricKey) {
319324
let local_public_key = Self::private_key_to_public_key(local_private_key);
320325

321326
hash.update(&local_public_key.serialize());
@@ -333,7 +338,7 @@ impl PeerHandshake {
333338
(act, chaining_key, temporary_key)
334339
}
335340

336-
fn process_act_message(act_bytes: [u8; 50], local_private_key: &SecretKey, chaining_key: [u8; 32], hash: &mut HandshakeHash) -> Result<(PublicKey, [u8; 32], [u8; 32]), String> {
341+
fn process_act_message(act_bytes: [u8; 50], local_private_key: &SecretKey, chaining_key: [u8; 32], hash: &mut HandshakeHash) -> Result<(PublicKey, SymmetricKey, SymmetricKey), String> {
337342
let version = act_bytes[0];
338343
if version != 0 {
339344
return Err("unexpected version".to_string());
@@ -358,7 +363,7 @@ impl PeerHandshake {
358363
// HKDF(chaining key, ECDH) -> chaining key' + next temporary key
359364
let (chaining_key, temporary_key) = hkdf::derive(&chaining_key, &ecdh);
360365

361-
// Validate chacha tag (temporary key, 0, self.hash, chacha_tag)
366+
// Validate chacha tag (temporary key, 0, hash, chacha_tag)
362367
let _tag_check = chacha::decrypt(&temporary_key, 0, &hash.value, &chacha_tag)?;
363368

364369
hash.update(&chacha_tag);
@@ -372,7 +377,7 @@ impl PeerHandshake {
372377
pk_object
373378
}
374379

375-
fn ecdh(private_key: &SecretKey, public_key: &PublicKey) -> [u8; 32] {
380+
fn ecdh(private_key: &SecretKey, public_key: &PublicKey) -> SymmetricKey {
376381
let curve = secp256k1::Secp256k1::new();
377382
let mut pk_object = public_key.clone();
378383
pk_object.mul_assign(&curve, &private_key[..]).expect("invalid multiplication");

lightning/src/ln/peers/handshake/states.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use ln::peers::handshake::hash::HandshakeHash;
22
use secp256k1::{SecretKey, PublicKey};
33

44
pub enum HandshakeState {
5-
Blank,
5+
Uninitiated,
66
AwaitingActOne(ActOneExpectation),
77
AwaitingActTwo(ActTwoExpectation),
88
AwaitingActThree(ActThreeExpectation),

0 commit comments

Comments
 (0)