@@ -11,6 +11,7 @@ use prelude::*;
1111
1212use ln:: msgs:: LightningError ;
1313use ln:: msgs;
14+ use ln:: wire;
1415
1516use bitcoin:: hashes:: { Hash , HashEngine } ;
1617use bitcoin:: hashes:: sha256:: Hash as Sha256 ;
@@ -22,6 +23,7 @@ use bitcoin::secp256k1;
2223
2324use util:: chacha20poly1305rfc:: ChaCha20Poly1305RFC ;
2425use util:: crypto:: hkdf_extract_expand_twice;
26+ use util:: ser:: VecWriter ;
2527use bitcoin:: hashes:: hex:: ToHex ;
2628
2729/// Maximum Lightning message data length according to
@@ -142,6 +144,19 @@ impl PeerChannelEncryptor {
142144 res[ plaintext. len ( ) ..] . copy_from_slice ( & tag) ;
143145 }
144146
147+ #[ inline]
148+ /// Encrypts the message in res[offset..] in-place and pushes a 16-byte tag onto the end of
149+ /// res.
150+ fn encrypt_in_place_with_ad ( res : & mut Vec < u8 > , offset : usize , n : u64 , key : & [ u8 ; 32 ] , h : & [ u8 ] ) {
151+ let mut nonce = [ 0 ; 12 ] ;
152+ nonce[ 4 ..] . copy_from_slice ( & n. to_le_bytes ( ) [ ..] ) ;
153+
154+ let mut chacha = ChaCha20Poly1305RFC :: new ( key, & nonce, h) ;
155+ let mut tag = [ 0 ; 16 ] ;
156+ chacha. encrypt_full_message_in_place ( & mut res[ offset..] , & mut tag) ;
157+ res. extend_from_slice ( & tag) ;
158+ }
159+
145160 #[ inline]
146161 fn decrypt_with_ad ( res : & mut [ u8 ] , n : u64 , key : & [ u8 ; 32 ] , h : & [ u8 ] , cyphertext : & [ u8 ] ) -> Result < ( ) , LightningError > {
147162 let mut nonce = [ 0 ; 12 ] ;
@@ -372,9 +387,9 @@ impl PeerChannelEncryptor {
372387 Ok ( self . their_node_id . unwrap ( ) . clone ( ) )
373388 }
374389
375- /// Encrypts the given message, returning the encrypted version
390+ /// Encrypts the given pre-serialized message, returning the encrypted version.
376391 /// panics if msg.len() > 65535 or Noise handshake has not finished.
377- pub fn encrypt_message ( & mut self , msg : & [ u8 ] ) -> Vec < u8 > {
392+ pub fn encrypt_buffer ( & mut self , msg : & [ u8 ] ) -> Vec < u8 > {
378393 if msg. len ( ) > LN_MAX_MSG_LEN {
379394 panic ! ( "Attempted to encrypt message longer than 65535 bytes!" ) ;
380395 }
@@ -403,6 +418,42 @@ impl PeerChannelEncryptor {
403418 res
404419 }
405420
421+ /// Encrypts the given message, returning the encrypted version.
422+ /// panics if the length of `message`, once encoded, is greater than 65535 or if the Noise
423+ /// handshake has not finished.
424+ pub fn encrypt_message < M : wire:: Type > ( & mut self , message : & M ) -> Vec < u8 > {
425+ // Allocate a buffer with 2KB, fitting most common messages. Reserve the first 16+2 bytes
426+ // for the 2-byte message type prefix and its MAC.
427+ let mut res = VecWriter ( Vec :: with_capacity ( 2048 ) ) ;
428+ res. 0 . resize ( 16 + 2 , 0 ) ;
429+ wire:: write ( message, & mut res) . expect ( "In-memory messages must never fail to serialize" ) ;
430+
431+ let msg_len = res. 0 . len ( ) - 16 - 2 ;
432+ if msg_len > LN_MAX_MSG_LEN {
433+ panic ! ( "Attempted to encrypt message longer than 65535 bytes!" ) ;
434+ }
435+
436+ match self . noise_state {
437+ NoiseState :: Finished { ref mut sk, ref mut sn, ref mut sck, rk : _, rn : _, rck : _ } => {
438+ if * sn >= 1000 {
439+ let ( new_sck, new_sk) = hkdf_extract_expand_twice ( sck, sk) ;
440+ * sck = new_sck;
441+ * sk = new_sk;
442+ * sn = 0 ;
443+ }
444+
445+ Self :: encrypt_with_ad ( & mut res. 0 [ 0 ..16 +2 ] , * sn, sk, & [ 0 ; 0 ] , & ( msg_len as u16 ) . to_be_bytes ( ) ) ;
446+ * sn += 1 ;
447+
448+ Self :: encrypt_in_place_with_ad ( & mut res. 0 , 16 +2 , * sn, sk, & [ 0 ; 0 ] ) ;
449+ * sn += 1 ;
450+ } ,
451+ _ => panic ! ( "Tried to encrypt a message prior to noise handshake completion" ) ,
452+ }
453+
454+ res. 0
455+ }
456+
406457 /// Decrypts a message length header from the remote peer.
407458 /// panics if noise handshake has not yet finished or msg.len() != 18
408459 pub fn decrypt_length_header ( & mut self , msg : & [ u8 ] ) -> Result < u16 , LightningError > {
@@ -682,7 +733,7 @@ mod tests {
682733
683734 for i in 0 ..1005 {
684735 let msg = [ 0x68 , 0x65 , 0x6c , 0x6c , 0x6f ] ;
685- let res = outbound_peer. encrypt_message ( & msg) ;
736+ let res = outbound_peer. encrypt_buffer ( & msg) ;
686737 assert_eq ! ( res. len( ) , 5 + 2 * 16 + 2 ) ;
687738
688739 let len_header = res[ 0 ..2 +16 ] . to_vec ( ) ;
@@ -716,7 +767,7 @@ mod tests {
716767 fn max_message_len_encryption ( ) {
717768 let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors ( ) ;
718769 let msg = [ 4u8 ; LN_MAX_MSG_LEN + 1 ] ;
719- outbound_peer. encrypt_message ( & msg) ;
770+ outbound_peer. encrypt_buffer ( & msg) ;
720771 }
721772
722773 #[ test]
0 commit comments