diff options
Diffstat (limited to 'src/wireguard/handshake')
-rw-r--r-- | src/wireguard/handshake/device.rs | 198 | ||||
-rw-r--r-- | src/wireguard/handshake/macs.rs | 6 | ||||
-rw-r--r-- | src/wireguard/handshake/noise.rs | 46 | ||||
-rw-r--r-- | src/wireguard/handshake/peer.rs | 26 | ||||
-rw-r--r-- | src/wireguard/handshake/tests.rs | 62 | ||||
-rw-r--r-- | src/wireguard/handshake/types.rs | 14 |
6 files changed, 206 insertions, 146 deletions
diff --git a/src/wireguard/handshake/device.rs b/src/wireguard/handshake/device.rs index edd1a07..4b5d8f6 100644 --- a/src/wireguard/handshake/device.rs +++ b/src/wireguard/handshake/device.rs @@ -1,4 +1,5 @@ use spin::RwLock; +use std::collections::hash_map; use std::collections::HashMap; use std::net::SocketAddr; use std::sync::Mutex; @@ -6,7 +7,10 @@ use zerocopy::AsBytes; use byteorder::{ByteOrder, LittleEndian}; -use rand::prelude::*; +use rand::Rng; +use rand_core::{CryptoRng, RngCore}; + +use clear_on_drop::clear::Clear; use x25519_dalek::PublicKey; use x25519_dalek::StaticSecret; @@ -22,42 +26,101 @@ use super::types::*; const MAX_PEER_PER_DEVICE: usize = 1 << 20; pub struct KeyState { - pub sk: StaticSecret, // static secret key - pub pk: PublicKey, // static public key - macs: macs::Validator, // validator for the mac fields + pub(super) sk: StaticSecret, // static secret key + pub(super) pk: PublicKey, // static public key + macs: macs::Validator, // validator for the mac fields } -pub struct Device { - keyst: Option<KeyState>, // secret/public key - pk_map: HashMap<[u8; 32], Peer>, // public key -> peer state - id_map: RwLock<HashMap<u32, [u8; 32]>>, // receiver ids -> public key +/// The device is generic over an "opaque" type +/// which can be used to associate the public key with this value. +/// (the instance is a Peer object in the parent module) +pub struct Device<O> { + keyst: Option<KeyState>, + id_map: RwLock<HashMap<u32, [u8; 32]>>, + pk_map: HashMap<[u8; 32], Peer<O>>, limiter: Mutex<RateLimiter>, } +pub struct Iter<'a, O> { + iter: hash_map::Iter<'a, [u8; 32], Peer<O>>, +} + +impl<'a, O> Iterator for Iter<'a, O> { + type Item = (PublicKey, &'a O); + + fn next(&mut self) -> Option<Self::Item> { + self.iter + .next() + .map(|(pk, peer)| (PublicKey::from(*pk), &peer.opaque)) + } +} + +/* These methods enable the Device to act as a map + * from public keys to the set of contained opaque values. + * + * It also abstracts away the problem of PublicKey not being hashable. + */ +impl<O> Device<O> { + pub fn clear(&mut self) { + self.id_map.write().clear(); + self.pk_map.clear(); + } + + pub fn len(&self) -> usize { + self.pk_map.len() + } + + /// Enables enumeration of (public key, opaque) pairs + /// without exposing internal peer type. + pub fn iter(&self) -> Iter<O> { + Iter { + iter: self.pk_map.iter(), + } + } + + /// Enables lookup by public key without exposing internal peer type. + pub fn get(&self, pk: &PublicKey) -> Option<&O> { + self.pk_map.get(pk.as_bytes()).map(|peer| &peer.opaque) + } + + pub fn contains_key(&self, pk: &PublicKey) -> bool { + self.pk_map.contains_key(pk.as_bytes()) + } +} + /* A mutable reference to the device needs to be held during configuration. * Wrapping the device in a RwLock enables peer config after "configuration time" */ -impl Device { +impl<O> Device<O> { /// Initialize a new handshake state machine - pub fn new() -> Device { + pub fn new() -> Device<O> { Device { keyst: None, - pk_map: HashMap::new(), id_map: RwLock::new(HashMap::new()), + pk_map: HashMap::new(), limiter: Mutex::new(RateLimiter::new()), } } - fn update_ss(&self, peer: &mut Peer) -> Option<PublicKey> { - if let Some(key) = self.keyst.as_ref() { - if *peer.pk.as_bytes() == *key.pk.as_bytes() { - return Some(peer.pk); + fn update_ss(&mut self) -> (Vec<u32>, Option<PublicKey>) { + let mut same = None; + let mut ids = Vec::with_capacity(self.pk_map.len()); + for (pk, peer) in self.pk_map.iter_mut() { + if let Some(key) = self.keyst.as_ref() { + if key.pk.as_bytes() == pk { + same = Some(PublicKey::from(*pk)); + peer.ss.clear() + } else { + let pk = PublicKey::from(*pk); + peer.ss = *key.sk.diffie_hellman(&pk).as_bytes(); + } + } else { + peer.ss.clear(); } - peer.ss = *key.sk.diffie_hellman(&peer.pk).as_bytes(); - } else { - peer.ss = [0u8; 32]; - }; - None + peer.reset_state().map(|id| ids.push(id)); + } + + (ids, same) } /// Update the secret key of the device @@ -74,29 +137,15 @@ impl Device { }); // recalculate / erase the shared secrets for every peer - let mut ids = vec![]; - let mut same = None; - for mut peer in self.pk_map.values_mut() { - // clear any existing handshake state - peer.reset_state().map(|id| ids.push(id)); - - // update precomputed shared secret - if let Some(key) = self.keyst.as_ref() { - peer.ss = *key.sk.diffie_hellman(&peer.pk).as_bytes(); - if *peer.pk.as_bytes() == *key.pk.as_bytes() { - same = Some(peer.pk) - } - } else { - peer.ss = [0u8; 32]; - }; - } + let (ids, same) = self.update_ss(); // release ids from aborted handshakes for id in ids { self.release(id) } - // if we found a peer matching the device public key, remove it. + // if we found a peer matching the device public key + // remove it and return its value to the caller same.map(|pk| { self.pk_map.remove(pk.as_bytes()); pk @@ -119,29 +168,32 @@ impl Device { /// /// * `pk` - The public key to add /// * `identifier` - Associated identifier which can be used to distinguish the peers - pub fn add(&mut self, pk: PublicKey) -> Result<(), ConfigError> { + pub fn add(&mut self, pk: PublicKey, opaque: O) -> Result<(), ConfigError> { // ensure less than 2^20 peers if self.pk_map.len() > MAX_PEER_PER_DEVICE { return Err(ConfigError::new("Too many peers for device")); } - // create peer and precompute static secret - let mut peer = Peer::new( - pk, - self.keyst - .as_ref() - .map(|key| *key.sk.diffie_hellman(&pk).as_bytes()) - .unwrap_or([0u8; 32]), - ); - - // add peer to device - match self.update_ss(&mut peer) { - Some(_) => Err(ConfigError::new("Public key of peer matches the device")), - None => { - self.pk_map.insert(*pk.as_bytes(), peer); - Ok(()) + // error if public key matches device + if let Some(key) = self.keyst.as_ref() { + if pk.as_bytes() == key.pk.as_bytes() { + return Err(ConfigError::new("Public key of peer matches the device")); } } + + // pre-compute shared secret and add to pk_map + self.pk_map.insert( + *pk.as_bytes(), + Peer::new( + pk, + self.keyst + .as_ref() + .map(|key| *key.sk.diffie_hellman(&pk).as_bytes()) + .unwrap_or([0u8; 32]), + opaque, + ), + ); + Ok(()) } /// Remove a peer by public key @@ -163,7 +215,7 @@ impl Device { .remove(pk.as_bytes()) .ok_or(ConfigError::new("Public key not in device"))?; - // pruge the id map (linear scan) + // purge the id map (linear scan) id_map.retain(|_, v| v != pk.as_bytes()); Ok(()) } @@ -231,11 +283,11 @@ impl Device { (_, None) => Err(HandshakeError::UnknownPublicKey), (None, _) => Err(HandshakeError::UnknownPublicKey), (Some(keyst), Some(peer)) => { - let local = self.allocate(rng, peer); + let local = self.allocate(rng, pk); let mut msg = Initiation::default(); // create noise part of initation - noise::create_initiation(rng, keyst, peer, local, &mut msg.noise)?; + noise::create_initiation(rng, keyst, peer, pk, local, &mut msg.noise)?; // add macs to initation peer.macs @@ -253,11 +305,11 @@ impl Device { /// /// * `msg` - Byte slice containing the message (untrusted input) pub fn process<'a, R: RngCore + CryptoRng>( - &self, - rng: &mut R, // rng instance to sample randomness from - msg: &[u8], // message buffer + &'a self, + rng: &mut R, // rng instance to sample randomness from + msg: &[u8], // message buffer src: Option<SocketAddr>, // optional source endpoint, set when "under load" - ) -> Result<Output, HandshakeError> { + ) -> Result<Output<'a, O>, HandshakeError> { // ensure type read in-range if msg.len() < 4 { return Err(HandshakeError::InvalidMessageFormat); @@ -303,17 +355,17 @@ impl Device { } // consume the initiation - let (peer, st) = noise::consume_initiation(self, keyst, &msg.noise)?; + let (peer, pk, st) = noise::consume_initiation(self, keyst, &msg.noise)?; // allocate new index for response - let local = self.allocate(rng, peer); + let local = self.allocate(rng, &pk); // 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, local, st, &mut resp.noise).map_err(|e| { + let keys = noise::create_response(rng, peer, &pk, local, st, &mut resp.noise) + .map_err(|e| { self.release(local); e })?; @@ -324,7 +376,11 @@ impl Device { .generate(resp.noise.as_bytes(), &mut resp.macs); // return unconfirmed keypair and the response as vector - Ok((Some(peer.pk), Some(resp.as_bytes().to_owned()), Some(keys))) + Ok(( + Some(&peer.opaque), + Some(resp.as_bytes().to_owned()), + Some(keys), + )) } TYPE_RESPONSE => { let msg = Response::parse(msg)?; @@ -363,7 +419,7 @@ impl Device { let msg = CookieReply::parse(msg)?; // lookup peer - let peer = self.lookup_id(msg.f_receiver.get())?; + let (peer, _) = self.lookup_id(msg.f_receiver.get())?; // validate cookie reply peer.macs.lock().process(&msg)?; @@ -379,7 +435,7 @@ impl Device { // Internal function // // Return the peer associated with the public key - pub(crate) fn lookup_pk(&self, pk: &PublicKey) -> Result<&Peer, HandshakeError> { + pub(super) fn lookup_pk(&self, pk: &PublicKey) -> Result<&Peer<O>, HandshakeError> { self.pk_map .get(pk.as_bytes()) .ok_or(HandshakeError::UnknownPublicKey) @@ -388,11 +444,11 @@ impl Device { // Internal function // // Return the peer currently associated with the receiver identifier - pub(crate) fn lookup_id(&self, id: u32) -> Result<&Peer, HandshakeError> { + pub(super) fn lookup_id(&self, id: u32) -> Result<(&Peer<O>, PublicKey), HandshakeError> { let im = self.id_map.read(); let pk = im.get(&id).ok_or(HandshakeError::UnknownReceiverId)?; match self.pk_map.get(pk) { - Some(peer) => Ok(peer), + Some(peer) => Ok((peer, PublicKey::from(*pk))), _ => unreachable!(), // if the id-lookup succeeded, the peer should exist } } @@ -400,7 +456,7 @@ impl Device { // Internal function // // Allocated a new receiver identifier for the peer - fn allocate<R: RngCore + CryptoRng>(&self, rng: &mut R, peer: &Peer) -> u32 { + fn allocate<R: RngCore + CryptoRng>(&self, rng: &mut R, pk: &PublicKey) -> u32 { loop { let id = rng.gen(); @@ -412,7 +468,7 @@ impl Device { // take write lock and add index let mut m = self.id_map.write(); if !m.contains_key(&id) { - m.insert(id, *peer.pk.as_bytes()); + m.insert(id, *pk.as_bytes()); return id; } } diff --git a/src/wireguard/handshake/macs.rs b/src/wireguard/handshake/macs.rs index 689826b..cb5d7d4 100644 --- a/src/wireguard/handshake/macs.rs +++ b/src/wireguard/handshake/macs.rs @@ -286,8 +286,7 @@ mod tests { use x25519_dalek::StaticSecret; fn new_validator_generator() -> (Validator, Generator) { - let mut rng = OsRng::new().unwrap(); - let sk = StaticSecret::new(&mut rng); + let sk = StaticSecret::new(&mut OsRng); let pk = PublicKey::from(&sk); (Validator::new(pk), Generator::new(pk)) } @@ -296,7 +295,6 @@ mod tests { #[test] fn test_cookie_reply(inner1 : Vec<u8>, inner2 : Vec<u8>, receiver : u32) { let mut msg = CookieReply::default(); - let mut rng = OsRng::new().expect("failed to create rng"); let mut macs = MacsFooter::default(); let src = "192.0.2.16:8080".parse().unwrap(); let (validator, mut generator) = new_validator_generator(); @@ -309,7 +307,7 @@ mod tests { // check validity of mac1 validator.check_mac1(&inner1[..], &macs).expect("mac1 of inner1 did not validate"); assert_eq!(validator.check_mac2(&inner1[..], &src, &macs), false, "mac2 of inner2 did not validate"); - validator.create_cookie_reply(&mut rng, receiver, &src, &macs, &mut msg); + validator.create_cookie_reply(&mut OsRng, receiver, &src, &macs, &mut msg); // consume cookie reply generator.process(&msg).expect("failed to process CookieReply"); diff --git a/src/wireguard/handshake/noise.rs b/src/wireguard/handshake/noise.rs index 072ac13..9e431cf 100644 --- a/src/wireguard/handshake/noise.rs +++ b/src/wireguard/handshake/noise.rs @@ -10,7 +10,7 @@ use hmac::Hmac; use aead::{Aead, NewAead, Payload}; use chacha20poly1305::ChaCha20Poly1305; -use rand::{CryptoRng, RngCore}; +use rand_core::{CryptoRng, RngCore}; use log::debug; @@ -215,20 +215,21 @@ mod tests { } } -pub fn create_initiation<R: RngCore + CryptoRng>( +pub(super) fn create_initiation<R: RngCore + CryptoRng, O>( rng: &mut R, keyst: &KeyState, - peer: &Peer, + peer: &Peer<O>, + pk: &PublicKey, local: u32, msg: &mut NoiseInitiation, ) -> Result<(), HandshakeError> { - debug!("create initation"); + debug!("create initiation"); clear_stack_on_return(CLEAR_PAGES, || { // initialize state let ck = INITIAL_CK; let hs = INITIAL_HS; - let hs = HASH!(&hs, peer.pk.as_bytes()); + let hs = HASH!(&hs, pk.as_bytes()); msg.f_type.set(TYPE_INITIATION as u32); msg.f_sender.set(local); // from us @@ -252,7 +253,7 @@ pub fn create_initiation<R: RngCore + CryptoRng>( // (C, k) := Kdf2(C, DH(E_priv, S_pub)) - let (ck, key) = KDF2!(&ck, eph_sk.diffie_hellman(&peer.pk).as_bytes()); + let (ck, key) = KDF2!(&ck, eph_sk.diffie_hellman(&pk).as_bytes()); // msg.static := Aead(k, 0, S_pub, H) @@ -297,12 +298,12 @@ pub fn create_initiation<R: RngCore + CryptoRng>( }) } -pub fn consume_initiation<'a>( - device: &'a Device, +pub(super) fn consume_initiation<'a, O>( + device: &'a Device<O>, keyst: &KeyState, msg: &NoiseInitiation, -) -> Result<(&'a Peer, TemporaryState), HandshakeError> { - debug!("consume initation"); +) -> Result<(&'a Peer<O>, PublicKey, TemporaryState), HandshakeError> { + debug!("consume initiation"); clear_stack_on_return(CLEAR_PAGES, || { // initialize new state @@ -369,13 +370,18 @@ pub fn consume_initiation<'a>( // return state (to create response) - Ok((peer, (msg.f_sender.get(), eph_r_pk, hs, ck))) + Ok(( + peer, + PublicKey::from(pk), + (msg.f_sender.get(), eph_r_pk, hs, ck), + )) }) } -pub fn create_response<R: RngCore + CryptoRng>( +pub(super) fn create_response<R: RngCore + CryptoRng, O>( rng: &mut R, - peer: &Peer, + peer: &Peer<O>, + pk: &PublicKey, local: u32, // sending identifier state: TemporaryState, // state from "consume_initiation" msg: &mut NoiseResponse, // resulting response @@ -388,7 +394,7 @@ pub fn create_response<R: RngCore + CryptoRng>( msg.f_type.set(TYPE_RESPONSE as u32); msg.f_sender.set(local); // from us - msg.f_receiver.set(receiver); // to the sender of the initation + msg.f_receiver.set(receiver); // to the sender of the initiation // (E_priv, E_pub) := DH-Generate() @@ -413,7 +419,7 @@ pub fn create_response<R: RngCore + CryptoRng>( // C := Kdf1(C, DH(E_priv, S_pub)) - let ck = KDF1!(&ck, eph_sk.diffie_hellman(&peer.pk).as_bytes()); + let ck = KDF1!(&ck, eph_sk.diffie_hellman(&pk).as_bytes()); // (C, tau, k) := Kdf3(C, Q) @@ -460,15 +466,15 @@ pub fn create_response<R: RngCore + CryptoRng>( * allow concurrent processing of potential responses to the initiation, * in order to better mitigate DoS from malformed response messages. */ -pub fn consume_response( - device: &Device, +pub(super) fn consume_response<'a, O>( + device: &'a Device<O>, keyst: &KeyState, msg: &NoiseResponse, -) -> Result<Output, HandshakeError> { +) -> Result<Output<'a, O>, HandshakeError> { debug!("consume response"); clear_stack_on_return(CLEAR_PAGES, || { // retrieve peer and copy initiation state - let peer = device.lookup_id(msg.f_receiver.get())?; + let (peer, _) = device.lookup_id(msg.f_receiver.get())?; let (hs, ck, local, eph_sk) = match *peer.state.lock() { State::InitiationSent { @@ -537,7 +543,7 @@ pub fn consume_response( // return confirmed key-pair Ok(( - Some(peer.pk), + Some(&peer.opaque), None, Some(KeyPair { birth, diff --git a/src/wireguard/handshake/peer.rs b/src/wireguard/handshake/peer.rs index a4df560..f4d15fc 100644 --- a/src/wireguard/handshake/peer.rs +++ b/src/wireguard/handshake/peer.rs @@ -22,19 +22,21 @@ const TIME_BETWEEN_INITIATIONS: Duration = Duration::from_millis(20); * * This type is only for internal use and not exposed. */ -pub struct Peer { +pub(super) struct Peer<O> { + // opaque type which identifies a peer + pub opaque: O, + // mutable state - pub(crate) state: Mutex<State>, - pub(crate) timestamp: Mutex<Option<timestamp::TAI64N>>, - pub(crate) last_initiation_consumption: Mutex<Option<Instant>>, + pub state: Mutex<State>, + pub timestamp: Mutex<Option<timestamp::TAI64N>>, + pub last_initiation_consumption: Mutex<Option<Instant>>, // state related to DoS mitigation fields - pub(crate) macs: Mutex<macs::Generator>, + pub macs: Mutex<macs::Generator>, // constant state - pub(crate) pk: PublicKey, // public key of peer - pub(crate) ss: [u8; 32], // precomputed DH(static, static) - pub(crate) psk: Psk, // psk of peer + pub ss: [u8; 32], // precomputed DH(static, static) + pub psk: Psk, // psk of peer } pub enum State { @@ -60,14 +62,14 @@ impl Drop for State { } } -impl Peer { - pub fn new(pk: PublicKey, ss: [u8; 32]) -> Self { +impl<O> Peer<O> { + pub fn new(pk: PublicKey, ss: [u8; 32], opaque: O) -> Self { Self { + opaque, macs: Mutex::new(macs::Generator::new(pk)), state: Mutex::new(State::Reset), timestamp: Mutex::new(None), last_initiation_consumption: Mutex::new(None), - pk, ss, psk: [0u8; 32], } @@ -88,7 +90,7 @@ impl Peer { /// * ts_new - The associated timestamp pub fn check_replay_flood( &self, - device: &Device, + device: &Device<O>, timestamp_new: ×tamp::TAI64N, ) -> Result<(), HandshakeError> { let mut state = self.state.lock(); diff --git a/src/wireguard/handshake/tests.rs b/src/wireguard/handshake/tests.rs index ff27b3e..bfdc5ab 100644 --- a/src/wireguard/handshake/tests.rs +++ b/src/wireguard/handshake/tests.rs @@ -12,8 +12,10 @@ use x25519_dalek::StaticSecret; use super::messages::{Initiation, Response}; -fn setup_devices<R: RngCore + CryptoRng>(rng: &mut R) -> (PublicKey, Device, PublicKey, Device) { - // generate new keypairs +fn setup_devices<R: RngCore + CryptoRng, O: Default>( + rng: &mut R, +) -> (PublicKey, Device<O>, PublicKey, Device<O>) { + // generate new key pairs let sk1 = StaticSecret::new(rng); let pk1 = PublicKey::from(&sk1); @@ -26,7 +28,7 @@ fn setup_devices<R: RngCore + CryptoRng>(rng: &mut R) -> (PublicKey, Device, Pub let mut psk = [0u8; 32]; rng.fill_bytes(&mut psk[..]); - // intialize devices on both ends + // initialize devices on both ends let mut dev1 = Device::new(); let mut dev2 = Device::new(); @@ -34,8 +36,8 @@ fn setup_devices<R: RngCore + CryptoRng>(rng: &mut R) -> (PublicKey, Device, Pub dev1.set_sk(Some(sk1)); dev2.set_sk(Some(sk2)); - dev1.add(pk2).unwrap(); - dev2.add(pk1).unwrap(); + dev1.add(pk2, O::default()).unwrap(); + dev2.add(pk1, O::default()).unwrap(); dev1.set_psk(pk2, psk).unwrap(); dev2.set_psk(pk1, psk).unwrap(); @@ -49,45 +51,44 @@ fn wait() { /* Test longest possible handshake interaction (7 messages): * - * 1. I -> R (initation) + * 1. I -> R (initiation) * 2. I <- R (cookie reply) - * 3. I -> R (initation) + * 3. I -> R (initiation) * 4. I <- R (response) * 5. I -> R (cookie reply) - * 6. I -> R (initation) + * 6. I -> R (initiation) * 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 (_pk1, dev1, pk2, dev2): (_, Device<usize>, _, _) = setup_devices(&mut OsRng); 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(); + // 1. device-1 : create first initiation + let msg_init = dev1.begin(&mut OsRng, &pk2).unwrap(); // 2. device-2 : responds with CookieReply - let msg_cookie = match dev2.process(&mut rng, &msg_init, Some(src1)).unwrap() { + let msg_cookie = match dev2.process(&mut OsRng, &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() { + match dev1.process(&mut OsRng, &msg_cookie, Some(src2)).unwrap() { (None, None, None) => (), _ => panic!("unexpected response"), } - // avoid initation flood detection + // avoid initiation flood detection wait(); - // 3. device-1 : create second initation - let msg_init = dev1.begin(&mut rng, &pk2).unwrap(); + // 3. device-1 : create second initiation + let msg_init = dev1.begin(&mut OsRng, &pk2).unwrap(); // 4. device-2 : responds with noise response - let msg_response = match dev2.process(&mut rng, &msg_init, Some(src1)).unwrap() { + let msg_response = match dev2.process(&mut OsRng, &msg_init, Some(src1)).unwrap() { (Some(_), Some(msg), Some(kp)) => { assert_eq!(kp.initiator, false); msg @@ -96,25 +97,25 @@ fn handshake_under_load() { }; // 5. device-1 : responds with CookieReply - let msg_cookie = match dev1.process(&mut rng, &msg_response, Some(src2)).unwrap() { + let msg_cookie = match dev1.process(&mut OsRng, &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() { + match dev2.process(&mut OsRng, &msg_cookie, Some(src1)).unwrap() { (None, None, None) => (), _ => panic!("unexpected response"), } - // avoid initation flood detection + // avoid initiation flood detection wait(); - // 6. device-1 : create third initation - let msg_init = dev1.begin(&mut rng, &pk2).unwrap(); + // 6. device-1 : create third initiation + let msg_init = dev1.begin(&mut OsRng, &pk2).unwrap(); // 7. device-2 : responds with noise response - let (msg_response, kp1) = match dev2.process(&mut rng, &msg_init, Some(src1)).unwrap() { + let (msg_response, kp1) = match dev2.process(&mut OsRng, &msg_init, Some(src1)).unwrap() { (Some(_), Some(msg), Some(kp)) => { assert_eq!(kp.initiator, false); (msg, kp) @@ -123,7 +124,7 @@ fn handshake_under_load() { }; // device-1 : process noise response - let kp2 = match dev1.process(&mut rng, &msg_response, Some(src2)).unwrap() { + let kp2 = match dev1.process(&mut OsRng, &msg_response, Some(src2)).unwrap() { (Some(_), None, Some(kp)) => { assert_eq!(kp.initiator, true); kp @@ -137,8 +138,7 @@ fn handshake_under_load() { #[test] fn handshake_no_load() { - let mut rng = OsRng::new().unwrap(); - let (pk1, mut dev1, pk2, mut dev2) = setup_devices(&mut rng); + let (pk1, mut dev1, pk2, mut dev2): (_, Device<usize>, _, _) = setup_devices(&mut OsRng); // do a few handshakes (every handshake should succeed) @@ -147,7 +147,7 @@ fn handshake_no_load() { // create initiation - let msg1 = dev1.begin(&mut rng, &pk2).unwrap(); + let msg1 = dev1.begin(&mut OsRng, &pk2).unwrap(); println!("msg1 = {} : {} bytes", hex::encode(&msg1[..]), msg1.len()); println!( @@ -158,7 +158,7 @@ fn handshake_no_load() { // process initiation and create response let (_, msg2, ks_r) = dev2 - .process(&mut rng, &msg1, None) + .process(&mut OsRng, &msg1, None) .expect("failed to process initiation"); let ks_r = ks_r.unwrap(); @@ -175,7 +175,7 @@ fn handshake_no_load() { // process response and obtain confirmed key-pair let (_, msg3, ks_i) = dev1 - .process(&mut rng, &msg2, None) + .process(&mut OsRng, &msg2, None) .expect("failed to process response"); let ks_i = ks_i.unwrap(); @@ -188,7 +188,7 @@ fn handshake_no_load() { dev1.release(ks_i.local_id()); dev2.release(ks_r.local_id()); - // avoid initation flood detection + // avoid initiation flood detection wait(); } diff --git a/src/wireguard/handshake/types.rs b/src/wireguard/handshake/types.rs index 5f984cc..ed2fcbb 100644 --- a/src/wireguard/handshake/types.rs +++ b/src/wireguard/handshake/types.rs @@ -1,10 +1,8 @@ +use super::super::types::KeyPair; + use std::error::Error; use std::fmt; -use x25519_dalek::PublicKey; - -use super::super::types::KeyPair; - /* Internal types for the noise IKpsk2 implementation */ // config error @@ -79,10 +77,10 @@ impl Error for HandshakeError { } } -pub type Output = ( - Option<PublicKey>, // external identifier associated with peer - Option<Vec<u8>>, // message to send - Option<KeyPair>, // resulting key-pair of successful handshake +pub type Output<'a, O> = ( + Option<&'a O>, // external identifier associated with peer + Option<Vec<u8>>, // message to send + Option<KeyPair>, // resulting key-pair of successful handshake ); // preshared key |