HMAC construction/verification for ReceiveTlvs

When receiving a PaymentContext from a blinded payment, the context must
be authenticated. Otherwise, the context can be forged and would appear
within a PaymentPurpose. Add functions for constructing and verifying an
HMAC for the ReceiveTlvs, which contains the PaymentContext.
This commit is contained in:
Jeffrey Czyz 2024-12-01 15:48:47 -05:00
parent 6e85a0db35
commit bd0dd9b9a8
No known key found for this signature in database
GPG key ID: 912EF12EA67705F5
2 changed files with 37 additions and 0 deletions

View file

@ -480,6 +480,20 @@ impl Verification for PaymentHash {
}
}
impl Verification for ReceiveTlvs {
fn hmac_for_offer_payment(
&self, nonce: Nonce, expanded_key: &inbound_payment::ExpandedKey,
) -> Hmac<Sha256> {
signer::hmac_for_payment_tlvs(self, nonce, expanded_key)
}
fn verify_for_offer_payment(
&self, hmac: Hmac<Sha256>, nonce: Nonce, expanded_key: &inbound_payment::ExpandedKey,
) -> Result<(), ()> {
signer::verify_payment_tlvs(self, hmac, nonce, expanded_key)
}
}
/// A user-provided identifier in [`ChannelManager::send_payment`] used to uniquely identify
/// a payment and ensure idempotency in LDK.
///

View file

@ -16,6 +16,7 @@ use bitcoin::hashes::sha256::Hash as Sha256;
use bitcoin::secp256k1::{Keypair, PublicKey, Secp256k1, SecretKey, self};
use types::payment::PaymentHash;
use core::fmt;
use crate::blinded_path::payment::ReceiveTlvs;
use crate::ln::channelmanager::PaymentId;
use crate::ln::inbound_payment::{ExpandedKey, IV_LEN};
use crate::offers::merkle::TlvRecord;
@ -46,6 +47,9 @@ const ASYNC_PAYMENT_ID_HMAC_INPUT: &[u8; 16] = &[6; 16];
// HMAC input for a `PaymentHash`. The HMAC is used in `OffersContext::InboundPayment`.
const PAYMENT_HASH_HMAC_INPUT: &[u8; 16] = &[7; 16];
// HMAC input for `ReceiveTlvs`. The HMAC is used in `blinded_path::payment::PaymentContext`.
const PAYMENT_TLVS_HMAC_INPUT: &[u8; 16] = &[8; 16];
/// Message metadata which possibly is derived from [`MetadataMaterial`] such that it can be
/// verified.
#[derive(Clone)]
@ -459,3 +463,22 @@ fn hmac_for_payment_id(
Hmac::from_engine(hmac)
}
pub(crate) fn hmac_for_payment_tlvs(
receive_tlvs: &ReceiveTlvs, nonce: Nonce, expanded_key: &ExpandedKey,
) -> Hmac<Sha256> {
const IV_BYTES: &[u8; IV_LEN] = b"LDK Payment TLVs";
let mut hmac = expanded_key.hmac_for_offer();
hmac.input(IV_BYTES);
hmac.input(&nonce.0);
hmac.input(PAYMENT_TLVS_HMAC_INPUT);
receive_tlvs.write(&mut hmac).unwrap();
Hmac::from_engine(hmac)
}
pub(crate) fn verify_payment_tlvs(
receive_tlvs: &ReceiveTlvs, hmac: Hmac<Sha256>, nonce: Nonce, expanded_key: &ExpandedKey,
) -> Result<(), ()> {
if hmac_for_payment_tlvs(receive_tlvs, nonce, expanded_key) == hmac { Ok(()) } else { Err(()) }
}