From fa6c0587e7de6ba1e9bd908f0ea4efbd3f827668 Mon Sep 17 00:00:00 2001 From: Jeffrey Czyz Date: Fri, 16 Aug 2024 11:26:44 -0500 Subject: [PATCH 1/2] Return a Result from verify_payment_id --- lightning/src/ln/channelmanager.rs | 2 +- lightning/src/offers/signer.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index c6645956b18..303c0d59ea2 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -10900,7 +10900,7 @@ where match context { Some(OffersContext::OutboundPayment { payment_id, nonce, hmac: Some(hmac) }) => { - if signer::verify_payment_id(payment_id, hmac, nonce, expanded_key) { + if let Ok(()) = signer::verify_payment_id(payment_id, hmac, nonce, expanded_key) { self.abandon_payment_with_reason( payment_id, PaymentFailureReason::InvoiceRequestRejected, ); diff --git a/lightning/src/offers/signer.rs b/lightning/src/offers/signer.rs index 0aa51cd3338..2ee54c58811 100644 --- a/lightning/src/offers/signer.rs +++ b/lightning/src/offers/signer.rs @@ -410,6 +410,6 @@ pub(crate) fn hmac_for_payment_id( pub(crate) fn verify_payment_id( payment_id: PaymentId, hmac: Hmac, nonce: Nonce, expanded_key: &ExpandedKey, -) -> bool { - hmac_for_payment_id(payment_id, nonce, expanded_key) == hmac +) -> Result<(), ()> { + if hmac_for_payment_id(payment_id, nonce, expanded_key) == hmac { Ok(()) } else { Err(()) } } From 5bee20e2375a8e0ef9dc9e229f5d1f6997901e46 Mon Sep 17 00:00:00 2001 From: Jeffrey Czyz Date: Wed, 14 Aug 2024 17:39:13 -0500 Subject: [PATCH 2/2] Add PaymentId authentication to public API When receiving an InvoiceError message, it should be authenticated before using it to abandon the payment. Add methods to PaymentId's public API for constructing and verifying an HMAC for use in OffersContext::OutboundPayment. This allows other implementations of OffersMessageHandler to construct the HMAC and authenticate the message. --- lightning/src/ln/channelmanager.rs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 303c0d59ea2..316148b1c5e 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -24,6 +24,7 @@ use bitcoin::key::constants::SECRET_KEY_SIZE; use bitcoin::network::Network; use bitcoin::hashes::Hash; +use bitcoin::hashes::hmac::Hmac; use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::hash_types::{BlockHash, Txid}; @@ -413,6 +414,22 @@ pub struct PaymentId(pub [u8; Self::LENGTH]); impl PaymentId { /// Number of bytes in the id. pub const LENGTH: usize = 32; + + /// Constructs an HMAC to include in [`OffersContext::OutboundPayment`] for the payment id + /// along with the given [`Nonce`]. + pub fn hmac_for_offer_payment( + &self, nonce: Nonce, expanded_key: &inbound_payment::ExpandedKey, + ) -> Hmac { + signer::hmac_for_payment_id(*self, nonce, expanded_key) + } + + /// Authenticates the payment id using an HMAC and a [`Nonce`] taken from an + /// [`OffersContext::OutboundPayment`]. + pub fn verify( + &self, hmac: Hmac, nonce: Nonce, expanded_key: &inbound_payment::ExpandedKey, + ) -> Result<(), ()> { + signer::verify_payment_id(*self, hmac, nonce, expanded_key) + } } impl Writeable for PaymentId { @@ -9024,7 +9041,7 @@ where }; let invoice_request = builder.build_and_sign()?; - let hmac = signer::hmac_for_payment_id(payment_id, nonce, expanded_key); + let hmac = payment_id.hmac_for_offer_payment(nonce, expanded_key); let context = OffersContext::OutboundPayment { payment_id, nonce, hmac: Some(hmac) }; let reply_paths = self.create_blinded_paths(context) .map_err(|_| Bolt12SemanticError::MissingPaths)?; @@ -10900,7 +10917,7 @@ where match context { Some(OffersContext::OutboundPayment { payment_id, nonce, hmac: Some(hmac) }) => { - if let Ok(()) = signer::verify_payment_id(payment_id, hmac, nonce, expanded_key) { + if let Ok(()) = payment_id.verify(hmac, nonce, expanded_key) { self.abandon_payment_with_reason( payment_id, PaymentFailureReason::InvoiceRequestRejected, );