Skip to content

Commit 5f068df

Browse files
committed
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.
1 parent 0c31021 commit 5f068df

File tree

2 files changed

+37
-0
lines changed

2 files changed

+37
-0
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,20 @@ impl Verification for PaymentHash {
477477
}
478478
}
479479

480+
impl Verification for ReceiveTlvs {
481+
fn hmac_for_offer_payment(
482+
&self, nonce: Nonce, expanded_key: &inbound_payment::ExpandedKey,
483+
) -> Hmac<Sha256> {
484+
signer::hmac_for_payment_tlvs(self, nonce, expanded_key)
485+
}
486+
487+
fn verify_for_offer_payment(
488+
&self, hmac: Hmac<Sha256>, nonce: Nonce, expanded_key: &inbound_payment::ExpandedKey,
489+
) -> Result<(), ()> {
490+
signer::verify_payment_tlvs(self, hmac, nonce, expanded_key)
491+
}
492+
}
493+
480494
/// A user-provided identifier in [`ChannelManager::send_payment`] used to uniquely identify
481495
/// a payment and ensure idempotency in LDK.
482496
///

lightning/src/offers/signer.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use bitcoin::hashes::sha256::Hash as Sha256;
1616
use bitcoin::secp256k1::{Keypair, PublicKey, Secp256k1, SecretKey, self};
1717
use types::payment::PaymentHash;
1818
use core::fmt;
19+
use crate::blinded_path::payment::ReceiveTlvs;
1920
use crate::ln::channelmanager::PaymentId;
2021
use crate::ln::inbound_payment::{ExpandedKey, IV_LEN};
2122
use crate::offers::merkle::TlvRecord;
@@ -46,6 +47,9 @@ const ASYNC_PAYMENT_ID_HMAC_INPUT: &[u8; 16] = &[6; 16];
4647
// HMAC input for a `PaymentHash`. The HMAC is used in `OffersContext::InboundPayment`.
4748
const PAYMENT_HASH_HMAC_INPUT: &[u8; 16] = &[7; 16];
4849

50+
// HMAC input for `ReceiveTlvs`. The HMAC is used in `blinded_path::payment::PaymentContext`.
51+
const PAYMENT_TLVS_HMAC_INPUT: &[u8; 16] = &[8; 16];
52+
4953
/// Message metadata which possibly is derived from [`MetadataMaterial`] such that it can be
5054
/// verified.
5155
#[derive(Clone)]
@@ -459,3 +463,22 @@ fn hmac_for_payment_id(
459463

460464
Hmac::from_engine(hmac)
461465
}
466+
467+
pub(crate) fn hmac_for_payment_tlvs(
468+
receive_tlvs: &ReceiveTlvs, nonce: Nonce, expanded_key: &ExpandedKey,
469+
) -> Hmac<Sha256> {
470+
const IV_BYTES: &[u8; IV_LEN] = b"LDK Payment TLVs";
471+
let mut hmac = expanded_key.hmac_for_offer();
472+
hmac.input(IV_BYTES);
473+
hmac.input(&nonce.0);
474+
hmac.input(PAYMENT_TLVS_HMAC_INPUT);
475+
receive_tlvs.write(&mut hmac).unwrap();
476+
477+
Hmac::from_engine(hmac)
478+
}
479+
480+
pub(crate) fn verify_payment_tlvs(
481+
receive_tlvs: &ReceiveTlvs, hmac: Hmac<Sha256>, nonce: Nonce, expanded_key: &ExpandedKey,
482+
) -> Result<(), ()> {
483+
if hmac_for_payment_tlvs(receive_tlvs, nonce, expanded_key) == hmac { Ok(()) } else { Err(()) }
484+
}

0 commit comments

Comments
 (0)