@@ -237,15 +237,7 @@ mod inbound_payment {
237237 pub ( super ) fn verify < L : Deref > ( payment_hash : PaymentHash , payment_data : msgs:: FinalOnionHopData , highest_seen_timestamp : u64 , keys : & ExpandedKey , logger : & L ) -> Result < Option < PaymentPreimage > , ( ) >
238238 where L :: Target : Logger
239239 {
240- let mut iv_bytes = [ 0 ; IV_LEN ] ;
241- let ( iv_slice, encrypted_metadata_bytes) = payment_data. payment_secret . 0 . split_at ( IV_LEN ) ;
242- iv_bytes. copy_from_slice ( iv_slice) ;
243-
244- let chacha_block = ChaCha20 :: get_single_block ( & keys. metadata_key , & iv_bytes) ;
245- let mut metadata_bytes: [ u8 ; METADATA_LEN ] = [ 0 ; METADATA_LEN ] ;
246- for i in 0 ..METADATA_LEN {
247- metadata_bytes[ i] = chacha_block[ i] ^ encrypted_metadata_bytes[ i] ;
248- }
240+ let ( iv_bytes, metadata_bytes) = decrypt_metadata ( payment_data. payment_secret , keys) ;
249241
250242 let payment_type_res = Method :: from_bits ( ( metadata_bytes[ 0 ] & 0b1110_0000 ) >> METHOD_TYPE_OFFSET ) ;
251243 let mut amt_msat_bytes = [ 0 ; AMT_MSAT_LEN ] ;
@@ -269,15 +261,13 @@ mod inbound_payment {
269261 }
270262 } ,
271263 Ok ( Method :: LdkPaymentHash ) => {
272- let mut hmac = HmacEngine :: < Sha256 > :: new ( & keys. ldk_pmt_hash_key ) ;
273- hmac. input ( & iv_bytes) ;
274- hmac. input ( & metadata_bytes) ;
275- let decoded_payment_preimage = Hmac :: from_engine ( hmac) . into_inner ( ) ;
276- if !fixed_time_eq ( & payment_hash. 0 , & Sha256 :: hash ( & decoded_payment_preimage) . into_inner ( ) ) {
277- log_trace ! ( logger, "Failing HTLC with payment_hash {}: payment preimage {} did not match" , log_bytes!( payment_hash. 0 ) , log_bytes!( decoded_payment_preimage) ) ;
278- return Err ( ( ) )
264+ match derive_ldk_payment_preimage ( payment_hash, & iv_bytes, & metadata_bytes, keys) {
265+ Ok ( preimage) => payment_preimage = Some ( preimage) ,
266+ Err ( bad_preimage_bytes) => {
267+ log_trace ! ( logger, "Failing HTLC with payment_hash {} due to mismatching preimage {}" , log_bytes!( payment_hash. 0 ) , log_bytes!( bad_preimage_bytes) ) ;
268+ return Err ( ( ) )
269+ }
279270 }
280- payment_preimage = Some ( PaymentPreimage ( decoded_payment_preimage) ) ;
281271 } ,
282272 Err ( unknown_bits) => {
283273 log_trace ! ( logger, "Failing HTLC with payment hash {} due to unknown payment type {}" , log_bytes!( payment_hash. 0 ) , unknown_bits) ;
@@ -298,6 +288,33 @@ mod inbound_payment {
298288 Ok ( payment_preimage)
299289 }
300290
291+ fn decrypt_metadata ( payment_secret : PaymentSecret , keys : & ExpandedKey ) -> ( [ u8 ; IV_LEN ] , [ u8 ; METADATA_LEN ] ) {
292+ let mut iv_bytes = [ 0 ; IV_LEN ] ;
293+ let ( iv_slice, encrypted_metadata_bytes) = payment_secret. 0 . split_at ( IV_LEN ) ;
294+ iv_bytes. copy_from_slice ( iv_slice) ;
295+
296+ let chacha_block = ChaCha20 :: get_single_block ( & keys. metadata_key , & iv_bytes) ;
297+ let mut metadata_bytes: [ u8 ; METADATA_LEN ] = [ 0 ; METADATA_LEN ] ;
298+ for i in 0 ..METADATA_LEN {
299+ metadata_bytes[ i] = chacha_block[ i] ^ encrypted_metadata_bytes[ i] ;
300+ }
301+
302+ ( iv_bytes, metadata_bytes)
303+ }
304+
305+ // Errors if the payment preimage doesn't match `payment_hash`. Returns the bad preimage bytes in
306+ // this case.
307+ fn derive_ldk_payment_preimage ( payment_hash : PaymentHash , iv_bytes : & [ u8 ; IV_LEN ] , metadata_bytes : & [ u8 ; METADATA_LEN ] , keys : & ExpandedKey ) -> Result < PaymentPreimage , [ u8 ; 32 ] > {
308+ let mut hmac = HmacEngine :: < Sha256 > :: new ( & keys. ldk_pmt_hash_key ) ;
309+ hmac. input ( iv_bytes) ;
310+ hmac. input ( metadata_bytes) ;
311+ let decoded_payment_preimage = Hmac :: from_engine ( hmac) . into_inner ( ) ;
312+ if !fixed_time_eq ( & payment_hash. 0 , & Sha256 :: hash ( & decoded_payment_preimage) . into_inner ( ) ) {
313+ return Err ( decoded_payment_preimage) ;
314+ }
315+ return Ok ( PaymentPreimage ( decoded_payment_preimage) )
316+ }
317+
301318 fn hkdf_extract_expand ( salt : & [ u8 ] , ikm : & KeyMaterial ) -> ExpandedKey {
302319 let mut hmac = HmacEngine :: < Sha256 > :: new ( salt) ;
303320 hmac. input ( & ikm. 0 ) ;
0 commit comments