From 0ca9faf0783ec7eecb5dac5c436411da71583ac7 Mon Sep 17 00:00:00 2001 From: Jeffrey Czyz Date: Thu, 18 Jul 2024 11:45:09 -0500 Subject: [PATCH] Add an HMAC to OffersContext::OutboundPayment When receiving an InvoiceError in response to an InvoiceRequest, the corresponding payment should be abandoned. Add an HMAC to OffersContext::OutboundPayment such that the payment ID can be authenticated prior to abandoning the payment. --- lightning/src/blinded_path/message.rs | 9 +++++++++ lightning/src/ln/channelmanager.rs | 9 ++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/lightning/src/blinded_path/message.rs b/lightning/src/blinded_path/message.rs index 47444eb90..313ac56bf 100644 --- a/lightning/src/blinded_path/message.rs +++ b/lightning/src/blinded_path/message.rs @@ -16,6 +16,8 @@ use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey}; #[allow(unused_imports)] use crate::prelude::*; +use bitcoin::hashes::hmac::Hmac; +use bitcoin::hashes::sha256::Hash as Sha256; use crate::blinded_path::{BlindedHop, BlindedPath, IntroductionNode, NextMessageHop, NodeIdLookUp}; use crate::blinded_path::utils; use crate::io; @@ -146,6 +148,12 @@ pub enum OffersContext { /// [`Refund`]: crate::offers::refund::Refund /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest nonce: Nonce, + + /// Authentication code for the [`PaymentId`], which should be checked when the context is + /// used with an [`InvoiceError`]. + /// + /// [`InvoiceError`]: crate::offers::invoice_error::InvoiceError + hmac: Hmac, }, /// Context used by a [`BlindedPath`] as a reply path for a [`Bolt12Invoice`]. /// @@ -173,6 +181,7 @@ impl_writeable_tlv_based_enum!(OffersContext, (1, OutboundPayment) => { (0, payment_id, required), (1, nonce, required), + (2, hmac, required), }, (2, InboundPayment) => { (0, payment_hash, required), diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 4ce3ebc37..b359df9e5 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -68,6 +68,7 @@ use crate::offers::nonce::Nonce; use crate::offers::offer::{Offer, OfferBuilder}; use crate::offers::parse::Bolt12SemanticError; use crate::offers::refund::{Refund, RefundBuilder}; +use crate::offers::signer; use crate::onion_message::async_payments::{AsyncPaymentsMessage, HeldHtlcAvailable, ReleaseHeldHtlc, AsyncPaymentsMessageHandler}; use crate::onion_message::messenger::{new_pending_onion_message, Destination, MessageRouter, PendingOnionMessage, Responder, ResponseInstruction}; use crate::onion_message::offers::{OffersMessage, OffersMessageHandler}; @@ -4227,7 +4228,7 @@ where None if invoice.is_for_refund_without_paths() => { invoice.verify_using_metadata(expanded_key, secp_ctx) }, - Some(&OffersContext::OutboundPayment { payment_id, nonce }) => { + Some(&OffersContext::OutboundPayment { payment_id, nonce, .. }) => { invoice.verify_using_payer_data(payment_id, nonce, expanded_key, secp_ctx) }, _ => Err(()), @@ -8886,7 +8887,8 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => { let secp_ctx = &$self.secp_ctx; let nonce = Nonce::from_entropy_source(entropy); - let context = OffersContext::OutboundPayment { payment_id, nonce }; + let hmac = signer::hmac_for_payment_id(payment_id, nonce, expanded_key); + let context = OffersContext::OutboundPayment { payment_id, nonce, hmac }; let path = $self.create_blinded_paths_using_absolute_expiry(context, Some(absolute_expiry)) .and_then(|paths| paths.into_iter().next().ok_or(())) .map_err(|_| Bolt12SemanticError::MissingPaths)?; @@ -9021,7 +9023,8 @@ where }; let invoice_request = builder.build_and_sign()?; - let context = OffersContext::OutboundPayment { payment_id, nonce }; + let hmac = signer::hmac_for_payment_id(payment_id, nonce, expanded_key); + let context = OffersContext::OutboundPayment { payment_id, nonce, hmac }; let reply_paths = self.create_blinded_paths(context) .map_err(|_| Bolt12SemanticError::MissingPaths)?; -- 2.39.5