From b1fbd7fbbaa92dde20d292307f4f4347e4c01450 Mon Sep 17 00:00:00 2001 From: Mathias Hall-Andersen Date: Mon, 18 Nov 2019 12:04:20 +0100 Subject: Bug fixes from compliance tests with WireGuard --- src/wireguard/handshake/device.rs | 202 ++------------------------------------ src/wireguard/handshake/mod.rs | 3 + src/wireguard/handshake/noise.rs | 27 ++--- src/wireguard/handshake/peer.rs | 6 +- src/wireguard/handshake/tests.rs | 197 +++++++++++++++++++++++++++++++++++++ src/wireguard/router/device.rs | 14 +++ src/wireguard/router/peer.rs | 2 +- src/wireguard/router/route.rs | 28 ++++-- src/wireguard/router/workers.rs | 3 - src/wireguard/types.rs | 24 ++++- src/wireguard/wireguard.rs | 15 ++- 11 files changed, 291 insertions(+), 230 deletions(-) create mode 100644 src/wireguard/handshake/tests.rs (limited to 'src') diff --git a/src/wireguard/handshake/device.rs b/src/wireguard/handshake/device.rs index 030c0f8..8e16248 100644 --- a/src/wireguard/handshake/device.rs +++ b/src/wireguard/handshake/device.rs @@ -231,11 +231,11 @@ impl Device { (_, None) => Err(HandshakeError::UnknownPublicKey), (None, _) => Err(HandshakeError::UnknownPublicKey), (Some(keyst), Some(peer)) => { - let sender = self.allocate(rng, peer); + let local = self.allocate(rng, peer); let mut msg = Initiation::default(); // create noise part of initation - noise::create_initiation(rng, keyst, peer, sender, &mut msg.noise)?; + noise::create_initiation(rng, keyst, peer, local, &mut msg.noise)?; // add macs to initation peer.macs @@ -312,18 +312,17 @@ impl Device { let (peer, st) = noise::consume_initiation(self, keyst, &msg.noise)?; // allocate new index for response - let sender = self.allocate(rng, peer); + let local = self.allocate(rng, peer); // prepare memory for response, TODO: take slice for zero allocation let mut resp = Response::default(); // create response (release id on error) - let keys = noise::create_response(rng, peer, sender, st, &mut resp.noise).map_err( - |e| { - self.release(sender); + let keys = + noise::create_response(rng, peer, local, st, &mut resp.noise).map_err(|e| { + self.release(local); e - }, - )?; + })?; // add macs to response peer.macs @@ -425,190 +424,3 @@ impl Device { } } } - -#[cfg(test)] -mod tests { - use super::super::messages::*; - use super::*; - use hex; - use rand::rngs::OsRng; - use std::net::SocketAddr; - use std::thread; - use std::time::Duration; - - fn setup_devices( - rng: &mut R, - ) -> (PublicKey, Device, PublicKey, Device) { - // generate new keypairs - - let sk1 = StaticSecret::new(rng); - let pk1 = PublicKey::from(&sk1); - - let sk2 = StaticSecret::new(rng); - let pk2 = PublicKey::from(&sk2); - - // pick random psk - - let mut psk = [0u8; 32]; - rng.fill_bytes(&mut psk[..]); - - // intialize devices on both ends - - let mut dev1 = Device::new(); - let mut dev2 = Device::new(); - - dev1.set_sk(Some(sk1)); - dev2.set_sk(Some(sk2)); - - dev1.add(pk2).unwrap(); - dev2.add(pk1).unwrap(); - - dev1.set_psk(pk2, psk).unwrap(); - dev2.set_psk(pk1, psk).unwrap(); - - (pk1, dev1, pk2, dev2) - } - - fn wait() { - thread::sleep(Duration::from_millis(20)); - } - - /* Test longest possible handshake interaction (7 messages): - * - * 1. I -> R (initation) - * 2. I <- R (cookie reply) - * 3. I -> R (initation) - * 4. I <- R (response) - * 5. I -> R (cookie reply) - * 6. I -> R (initation) - * 7. I <- R (response) - */ - #[test] - fn handshake_under_load() { - let mut rng = OsRng::new().unwrap(); - let (_pk1, dev1, pk2, dev2) = setup_devices(&mut rng); - - let src1: SocketAddr = "172.16.0.1:8080".parse().unwrap(); - let src2: SocketAddr = "172.16.0.2:7070".parse().unwrap(); - - // 1. device-1 : create first initation - let msg_init = dev1.begin(&mut rng, &pk2).unwrap(); - - // 2. device-2 : responds with CookieReply - let msg_cookie = match dev2.process(&mut rng, &msg_init, Some(&src1)).unwrap() { - (None, Some(msg), None) => msg, - _ => panic!("unexpected response"), - }; - - // device-1 : processes CookieReply (no response) - match dev1.process(&mut rng, &msg_cookie, Some(&src2)).unwrap() { - (None, None, None) => (), - _ => panic!("unexpected response"), - } - - // avoid initation flood detection - wait(); - - // 3. device-1 : create second initation - let msg_init = dev1.begin(&mut rng, &pk2).unwrap(); - - // 4. device-2 : responds with noise response - let msg_response = match dev2.process(&mut rng, &msg_init, Some(&src1)).unwrap() { - (Some(_), Some(msg), Some(kp)) => { - assert_eq!(kp.initiator, false); - msg - } - _ => panic!("unexpected response"), - }; - - // 5. device-1 : responds with CookieReply - let msg_cookie = match dev1.process(&mut rng, &msg_response, Some(&src2)).unwrap() { - (None, Some(msg), None) => msg, - _ => panic!("unexpected response"), - }; - - // device-2 : processes CookieReply (no response) - match dev2.process(&mut rng, &msg_cookie, Some(&src1)).unwrap() { - (None, None, None) => (), - _ => panic!("unexpected response"), - } - - // avoid initation flood detection - wait(); - - // 6. device-1 : create third initation - let msg_init = dev1.begin(&mut rng, &pk2).unwrap(); - - // 7. device-2 : responds with noise response - let (msg_response, kp1) = match dev2.process(&mut rng, &msg_init, Some(&src1)).unwrap() { - (Some(_), Some(msg), Some(kp)) => { - assert_eq!(kp.initiator, false); - (msg, kp) - } - _ => panic!("unexpected response"), - }; - - // device-1 : process noise response - let kp2 = match dev1.process(&mut rng, &msg_response, Some(&src2)).unwrap() { - (Some(_), None, Some(kp)) => { - assert_eq!(kp.initiator, true); - kp - } - _ => panic!("unexpected response"), - }; - - assert_eq!(kp1.send, kp2.recv); - assert_eq!(kp1.recv, kp2.send); - } - - #[test] - fn handshake_no_load() { - let mut rng = OsRng::new().unwrap(); - let (pk1, mut dev1, pk2, mut dev2) = setup_devices(&mut rng); - - // do a few handshakes (every handshake should succeed) - - for i in 0..10 { - println!("handshake : {}", i); - - // create initiation - - let msg1 = dev1.begin(&mut rng, &pk2).unwrap(); - - println!("msg1 = {} : {} bytes", hex::encode(&msg1[..]), msg1.len()); - println!("msg1 = {:?}", Initiation::parse(&msg1[..]).unwrap()); - - // process initiation and create response - - let (_, msg2, ks_r) = dev2.process(&mut rng, &msg1, None).unwrap(); - - let ks_r = ks_r.unwrap(); - let msg2 = msg2.unwrap(); - - println!("msg2 = {} : {} bytes", hex::encode(&msg2[..]), msg2.len()); - println!("msg2 = {:?}", Response::parse(&msg2[..]).unwrap()); - - assert!(!ks_r.initiator, "Responders key-pair is confirmed"); - - // process response and obtain confirmed key-pair - - let (_, msg3, ks_i) = dev1.process(&mut rng, &msg2, None).unwrap(); - let ks_i = ks_i.unwrap(); - - assert!(msg3.is_none(), "Returned message after response"); - assert!(ks_i.initiator, "Initiators key-pair is not confirmed"); - - assert_eq!(ks_i.send, ks_r.recv, "KeyI.send != KeyR.recv"); - assert_eq!(ks_i.recv, ks_r.send, "KeyI.recv != KeyR.send"); - - dev1.release(ks_i.send.id); - dev2.release(ks_r.send.id); - - // avoid initation flood detection - wait(); - } - - dev1.remove(pk2).unwrap(); - dev2.remove(pk1).unwrap(); - } -} diff --git a/src/wireguard/handshake/mod.rs b/src/wireguard/handshake/mod.rs index 071a41f..3a95817 100644 --- a/src/wireguard/handshake/mod.rs +++ b/src/wireguard/handshake/mod.rs @@ -15,6 +15,9 @@ mod ratelimiter; mod timestamp; mod types; +#[cfg(test)] +mod tests; + // publicly exposed interface pub use device::Device; diff --git a/src/wireguard/handshake/noise.rs b/src/wireguard/handshake/noise.rs index 6db300a..46188b4 100644 --- a/src/wireguard/handshake/noise.rs +++ b/src/wireguard/handshake/noise.rs @@ -221,7 +221,7 @@ pub fn create_initiation( rng: &mut R, keyst: &KeyState, peer: &Peer, - sender: u32, + local: u32, msg: &mut NoiseInitiation, ) -> Result<(), HandshakeError> { debug!("create initation"); @@ -233,7 +233,7 @@ pub fn create_initiation( let hs = HASH!(&hs, peer.pk.as_bytes()); msg.f_type.set(TYPE_INITIATION as u32); - msg.f_sender.set(sender); + msg.f_sender.set(local); // from us // (E_priv, E_pub) := DH-Generate() @@ -292,7 +292,7 @@ pub fn create_initiation( hs, ck, eph_sk, - sender, + local, }; Ok(()) @@ -378,7 +378,7 @@ pub fn consume_initiation<'a>( pub fn create_response( rng: &mut R, peer: &Peer, - sender: u32, // sending identifier + local: u32, // sending identifier state: TemporaryState, // state from "consume_initiation" msg: &mut NoiseResponse, // resulting response ) -> Result { @@ -389,8 +389,8 @@ pub fn create_response( let (receiver, eph_r_pk, hs, ck) = state; msg.f_type.set(TYPE_RESPONSE as u32); - msg.f_sender.set(sender); - msg.f_receiver.set(receiver); + msg.f_sender.set(local); // from us + msg.f_receiver.set(receiver); // to the sender of the initation // (E_priv, E_pub) := DH-Generate() @@ -447,11 +447,11 @@ pub fn create_response( birth: Instant::now(), initiator: false, send: Key { - id: sender, + id: receiver, key: key_send.into(), }, recv: Key { - id: receiver, + id: local, key: key_recv.into(), }, }) @@ -472,13 +472,13 @@ pub fn consume_response( // retrieve peer and copy initiation state let peer = device.lookup_id(msg.f_receiver.get())?; - let (hs, ck, sender, eph_sk) = match *peer.state.lock() { + let (hs, ck, local, eph_sk) = match *peer.state.lock() { State::InitiationSent { hs, ck, - sender, + local, ref eph_sk, - } => Ok((hs, ck, sender, StaticSecret::from(eph_sk.to_bytes()))), + } => Ok((hs, ck, local, StaticSecret::from(eph_sk.to_bytes()))), _ => Err(HandshakeError::InvalidState), }?; @@ -535,6 +535,7 @@ pub fn consume_response( // null the initiation state // (to avoid replay of this response message) *state = State::Reset; + let remote = msg.f_sender.get(); // return confirmed key-pair Ok(( @@ -544,11 +545,11 @@ pub fn consume_response( birth, initiator: true, send: Key { - id: sender, + id: remote, key: key_send.into(), }, recv: Key { - id: msg.f_sender.get(), + id: local, key: key_recv.into(), }, }), diff --git a/src/wireguard/handshake/peer.rs b/src/wireguard/handshake/peer.rs index 2d69244..b7d8740 100644 --- a/src/wireguard/handshake/peer.rs +++ b/src/wireguard/handshake/peer.rs @@ -40,7 +40,7 @@ pub struct Peer { pub enum State { Reset, InitiationSent { - sender: u32, // assigned sender id + local: u32, // local id assigned eph_sk: StaticSecret, hs: GenericArray, ck: GenericArray, @@ -83,7 +83,7 @@ impl Peer { pub fn reset_state(&self) -> Option { match mem::replace(&mut *self.state.lock(), State::Reset) { - State::InitiationSent { sender, .. } => Some(sender), + State::InitiationSent { local, .. } => Some(local), _ => None, } } @@ -125,7 +125,7 @@ impl Peer { // reset state match *state { - State::InitiationSent { sender, .. } => device.release(sender), + State::InitiationSent { local, .. } => device.release(local), _ => (), } diff --git a/src/wireguard/handshake/tests.rs b/src/wireguard/handshake/tests.rs new file mode 100644 index 0000000..6be7b51 --- /dev/null +++ b/src/wireguard/handshake/tests.rs @@ -0,0 +1,197 @@ +use super::*; +use hex; +use rand::rngs::OsRng; +use std::net::SocketAddr; +use std::thread; +use std::time::Duration; + +use rand::prelude::*; + +use x25519_dalek::PublicKey; +use x25519_dalek::StaticSecret; + +use super::messages::{Initiation, Response}; + +fn setup_devices(rng: &mut R) -> (PublicKey, Device, PublicKey, Device) { + // generate new keypairs + + let sk1 = StaticSecret::new(rng); + let pk1 = PublicKey::from(&sk1); + + let sk2 = StaticSecret::new(rng); + let pk2 = PublicKey::from(&sk2); + + // pick random psk + + let mut psk = [0u8; 32]; + rng.fill_bytes(&mut psk[..]); + + // intialize devices on both ends + + let mut dev1 = Device::new(); + let mut dev2 = Device::new(); + + dev1.set_sk(Some(sk1)); + dev2.set_sk(Some(sk2)); + + dev1.add(pk2).unwrap(); + dev2.add(pk1).unwrap(); + + dev1.set_psk(pk2, psk).unwrap(); + dev2.set_psk(pk1, psk).unwrap(); + + (pk1, dev1, pk2, dev2) +} + +fn wait() { + thread::sleep(Duration::from_millis(20)); +} + +/* Test longest possible handshake interaction (7 messages): + * + * 1. I -> R (initation) + * 2. I <- R (cookie reply) + * 3. I -> R (initation) + * 4. I <- R (response) + * 5. I -> R (cookie reply) + * 6. I -> R (initation) + * 7. I <- R (response) + */ +#[test] +fn handshake_under_load() { + let mut rng = OsRng::new().unwrap(); + let (_pk1, dev1, pk2, dev2) = setup_devices(&mut rng); + + let src1: SocketAddr = "172.16.0.1:8080".parse().unwrap(); + let src2: SocketAddr = "172.16.0.2:7070".parse().unwrap(); + + // 1. device-1 : create first initation + let msg_init = dev1.begin(&mut rng, &pk2).unwrap(); + + // 2. device-2 : responds with CookieReply + let msg_cookie = match dev2.process(&mut rng, &msg_init, Some(&src1)).unwrap() { + (None, Some(msg), None) => msg, + _ => panic!("unexpected response"), + }; + + // device-1 : processes CookieReply (no response) + match dev1.process(&mut rng, &msg_cookie, Some(&src2)).unwrap() { + (None, None, None) => (), + _ => panic!("unexpected response"), + } + + // avoid initation flood detection + wait(); + + // 3. device-1 : create second initation + let msg_init = dev1.begin(&mut rng, &pk2).unwrap(); + + // 4. device-2 : responds with noise response + let msg_response = match dev2.process(&mut rng, &msg_init, Some(&src1)).unwrap() { + (Some(_), Some(msg), Some(kp)) => { + assert_eq!(kp.initiator, false); + msg + } + _ => panic!("unexpected response"), + }; + + // 5. device-1 : responds with CookieReply + let msg_cookie = match dev1.process(&mut rng, &msg_response, Some(&src2)).unwrap() { + (None, Some(msg), None) => msg, + _ => panic!("unexpected response"), + }; + + // device-2 : processes CookieReply (no response) + match dev2.process(&mut rng, &msg_cookie, Some(&src1)).unwrap() { + (None, None, None) => (), + _ => panic!("unexpected response"), + } + + // avoid initation flood detection + wait(); + + // 6. device-1 : create third initation + let msg_init = dev1.begin(&mut rng, &pk2).unwrap(); + + // 7. device-2 : responds with noise response + let (msg_response, kp1) = match dev2.process(&mut rng, &msg_init, Some(&src1)).unwrap() { + (Some(_), Some(msg), Some(kp)) => { + assert_eq!(kp.initiator, false); + (msg, kp) + } + _ => panic!("unexpected response"), + }; + + // device-1 : process noise response + let kp2 = match dev1.process(&mut rng, &msg_response, Some(&src2)).unwrap() { + (Some(_), None, Some(kp)) => { + assert_eq!(kp.initiator, true); + kp + } + _ => panic!("unexpected response"), + }; + + assert_eq!(kp1.send, kp2.recv); + assert_eq!(kp1.recv, kp2.send); +} + +#[test] +fn handshake_no_load() { + let mut rng = OsRng::new().unwrap(); + let (pk1, mut dev1, pk2, mut dev2) = setup_devices(&mut rng); + + // do a few handshakes (every handshake should succeed) + + for i in 0..10 { + println!("handshake : {}", i); + + // create initiation + + let msg1 = dev1.begin(&mut rng, &pk2).unwrap(); + + println!("msg1 = {} : {} bytes", hex::encode(&msg1[..]), msg1.len()); + println!( + "msg1 = {:?}", + Initiation::parse(&msg1[..]).expect("failed to parse initiation") + ); + + // process initiation and create response + + let (_, msg2, ks_r) = dev2 + .process(&mut rng, &msg1, None) + .expect("failed to process initiation"); + + let ks_r = ks_r.unwrap(); + let msg2 = msg2.unwrap(); + + println!("msg2 = {} : {} bytes", hex::encode(&msg2[..]), msg2.len()); + println!( + "msg2 = {:?}", + Response::parse(&msg2[..]).expect("failed to parse response") + ); + + assert!(!ks_r.initiator, "Responders key-pair is confirmed"); + + // process response and obtain confirmed key-pair + + let (_, msg3, ks_i) = dev1 + .process(&mut rng, &msg2, None) + .expect("failed to process response"); + let ks_i = ks_i.unwrap(); + + assert!(msg3.is_none(), "Returned message after response"); + assert!(ks_i.initiator, "Initiators key-pair is not confirmed"); + + assert_eq!(ks_i.send, ks_r.recv, "KeyI.send != KeyR.recv"); + assert_eq!(ks_i.recv, ks_r.send, "KeyI.recv != KeyR.send"); + + dev1.release(ks_i.local_id()); + dev2.release(ks_r.local_id()); + + // avoid initation flood detection + wait(); + } + + dev1.remove(pk2).unwrap(); + dev2.remove(pk1).unwrap(); +} diff --git a/src/wireguard/router/device.rs b/src/wireguard/router/device.rs index b3f1787..04b2045 100644 --- a/src/wireguard/router/device.rs +++ b/src/wireguard/router/device.rs @@ -147,6 +147,12 @@ impl> Device) -> Result<(), RouterError> { + debug_assert!(msg.len() > SIZE_MESSAGE_PREFIX); + log::trace!( + "Router, outbound packet = {}", + hex::encode(&msg[SIZE_MESSAGE_PREFIX..]) + ); + // ignore header prefix (for in-place transport message construction) let packet = &msg[SIZE_MESSAGE_PREFIX..]; @@ -182,12 +188,20 @@ impl> Device = header; + debug_assert!( header.f_type.get() == TYPE_TRANSPORT as u32, "this should be checked by the message type multiplexer" ); + log::trace!( + "Router, handle transport message: (receiver = {}, counter = {})", + header.f_receiver, + header.f_counter + ); + // lookup peer based on receiver id let dec = self.state.recv.read(); let dec = dec diff --git a/src/wireguard/router/peer.rs b/src/wireguard/router/peer.rs index 0d9b435..21b596a 100644 --- a/src/wireguard/router/peer.rs +++ b/src/wireguard/router/peer.rs @@ -474,7 +474,7 @@ impl> Peer Vec { - debug!("peer.add_keypair"); + log::trace!("Router, add_keypair: {:?}", new); let initiator = new.initiator; let release = { diff --git a/src/wireguard/router/route.rs b/src/wireguard/router/route.rs index 94c7e23..29e7635 100644 --- a/src/wireguard/router/route.rs +++ b/src/wireguard/router/route.rs @@ -18,12 +18,15 @@ pub fn get_route>( ) -> Option>> { match packet.get(0)? >> 4 { VERSION_IP4 => { - trace!("cryptokey router, get route for IPv4 packet"); - // check length and cast to IPv4 header let (header, _): (LayoutVerified<&[u8], IPv4Header>, _) = LayoutVerified::new_from_prefix(packet)?; + log::trace!( + "Router, get route for IPv4 destination: {:?}", + Ipv4Addr::from(header.f_destination) + ); + // check IPv4 source address device .ipv4 @@ -32,12 +35,15 @@ pub fn get_route>( .and_then(|(_, _, p)| Some(p.clone())) } VERSION_IP6 => { - trace!("cryptokey router, get route for IPv6 packet"); - // check length and cast to IPv6 header let (header, _): (LayoutVerified<&[u8], IPv6Header>, _) = LayoutVerified::new_from_prefix(packet)?; + log::trace!( + "Router, get route for IPv6 destination: {:?}", + Ipv6Addr::from(header.f_destination) + ); + // check IPv6 source address device .ipv6 @@ -57,12 +63,15 @@ pub fn check_route ) -> Option { match packet.get(0)? >> 4 { VERSION_IP4 => { - trace!("cryptokey route, check route for IPv4 packet"); - // check length and cast to IPv4 header let (header, _): (LayoutVerified<&[u8], IPv4Header>, _) = LayoutVerified::new_from_prefix(packet)?; + log::trace!( + "Router, check route for IPv4 source: {:?}", + Ipv4Addr::from(header.f_source) + ); + // check IPv4 source address device .ipv4 @@ -77,12 +86,15 @@ pub fn check_route }) } VERSION_IP6 => { - trace!("cryptokey route, check route for IPv6 packet"); - // check length and cast to IPv6 header let (header, _): (LayoutVerified<&[u8], IPv6Header>, _) = LayoutVerified::new_from_prefix(packet)?; + log::trace!( + "Router, check route for IPv6 source: {:?}", + Ipv6Addr::from(header.f_source) + ); + // check IPv6 source address device .ipv6 diff --git a/src/wireguard/router/workers.rs b/src/wireguard/router/workers.rs index 5482cee..d87174f 100644 --- a/src/wireguard/router/workers.rs +++ b/src/wireguard/router/workers.rs @@ -24,20 +24,17 @@ use super::super::{bind, tun, Endpoint}; pub const SIZE_TAG: usize = 16; -#[derive(Debug)] pub struct JobEncryption { pub msg: Vec, pub keypair: Arc, pub counter: u64, } -#[derive(Debug)] pub struct JobDecryption { pub msg: Vec, pub keypair: Arc, } -#[derive(Debug)] pub enum JobParallel { Encryption(oneshot::Sender, JobEncryption), Decryption(oneshot::Sender>, JobDecryption), diff --git a/src/wireguard/types.rs b/src/wireguard/types.rs index 51898a0..d4355a9 100644 --- a/src/wireguard/types.rs +++ b/src/wireguard/types.rs @@ -1,4 +1,5 @@ use clear_on_drop::clear::Clear; +use std::fmt; use std::time::Instant; #[cfg(test)] @@ -28,7 +29,7 @@ pub fn dummy_keypair(initiator: bool) -> KeyPair { } } -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct Key { pub key: [u8; 32], pub id: u32, @@ -48,7 +49,13 @@ impl PartialEq for Key { } } -#[derive(Debug, Clone)] +impl fmt::Debug for Key { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Key {{ id = {} }}", self.id) + } +} + +#[derive(Clone)] pub struct KeyPair { pub birth: Instant, // when was the key-pair created pub initiator: bool, // has the key-pair been confirmed? @@ -56,6 +63,19 @@ pub struct KeyPair { pub recv: Key, // key for inbound messages } +impl fmt::Debug for KeyPair { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "KeyPair {{ initator = {}, age = {} secs, send = {:?}, recv = {:?}}}", + self.initiator, + self.birth.elapsed().as_secs(), + self.send, + self.recv + ) + } +} + impl KeyPair { pub fn local_id(&self) -> u32 { self.recv.id diff --git a/src/wireguard/wireguard.rs b/src/wireguard/wireguard.rs index 613c0a8..00ee053 100644 --- a/src/wireguard/wireguard.rs +++ b/src/wireguard/wireguard.rs @@ -120,7 +120,7 @@ pub struct Wireguard { const fn padding(size: usize, mtu: usize) -> usize { #[inline(always)] const fn min(a: usize, b: usize) -> usize { - let m = (a > b) as usize; + let m = (a < b) as usize; a * m + (1 - m) * b } let pad = MESSAGE_PADDING_MULTIPLE; @@ -491,11 +491,16 @@ impl Wireguard { debug!("TUN worker, IP packet of {} bytes (MTU = {})", payload, mtu); // truncate padding - let payload = padding(payload, mtu); - msg.truncate(router::SIZE_MESSAGE_PREFIX + payload); - debug_assert!(payload <= mtu); + let padded = padding(payload, mtu); + log::trace!( + "TUN worker, payload length = {}, padded length = {}", + payload, + padded + ); + msg.truncate(router::SIZE_MESSAGE_PREFIX + padded); + debug_assert!(padded <= mtu); debug_assert_eq!( - if payload < mtu { + if padded < mtu { (msg.len() - router::SIZE_MESSAGE_PREFIX) % MESSAGE_PADDING_MULTIPLE } else { 0 -- cgit v1.2.3-59-g8ed1b