@@ -15,7 +15,7 @@ use routing::gossip::NetworkUpdate;
15
15
use routing:: router:: RouteHop ;
16
16
use util:: chacha20:: { ChaCha20 , ChaChaReader } ;
17
17
use util:: errors:: { self , APIError } ;
18
- use util:: ser:: { Readable , Writeable , LengthCalculatingWriter } ;
18
+ use util:: ser:: { Readable , ReadableArgs , Writeable , LengthCalculatingWriter } ;
19
19
use util:: logger:: Logger ;
20
20
21
21
use bitcoin:: hashes:: { Hash , HashEngine } ;
@@ -82,7 +82,7 @@ pub(super) fn gen_ammag_from_shared_secret(shared_secret: &[u8]) -> [u8; 32] {
82
82
Hmac :: from_engine ( hmac) . into_inner ( )
83
83
}
84
84
85
- pub ( super ) fn next_hop_packet_pubkey < T : secp256k1:: Signing + secp256k1:: Verification > ( secp_ctx : & Secp256k1 < T > , mut packet_pubkey : PublicKey , packet_shared_secret : & [ u8 ; 32 ] ) -> Result < PublicKey , secp256k1:: Error > {
85
+ pub ( crate ) fn next_hop_packet_pubkey < T : secp256k1:: Signing + secp256k1:: Verification > ( secp_ctx : & Secp256k1 < T > , mut packet_pubkey : PublicKey , packet_shared_secret : & [ u8 ; 32 ] ) -> Result < PublicKey , secp256k1:: Error > {
86
86
let blinding_factor = {
87
87
let mut sha = Sha256 :: engine ( ) ;
88
88
sha. input ( & packet_pubkey. serialize ( ) [ ..] ) ;
@@ -580,7 +580,50 @@ pub(super) fn process_onion_failure<T: secp256k1::Signing, L: Deref>(secp_ctx: &
580
580
} else { unreachable ! ( ) ; }
581
581
}
582
582
583
- /// Data decrypted from the onion payload.
583
+ /// An input used when decoding an onion packet.
584
+ pub ( crate ) trait DecodeInput {
585
+ type Arg ;
586
+ /// If Some, this is the input when checking the hmac of the onion packet.
587
+ fn payment_hash ( & self ) -> Option < & PaymentHash > ;
588
+ /// Read argument when decrypting our hop payload.
589
+ fn read_arg ( self ) -> Self :: Arg ;
590
+ }
591
+
592
+ impl DecodeInput for PaymentHash {
593
+ type Arg = ( ) ;
594
+ fn payment_hash ( & self ) -> Option < & PaymentHash > {
595
+ Some ( self )
596
+ }
597
+ fn read_arg ( self ) -> Self :: Arg { ( ) }
598
+ }
599
+
600
+ impl DecodeInput for SharedSecret {
601
+ type Arg = SharedSecret ;
602
+ fn payment_hash ( & self ) -> Option < & PaymentHash > {
603
+ None
604
+ }
605
+ fn read_arg ( self ) -> Self :: Arg { self }
606
+ }
607
+
608
+ /// Allows `decode_next_hop` to return the next hop packet bytes for either payments or onion
609
+ /// message forwards.
610
+ pub ( crate ) trait NextPacketBytes : AsMut < [ u8 ] > {
611
+ fn new ( len : usize ) -> Self ;
612
+ }
613
+
614
+ impl NextPacketBytes for FixedSizeOnionPacket {
615
+ fn new ( _len : usize ) -> Self {
616
+ Self ( [ 0 as u8 ; ONION_DATA_LEN ] )
617
+ }
618
+ }
619
+
620
+ impl NextPacketBytes for Vec < u8 > {
621
+ fn new ( len : usize ) -> Self {
622
+ vec ! [ 0 as u8 ; len]
623
+ }
624
+ }
625
+
626
+ /// Data decrypted from a payment's onion payload.
584
627
pub ( crate ) enum Hop {
585
628
/// This onion payload was for us, not for forwarding to a next-hop. Contains information for
586
629
/// verifying the incoming payment.
@@ -592,11 +635,12 @@ pub(crate) enum Hop {
592
635
/// HMAC of the next hop's onion packet.
593
636
next_hop_hmac : [ u8 ; 32 ] ,
594
637
/// Bytes of the onion packet we're forwarding.
595
- new_packet_bytes : [ u8 ; 20 * 65 ] ,
638
+ new_packet_bytes : [ u8 ; ONION_DATA_LEN ] ,
596
639
} ,
597
640
}
598
641
599
642
/// Error returned when we fail to decode the onion packet.
643
+ #[ derive( Debug ) ]
600
644
pub ( crate ) enum OnionDecodeErr {
601
645
/// The HMAC of the onion packet did not match the hop data.
602
646
Malformed {
@@ -610,11 +654,27 @@ pub(crate) enum OnionDecodeErr {
610
654
} ,
611
655
}
612
656
613
- pub ( crate ) fn decode_next_hop ( shared_secret : [ u8 ; 32 ] , hop_data : & [ u8 ] , hmac_bytes : [ u8 ; 32 ] , payment_hash : PaymentHash ) -> Result < Hop , OnionDecodeErr > {
657
+ pub ( crate ) fn decode_next_payment_hop ( shared_secret : [ u8 ; 32 ] , hop_data : & [ u8 ] , hmac_bytes : [ u8 ; 32 ] , payment_hash : PaymentHash ) -> Result < Hop , OnionDecodeErr > {
658
+ match decode_next_hop ( shared_secret, hop_data, hmac_bytes, payment_hash) {
659
+ Ok ( ( next_hop_data, None ) ) => Ok ( Hop :: Receive ( next_hop_data) ) ,
660
+ Ok ( ( next_hop_data, Some ( ( next_hop_hmac, FixedSizeOnionPacket ( new_packet_bytes) ) ) ) ) => {
661
+ Ok ( Hop :: Forward {
662
+ next_hop_data,
663
+ next_hop_hmac,
664
+ new_packet_bytes
665
+ } )
666
+ } ,
667
+ Err ( e) => Err ( e) ,
668
+ }
669
+ }
670
+
671
+ pub ( crate ) fn decode_next_hop < D : DecodeInput , R : ReadableArgs < D :: Arg > , N : NextPacketBytes > ( shared_secret : [ u8 ; 32 ] , hop_data : & [ u8 ] , hmac_bytes : [ u8 ; 32 ] , decode_input : D ) -> Result < ( R , Option < ( [ u8 ; 32 ] , N ) > ) , OnionDecodeErr > {
614
672
let ( rho, mu) = gen_rho_mu_from_shared_secret ( & shared_secret) ;
615
673
let mut hmac = HmacEngine :: < Sha256 > :: new ( & mu) ;
616
674
hmac. input ( hop_data) ;
617
- hmac. input ( & payment_hash. 0 [ ..] ) ;
675
+ if let Some ( payment_hash) = decode_input. payment_hash ( ) {
676
+ hmac. input ( & payment_hash. 0 [ ..] ) ;
677
+ }
618
678
if !fixed_time_eq ( & Hmac :: from_engine ( hmac) . into_inner ( ) , & hmac_bytes) {
619
679
return Err ( OnionDecodeErr :: Malformed {
620
680
err_msg : "HMAC Check failed" ,
@@ -624,7 +684,7 @@ pub(crate) fn decode_next_hop(shared_secret: [u8; 32], hop_data: &[u8], hmac_byt
624
684
625
685
let mut chacha = ChaCha20 :: new ( & rho, & [ 0u8 ; 8 ] ) ;
626
686
let mut chacha_stream = ChaChaReader { chacha : & mut chacha, read : Cursor :: new ( & hop_data[ ..] ) } ;
627
- match <msgs :: OnionHopData as Readable > :: read ( & mut chacha_stream) {
687
+ match R :: read ( & mut chacha_stream, decode_input . read_arg ( ) ) {
628
688
Err ( err) => {
629
689
let error_code = match err {
630
690
msgs:: DecodeError :: UnknownVersion => 0x4000 | 1 , // unknown realm byte
@@ -662,10 +722,10 @@ pub(crate) fn decode_next_hop(shared_secret: [u8; 32], hop_data: &[u8], hmac_byt
662
722
chacha_stream. read_exact ( & mut next_bytes) . unwrap ( ) ;
663
723
assert_ne ! ( next_bytes[ ..] , [ 0 ; 32 ] [ ..] ) ;
664
724
}
665
- return Ok ( Hop :: Receive ( msg) ) ;
725
+ return Ok ( ( msg, None ) ) ; // We are the final destination for this packet
666
726
} else {
667
- let mut new_packet_bytes = [ 0 ; 20 * 65 ] ;
668
- let read_pos = chacha_stream. read ( & mut new_packet_bytes) . unwrap ( ) ;
727
+ let mut new_packet_bytes = N :: new ( hop_data . len ( ) ) ;
728
+ let read_pos = chacha_stream. read ( new_packet_bytes. as_mut ( ) ) . unwrap ( ) ;
669
729
#[ cfg( debug_assertions) ]
670
730
{
671
731
// Check two things:
@@ -677,12 +737,8 @@ pub(crate) fn decode_next_hop(shared_secret: [u8; 32], hop_data: &[u8], hmac_byt
677
737
}
678
738
// Once we've emptied the set of bytes our peer gave us, encrypt 0 bytes until we
679
739
// fill the onion hop data we'll forward to our next-hop peer.
680
- chacha_stream. chacha . process_in_place ( & mut new_packet_bytes[ read_pos..] ) ;
681
- return Ok ( Hop :: Forward {
682
- next_hop_data : msg,
683
- next_hop_hmac : hmac,
684
- new_packet_bytes,
685
- } )
740
+ chacha_stream. chacha . process_in_place ( & mut new_packet_bytes. as_mut ( ) [ read_pos..] ) ;
741
+ return Ok ( ( msg, Some ( ( hmac, new_packet_bytes) ) ) ) // This packet needs forwarding
686
742
}
687
743
} ,
688
744
}
0 commit comments