From a7272f5cbac74d865bd6e00defe1de2f1734765e Mon Sep 17 00:00:00 2001 From: Erik Hollensbe Date: Mon, 18 Apr 2022 10:54:02 -0700 Subject: [PATCH 1/2] initial test fixing on linux Signed-off-by: Erik Hollensbe --- aes-gmac-siv/src/impl_openssl.rs | 19 ++- .../src/vl1/identity.rs | 108 +++++++------ .../src/vl1/inetaddress.rs | 148 +++++++++++------- zerotier-network-hypervisor/src/vl1/peer.rs | 78 +++++---- 4 files changed, 197 insertions(+), 156 deletions(-) diff --git a/aes-gmac-siv/src/impl_openssl.rs b/aes-gmac-siv/src/impl_openssl.rs index fa3c8d187..b6e4613ec 100644 --- a/aes-gmac-siv/src/impl_openssl.rs +++ b/aes-gmac-siv/src/impl_openssl.rs @@ -8,7 +8,7 @@ // AES-GMAC-SIV implemented using OpenSSL. -use openssl::symm::{Crypter, Cipher, Mode}; +use openssl::symm::{Cipher, Crypter, Mode}; fn aes_ctr_by_key_size(ks: usize) -> Cipher { match ks { @@ -145,7 +145,8 @@ impl AesGmacSiv { let gmac = self.gmac.as_mut().unwrap(); let _ = gmac.finalize(&mut self.tmp); let _ = gmac.get_tag(&mut self.tmp); - unsafe { // tag[8..16] = tmp[0..8] ^ tmp[8..16] + unsafe { + // tag[8..16] = tmp[0..8] ^ tmp[8..16] let tmp = self.tmp.as_mut_ptr().cast::(); *self.tag.as_mut_ptr().cast::().offset(1) = *tmp ^ *tmp.offset(1); } @@ -185,7 +186,8 @@ impl AesGmacSiv { let mut tag_tmp = [0_u8; 32]; let _ = Crypter::new(aes_ecb_by_key_size(self.k1.len()), Mode::Decrypt, self.k1.as_slice(), None).unwrap().update(&self.tag, &mut tag_tmp); self.tag.copy_from_slice(&tag_tmp[0..16]); - unsafe { // tmp[0..8] = tag[0..8], tmp[8..16] = 0 + unsafe { + // tmp[0..8] = tag[0..8], tmp[8..16] = 0 let tmp = self.tmp.as_mut_ptr().cast::(); *tmp = *self.tag.as_mut_ptr().cast::(); *tmp.offset(1) = 0; @@ -227,13 +229,18 @@ impl AesGmacSiv { /// Finish decryption and return true if authentication appears valid. /// If this returns false the message should be dropped. #[inline(always)] - pub fn decrypt_finish(&mut self) -> bool { + pub fn decrypt_finish(&mut self) -> Option<&[u8; 16]> { let gmac = self.gmac.as_mut().unwrap(); let _ = gmac.finalize(&mut self.tmp); let _ = gmac.get_tag(&mut self.tmp); - unsafe { // tag[8..16] == tmp[0..8] ^ tmp[8..16] + unsafe { + // tag[8..16] == tmp[0..8] ^ tmp[8..16] let tmp = self.tmp.as_mut_ptr().cast::(); - *self.tag.as_mut_ptr().cast::().offset(1) == *tmp ^ *tmp.offset(1) + if *self.tag.as_mut_ptr().cast::().offset(1) == *tmp ^ *tmp.offset(1) { + Some(&self.tag) + } else { + None + } } } } diff --git a/zerotier-network-hypervisor/src/vl1/identity.rs b/zerotier-network-hypervisor/src/vl1/identity.rs index 836c24061..e113c57cf 100644 --- a/zerotier-network-hypervisor/src/vl1/identity.rs +++ b/zerotier-network-hypervisor/src/vl1/identity.rs @@ -26,9 +26,9 @@ use zerotier_core_crypto::secret::Secret; use crate::error::{InvalidFormatError, InvalidParameterError}; use crate::util::buffer::Buffer; -use crate::util::pool::{Pool, Pooled, PoolFactory}; -use crate::vl1::Address; +use crate::util::pool::{Pool, PoolFactory, Pooled}; use crate::vl1::protocol::{ADDRESS_SIZE, ADDRESS_SIZE_STRING, IDENTITY_POW_THRESHOLD}; +use crate::vl1::Address; /// Curve25519 and Ed25519 pub const IDENTITY_ALGORITHM_X25519: u8 = 0x01; @@ -40,7 +40,8 @@ pub const IDENTITY_ALGORITHM_EC_NIST_P384: u8 = 0x02; pub const IDENTITY_ALGORITHM_ALL: u8 = 0xff; /// Current sanity limit for the size of a marshaled Identity (can be increased if needed). -pub const MAX_MARSHAL_SIZE: usize = ADDRESS_SIZE + C25519_PUBLIC_KEY_SIZE + ED25519_PUBLIC_KEY_SIZE + C25519_SECRET_KEY_SIZE + ED25519_SECRET_KEY_SIZE + P384_PUBLIC_KEY_SIZE + P384_PUBLIC_KEY_SIZE + P384_SECRET_KEY_SIZE + P384_SECRET_KEY_SIZE + P384_ECDSA_SIGNATURE_SIZE + ED25519_SIGNATURE_SIZE + 16; +pub const MAX_MARSHAL_SIZE: usize = + ADDRESS_SIZE + C25519_PUBLIC_KEY_SIZE + ED25519_PUBLIC_KEY_SIZE + C25519_SECRET_KEY_SIZE + ED25519_SECRET_KEY_SIZE + P384_PUBLIC_KEY_SIZE + P384_PUBLIC_KEY_SIZE + P384_SECRET_KEY_SIZE + P384_SECRET_KEY_SIZE + P384_ECDSA_SIGNATURE_SIZE + ED25519_SIGNATURE_SIZE + 16; #[derive(Clone)] pub struct IdentityP384Secret { @@ -70,7 +71,7 @@ pub struct Identity { pub ed25519: [u8; ED25519_PUBLIC_KEY_SIZE], pub p384: Option, pub secret: Option, - pub fingerprint: [u8; SHA512_HASH_SIZE] + pub fingerprint: [u8; SHA512_HASH_SIZE], } #[inline(always)] @@ -129,12 +130,8 @@ impl Identity { c25519: c25519_pub, ed25519: ed25519_pub, p384: None, - secret: Some(IdentitySecret { - c25519, - ed25519, - p384: None, - }), - fingerprint: [0_u8; 64] // replaced in upgrade() + secret: Some(IdentitySecret { c25519, ed25519, p384: None }), + fingerprint: [0_u8; 64], // replaced in upgrade() }; assert!(id.upgrade().is_ok()); assert!(id.p384.is_some() && id.secret.as_ref().unwrap().p384.is_some()); @@ -176,10 +173,7 @@ impl Identity { ecdsa_self_signature, ed25519_self_signature, }); - let _ = self.secret.as_mut().unwrap().p384.insert(IdentityP384Secret { - ecdh: p384_ecdh, - ecdsa: p384_ecdsa, - }); + let _ = self.secret.as_mut().unwrap().p384.insert(IdentityP384Secret { ecdh: p384_ecdh, ecdsa: p384_ecdsa }); self.fingerprint = SHA512::hash(self_sign_buf.as_slice()); return Ok(true); @@ -251,9 +245,7 @@ impl Identity { // for the final result to be technically FIPS compliant. Non-FIPS algorithm secrets are considered // a salt in the HMAC(salt, key) HKDF construction. if secret.p384.is_some() && other.p384.is_some() { - secret.p384.as_ref().unwrap().ecdh.agree(&other.p384.as_ref().unwrap().ecdh).map(|p384_secret| { - Secret(hmac_sha512(&c25519_secret.0, &p384_secret.0)) - }) + secret.p384.as_ref().unwrap().ecdh.agree(&other.p384.as_ref().unwrap().ecdh).map(|p384_secret| Secret(hmac_sha512(&c25519_secret.0, &p384_secret.0))) } else { Some(c25519_secret) } @@ -291,7 +283,8 @@ impl Identity { /// Verify a signature against this identity. pub fn verify(&self, msg: &[u8], mut signature: &[u8]) -> bool { - if signature.len() == 96 { // legacy ed25519-only signature with hash included + if signature.len() == 96 { + // legacy ed25519-only signature with hash included ed25519_verify(&self.ed25519, signature, msg) } else if signature.len() > 1 { let algorithms = signature[0]; @@ -519,7 +512,7 @@ impl Identity { } else { None }, - fingerprint: sha.finish() + fingerprint: sha.finish(), }) } @@ -532,46 +525,42 @@ impl Identity { let p384 = self.p384.as_ref().unwrap(); let p384_secret_joined: [u8; P384_SECRET_KEY_SIZE + P384_SECRET_KEY_SIZE] = concat_arrays_2(p384_secret.ecdh.secret_key_bytes().as_bytes(), p384_secret.ecdsa.secret_key_bytes().as_bytes()); let p384_joined: [u8; P384_PUBLIC_KEY_SIZE + P384_PUBLIC_KEY_SIZE + P384_ECDSA_SIGNATURE_SIZE + ED25519_SIGNATURE_SIZE] = concat_arrays_4(p384.ecdh.as_bytes(), p384.ecdsa.as_bytes(), &p384.ecdsa_self_signature, &p384.ed25519_self_signature); - format!("{}:0:{}{}:{}{}:2:{}:{}", + format!( + "{}:0:{}{}:{}{}:2:{}:{}", self.address.to_string(), hex::to_string(&self.c25519), hex::to_string(&self.ed25519), hex::to_string(&secret.c25519.secret_bytes().0), hex::to_string(&secret.ed25519.secret_bytes().0), base64::encode_config(p384_joined, base64::URL_SAFE_NO_PAD), - base64::encode_config(p384_secret_joined, base64::URL_SAFE_NO_PAD)) + base64::encode_config(p384_secret_joined, base64::URL_SAFE_NO_PAD) + ) } else { - format!("{}:0:{}{}:{}{}", - self.address.to_string(), - hex::to_string(&self.c25519), - hex::to_string(&self.ed25519), - hex::to_string(&secret.c25519.secret_bytes().0), - hex::to_string(&secret.ed25519.secret_bytes().0)) + format!("{}:0:{}{}:{}{}", self.address.to_string(), hex::to_string(&self.c25519), hex::to_string(&self.ed25519), hex::to_string(&secret.c25519.secret_bytes().0), hex::to_string(&secret.ed25519.secret_bytes().0)) } } else { - self.p384.as_ref().map_or_else(|| { - format!("{}:0:{}{}", - self.address.to_string(), - hex::to_string(&self.c25519),hex::to_string(&self.ed25519)) - }, |p384| { - let p384_joined: [u8; P384_PUBLIC_KEY_SIZE + P384_PUBLIC_KEY_SIZE + P384_ECDSA_SIGNATURE_SIZE + ED25519_SIGNATURE_SIZE] = concat_arrays_4(p384.ecdh.as_bytes(), p384.ecdsa.as_bytes(), &p384.ecdsa_self_signature, &p384.ed25519_self_signature); - format!("{}:0:{}{}::2:{}", - self.address.to_string(), - hex::to_string(&self.c25519), - hex::to_string(&self.ed25519), - base64::encode_config(p384_joined, base64::URL_SAFE_NO_PAD)) - }) + self.p384.as_ref().map_or_else( + || format!("{}:0:{}{}", self.address.to_string(), hex::to_string(&self.c25519), hex::to_string(&self.ed25519)), + |p384| { + let p384_joined: [u8; P384_PUBLIC_KEY_SIZE + P384_PUBLIC_KEY_SIZE + P384_ECDSA_SIGNATURE_SIZE + ED25519_SIGNATURE_SIZE] = concat_arrays_4(p384.ecdh.as_bytes(), p384.ecdsa.as_bytes(), &p384.ecdsa_self_signature, &p384.ed25519_self_signature); + format!("{}:0:{}{}::2:{}", self.address.to_string(), hex::to_string(&self.c25519), hex::to_string(&self.ed25519), base64::encode_config(p384_joined, base64::URL_SAFE_NO_PAD)) + }, + ) } } /// Get this identity in string form with all ciphers and with secrets (if present) - pub fn to_secret_string(&self) -> String { self.to_string_with_options(IDENTITY_ALGORITHM_ALL, true) } + pub fn to_secret_string(&self) -> String { + self.to_string_with_options(IDENTITY_ALGORITHM_ALL, true) + } } impl ToString for Identity { /// Get only the public portion of this identity as a string, including all cipher suites. #[inline(always)] - fn to_string(&self) -> String { self.to_string_with_options(IDENTITY_ALGORITHM_ALL, false) } + fn to_string(&self) -> String { + self.to_string_with_options(IDENTITY_ALGORITHM_ALL, false) + } } impl FromStr for Identity { @@ -616,7 +605,8 @@ impl FromStr for Identity { ptr += 1; } - let keys = [hex::from_string(keys[0].unwrap_or("")), hex::from_string(keys[1].unwrap_or("")), base64::decode_config(keys[2].unwrap_or(""), base64::URL_SAFE_NO_PAD).unwrap_or_else(|_| Vec::new()), base64::decode_config(keys[3].unwrap_or(""), base64::URL_SAFE_NO_PAD).unwrap_or_else(|_| Vec::new())]; + let keys = + [hex::from_string(keys[0].unwrap_or("")), hex::from_string(keys[1].unwrap_or("")), base64::decode_config(keys[2].unwrap_or(""), base64::URL_SAFE_NO_PAD).unwrap_or_else(|_| Vec::new()), base64::decode_config(keys[3].unwrap_or(""), base64::URL_SAFE_NO_PAD).unwrap_or_else(|_| Vec::new())]; if keys[0].len() != C25519_PUBLIC_KEY_SIZE + ED25519_PUBLIC_KEY_SIZE { return Err(InvalidFormatError); } @@ -697,30 +687,38 @@ impl FromStr for Identity { }, }) }, - fingerprint: sha.finish() + fingerprint: sha.finish(), }) } } impl PartialEq for Identity { #[inline(always)] - fn eq(&self, other: &Self) -> bool { self.fingerprint == other.fingerprint } + fn eq(&self, other: &Self) -> bool { + self.fingerprint == other.fingerprint + } } impl Eq for Identity {} impl Ord for Identity { - fn cmp(&self, other: &Self) -> Ordering { self.address.cmp(&other.address).then_with(|| self.fingerprint.cmp(&other.fingerprint)) } + fn cmp(&self, other: &Self) -> Ordering { + self.address.cmp(&other.address).then_with(|| self.fingerprint.cmp(&other.fingerprint)) + } } impl PartialOrd for Identity { #[inline(always)] - fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } } impl Hash for Identity { #[inline(always)] - fn hash(&self, state: &mut H) { state.write_u64(self.address.to_u64()) } + fn hash(&self, state: &mut H) { + state.write_u64(self.address.to_u64()) + } } const ADDRESS_DERIVATION_HASH_MEMORY_SIZE: usize = 2097152; @@ -767,19 +765,25 @@ struct AddressDerivationMemory(*mut u8); impl AddressDerivationMemory { #[inline(always)] - fn get_memory(&mut self) -> *mut u8 { self.0 } + fn get_memory(&mut self) -> *mut u8 { + self.0 + } } impl Drop for AddressDerivationMemory { #[inline(always)] - fn drop(&mut self) { unsafe { dealloc(self.0, Layout::from_size_align(ADDRESS_DERIVATION_HASH_MEMORY_SIZE, 8).unwrap()) }; } + fn drop(&mut self) { + unsafe { dealloc(self.0, Layout::from_size_align(ADDRESS_DERIVATION_HASH_MEMORY_SIZE, 8).unwrap()) }; + } } struct AddressDerivationMemoryFactory; impl PoolFactory for AddressDerivationMemoryFactory { #[inline(always)] - fn create(&self) -> AddressDerivationMemory { AddressDerivationMemory(unsafe { alloc(Layout::from_size_align(ADDRESS_DERIVATION_HASH_MEMORY_SIZE, 8).unwrap()) }) } + fn create(&self) -> AddressDerivationMemory { + AddressDerivationMemory(unsafe { alloc(Layout::from_size_align(ADDRESS_DERIVATION_HASH_MEMORY_SIZE, 8).unwrap()) }) + } #[inline(always)] fn reset(&self, _: &mut AddressDerivationMemory) {} @@ -799,10 +803,10 @@ pub(crate) fn purge_verification_memory_pool() { #[cfg(test)] mod tests { + use crate::vl1::identity::{Identity, IDENTITY_ALGORITHM_ALL}; use std::str::FromStr; use std::time::{Duration, SystemTime}; use zerotier_core_crypto::hex; - use crate::vl1::identity::{Identity, IDENTITY_ALGORITHM_ALL}; const GOOD_V0_IDENTITIES: [&'static str; 10] = [ "51ef313c3a:0:79fee239cf79833be3a9068565661dc33e04759fa0f7e2218d10f1a51d441f1bf71332eba26dfc3755ce60e14650fe68dede66cf145e429972a7f51e026374de:6d12b1c5e0eae3983a5ee5872fa9061963d9e2f8cdd85adab54bdec4bd67f538cafc91b8b5b93fca658a630aab030ec10d66235f2443ccf362c55c41ae01b46e", @@ -814,7 +818,7 @@ mod tests { "c5bdb4a6a6:0:e0a8575bc0277ecf59aaa4a2724acc55554151fff510c8211b0b863398a04224ed918c16405552336ad4c4da3b98eb6224574f1cacaa69e19cdfde184fd9292d:0d45f17d73337cc1898f7be6aae54a050b39ed0259b608b80619c3f898caf8a3a48ae56e51c3d7d8426ef295c0628d81b1a99616a3ed28da49bf8f81e1bec863", "c622dedbe4:0:0cfec354be26b4b2fa9ea29166b4acaf9476d169d51fd741d7e4cd9de93f321c6b80628c50da566d0a6b07d58d651eba8af63e0edc36202c05c3f97c828788ad:31a75d2b46c1b0f33228d3869bc807b42b371bbcef4c96f7232a27c62f56397568558f115d9cff3d6f7b8efb726a1ea49a591662d9aacd1049e295cbb0cf3197", "e28829ab3c:0:8e36c4f6cb524cae6bbea5f26dadb601a76f2a3793961779317365effb17ac6cde4ff4149a1b3480fbdbdbabfe62e1f264e764f95540b63158d1ea8b1eb0df5b:957508a7546df18784cd285da2e6216e4265906c6c7fba9a895f29a724d63a2e0268128c0c9c2cc304c8c3304863cdfe437a7b93b12dc778c0372a116088e9cd", - "aec623e59d:0:d7b1a715d95490611b8d467bbee442e3c88949f677371d3692da92f5b23d9e01bb916596cc1ddd2d5e0e5ecd6c750bb71ad2ba594b614b771c6f07b39dbe4126:ae4e4759d67158dcc54ede8c8ddb08acac49baf8b816883fc0ac5b6e328d17ced5f05ee0b4cd20b03bc5005471795c29206b835081b873fef26d3941416bd626" + "aec623e59d:0:d7b1a715d95490611b8d467bbee442e3c88949f677371d3692da92f5b23d9e01bb916596cc1ddd2d5e0e5ecd6c750bb71ad2ba594b614b771c6f07b39dbe4126:ae4e4759d67158dcc54ede8c8ddb08acac49baf8b816883fc0ac5b6e328d17ced5f05ee0b4cd20b03bc5005471795c29206b835081b873fef26d3941416bd626", ]; const GOOD_V1_IDENTITIES: [&'static str; 10] = [ "a8f6e0566e:0:a13a6394de205384eb75eb62179ef11423295c5ecdccfeed7f2eff6c7a74f8059c99eed164c5dfaf2a4cf395ec7b72b68ee1c3c31916de4bc57c07abfe77f9c2::2:A1Cj2O0hKLlhDQ6guCCv5H1UgzbegZwse0iqTaaZov9LpKifyKH0e1VzmHrPmoKcvgJyzI-BAqRQzBiUjScXIjojneNKOywc0Gvq-zeDCYPcXN393xi3q25mB3ud9iEN-GN6wiXPWFjHy-CBD9tGDJzr-G3ZJZvrdiLGT5rZ5W2cZtx8ORYnp9L9HJJOeb8qgdfVr67B5pT9jPsxSsw8P4qlzFFOlX2WN9Hvvu0TO6S_N4yq173deyr-f-ehcBFiBXsSG96p44oU4uRRBEDZWhzHDuD22Vw8PhsB8mko9IRqVXCGbvlaKJ0vyAZ_PyVRM9n_Z-HAEvLveAT-f61mh4YP", diff --git a/zerotier-network-hypervisor/src/vl1/inetaddress.rs b/zerotier-network-hypervisor/src/vl1/inetaddress.rs index 0754683d0..3067a3b64 100644 --- a/zerotier-network-hypervisor/src/vl1/inetaddress.rs +++ b/zerotier-network-hypervisor/src/vl1/inetaddress.rs @@ -8,13 +8,13 @@ use std::cmp::Ordering; use std::hash::{Hash, Hasher}; -use std::mem::{MaybeUninit, size_of, transmute_copy, zeroed}; +use std::mem::{size_of, transmute_copy, zeroed, MaybeUninit}; use std::net::{IpAddr, Ipv6Addr}; use std::ptr::{copy_nonoverlapping, null, slice_from_raw_parts, write_bytes}; use std::str::FromStr; #[cfg(windows)] -use winapi::um::winsock2 as winsock2; +use winapi::um::winsock2; use crate::error::InvalidFormatError; use crate::util::buffer::Buffer; @@ -74,18 +74,24 @@ pub union InetAddress { impl Clone for InetAddress { #[inline(always)] - fn clone(&self) -> Self { unsafe { transmute_copy(self) } } + fn clone(&self) -> Self { + unsafe { transmute_copy(self) } + } } impl Default for InetAddress { #[inline(always)] - fn default() -> InetAddress { unsafe { zeroed() } } + fn default() -> InetAddress { + unsafe { zeroed() } + } } impl InetAddress { /// Get a new zero/nil InetAddress. #[inline(always)] - pub fn new() -> InetAddress { unsafe { zeroed() } } + pub fn new() -> InetAddress { + unsafe { zeroed() } + } /// Construct from IP and port. /// If the IP is not either 4 or 16 bytes in length, a nil/0 InetAddress is returned. @@ -100,7 +106,9 @@ impl InetAddress { /// Zero the contents of this InetAddress. #[inline(always)] - pub fn zero(&mut self) { unsafe { write_bytes((self as *mut Self).cast::(), 0, size_of::()) }; } + pub fn zero(&mut self) { + unsafe { write_bytes((self as *mut Self).cast::(), 0, size_of::()) }; + } /// Get an instance of 127.0.0.1/port pub fn ipv4_loopback(port: u16) -> InetAddress { @@ -138,19 +146,35 @@ impl InetAddress { /// Returns true if this InetAddress is the nil value (zero). #[inline(always)] - pub fn is_nil(&self) -> bool { unsafe { self.sa.sa_family == 0 } } + pub fn is_nil(&self) -> bool { + unsafe { self.sa.sa_family == 0 } + } /// Check if this is an IPv4 address. #[inline(always)] - pub fn is_ipv4(&self) -> bool { unsafe { self.sa.sa_family as u8 == AF_INET } } + pub fn is_ipv4(&self) -> bool { + unsafe { self.sa.sa_family as u8 == AF_INET } + } /// Check if this is an IPv6 address. #[inline(always)] - pub fn is_ipv6(&self) -> bool { unsafe { self.sa.sa_family as u8 == AF_INET6 } } + pub fn is_ipv6(&self) -> bool { + unsafe { self.sa.sa_family as u8 == AF_INET6 } + } /// Get the address family of this InetAddress: AF_INET, AF_INET6, or 0 if uninitialized. #[inline(always)] - pub fn family(&self) -> u8 { unsafe { self.sa.sa_family } } + #[cfg(not(target_os = "linux"))] + pub fn family(&self) -> u8 { + unsafe { self.sa.sa_family } + } + + /// Get the address family of this InetAddress: AF_INET, AF_INET6, or 0 if uninitialized. + #[inline(always)] + #[cfg(target_os = "linux")] + pub fn family(&self) -> u16 { + unsafe { self.sa.sa_family } + } /// Get a pointer to the C "sockaddr" structure and the size of the returned structure in bytes. /// This is useful for interacting with C-level socket APIs. This returns a null pointer if @@ -161,7 +185,7 @@ impl InetAddress { match self.sa.sa_family as u8 { AF_INET => ((&self.sin as *const sockaddr_in).cast(), size_of::()), AF_INET6 => ((&self.sin6 as *const sockaddr_in6).cast(), size_of::()), - _ => (null(), 0) + _ => (null(), 0), } } } @@ -223,7 +247,7 @@ impl InetAddress { u16::from_be(match self.sa.sa_family as u8 { AF_INET => self.sin.sin_port as u16, AF_INET6 => self.sin6.sin6_port as u16, - _ => 0 + _ => 0, }) } } @@ -256,42 +280,48 @@ impl InetAddress { 0x0a => IpScope::Private, // 10.0.0.0/8 0x7f => IpScope::Loopback, // 127.0.0.0/8 0x64 => { - if (ip & 0xffc00000) == 0x64400000 { // 100.64.0.0/10 + if (ip & 0xffc00000) == 0x64400000 { + // 100.64.0.0/10 IpScope::Private } else { IpScope::Global } } 0xa9 => { - if (ip & 0xffff0000) == 0xa9fe0000 { // 169.254.0.0/16 + if (ip & 0xffff0000) == 0xa9fe0000 { + // 169.254.0.0/16 IpScope::LinkLocal } else { IpScope::Global } } 0xac => { - if (ip & 0xfff00000) == 0xac100000 { // 172.16.0.0/12 + if (ip & 0xfff00000) == 0xac100000 { + // 172.16.0.0/12 IpScope::Private } else { IpScope::Global } } 0xc0 => { - if (ip & 0xffff0000) == 0xc0a80000 || (ip & 0xffffff00) == 0xc0000200 { // 192.168.0.0/16 and 192.0.2.0/24 + if (ip & 0xffff0000) == 0xc0a80000 || (ip & 0xffffff00) == 0xc0000200 { + // 192.168.0.0/16 and 192.0.2.0/24 IpScope::Private } else { IpScope::Global } } 0xc6 => { - if (ip & 0xfffe0000) == 0xc6120000 || (ip & 0xffffff00) == 0xc6336400 { // 198.18.0.0/15 and 198.51.100.0/24 + if (ip & 0xfffe0000) == 0xc6120000 || (ip & 0xffffff00) == 0xc6336400 { + // 198.18.0.0/15 and 198.51.100.0/24 IpScope::Private } else { IpScope::Global } } 0xcb => { - if (ip & 0xffffff00) == 0xcb007100 { // 203.0.113.0/24 + if (ip & 0xffffff00) == 0xcb007100 { + // 203.0.113.0/24 IpScope::Private } else { IpScope::Global @@ -310,13 +340,15 @@ impl InetAddress { 0x33_u8, // 51.0.0.0/8 (UK Department of Social Security) 0x37_u8, // 55.0.0.0/8 (US DoD) 0x38_u8, // 56.0.0.0/8 (US Postal Service) - ].contains(&class_a) { + ] + .contains(&class_a) + { IpScope::PseudoPrivate } else { match ip >> 28 { 0xe => IpScope::Multicast, // 224.0.0.0/4 0xf => IpScope::Private, // 240.0.0.0/4 ("reserved," usually unusable) - _ => IpScope::Global + _ => IpScope::Global, } } } @@ -356,7 +388,7 @@ impl InetAddress { } IpScope::Global } - _ => IpScope::None + _ => IpScope::None, } } } @@ -370,7 +402,7 @@ impl InetAddress { format!("{}.{}.{}.{}", ip[0], ip[1], ip[2], ip[3]) } AF_INET6 => Ipv6Addr::from(*(&(self.sin6.sin6_addr) as *const in6_addr).cast::<[u8; 16]>()).to_string(), - _ => String::from("(null)") + _ => String::from("(null)"), } } } @@ -394,7 +426,7 @@ impl InetAddress { b[18] = *(&self.sin6.sin6_port as *const u16).cast::().offset(1); Ok(()) } - _ => buf.append_u8(0) + _ => buf.append_u8(0), } } } @@ -438,33 +470,37 @@ impl FromStr for InetAddress { fn from_str(s: &str) -> Result { let mut addr = InetAddress::new(); - let (ip_str, port) = s.find('/').map_or_else(|| { - (s, 0) - }, |pos| { - let ss = s.split_at(pos); - let mut port_str = ss.1; - if port_str.starts_with('/') { - port_str = &port_str[1..]; - } - (ss.0, u16::from_str_radix(port_str, 10).unwrap_or(0).to_be()) - }); - IpAddr::from_str(ip_str).map_or_else(|_| Err(InvalidFormatError), |ip| { - unsafe { - match ip { - IpAddr::V4(v4) => { - addr.sin.sin_family = AF_INET.into(); - addr.sin.sin_port = port.into(); - copy_nonoverlapping(v4.octets().as_ptr(), (&mut (addr.sin.sin_addr.s_addr) as *mut u32).cast(), 4); - } - IpAddr::V6(v6) => { - addr.sin6.sin6_family = AF_INET6.into(); - addr.sin6.sin6_port = port.into(); - copy_nonoverlapping(v6.octets().as_ptr(), (&mut (addr.sin6.sin6_addr) as *mut in6_addr).cast(), 16); + let (ip_str, port) = s.find('/').map_or_else( + || (s, 0), + |pos| { + let ss = s.split_at(pos); + let mut port_str = ss.1; + if port_str.starts_with('/') { + port_str = &port_str[1..]; + } + (ss.0, u16::from_str_radix(port_str, 10).unwrap_or(0).to_be()) + }, + ); + IpAddr::from_str(ip_str).map_or_else( + |_| Err(InvalidFormatError), + |ip| { + unsafe { + match ip { + IpAddr::V4(v4) => { + addr.sin.sin_family = AF_INET.into(); + addr.sin.sin_port = port.into(); + copy_nonoverlapping(v4.octets().as_ptr(), (&mut (addr.sin.sin_addr.s_addr) as *mut u32).cast(), 4); + } + IpAddr::V6(v6) => { + addr.sin6.sin6_family = AF_INET6.into(); + addr.sin6.sin6_port = port.into(); + copy_nonoverlapping(v6.octets().as_ptr(), (&mut (addr.sin6.sin6_addr) as *mut in6_addr).cast(), 16); + } } } - } - Ok(addr) - }) + Ok(addr) + }, + ) } } @@ -473,7 +509,7 @@ impl PartialEq for InetAddress { unsafe { if self.sa.sa_family == other.sa.sa_family { match self.sa.sa_family as u8 { - AF_INET => { self.sin.sin_port == other.sin.sin_port && self.sin.sin_addr.s_addr == other.sin.sin_addr.s_addr } + AF_INET => self.sin.sin_port == other.sin.sin_port && self.sin.sin_addr.s_addr == other.sin.sin_addr.s_addr, AF_INET6 => { if self.sin6.sin6_port == other.sin6.sin6_port { (*(&(self.sin6.sin6_addr) as *const in6_addr).cast::<[u8; 16]>()).eq(&*(&(other.sin6.sin6_addr) as *const in6_addr).cast::<[u8; 16]>()) @@ -481,7 +517,7 @@ impl PartialEq for InetAddress { false } } - _ => true + _ => true, } } else { false @@ -494,7 +530,9 @@ impl Eq for InetAddress {} impl PartialOrd for InetAddress { #[inline(always)] - fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } } // Manually implement Ord to ensure consistent sort order across platforms, since we don't know exactly @@ -504,9 +542,7 @@ impl Ord for InetAddress { unsafe { if self.sa.sa_family == other.sa.sa_family { match self.sa.sa_family as u8 { - 0 => { - Ordering::Equal - } + 0 => Ordering::Equal, AF_INET => { let ip_ordering = u32::from_be(self.sin.sin_addr.s_addr as u32).cmp(&u32::from_be(other.sin.sin_addr.s_addr as u32)); if ip_ordering == Ordering::Equal { @@ -532,9 +568,7 @@ impl Ord for InetAddress { } } else { match self.sa.sa_family as u8 { - 0 => { - Ordering::Less - } + 0 => Ordering::Less, AF_INET => { if other.sa.sa_family as u8 == AF_INET6 { Ordering::Less diff --git a/zerotier-network-hypervisor/src/vl1/peer.rs b/zerotier-network-hypervisor/src/vl1/peer.rs index 2c887551e..234dc98fb 100644 --- a/zerotier-network-hypervisor/src/vl1/peer.rs +++ b/zerotier-network-hypervisor/src/vl1/peer.rs @@ -9,8 +9,8 @@ use std::convert::TryInto; use std::mem::MaybeUninit; use std::num::NonZeroI64; -use std::sync::Arc; use std::sync::atomic::{AtomicI64, AtomicU64, AtomicU8, Ordering}; +use std::sync::Arc; use parking_lot::Mutex; @@ -22,15 +22,15 @@ use zerotier_core_crypto::random::{fill_bytes_secure, get_bytes_secure, next_u64 use zerotier_core_crypto::salsa::Salsa; use zerotier_core_crypto::secret::Secret; -use crate::{PacketBuffer, VERSION_MAJOR, VERSION_MINOR, VERSION_PROTO, VERSION_REVISION}; -use crate::util::{array_range, u64_as_bytes}; use crate::util::buffer::Buffer; -use crate::vl1::{Dictionary, Endpoint, Identity, InetAddress, Path}; +use crate::util::{array_range, u64_as_bytes}; use crate::vl1::hybridkey::{HybridKeyPair, HybridPublicKey}; use crate::vl1::identity::{IDENTITY_ALGORITHM_ALL, IDENTITY_ALGORITHM_X25519}; use crate::vl1::node::*; use crate::vl1::protocol::*; use crate::vl1::symmetricsecret::{EphemeralSymmetricSecret, SymmetricSecret}; +use crate::vl1::{Dictionary, Endpoint, Identity, InetAddress, Path}; +use crate::{PacketBuffer, VERSION_MAJOR, VERSION_MINOR, VERSION_PROTO, VERSION_REVISION}; /// A remote peer known to this node. /// Sending-related and receiving-related fields are locked separately since concurrent @@ -140,10 +140,12 @@ fn try_aead_decrypt(secret: &SymmetricSecret, packet_frag0_payload_bytes: &[u8], poly.update(packet_frag0_payload_bytes); let _ = payload.append_bytes_get_mut(packet_frag0_payload_bytes.len()).map(|b| salsa.crypt(packet_frag0_payload_bytes, b)); for f in fragments.iter() { - let _ = f.as_ref().map(|f| f.as_bytes_starting_at(FRAGMENT_HEADER_SIZE).map(|f| { - poly.update(f); - let _ = payload.append_bytes_get_mut(f.len()).map(|b| salsa.crypt(f, b)); - })); + let _ = f.as_ref().map(|f| { + f.as_bytes_starting_at(FRAGMENT_HEADER_SIZE).map(|f| { + poly.update(f); + let _ = payload.append_bytes_get_mut(f.len()).map(|b| salsa.crypt(f, b)); + }) + }); } if poly.finish()[0..8].eq(&header.mac) { Some(u64::from_ne_bytes(header.id)) @@ -211,24 +213,15 @@ impl Peer { /// Get the next message ID for sending a message to this peer. #[inline(always)] - pub(crate) fn next_message_id(&self) -> u64 { self.message_id_counter.fetch_add(1, Ordering::Relaxed) } + pub(crate) fn next_message_id(&self) -> u64 { + self.message_id_counter.fetch_add(1, Ordering::Relaxed) + } /// Receive, decrypt, authenticate, and process an incoming packet from this peer. /// /// If the packet comes in multiple fragments, the fragments slice should contain all /// those fragments after the main packet header and first chunk. - pub(crate) fn receive( - &self, - node: &Node, - si: &SI, - vi: &VI, - time_ticks: i64, - source_endpoint: &Endpoint, - source_path: &Arc, - header: &PacketHeader, - frag0: &Buffer<{ PACKET_SIZE_MAX }>, - fragments: &[Option]) - { + pub(crate) fn receive(&self, node: &Node, si: &SI, vi: &VI, time_ticks: i64, source_endpoint: &Endpoint, source_path: &Arc, header: &PacketHeader, frag0: &Buffer<{ PACKET_SIZE_MAX }>, fragments: &[Option]) { let _ = frag0.as_bytes_starting_at(PACKET_VERB_INDEX).map(|packet_frag0_payload_bytes| { let mut payload: Buffer = unsafe { Buffer::new_without_memzero() }; @@ -313,10 +306,11 @@ impl Peer { } } else { // In debug build check to make sure the next layer (VL2) is complying with the API contract. - #[cfg(debug)] { + #[cfg(debug)] + { if match verb { VERB_VL1_NOP | VERB_VL1_HELLO | VERB_VL1_ERROR | VERB_VL1_OK | VERB_VL1_WHOIS | VERB_VL1_RENDEZVOUS | VERB_VL1_ECHO | VERB_VL1_PUSH_DIRECT_PATHS | VERB_VL1_USER_MESSAGE => true, - _ => false + _ => false, } { panic!("The next layer handled a VL1 packet! It should not do this."); } @@ -419,14 +413,15 @@ impl Peer { /// static identity key. pub(crate) fn send_hello(&self, si: &SI, node: &Node, explicit_endpoint: Option<&Endpoint>) -> bool { let mut path = None; - let destination = explicit_endpoint.map_or_else(|| { - self.path(node).map_or(None, |p| { - path = Some(p.clone()); - Some(p.endpoint().as_ref().clone()) - }) - }, |endpoint| { - Some(endpoint.clone()) - }); + let destination = explicit_endpoint.map_or_else( + || { + self.path(node).map_or(None, |p| { + path = Some(p.clone()); + Some(p.endpoint().as_ref().clone()) + }) + }, + |endpoint| Some(endpoint.clone()), + ); if destination.is_none() { return false; } @@ -519,16 +514,17 @@ impl Peer { self.last_send_time_ticks.store(time_ticks, Ordering::Relaxed); self.total_bytes_sent.fetch_add(packet.len() as u64, Ordering::Relaxed); - path.map_or_else(|| { - self.send_to_endpoint(si, &destination, None, None, &packet) - }, |p| { - if self.send_to_endpoint(si, &destination, p.local_socket(), p.local_interface(), &packet) { - p.log_send_anything(time_ticks); - true - } else { - false - } - }) + path.map_or_else( + || self.send_to_endpoint(si, &destination, None, None, &packet), + |p| { + if self.send_to_endpoint(si, &destination, p.local_socket(), p.local_interface(), &packet) { + p.log_send_anything(time_ticks); + true + } else { + false + } + }, + ) } pub(crate) const CALL_EVERY_INTERVAL_MS: i64 = EPHEMERAL_SECRET_REKEY_AFTER_TIME / 10; From 17594ca5e1127159b6e3521121f313fbefc66245 Mon Sep 17 00:00:00 2001 From: Erik Hollensbe Date: Mon, 18 Apr 2022 10:57:11 -0700 Subject: [PATCH 2/2] Add a `make test` target Signed-off-by: Erik Hollensbe --- Makefile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Makefile b/Makefile index 993b02c72..a8c915186 100644 --- a/Makefile +++ b/Makefile @@ -3,4 +3,9 @@ all: clean: FORCE rm -rf zerotier-core-crypto/target zerotier-network-hypervisor/target zerotier-system-service/target syncwhole/target aes-gmac-siv/target iblt/target +test: + for i in */Cargo.toml; do cd $$(dirname $$i); cargo test || exit 1; cd ..; done + FORCE: + +.PHONY: test