@@ -11,6 +11,7 @@ use prelude::*;
11
11
12
12
use ln:: msgs:: LightningError ;
13
13
use ln:: msgs;
14
+ use ln:: wire;
14
15
15
16
use bitcoin:: hashes:: { Hash , HashEngine } ;
16
17
use bitcoin:: hashes:: sha256:: Hash as Sha256 ;
@@ -22,6 +23,7 @@ use bitcoin::secp256k1;
22
23
23
24
use util:: chacha20poly1305rfc:: ChaCha20Poly1305RFC ;
24
25
use util:: crypto:: hkdf_extract_expand_twice;
26
+ use util:: ser:: VecWriter ;
25
27
use bitcoin:: hashes:: hex:: ToHex ;
26
28
27
29
/// Maximum Lightning message data length according to
@@ -142,6 +144,19 @@ impl PeerChannelEncryptor {
142
144
res[ plaintext. len ( ) ..] . copy_from_slice ( & tag) ;
143
145
}
144
146
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
+
145
160
#[ inline]
146
161
fn decrypt_with_ad ( res : & mut [ u8 ] , n : u64 , key : & [ u8 ; 32 ] , h : & [ u8 ] , cyphertext : & [ u8 ] ) -> Result < ( ) , LightningError > {
147
162
let mut nonce = [ 0 ; 12 ] ;
@@ -372,9 +387,9 @@ impl PeerChannelEncryptor {
372
387
Ok ( self . their_node_id . unwrap ( ) . clone ( ) )
373
388
}
374
389
375
- /// Encrypts the given message, returning the encrypted version
390
+ /// Encrypts the given pre-serialized message, returning the encrypted version.
376
391
/// 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 > {
378
393
if msg. len ( ) > LN_MAX_MSG_LEN {
379
394
panic ! ( "Attempted to encrypt message longer than 65535 bytes!" ) ;
380
395
}
@@ -403,6 +418,42 @@ impl PeerChannelEncryptor {
403
418
res
404
419
}
405
420
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
+
406
457
/// Decrypts a message length header from the remote peer.
407
458
/// panics if noise handshake has not yet finished or msg.len() != 18
408
459
pub fn decrypt_length_header ( & mut self , msg : & [ u8 ] ) -> Result < u16 , LightningError > {
@@ -682,7 +733,7 @@ mod tests {
682
733
683
734
for i in 0 ..1005 {
684
735
let msg = [ 0x68 , 0x65 , 0x6c , 0x6c , 0x6f ] ;
685
- let res = outbound_peer. encrypt_message ( & msg) ;
736
+ let res = outbound_peer. encrypt_buffer ( & msg) ;
686
737
assert_eq ! ( res. len( ) , 5 + 2 * 16 + 2 ) ;
687
738
688
739
let len_header = res[ 0 ..2 +16 ] . to_vec ( ) ;
@@ -716,7 +767,7 @@ mod tests {
716
767
fn max_message_len_encryption ( ) {
717
768
let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors ( ) ;
718
769
let msg = [ 4u8 ; LN_MAX_MSG_LEN + 1 ] ;
719
- outbound_peer. encrypt_message ( & msg) ;
770
+ outbound_peer. encrypt_buffer ( & msg) ;
720
771
}
721
772
722
773
#[ test]
0 commit comments