From 5fd0e2998b9c98585b361df39b9a8a9b2797a738 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 13 Dec 2021 15:45:02 -0500 Subject: [PATCH] Build fixes. --- .../src/util/buffer.rs | 7 +++ zerotier-network-hypervisor/src/util/mod.rs | 7 +++ .../src/vl1/identity.rs | 47 +++++++++-------- zerotier-network-hypervisor/src/vl1/peer.rs | 52 ++++++++----------- zerotier-system-service/src/utils.rs | 2 +- 5 files changed, 62 insertions(+), 53 deletions(-) diff --git a/zerotier-network-hypervisor/src/util/buffer.rs b/zerotier-network-hypervisor/src/util/buffer.rs index 4b18e600a..4a3f1177f 100644 --- a/zerotier-network-hypervisor/src/util/buffer.rs +++ b/zerotier-network-hypervisor/src/util/buffer.rs @@ -8,6 +8,7 @@ use std::io::Write; use std::mem::{MaybeUninit, size_of}; +use crate::util::{array_range, array_range_mut}; use crate::util::pool::PoolFactory; @@ -62,12 +63,18 @@ impl Buffer { #[inline(always)] pub fn as_bytes_mut(&mut self) -> &mut [u8] { &mut self.1[0..self.0] } + #[inline(always)] + pub fn as_range_fixed(&self) -> &[u8; LEN] { array_range::(&self.1) } + #[inline(always)] pub fn as_ptr(&self) -> *const u8 { self.1.as_ptr() } #[inline(always)] pub fn as_mut_ptr(&mut self) -> *mut u8 { self.1.as_mut_ptr() } + #[inline(always)] + pub fn as_mut_range_fixed(&mut self) -> &mut [u8; LEN] { array_range_mut::(&mut self.1) } + /// Get all bytes after a given position. #[inline(always)] pub fn as_bytes_starting_at(&self, start: usize) -> std::io::Result<&[u8]> { diff --git a/zerotier-network-hypervisor/src/util/mod.rs b/zerotier-network-hypervisor/src/util/mod.rs index 8874f4f81..aec1daa62 100644 --- a/zerotier-network-hypervisor/src/util/mod.rs +++ b/zerotier-network-hypervisor/src/util/mod.rs @@ -22,6 +22,13 @@ pub(crate) fn array_range() } } +/// Obtain a reference to a sub-array within an existing array. +#[inline(always)] +pub(crate) fn array_range_mut(a: &mut [T; A]) -> &mut [T; LEN] { + assert!((START + LEN) <= A); + unsafe { &mut *a.as_mut_ptr().add(START).cast::<[T; LEN]>() } +} + #[inline(always)] pub(crate) fn u64_as_bytes(i: &u64) -> &[u8; 8] { unsafe { &*(i as *const u64).cast() } } diff --git a/zerotier-network-hypervisor/src/vl1/identity.rs b/zerotier-network-hypervisor/src/vl1/identity.rs index 8f19972de..589bdeb26 100644 --- a/zerotier-network-hypervisor/src/vl1/identity.rs +++ b/zerotier-network-hypervisor/src/vl1/identity.rs @@ -122,7 +122,7 @@ impl Identity { let mut address; let mut c25519; let mut c25519_pub; - let mut genmem_pool_obj = unsafe { FRANKENHASH_POW_MEMORY_POOL.get() }; + let mut genmem_pool_obj = unsafe { ADDRESS_DERVIATION_MEMORY_POOL.get() }; loop { c25519 = C25519KeyPair::generate(false); c25519_pub = c25519.public_bytes(); @@ -130,7 +130,7 @@ impl Identity { sha.update(&c25519_pub); sha.update(&ed25519_pub); let mut digest = sha.finish(); - zt_frankenhash(&mut digest, &mut genmem_pool_obj); + zt_address_derivation_memory_intensive_hash(&mut digest, &mut genmem_pool_obj); if digest[0] < IDENTITY_V1_POW_THRESHOLD { let addr = Address::from_bytes(&digest[59..64]); @@ -234,8 +234,8 @@ impl Identity { sha.update(&self.c25519); sha.update(&self.ed25519); let mut digest = sha.finish(); - let mut genmem_pool_obj = unsafe { FRANKENHASH_POW_MEMORY_POOL.get() }; - zt_frankenhash(&mut digest, &mut genmem_pool_obj); + let mut genmem_pool_obj = unsafe { ADDRESS_DERVIATION_MEMORY_POOL.get() }; + zt_address_derivation_memory_intensive_hash(&mut digest, &mut genmem_pool_obj); drop(genmem_pool_obj); return digest[0] < pow_threshold && Address::from_bytes(&digest[59..64]).map_or(false, |a| a == self.address); @@ -286,13 +286,14 @@ impl Identity { pub fn marshal(&self, buf: &mut Buffer, include_cipher_suites: u8, include_private: bool) -> std::io::Result<()> { let cipher_suites = self.cipher_suites() & include_cipher_suites; + let secret = self.secret.as_ref(); buf.append_bytes_fixed(&self.address.to_bytes())?; buf.append_u8(IDENTITY_CIPHER_SUITE_X25519)?; buf.append_bytes_fixed(&self.c25519)?; buf.append_bytes_fixed(&self.ed25519)?; - if include_private && self.secret.is_some() { - let secret = self.secret.as_ref().unwrap(); + if include_private && secret.is_some() { + let secret = secret.unwrap(); buf.append_u8((C25519_SECRET_KEY_SIZE + ED25519_SECRET_KEY_SIZE) as u8)?; buf.append_bytes_fixed(&secret.c25519.secret_bytes().0)?; buf.append_bytes_fixed(&secret.ed25519.secret_bytes().0)?; @@ -302,7 +303,7 @@ impl Identity { if (cipher_suites & IDENTITY_CIPHER_SUITE_EC_NIST_P521) == IDENTITY_CIPHER_SUITE_EC_NIST_P521 && self.p521.is_some() { let p521 = self.p521.as_ref().unwrap(); - let size = if include_private && self.secret.map_or(false, |s| s.p521.is_some()) { + let size = if include_private && secret.map_or(false, |s| s.p521.is_some()) { (P521_PUBLIC_KEY_SIZE + P521_PUBLIC_KEY_SIZE + P521_ECDSA_SIGNATURE_SIZE + ED25519_SIGNATURE_SIZE + P521_SECRET_KEY_SIZE + P521_SECRET_KEY_SIZE) as u16 } else { (P521_PUBLIC_KEY_SIZE + P521_PUBLIC_KEY_SIZE + P521_ECDSA_SIGNATURE_SIZE + ED25519_SIGNATURE_SIZE) as u16 @@ -314,7 +315,7 @@ impl Identity { buf.append_bytes_fixed(&p521.ecdsa_self_signature)?; buf.append_bytes_fixed(&p521.ed25519_self_signature)?; if size > (P521_PUBLIC_KEY_SIZE + P521_PUBLIC_KEY_SIZE + P521_ECDSA_SIGNATURE_SIZE + ED25519_SIGNATURE_SIZE) as u16 { - let p521s = self.secret.as_ref().unwrap().p521.as_ref().unwrap(); + let p521s = secret.unwrap().p521.as_ref().unwrap(); buf.append_bytes_fixed(&p521s.ecdh.secret_key_bytes().0)?; buf.append_bytes_fixed(&p521s.ecdsa.secret_key_bytes().0)?; } @@ -589,8 +590,8 @@ impl PartialEq for Identity { self.address == other.address && self.c25519 == other.c25519 && self.ed25519 == other.ed25519 && - self.p521.map_or(other.p521.is_none(), |p521| { - other.p521.map_or(false, |other_p521| { + self.p521.as_ref().map_or(other.p521.is_none(), |p521| { + other.p521.as_ref().map_or(false, |other_p521| { p521.ecdh == other_p521.ecdh && p521.ecdsa == other_p521.ecdsa }) }) @@ -614,7 +615,7 @@ impl PartialOrd for Identity { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } -const FRANKENHASH_POW_MEMORY_SIZE: usize = 2097152; +const ADDRESS_DERIVATION_HASH_MEMORY_SIZE: usize = 2097152; /// This is a compound hasher used for the work function that derives an address. /// @@ -622,26 +623,26 @@ const FRANKENHASH_POW_MEMORY_SIZE: usize = 2097152; /// what truly determines node identity. For FIPS purposes this can be considered a /// non-cryptographic hash. Its memory hardness and use in a work function is a defense /// in depth feature rather than a primary security feature. -fn zt_frankenhash(digest: &mut [u8; 64], genmem_pool_obj: &mut Pooled) { +fn zt_address_derivation_memory_intensive_hash(digest: &mut [u8; 64], genmem_pool_obj: &mut Pooled) { let genmem_ptr = genmem_pool_obj.0.as_mut_ptr().cast::(); - let (genmem, genmem_alias_hack) = unsafe { (&mut *slice_from_raw_parts_mut(genmem_ptr, FRANKENHASH_POW_MEMORY_SIZE), &*slice_from_raw_parts(genmem_ptr, FRANKENHASH_POW_MEMORY_SIZE)) }; + let (genmem, genmem_alias_hack) = unsafe { (&mut *slice_from_raw_parts_mut(genmem_ptr, ADDRESS_DERIVATION_HASH_MEMORY_SIZE), &*slice_from_raw_parts(genmem_ptr, ADDRESS_DERIVATION_HASH_MEMORY_SIZE)) }; let genmem_u64_ptr = genmem_ptr.cast::(); let mut s20 = Salsa::new(&digest[0..32], &digest[32..40], false).unwrap(); s20.crypt(&crate::util::ZEROES[0..64], &mut genmem[0..64]); let mut i: usize = 64; - while i < FRANKENHASH_POW_MEMORY_SIZE { + while i < ADDRESS_DERIVATION_HASH_MEMORY_SIZE { let ii = i + 64; s20.crypt(&genmem_alias_hack[(i - 64)..i], &mut genmem[i..ii]); i = ii; } i = 0; - while i < (FRANKENHASH_POW_MEMORY_SIZE / 8) { + while i < (ADDRESS_DERIVATION_HASH_MEMORY_SIZE / 8) { unsafe { let idx1 = (((*genmem_u64_ptr.add(i)).to_be() & 7) * 8) as usize; - let idx2 = ((*genmem_u64_ptr.add(i + 1)).to_be() % (FRANKENHASH_POW_MEMORY_SIZE as u64 / 8)) as usize; + let idx2 = ((*genmem_u64_ptr.add(i + 1)).to_be() % (ADDRESS_DERIVATION_HASH_MEMORY_SIZE as u64 / 8)) as usize; let genmem_u64_at_idx2_ptr = genmem_u64_ptr.add(idx2); let tmp = *genmem_u64_at_idx2_ptr; let digest_u64_ptr = digest.as_mut_ptr().add(idx1).cast::(); @@ -654,20 +655,20 @@ fn zt_frankenhash(digest: &mut [u8; 64], genmem_pool_obj: &mut Pooled for FrankenhashMemoryFactory { +impl PoolFactory for AddressDerivationMemoryFactory { #[inline(always)] - fn create(&self) -> FrankenhashMemory { FrankenhashMemory([0_u128; FRANKENHASH_POW_MEMORY_SIZE / 16]) } + fn create(&self) -> AddressDerivationMemory { AddressDerivationMemory([0_u128; ADDRESS_DERIVATION_HASH_MEMORY_SIZE / 16]) } #[inline(always)] - fn reset(&self, _: &mut FrankenhashMemory) {} + fn reset(&self, _: &mut AddressDerivationMemory) {} } lazy_static! { - static ref FRANKENHASH_POW_MEMORY_POOL: Pool = Pool::new(0, FrankenhashMemoryFactory); + static ref ADDRESS_DERVIATION_MEMORY_POOL: Pool = Pool::new(0, AddressDerivationMemoryFactory); } /// Purge the memory pool used to verify identities. This can be called periodically @@ -675,5 +676,5 @@ lazy_static! { /// verification. #[inline(always)] pub(crate) fn purge_verification_memory_pool() { - unsafe { FRANKENHASH_POW_MEMORY_POOL.purge() }; + unsafe { ADDRESS_DERVIATION_MEMORY_POOL.purge() }; } diff --git a/zerotier-network-hypervisor/src/vl1/peer.rs b/zerotier-network-hypervisor/src/vl1/peer.rs index f8b37797d..fd4c8ca1a 100644 --- a/zerotier-network-hypervisor/src/vl1/peer.rs +++ b/zerotier-network-hypervisor/src/vl1/peer.rs @@ -403,34 +403,26 @@ impl Peer { /// If explicit_endpoint is not None the packet will be sent directly to this endpoint. /// Otherwise it will be sent via the best direct or indirect path known. pub(crate) fn send_hello(&self, ci: &CI, node: &Node, explicit_endpoint: Option<&Endpoint>) -> bool { - let (path, endpoint) = if explicit_endpoint.is_some() { - (None, explicit_endpoint.unwrap()) - } else { - let p = self.path(node); - if p.is_none() { - return false; - } - (p, p.as_ref().unwrap().endpoint()) - }; - let mut packet: Buffer<{ PACKET_SIZE_MAX }> = Buffer::new(); let time_ticks = ci.time_ticks(); let message_id = self.next_message_id(); - let packet_header: &mut PacketHeader = packet.append_struct_get_mut().unwrap(); - let hello_fixed_headers: &mut message_component_structs::HelloFixedHeaderFields = packet.append_struct_get_mut().unwrap(); - - packet_header.id = message_id.to_ne_bytes(); // packet ID and message ID are the same when Poly1305 MAC is used - packet_header.dest = self.identity.address.to_bytes(); - packet_header.src = node.address().to_bytes(); - packet_header.flags_cipher_hops = CIPHER_NOCRYPT_POLY1305; - - hello_fixed_headers.verb = VERB_VL1_HELLO | VERB_FLAG_EXTENDED_AUTHENTICATION; - hello_fixed_headers.version_proto = VERSION_PROTO; - hello_fixed_headers.version_major = VERSION_MAJOR; - hello_fixed_headers.version_minor = VERSION_MINOR; - hello_fixed_headers.version_revision = (VERSION_REVISION as u16).to_be_bytes(); - hello_fixed_headers.timestamp = (time_ticks as u64).to_be_bytes(); + { + let packet_header: &mut PacketHeader = packet.append_struct_get_mut().unwrap(); + packet_header.id = message_id.to_ne_bytes(); // packet ID and message ID are the same when Poly1305 MAC is used + packet_header.dest = self.identity.address.to_bytes(); + packet_header.src = node.address().to_bytes(); + packet_header.flags_cipher_hops = CIPHER_NOCRYPT_POLY1305; + } + { + let hello_fixed_headers: &mut message_component_structs::HelloFixedHeaderFields = packet.append_struct_get_mut().unwrap(); + hello_fixed_headers.verb = VERB_VL1_HELLO | VERB_FLAG_EXTENDED_AUTHENTICATION; + hello_fixed_headers.version_proto = VERSION_PROTO; + hello_fixed_headers.version_major = VERSION_MAJOR; + hello_fixed_headers.version_minor = VERSION_MINOR; + hello_fixed_headers.version_revision = (VERSION_REVISION as u16).to_be_bytes(); + hello_fixed_headers.timestamp = (time_ticks as u64).to_be_bytes(); + } assert!(self.identity.marshal(&mut packet, IDENTITY_CIPHER_SUITE_INCLUDE_ALL, false).is_ok()); if self.identity.cipher_suites() == IDENTITY_CIPHER_SUITE_X25519 { @@ -462,16 +454,18 @@ impl Peer { // LEGACY: set MAC field in header to poly1305 for older nodes. let (_, mut poly) = salsa_poly_create(&self.static_secret, packet.struct_at::(0).unwrap(), packet.len()); poly.update(packet.as_bytes_starting_at(PACKET_HEADER_SIZE).unwrap()); - packet_header.mac.copy_from_slice(&poly.finish()[0..8]); + packet.as_mut_range_fixed::().copy_from_slice(&poly.finish()[0..8]); self.last_send_time_ticks.store(time_ticks, Ordering::Relaxed); self.total_bytes_sent.fetch_add(packet.len() as u64, Ordering::Relaxed); - path.as_ref().map_or_else(|| { + explicit_endpoint.map_or_else(|| { + self.path(node).map_or(false, |path| { + path.log_send(time_ticks); + self.send_to_endpoint(ci, path.endpoint(), path.local_socket(), path.local_interface(), &packet) + }) + }, |endpoint| { self.send_to_endpoint(ci, endpoint, None, None, &packet) - }, |path| { - path.log_send(time_ticks); - self.send_to_endpoint(ci, endpoint, path.local_socket(), path.local_interface(), &packet) }) } diff --git a/zerotier-system-service/src/utils.rs b/zerotier-system-service/src/utils.rs index 0c8f976db..89ec96412 100644 --- a/zerotier-system-service/src/utils.rs +++ b/zerotier-system-service/src/utils.rs @@ -29,7 +29,7 @@ pub fn ms_monotonic() -> i64 { unsafe { let mut tb: mach::mach_time::mach_timebase_info_data_t = std::mem::zeroed(); if mach::mach_time::mach_timebase_info(&mut tb) == 0 { - let mt = mach::mach_time::mach_continuous_approximate_time(); + let mt = mach::mach_time::mach_continuous_approximate_time(); // ZT doesn't need it to be *that* exact, and this is faster (((mt as u128) * tb.numer as u128 * 1000000_u128) / (tb.denom as u128)) as i64 // milliseconds since X } else { panic!("FATAL: mach_timebase_info() failed");