Skip to content

Commit bd0dd9b

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 6e85a0d commit bd0dd9b

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
@@ -480,6 +480,20 @@ impl Verification for PaymentHash {
480480
}
481481
}
482482

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

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)