From fb0676ba6ba1c1b918e973eeb6b1b2427cdeeb5f Mon Sep 17 00:00:00 2001 From: Dennis Schwerdel Date: Fri, 26 Mar 2021 22:55:40 +0000 Subject: [PATCH] Tests work --- src/crypto/common.rs | 84 ++++++++-------- src/crypto/init.rs | 184 +++++++++++++++++------------------- src/engine/mod.rs | 3 +- src/engine/socket_thread.rs | 10 +- src/tests/common.rs | 1 + 5 files changed, 140 insertions(+), 142 deletions(-) diff --git a/src/crypto/common.rs b/src/crypto/common.rs index 374a1d9..503593e 100644 --- a/src/crypto/common.rs +++ b/src/crypto/common.rs @@ -1,24 +1,24 @@ use super::{core::test_speed, rotate::RotationState}; pub use super::{ core::{CryptoCore, EXTRA_LEN, TAG_LEN}, - init::{is_init_message, InitResult, InitState, INIT_MESSAGE_FIRST_BYTE} + init::{is_init_message, InitMsg, InitResult, InitState, INIT_MESSAGE_FIRST_BYTE, STAGE_PONG}, }; use crate::{ error::Error, types::NodeId, - util::{from_base62, to_base62, MsgBuffer} + util::{from_base62, to_base62, MsgBuffer}, }; +use libc::BPF_FS_MAGIC; use ring::{ aead::{self, Algorithm, LessSafeKey, UnboundKey}, agreement::{EphemeralPrivateKey, UnparsedPublicKey}, pbkdf2, rand::{SecureRandom, SystemRandom}, - signature::{Ed25519KeyPair, KeyPair, ED25519_PUBLIC_KEY_LEN} + signature::{Ed25519KeyPair, KeyPair, ED25519_PUBLIC_KEY_LEN}, }; use smallvec::{smallvec, SmallVec}; use std::{fmt::Debug, io::Read, num::NonZeroU32, sync::Arc, time::Duration}; - const SALT: &[u8; 32] = b"vpncloudVPNCLOUDvpncl0udVpnCloud"; pub const MESSAGE_TYPE_ROTATION: u8 = 0x10; @@ -28,7 +28,6 @@ pub type EcdhPublicKey = UnparsedPublicKey>; pub type EcdhPrivateKey = EphemeralPrivateKey; pub type Key = SmallVec<[u8; 32]>; - const DEFAULT_ALGORITHMS: [&str; 3] = ["AES128", "AES256", "CHACHA20"]; #[cfg(test)] @@ -38,17 +37,15 @@ const SPEED_TEST_TIME: f32 = 0.1; const ROTATE_INTERVAL: usize = 120; - pub trait Payload: Debug + PartialEq + Sized { fn write_to(&self, buffer: &mut MsgBuffer); fn read_from(r: R) -> Result; } - #[derive(Clone)] pub struct Algorithms { pub algorithm_speeds: SmallVec<[(&'static Algorithm, f32); 3]>, - pub allow_unencrypted: bool + pub allow_unencrypted: bool, } #[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq)] @@ -58,14 +55,14 @@ pub struct Config { pub private_key: Option, pub public_key: Option, pub trusted_keys: Vec, - pub algorithms: Vec + pub algorithms: Vec, } pub struct Crypto { node_id: NodeId, key_pair: Arc, trusted_keys: Arc<[Ed25519PublicKey]>, - algorithms: Algorithms + algorithms: Algorithms, } impl Crypto { @@ -78,12 +75,12 @@ impl Crypto { let algo = match &name.to_uppercase() as &str { "UNENCRYPTED" | "NONE" | "PLAIN" => { unencrypted = true; - continue + continue; } "AES128" | "AES128_GCM" | "AES_128" | "AES_128_GCM" => &aead::AES_128_GCM, "AES256" | "AES256_GCM" | "AES_256" | "AES_256_GCM" => &aead::AES_256_GCM, "CHACHA" | "CHACHA20" | "CHACHA20_POLY1305" => &aead::CHACHA20_POLY1305, - _ => return Err(Error::InvalidConfig("Unknown crypto method")) + _ => return Err(Error::InvalidConfig("Unknown crypto method")), }; algos.push(algo) } @@ -100,7 +97,7 @@ impl Crypto { } else if let Some(password) = &config.password { Self::keypair_from_password(password) } else { - return Err(Error::InvalidConfig("Either private_key or password must be set")) + return Err(Error::InvalidConfig("Either private_key or password must be set")); }; let mut trusted_keys = vec![]; for tn in &config.trusted_keys { @@ -134,7 +131,7 @@ impl Crypto { node_id, key_pair: Arc::new(key_pair), trusted_keys: trusted_keys.into_boxed_slice().into(), - algorithms: algos + algorithms: algos, }) } @@ -151,7 +148,7 @@ impl Crypto { NonZeroU32::new(4096).unwrap(), SALT, password.as_bytes(), - &mut bytes + &mut bytes, ); } } @@ -193,7 +190,7 @@ impl Crypto { fn parse_public_key(pubkey: &str) -> Result { let pubkey = from_base62(pubkey).map_err(|_| Error::InvalidConfig("Failed to parse public key"))?; if pubkey.len() != ED25519_PUBLIC_KEY_LEN { - return Err(Error::InvalidConfig("Failed to parse public key")) + return Err(Error::InvalidConfig("Failed to parse public key")); } let mut result = [0; ED25519_PUBLIC_KEY_LEN]; result.clone_from_slice(&pubkey); @@ -205,53 +202,61 @@ impl Crypto { } } - #[derive(Debug, PartialEq)] pub enum MessageResult { Message(u8), Reply, - None + None, } - pub enum PeerCrypto { Encrypted { last_init_message: Vec, + trusted_keys: Arc<[Ed25519PublicKey]>, algorithm: &'static Algorithm, rotation: RotationState, core: Arc, - rotate_counter: usize + rotate_counter: usize, }, Unencrypted { - last_init_message: Vec - } + last_init_message: Vec, + trusted_keys: Arc<[Ed25519PublicKey]>, + }, } impl PeerCrypto { pub fn algorithm_name(&self) -> &'static str { match self { - PeerCrypto::Encrypted { algorithm, .. } => { - match *algorithm { - x if x == &aead::CHACHA20_POLY1305 => "CHACHA20", - x if x == &aead::AES_128_GCM => "AES128", - x if x == &aead::AES_256_GCM => "AES256", - _ => unreachable!() - } - } - PeerCrypto::Unencrypted { .. } => "PLAIN" + PeerCrypto::Encrypted { algorithm, .. } => match *algorithm { + x if x == &aead::CHACHA20_POLY1305 => "CHACHA20", + x if x == &aead::AES_128_GCM => "AES128", + x if x == &aead::AES_256_GCM => "AES256", + _ => unreachable!(), + }, + PeerCrypto::Unencrypted { .. } => "PLAIN", } } pub fn get_core(&self) -> Option> { match self { PeerCrypto::Encrypted { core, .. } => Some(core.clone()), - PeerCrypto::Unencrypted { .. } => None + PeerCrypto::Unencrypted { .. } => None, } } fn handle_init_message(&mut self, buffer: &mut MsgBuffer) -> Result { - // TODO: parse message stage - // TODO: depending on stage resend last message + match self { + PeerCrypto::Encrypted { trusted_keys, last_init_message, .. } + | PeerCrypto::Unencrypted { trusted_keys, last_init_message, .. } => { + let (msg, _) = InitMsg::read_from(buffer.buffer(), &trusted_keys)?; + buffer.clear(); + if msg.stage() == STAGE_PONG { + buffer.set_length(last_init_message.len()); + buffer.message_mut().copy_from_slice(last_init_message); + } + return Ok(MessageResult::Reply) + } + } Ok(MessageResult::None) } @@ -264,7 +269,7 @@ impl PeerCrypto { } Ok(()) } - PeerCrypto::Unencrypted { .. } => Err(Error::Crypto("Rotation when unencrypted")) + PeerCrypto::Unencrypted { .. } => Err(Error::Crypto("Rotation when unencrypted")), } } @@ -287,7 +292,7 @@ impl PeerCrypto { pub fn handle_message(&mut self, buffer: &mut MsgBuffer) -> Result { // HOT PATH if buffer.is_empty() { - return Err(Error::InvalidCryptoState("No message in buffer")) + return Err(Error::InvalidCryptoState("No message in buffer")); } if is_init_message(buffer.buffer()) { // COLD PATH @@ -330,7 +335,6 @@ impl PeerCrypto { } } - #[cfg(test)] mod tests { use super::*; @@ -362,18 +366,18 @@ mod tests { debug!("Node1 <- Node2"); let res = node1.handle_init(&mut msg).unwrap(); - assert_eq!(res, InitResult::Success { peer_payload: vec![], is_initiator: false }); + assert_eq!(res, InitResult::Success { peer_payload: vec![], is_initiator: true }); assert!(!msg.is_empty()); debug!("Node1 -> Node2"); let res = node2.handle_init(&mut msg).unwrap(); - assert_eq!(res, InitResult::Success { peer_payload: vec![], is_initiator: true }); + assert_eq!(res, InitResult::Success { peer_payload: vec![], is_initiator: false }); assert!(msg.is_empty()); let mut node1 = node1.finish(&mut msg); assert!(msg.is_empty()); let mut node2 = node2.finish(&mut msg); - assert!(msg.is_empty()); + assert!(!msg.is_empty()); debug!("Node1 <- Node2"); let res = node1.handle_message(&mut msg).unwrap(); diff --git a/src/crypto/init.rs b/src/crypto/init.rs index 86d30af..ce37da1 100644 --- a/src/crypto/init.rs +++ b/src/crypto/init.rs @@ -54,12 +54,11 @@ // Once every second, both nodes check whether they have already finished the initialization. If not, they repeat their // last message. After 5 seconds, the initialization is aborted as failed. - use super::{ + common::MESSAGE_TYPE_ROTATION, core::{CryptoCore, EXTRA_LEN}, rotate::RotationState, Algorithms, EcdhPrivateKey, EcdhPublicKey, Ed25519PublicKey, Payload, PeerCrypto, - common::MESSAGE_TYPE_ROTATION }; use crate::{error::Error, types::NodeId, util::MsgBuffer}; use byteorder::{NetworkEndian, ReadBytesExt, WriteBytesExt}; @@ -68,14 +67,14 @@ use ring::{ agreement::{agree_ephemeral, X25519}, digest, rand::{SecureRandom, SystemRandom}, - signature::{self, Ed25519KeyPair, KeyPair, ED25519, ED25519_PUBLIC_KEY_LEN} + signature::{self, Ed25519KeyPair, KeyPair, ED25519, ED25519_PUBLIC_KEY_LEN}, }; use smallvec::{smallvec, SmallVec}; use std::{ cmp, f32, fmt::Debug, io::{self, Cursor, Read, Write}, - sync::Arc + sync::Arc, }; pub const INIT_MESSAGE_FIRST_BYTE: u8 = 0xff; @@ -91,29 +90,27 @@ pub const MAX_FAILED_RETRIES: usize = 120; pub const SALTED_NODE_ID_HASH_LEN: usize = 20; pub type SaltedNodeIdHash = [u8; SALTED_NODE_ID_HASH_LEN]; - pub fn is_init_message(msg: &[u8]) -> bool { !msg.is_empty() && msg[0] == INIT_MESSAGE_FIRST_BYTE } - #[allow(clippy::large_enum_variant)] pub enum InitMsg { Ping { salted_node_id_hash: SaltedNodeIdHash, ecdh_public_key: EcdhPublicKey, - algorithms: Algorithms + algorithms: Algorithms, }, Pong { salted_node_id_hash: SaltedNodeIdHash, ecdh_public_key: EcdhPublicKey, algorithms: Algorithms, - encrypted_payload: MsgBuffer + encrypted_payload: MsgBuffer, }, Peng { salted_node_id_hash: SaltedNodeIdHash, - encrypted_payload: MsgBuffer - } + encrypted_payload: MsgBuffer, + }, } impl InitMsg { @@ -124,11 +121,11 @@ impl InitMsg { const PART_SALTED_NODE_ID_HASH: u8 = 2; const PART_STAGE: u8 = 1; - fn stage(&self) -> u8 { + pub fn stage(&self) -> u8 { match self { InitMsg::Ping { .. } => STAGE_PING, InitMsg::Pong { .. } => STAGE_PONG, - InitMsg::Peng { .. } => STAGE_PENG + InitMsg::Peng { .. } => STAGE_PENG, } } @@ -136,7 +133,7 @@ impl InitMsg { match self { InitMsg::Ping { salted_node_id_hash, .. } | InitMsg::Pong { salted_node_id_hash, .. } - | InitMsg::Peng { salted_node_id_hash, .. } => salted_node_id_hash + | InitMsg::Peng { salted_node_id_hash, .. } => salted_node_id_hash, } } @@ -150,11 +147,11 @@ impl InitMsg { short_hash } - fn read_from(buffer: &[u8], trusted_keys: &[Ed25519PublicKey]) -> Result<(Self, Ed25519PublicKey), Error> { + pub fn read_from(buffer: &[u8], trusted_keys: &[Ed25519PublicKey]) -> Result<(Self, Ed25519PublicKey), Error> { let mut r = Cursor::new(buffer); if r.read_u8().map_err(|_| Error::Parse("Init message too short"))? != INIT_MESSAGE_FIRST_BYTE { - return Err(Error::Parse("Init message has invalid first byte")) + return Err(Error::Parse("Init message has invalid first byte")); } let mut public_key_salt = [0; 4]; r.read_exact(&mut public_key_salt).map_err(|_| Error::Parse("Init message too short"))?; @@ -166,11 +163,11 @@ impl InitMsg { if Self::calculate_hash(tk, &public_key_salt) == public_key_hash { public_key_data.clone_from_slice(tk); found_key = true; - break + break; } } if !found_key { - return Err(Error::Crypto("untrusted peer")) + return Err(Error::Crypto("untrusted peer")); } let mut stage = None; @@ -182,19 +179,19 @@ impl InitMsg { loop { let field = r.read_u8().map_err(|_| Error::Parse("Init message too short"))?; if field == Self::PART_END { - break + break; } let field_len = r.read_u16::().map_err(|_| Error::Parse("Init message too short"))? as usize; match field { Self::PART_STAGE => { if field_len != 1 { - return Err(Error::CryptoInit("Invalid size for stage field")) + return Err(Error::CryptoInit("Invalid size for stage field")); } stage = Some(r.read_u8().map_err(|_| Error::Parse("Init message too short"))?) } Self::PART_SALTED_NODE_ID_HASH => { if field_len != SALTED_NODE_ID_HASH_LEN { - return Err(Error::CryptoInit("Invalid size for salted node id hash field")) + return Err(Error::CryptoInit("Invalid size for salted node id hash field")); } let mut id = [0; SALTED_NODE_ID_HASH_LEN]; r.read_exact(&mut id).map_err(|_| Error::Parse("Init message too short"))?; @@ -224,7 +221,7 @@ impl InitMsg { 1 => Some(&AES_128_GCM), 2 => Some(&AES_256_GCM), 3 => Some(&CHACHA20_POLY1305), - _ => None + _ => None, }; let speed = r.read_f32::().map_err(|_| Error::Parse("Init message too short"))?; @@ -250,53 +247,53 @@ impl InitMsg { let signed_data = &r.into_inner()[0..pos]; let public_key = signature::UnparsedPublicKey::new(&ED25519, &public_key_data); if public_key.verify(&signed_data, &signature).is_err() { - return Err(Error::Crypto("invalid signature")) + return Err(Error::Crypto("invalid signature")); } let stage = match stage { Some(val) => val, - None => return Err(Error::CryptoInit("Init message without stage")) + None => return Err(Error::CryptoInit("Init message without stage")), }; let salted_node_id_hash = match salted_node_id_hash { Some(val) => val, - None => return Err(Error::CryptoInit("Init message without node id")) + None => return Err(Error::CryptoInit("Init message without node id")), }; let msg = match stage { STAGE_PING => { let ecdh_public_key = match ecdh_public_key { Some(val) => val, - None => return Err(Error::CryptoInit("Init message without ecdh public key")) + None => return Err(Error::CryptoInit("Init message without ecdh public key")), }; let algorithms = match algorithms { Some(val) => val, - None => return Err(Error::CryptoInit("Init message without algorithms")) + None => return Err(Error::CryptoInit("Init message without algorithms")), }; Self::Ping { salted_node_id_hash, ecdh_public_key, algorithms } } STAGE_PONG => { let ecdh_public_key = match ecdh_public_key { Some(val) => val, - None => return Err(Error::CryptoInit("Init message without ecdh public key")) + None => return Err(Error::CryptoInit("Init message without ecdh public key")), }; let algorithms = match algorithms { Some(val) => val, - None => return Err(Error::CryptoInit("Init message without algorithms")) + None => return Err(Error::CryptoInit("Init message without algorithms")), }; let encrypted_payload = match encrypted_payload { Some(val) => val, - None => return Err(Error::CryptoInit("Init message without payload")) + None => return Err(Error::CryptoInit("Init message without payload")), }; Self::Pong { salted_node_id_hash, ecdh_public_key, algorithms, encrypted_payload } } STAGE_PENG => { let encrypted_payload = match encrypted_payload { Some(val) => val, - None => return Err(Error::CryptoInit("Init message without payload")) + None => return Err(Error::CryptoInit("Init message without payload")), }; Self::Peng { salted_node_id_hash, encrypted_payload } } - _ => return Err(Error::CryptoInit("Invalid stage")) + _ => return Err(Error::CryptoInit("Invalid stage")), }; Ok((msg, public_key_data)) @@ -336,7 +333,7 @@ impl InitMsg { w.write_u16::(key_bytes.len() as u16)?; w.write_all(&key_bytes)?; } - _ => () + _ => (), } match &self { @@ -364,7 +361,7 @@ impl InitMsg { w.write_f32::(*speed)?; } } - _ => () + _ => (), } match &self { @@ -373,7 +370,7 @@ impl InitMsg { w.write_u16::(encrypted_payload.len() as u16)?; w.write_all(encrypted_payload.message())?; } - _ => () + _ => (), } w.write_u8(Self::PART_END)?; @@ -387,11 +384,10 @@ impl InitMsg { } } - #[derive(PartialEq, Debug)] pub enum InitResult { Continue, - Success { peer_payload: P, is_initiator: bool } + Success { peer_payload: P, is_initiator: bool }, } pub struct InitState { @@ -409,13 +405,13 @@ pub struct InitState { algorithms: Algorithms, #[allow(dead_code)] // Used in tests selected_algorithm: Option<&'static Algorithm>, - failed_retries: usize + failed_retries: usize, } impl InitState

{ pub fn new( node_id: NodeId, payload: P, key_pair: Arc, trusted_keys: Arc<[Ed25519PublicKey]>, - algorithms: Algorithms + algorithms: Algorithms, ) -> Self { let mut hash = [0; SALTED_NODE_ID_HASH_LEN]; let rng = SystemRandom::new(); @@ -437,7 +433,7 @@ impl InitState

{ selected_algorithm: None, algorithms, failed_retries: 0, - close_time: 60 + close_time: 60, } } @@ -523,28 +519,22 @@ impl InitState

{ let mut public_key = [0; ED25519_PUBLIC_KEY_LEN]; public_key.clone_from_slice(self.key_pair.as_ref().public_key().as_ref()); let msg = match stage { - STAGE_PING => { - InitMsg::Ping { - salted_node_id_hash: self.salted_node_id_hash, - ecdh_public_key: ecdh_public_key.unwrap(), - algorithms: self.algorithms.clone() - } - } - STAGE_PONG => { - InitMsg::Pong { - salted_node_id_hash: self.salted_node_id_hash, - ecdh_public_key: ecdh_public_key.unwrap(), - algorithms: self.algorithms.clone(), - encrypted_payload: self.encrypt_payload() - } - } - STAGE_PENG => { - InitMsg::Peng { - salted_node_id_hash: self.salted_node_id_hash, - encrypted_payload: self.encrypt_payload() - } - } - _ => unreachable!() + STAGE_PING => InitMsg::Ping { + salted_node_id_hash: self.salted_node_id_hash, + ecdh_public_key: ecdh_public_key.unwrap(), + algorithms: self.algorithms.clone(), + }, + STAGE_PONG => InitMsg::Pong { + salted_node_id_hash: self.salted_node_id_hash, + ecdh_public_key: ecdh_public_key.unwrap(), + algorithms: self.algorithms.clone(), + encrypted_payload: self.encrypt_payload(), + }, + STAGE_PENG => InitMsg::Peng { + salted_node_id_hash: self.salted_node_id_hash, + encrypted_payload: self.encrypt_payload(), + }, + _ => unreachable!(), }; let mut bytes = out.buffer(); let len = msg.write_to(&mut bytes, &self.key_pair).expect("Buffer too small"); @@ -563,7 +553,7 @@ impl InitState

{ fn select_algorithm(&self, peer_algos: &Algorithms) -> Result, Error> { if self.algorithms.allow_unencrypted && peer_algos.allow_unencrypted { - return Ok(None) + return Ok(None); } // For each supported algorithm, find the algorithm in the list of the peer (ignore algorithm if not found). // Take the minimal speed reported by either us or the peer. @@ -597,7 +587,7 @@ impl InitState

{ if self.salted_node_id_hash == salted_node_id_hash || self.check_salted_node_id_hash(&salted_node_id_hash, self.node_id) { - return Err(Error::CryptoInitFatal("Connected to self")) + return Err(Error::CryptoInitFatal("Connected to self")); } if stage != self.next_stage { if self.next_stage == STAGE_PONG && stage == STAGE_PING { @@ -610,15 +600,15 @@ impl InitState

{ self.last_message = None; self.ecdh_private_key = None; } else { - return Ok(InitResult::Continue) + return Ok(InitResult::Continue); } } else if self.next_stage == CLOSING { - return Ok(InitResult::Continue) + return Ok(InitResult::Continue); } else if self.last_message.is_some() { self.repeat_last_message(out); - return Ok(InitResult::Continue) + return Ok(InitResult::Continue); } else { - return Err(Error::CryptoInitFatal("Received invalid stage as first message")) + return Err(Error::CryptoInitFatal("Received invalid stage as first message")); } } self.failed_retries = 0; @@ -683,23 +673,25 @@ impl InitState

{ let rotation = RotationState::new(!self.is_initiator, buffer); if !buffer.is_empty() { buffer.prepend_byte(MESSAGE_TYPE_ROTATION); + crypto.encrypt(buffer); } PeerCrypto::Encrypted { algorithm: crypto.algorithm(), + trusted_keys: self.trusted_keys.clone(), core: crypto, rotation, rotate_counter: 0, - last_init_message: self.last_message.unwrap() + last_init_message: self.last_message.unwrap(), } } else { PeerCrypto::Unencrypted { - last_init_message: self.last_message.unwrap() + last_init_message: self.last_message.unwrap(), + trusted_keys: self.trusted_keys.clone(), } } } } - #[cfg(test)] mod tests { use super::*; @@ -731,7 +723,7 @@ mod tests { rng.fill(&mut node2).unwrap(); let algorithms = Algorithms { algorithm_speeds: smallvec![(&AES_128_GCM, 600.0), (&AES_256_GCM, 500.0), (&CHACHA20_POLY1305, 400.0)], - allow_unencrypted: false + allow_unencrypted: false, }; let sender = InitState::new(node1, vec![1], key_pair.clone(), trusted_nodes.clone(), algorithms.clone()); let receiver = InitState::new(node2, vec![2], key_pair, trusted_nodes, algorithms); @@ -751,12 +743,12 @@ mod tests { assert_eq!(sender.stage(), WAITING_TO_CLOSE); let result = match result { InitResult::Success { .. } => receiver.handle_init(&mut out).unwrap(), - InitResult::Continue => unreachable!() + InitResult::Continue => unreachable!(), }; assert_eq!(receiver.stage(), CLOSING); match result { InitResult::Success { .. } => assert!(out.is_empty()), - InitResult::Continue => unreachable!() + InitResult::Continue => unreachable!(), } } @@ -782,14 +774,14 @@ mod tests { // lost peng, sender recovers out.clear(); } - InitResult::Continue => unreachable!() + InitResult::Continue => unreachable!(), }; sender.every_second(&mut out).unwrap(); let result = receiver.handle_init(&mut out).unwrap(); assert_eq!(receiver.stage(), CLOSING); match result { InitResult::Success { .. } => assert!(out.is_empty()), - InitResult::Continue => unreachable!() + InitResult::Continue => unreachable!(), } } @@ -813,7 +805,7 @@ mod tests { // lost peng, sender recovers out.clear(); } - InitResult::Continue => unreachable!() + InitResult::Continue => unreachable!(), }; receiver.every_second(&mut out).unwrap(); sender.handle_init(&mut out).unwrap(); @@ -821,7 +813,7 @@ mod tests { assert_eq!(receiver.stage(), CLOSING); match result { InitResult::Success { .. } => assert!(out.is_empty()), - InitResult::Continue => unreachable!() + InitResult::Continue => unreachable!(), } } @@ -870,7 +862,7 @@ mod tests { } fn test_algorithm_negotiation( - algos1: Algorithms, algos2: Algorithms, success: bool, selected: Option<&'static Algorithm> + algos1: Algorithms, algos2: Algorithms, success: bool, selected: Option<&'static Algorithm>, ) { let (mut sender, mut receiver) = create_pair(); sender.algorithms = algos1; @@ -880,7 +872,7 @@ mod tests { let res = receiver.handle_init(&mut out); assert_eq!(res.is_ok(), success); if !success { - return + return; } sender.handle_init(&mut out).unwrap(); receiver.handle_init(&mut out).unwrap(); @@ -894,70 +886,70 @@ mod tests { test_algorithm_negotiation( Algorithms { algorithm_speeds: smallvec![(&AES_128_GCM, 600.0), (&AES_256_GCM, 500.0), (&CHACHA20_POLY1305, 400.0)], - allow_unencrypted: false + allow_unencrypted: false, }, Algorithms { algorithm_speeds: smallvec![(&AES_128_GCM, 600.0), (&AES_256_GCM, 500.0), (&CHACHA20_POLY1305, 400.0)], - allow_unencrypted: false + allow_unencrypted: false, }, true, - Some(&AES_128_GCM) + Some(&AES_128_GCM), ); // Overlapping but different test_algorithm_negotiation( Algorithms { algorithm_speeds: smallvec![(&AES_256_GCM, 500.0), (&CHACHA20_POLY1305, 400.0)], - allow_unencrypted: false + allow_unencrypted: false, }, Algorithms { algorithm_speeds: smallvec![(&AES_128_GCM, 600.0), (&AES_256_GCM, 500.0)], - allow_unencrypted: false + allow_unencrypted: false, }, true, - Some(&AES_256_GCM) + Some(&AES_256_GCM), ); // Select fastest pair test_algorithm_negotiation( Algorithms { algorithm_speeds: smallvec![(&AES_128_GCM, 600.0), (&AES_256_GCM, 500.0), (&CHACHA20_POLY1305, 400.0)], - allow_unencrypted: false + allow_unencrypted: false, }, Algorithms { algorithm_speeds: smallvec![(&AES_128_GCM, 40.0), (&AES_256_GCM, 50.0), (&CHACHA20_POLY1305, 60.0)], - allow_unencrypted: false + allow_unencrypted: false, }, true, - Some(&CHACHA20_POLY1305) + Some(&CHACHA20_POLY1305), ); // Select unencrypted if supported by both test_algorithm_negotiation( Algorithms { algorithm_speeds: smallvec![(&AES_128_GCM, 600.0), (&AES_256_GCM, 500.0), (&CHACHA20_POLY1305, 400.0)], - allow_unencrypted: true + allow_unencrypted: true, }, Algorithms { algorithm_speeds: smallvec![(&AES_128_GCM, 600.0), (&AES_256_GCM, 500.0), (&CHACHA20_POLY1305, 400.0)], - allow_unencrypted: true + allow_unencrypted: true, }, true, - None + None, ); // Do not select unencrypted if only supported by one test_algorithm_negotiation( Algorithms { algorithm_speeds: smallvec![(&AES_128_GCM, 600.0), (&AES_256_GCM, 500.0), (&CHACHA20_POLY1305, 400.0)], - allow_unencrypted: true + allow_unencrypted: true, }, Algorithms { algorithm_speeds: smallvec![(&AES_128_GCM, 600.0), (&AES_256_GCM, 500.0), (&CHACHA20_POLY1305, 400.0)], - allow_unencrypted: false + allow_unencrypted: false, }, true, - Some(&AES_128_GCM) + Some(&AES_128_GCM), ); // Fail if no match @@ -965,10 +957,10 @@ mod tests { Algorithms { algorithm_speeds: smallvec![(&AES_128_GCM, 600.0)], allow_unencrypted: true }, Algorithms { algorithm_speeds: smallvec![(&AES_256_GCM, 500.0), (&CHACHA20_POLY1305, 400.0)], - allow_unencrypted: false + allow_unencrypted: false, }, false, - Some(&AES_128_GCM) + Some(&AES_128_GCM), ); } } diff --git a/src/engine/mod.rs b/src/engine/mod.rs index a1145cd..5daca8a 100644 --- a/src/engine/mod.rs +++ b/src/engine/mod.rs @@ -75,7 +75,7 @@ impl GenericCloud::new( + let mut socket_thread = SocketThread::::new( config.clone(), device, socket, @@ -85,6 +85,7 @@ impl GenericCloud SocketThread SocketThread { - self.update_peer_info(src, None).await?; self.buffer.clear(); + self.update_peer_info(src, None).await?; } MESSAGE_TYPE_CLOSE => { - self.remove_peer(src); self.buffer.clear(); + self.remove_peer(src); } _ => { - self.traffic.count_invalid_protocol(self.buffer.len()); self.buffer.clear(); + self.traffic.count_invalid_protocol(self.buffer.len()); return Err(Error::Message("Unknown message type")); } }, diff --git a/src/tests/common.rs b/src/tests/common.rs index b1e37e2..e61005d 100644 --- a/src/tests/common.rs +++ b/src/tests/common.rs @@ -93,6 +93,7 @@ impl Simulator

{ DebugLogger::set_node(self.next_port as usize); self.next_port += 1; let node = TestNode::new(&config, MockSocket::new(addr), MockDevice::new(), None, None).await.unwrap(); + DebugLogger::set_node(0); self.nodes.insert(addr, node); addr