Ok(msgs::OnionPacket{
version: 0,
- public_key: onion_keys.first().unwrap().ephemeral_pubkey,
+ public_key: Ok(onion_keys.first().unwrap().ephemeral_pubkey),
hop_data: packet_data,
hmac: hmac_res,
})
ChannelManager::encrypt_failure_packet(shared_secret, &failure_packet.encode()[..])
}
- fn decode_update_add_htlc_onion(&self, msg: &msgs::UpdateAddHTLC) -> (PendingHTLCStatus, SharedSecret, MutexGuard<ChannelHolder>) {
- let shared_secret = SharedSecret::new(&self.secp_ctx, &msg.onion_routing_packet.public_key, &self.our_network_key);
- let (rho, mu) = ChannelManager::gen_rho_mu_from_shared_secret(&shared_secret);
-
+ fn decode_update_add_htlc_onion(&self, msg: &msgs::UpdateAddHTLC) -> (PendingHTLCStatus, Option<SharedSecret>, MutexGuard<ChannelHolder>) {
macro_rules! get_onion_hash {
() => {
{
}
}
+ if let Err(_) = msg.onion_routing_packet.public_key {
+ log_info!(self, "Failed to accept/forward incoming HTLC with invalid ephemeral pubkey");
+ return (PendingHTLCStatus::Fail(HTLCFailureMsg::Malformed(msgs::UpdateFailMalformedHTLC {
+ channel_id: msg.channel_id,
+ htlc_id: msg.htlc_id,
+ sha256_of_onion: get_onion_hash!(),
+ failure_code: 0x8000 | 0x4000 | 6,
+ })), None, self.channel_state.lock().unwrap());
+ }
+
+ let shared_secret = SharedSecret::new(&self.secp_ctx, &msg.onion_routing_packet.public_key.unwrap(), &self.our_network_key);
+ let (rho, mu) = ChannelManager::gen_rho_mu_from_shared_secret(&shared_secret);
+
let mut channel_state = None;
macro_rules! return_err {
($msg: expr, $err_code: expr, $data: expr) => {
channel_id: msg.channel_id,
htlc_id: msg.htlc_id,
reason: ChannelManager::build_first_hop_failure_packet(&shared_secret, $err_code, $data),
- })), shared_secret, channel_state.unwrap());
+ })), Some(shared_secret), channel_state.unwrap());
}
}
}
chacha.process(&msg.onion_routing_packet.hop_data[65..], &mut new_packet_data[0..19*65]);
chacha.process(&ChannelManager::ZERO[0..65], &mut new_packet_data[19*65..]);
- let mut new_pubkey = msg.onion_routing_packet.public_key.clone();
+ let mut new_pubkey = msg.onion_routing_packet.public_key.unwrap();
let blinding_factor = {
let mut sha = Sha256::new();
sha.result(&mut res);
match SecretKey::from_slice(&self.secp_ctx, &res) {
Err(_) => {
- // Return temporary node failure as its technically our issue, not the
- // channel's issue.
- return_err!("Blinding factor is an invalid private key", 0x2000 | 2, &[0;0]);
+ return_err!("Blinding factor is an invalid private key", 0x8000 | 0x4000 | 6, &get_onion_hash!());
},
Ok(key) => key
}
};
- match new_pubkey.mul_assign(&self.secp_ctx, &blinding_factor) {
- Err(_) => {
- // Return temporary node failure as its technically our issue, not the
- // channel's issue.
- return_err!("New blinding factor is an invalid private key", 0x2000 | 2, &[0;0]);
- },
- Ok(_) => {}
- };
+ if let Err(_) = new_pubkey.mul_assign(&self.secp_ctx, &blinding_factor) {
+ return_err!("New blinding factor is an invalid private key", 0x8000 | 0x4000 | 6, &get_onion_hash!());
+ }
let outgoing_packet = msgs::OnionPacket {
version: 0,
- public_key: new_pubkey,
+ public_key: Ok(new_pubkey),
hop_data: new_packet_data,
hmac: next_hop_data.hmac.clone(),
};
}
}
- (pending_forward_info, shared_secret, channel_state.unwrap())
+ (pending_forward_info, Some(shared_secret), channel_state.unwrap())
}
/// only fails if the channel does not yet have an assigned short_id
pending_forward_info = PendingHTLCStatus::Fail(HTLCFailureMsg::Relay(msgs::UpdateFailHTLC {
channel_id: msg.channel_id,
htlc_id: msg.htlc_id,
- reason: ChannelManager::build_first_hop_failure_packet(&shared_secret, 0x4000 | 0x2000 | 2, &[0;0]),
+ reason: ChannelManager::build_first_hop_failure_packet(&shared_secret.unwrap(), 0x4000 | 0x2000 | 2, &[0;0]),
}));
} else {
will_forward = true;
};
*outbound_route = PendingOutboundHTLC::CycledRoute {
source_short_channel_id,
- incoming_packet_shared_secret: shared_secret,
+ incoming_packet_shared_secret: shared_secret.unwrap(),
route,
session_priv,
};
hash_map::Entry::Vacant(e) => {
e.insert(PendingOutboundHTLC::IntermediaryHopData {
source_short_channel_id,
- incoming_packet_shared_secret: shared_secret,
+ incoming_packet_shared_secret: shared_secret.unwrap(),
});
}
}
use secp256k1::key::PublicKey;
use secp256k1::{Secp256k1, Signature};
+use secp256k1;
use bitcoin::util::hash::Sha256dHash;
use bitcoin::network::serialize::{deserialize,serialize};
use bitcoin::blockdata::script::Script;
#[derive(Clone)]
pub struct OnionPacket {
pub version: u8,
- pub public_key: PublicKey,
+ /// In order to ensure we always return an error on Onion decode in compliance with BOLT 4, we
+ /// have to deserialize OnionPackets contained in UpdateAddHTLCs even if the ephemeral public
+ /// key (here) is bogus, so we hold a Result instead of a PublicKey as we'd like.
+ pub public_key: Result<PublicKey, secp256k1::Error>,
pub hop_data: [u8; 20*65],
pub hmac: [u8; 32],
}
let secp_ctx = Secp256k1::without_caps();
Ok(Self {
version: v[0],
- public_key: secp_pubkey!(&secp_ctx, &v[1..34]),
+ public_key: PublicKey::from_slice(&secp_ctx, &v[1..34]),
hop_data,
hmac,
})
fn encode(&self) -> Vec<u8> {
let mut res = Vec::with_capacity(1 + 33 + 20*65 + 32);
res.push(self.version);
- res.extend_from_slice(&self.public_key.serialize());
+ match self.public_key {
+ Ok(pubkey) => res.extend_from_slice(&pubkey.serialize()),
+ Err(_) => res.extend_from_slice(&[0; 33]),
+ }
res.extend_from_slice(&self.hop_data);
res.extend_from_slice(&self.hmac);
res