Build fixes.

This commit is contained in:
Adam Ierymenko 2021-12-13 15:45:02 -05:00
parent 4a9938dfd3
commit 5fd0e2998b
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
5 changed files with 62 additions and 53 deletions

View file

@ -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<const L: usize> Buffer<L> {
#[inline(always)]
pub fn as_bytes_mut(&mut self) -> &mut [u8] { &mut self.1[0..self.0] }
#[inline(always)]
pub fn as_range_fixed<const START: usize, const LEN: usize>(&self) -> &[u8; LEN] { array_range::<u8, L, START, LEN>(&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<const START: usize, const LEN: usize>(&mut self) -> &mut [u8; LEN] { array_range_mut::<u8, L, START, LEN>(&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]> {

View file

@ -22,6 +22,13 @@ pub(crate) fn array_range<T, const A: usize, const START: usize, const LEN: usiz
unsafe { &*a.as_ptr().add(START).cast::<[T; LEN]>() }
}
/// Obtain a reference to a sub-array within an existing array.
#[inline(always)]
pub(crate) fn array_range_mut<T, const A: usize, const START: usize, const LEN: usize>(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() } }

View file

@ -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<const BL: usize>(&self, buf: &mut Buffer<BL>, 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<Ordering> { 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<FrankenhashMemory, FrankenhashMemoryFactory>) {
fn zt_address_derivation_memory_intensive_hash(digest: &mut [u8; 64], genmem_pool_obj: &mut Pooled<AddressDerivationMemory, AddressDerivationMemoryFactory>) {
let genmem_ptr = genmem_pool_obj.0.as_mut_ptr().cast::<u8>();
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::<u64>();
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::<u64>();
@ -654,20 +655,20 @@ fn zt_frankenhash(digest: &mut [u8; 64], genmem_pool_obj: &mut Pooled<Frankenhas
}
#[repr(transparent)]
struct FrankenhashMemory([u128; FRANKENHASH_POW_MEMORY_SIZE / 16]); // use u128 to align by 16 bytes
struct AddressDerivationMemory([u128; ADDRESS_DERIVATION_HASH_MEMORY_SIZE / 16]); // use u128 to align by 16 bytes
struct FrankenhashMemoryFactory;
struct AddressDerivationMemoryFactory;
impl PoolFactory<FrankenhashMemory> for FrankenhashMemoryFactory {
impl PoolFactory<AddressDerivationMemory> 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<FrankenhashMemory, FrankenhashMemoryFactory> = Pool::new(0, FrankenhashMemoryFactory);
static ref ADDRESS_DERVIATION_MEMORY_POOL: Pool<AddressDerivationMemory, AddressDerivationMemoryFactory> = 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() };
}

View file

@ -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<CI: NodeInterface>(&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::<PacketHeader>(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::<HEADER_MAC_FIELD_INDEX, { HEADER_MAC_FIELD_INDEX + 8 }>().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)
})
}

View file

@ -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");