Skip to content

Commit 5fb2cc4

Browse files
authored
Merge pull request #143 from TheBlueMatt/2018-08-announcement_sigs_erroraction
Ensure handle_announcement_signatures always has a ErrorAction
2 parents 1992464 + a9434db commit 5fb2cc4

File tree

2 files changed

+26
-15
lines changed

2 files changed

+26
-15
lines changed

src/ln/channel.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2113,7 +2113,16 @@ impl Channel {
21132113
if tx.txid() == self.channel_monitor.get_funding_txo().unwrap().txid {
21142114
let txo_idx = self.channel_monitor.get_funding_txo().unwrap().index as usize;
21152115
if txo_idx >= tx.output.len() || tx.output[txo_idx].script_pubkey != self.get_funding_redeemscript().to_v0_p2wsh() ||
2116-
tx.output[txo_idx].value != self.channel_value_satoshis {
2116+
tx.output[txo_idx].value != self.channel_value_satoshis {
2117+
if self.channel_outbound {
2118+
// If we generated the funding transaction and it doesn't match what it
2119+
// should, the client is really broken and we should just panic and
2120+
// tell them off. That said, because hash collisions happen with high
2121+
// probability in fuzztarget mode, if we're fuzzing we just close the
2122+
// channel and move on.
2123+
#[cfg(not(feature = "fuzztarget"))]
2124+
panic!("Client called ChannelManager::funding_transaction_generated with bogus transaction!");
2125+
}
21172126
self.channel_state = ChannelState::ShutdownComplete as u32;
21182127
self.channel_update_count += 1;
21192128
return Err(HandleError{err: "funding tx had wrong script/value", action: Some(ErrorAction::DisconnectPeer{msg: None})});

src/ln/channelmanager.rs

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -189,11 +189,10 @@ pub struct ChannelManager {
189189
const CLTV_EXPIRY_DELTA: u16 = 6 * 24 * 2; //TODO?
190190

191191
macro_rules! secp_call {
192-
( $res : expr ) => {
192+
( $res: expr, $err_msg: expr, $action: expr ) => {
193193
match $res {
194194
Ok(key) => key,
195-
//TODO: Make the err a parameter!
196-
Err(_) => return Err(HandleError{err: "Key error", action: None})
195+
Err(_) => return Err(HandleError{err: $err_msg, action: Some($action)})
197196
}
198197
};
199198
}
@@ -475,7 +474,7 @@ impl ChannelManager {
475474

476475
// can only fail if an intermediary hop has an invalid public key or session_priv is invalid
477476
#[inline]
478-
fn construct_onion_keys_callback<T: secp256k1::Signing, FType: FnMut(SharedSecret, [u8; 32], PublicKey, &RouteHop)> (secp_ctx: &Secp256k1<T>, route: &Route, session_priv: &SecretKey, mut callback: FType) -> Result<(), HandleError> {
477+
fn construct_onion_keys_callback<T: secp256k1::Signing, FType: FnMut(SharedSecret, [u8; 32], PublicKey, &RouteHop)> (secp_ctx: &Secp256k1<T>, route: &Route, session_priv: &SecretKey, mut callback: FType) -> Result<(), secp256k1::Error> {
479478
let mut blinded_priv = session_priv.clone();
480479
let mut blinded_pub = PublicKey::from_secret_key(secp_ctx, &blinded_priv);
481480

@@ -490,7 +489,7 @@ impl ChannelManager {
490489

491490
let ephemeral_pubkey = blinded_pub;
492491

493-
secp_call!(blinded_priv.mul_assign(secp_ctx, &secp_call!(SecretKey::from_slice(secp_ctx, &blinding_factor))));
492+
blinded_priv.mul_assign(secp_ctx, &SecretKey::from_slice(secp_ctx, &blinding_factor)?)?;
494493
blinded_pub = PublicKey::from_secret_key(secp_ctx, &blinded_priv);
495494

496495
callback(shared_secret, blinding_factor, ephemeral_pubkey, hop);
@@ -500,7 +499,7 @@ impl ChannelManager {
500499
}
501500

502501
// can only fail if an intermediary hop has an invalid public key or session_priv is invalid
503-
fn construct_onion_keys<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, route: &Route, session_priv: &SecretKey) -> Result<Vec<OnionKeys>, HandleError> {
502+
fn construct_onion_keys<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, route: &Route, session_priv: &SecretKey) -> Result<Vec<OnionKeys>, secp256k1::Error> {
504503
let mut res = Vec::with_capacity(route.hops.len());
505504

506505
Self::construct_onion_keys_callback(secp_ctx, route, session_priv, |shared_secret, _blinding_factor, ephemeral_pubkey, _| {
@@ -905,15 +904,17 @@ impl ChannelManager {
905904
}
906905
}
907906

908-
let session_priv = secp_call!(SecretKey::from_slice(&self.secp_ctx, &{
907+
let session_priv = SecretKey::from_slice(&self.secp_ctx, &{
909908
let mut session_key = [0; 32];
910909
rng::fill_bytes(&mut session_key);
911910
session_key
912-
}));
911+
}).expect("RNG is bad!");
913912

914913
let cur_height = self.latest_block_height.load(Ordering::Acquire) as u32 + 1;
915914

916-
let onion_keys = ChannelManager::construct_onion_keys(&self.secp_ctx, &route, &session_priv)?;
915+
//TODO: This should return something other than HandleError, that's really intended for
916+
//p2p-returns only.
917+
let onion_keys = secp_call!(ChannelManager::construct_onion_keys(&self.secp_ctx, &route, &session_priv), "Pubkey along hop was maliciously selected", msgs::ErrorAction::IgnoreError);
917918
let (onion_payloads, htlc_msat, htlc_cltv) = ChannelManager::build_onion_payloads(&route, cur_height)?;
918919
let onion_packet = ChannelManager::construct_onion_packet(onion_payloads, onion_keys, &payment_hash)?;
919920

@@ -1982,19 +1983,20 @@ impl ChannelMessageHandler for ChannelManager {
19821983
match channel_state.by_id.get_mut(&msg.channel_id) {
19831984
Some(chan) => {
19841985
if chan.get_their_node_id() != *their_node_id {
1985-
return Err(HandleError{err: "Got a message for a channel from the wrong node!", action: None})
1986+
return Err(HandleError{err: "Got a message for a channel from the wrong node!", action: Some(msgs::ErrorAction::IgnoreError) })
19861987
}
19871988
if !chan.is_usable() {
1988-
return Err(HandleError{err: "Got an announcement_signatures before we were ready for it", action: None });
1989+
return Err(HandleError{err: "Got an announcement_signatures before we were ready for it", action: Some(msgs::ErrorAction::IgnoreError) });
19891990
}
19901991

19911992
let our_node_id = self.get_our_node_id();
19921993
let (announcement, our_bitcoin_sig) = chan.get_channel_announcement(our_node_id.clone(), self.genesis_hash.clone())?;
19931994

19941995
let were_node_one = announcement.node_id_1 == our_node_id;
19951996
let msghash = Message::from_slice(&Sha256dHash::from_data(&announcement.encode()[..])[..]).unwrap();
1996-
secp_call!(self.secp_ctx.verify(&msghash, &msg.node_signature, if were_node_one { &announcement.node_id_2 } else { &announcement.node_id_1 }));
1997-
secp_call!(self.secp_ctx.verify(&msghash, &msg.bitcoin_signature, if were_node_one { &announcement.bitcoin_key_2 } else { &announcement.bitcoin_key_1 }));
1997+
let bad_sig_action = msgs::ErrorAction::SendErrorMessage { msg: msgs::ErrorMessage { channel_id: msg.channel_id.clone(), data: "Invalid signature in announcement_signatures".to_string() } };
1998+
secp_call!(self.secp_ctx.verify(&msghash, &msg.node_signature, if were_node_one { &announcement.node_id_2 } else { &announcement.node_id_1 }), "Bad announcement_signatures node_signature", bad_sig_action);
1999+
secp_call!(self.secp_ctx.verify(&msghash, &msg.bitcoin_signature, if were_node_one { &announcement.bitcoin_key_2 } else { &announcement.bitcoin_key_1 }), "Bad announcement_signatures bitcoin_signature", bad_sig_action);
19982000

19992001
let our_node_sig = self.secp_ctx.sign(&msghash, &self.our_network_key);
20002002

@@ -2006,7 +2008,7 @@ impl ChannelMessageHandler for ChannelManager {
20062008
contents: announcement,
20072009
}, self.get_channel_update(chan).unwrap()) // can only fail if we're not in a ready state
20082010
},
2009-
None => return Err(HandleError{err: "Failed to find corresponding channel", action: None})
2011+
None => return Err(HandleError{err: "Failed to find corresponding channel", action: Some(msgs::ErrorAction::IgnoreError)})
20102012
}
20112013
};
20122014
let mut pending_events = self.pending_events.lock().unwrap();

0 commit comments

Comments
 (0)