mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-04-26 17:03:43 +02:00
Formatting, build fixes, tests.
This commit is contained in:
parent
c5ed599ef3
commit
a23bd89202
13 changed files with 124 additions and 89 deletions
|
@ -55,9 +55,7 @@ impl Write for SHA512 {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn flush(&mut self) -> std::io::Result<()> {
|
||||
self.0.flush()
|
||||
}
|
||||
fn flush(&mut self) -> std::io::Result<()> { self.0.flush() }
|
||||
}
|
||||
|
||||
pub struct SHA384(gcrypt::digest::MessageDigest);
|
||||
|
@ -110,7 +108,5 @@ impl Write for SHA384 {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn flush(&mut self) -> std::io::Result<()> {
|
||||
self.0.flush()
|
||||
}
|
||||
fn flush(&mut self) -> std::io::Result<()> { self.0.flush() }
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/// The poly1305 message authentication function.
|
||||
pub struct Poly1305(gcrypt::mac::Mac);
|
||||
|
||||
pub const POLY1305_ONE_TIME_KEY_SIZE: usize = 32;
|
||||
|
|
|
@ -2,13 +2,12 @@ use rand_core::{RngCore, Error};
|
|||
use rand_core::CryptoRng;
|
||||
use gcrypt::rand::{Level, randomize};
|
||||
|
||||
/// Secure random source based on the desired third party library (gcrypt).
|
||||
pub struct SecureRandom;
|
||||
|
||||
impl SecureRandom {
|
||||
#[inline(always)]
|
||||
pub fn get() -> Self {
|
||||
Self
|
||||
}
|
||||
pub fn get() -> Self { Self }
|
||||
}
|
||||
|
||||
impl RngCore for SecureRandom {
|
||||
|
@ -27,9 +26,7 @@ impl RngCore for SecureRandom {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn fill_bytes(&mut self, dest: &mut [u8]) {
|
||||
randomize(Level::Strong, dest);
|
||||
}
|
||||
fn fill_bytes(&mut self, dest: &mut [u8]) { randomize(Level::Strong, dest); }
|
||||
|
||||
#[inline(always)]
|
||||
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
|
||||
|
@ -41,20 +38,18 @@ impl RngCore for SecureRandom {
|
|||
impl CryptoRng for SecureRandom {}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn next_u32_secure() -> u32 {
|
||||
pub fn next_u32_secure() -> u32 {
|
||||
let mut tmp = 0_u32;
|
||||
randomize(Level::Strong, unsafe { &mut *(&mut tmp as *mut u32).cast::<[u8; 4]>() });
|
||||
tmp
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn next_u64_secure() -> u64 {
|
||||
pub fn next_u64_secure() -> u64 {
|
||||
let mut tmp = 0_u64;
|
||||
randomize(Level::Strong, unsafe { &mut *(&mut tmp as *mut u64).cast::<[u8; 8]>() });
|
||||
tmp
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn fill_bytes_secure(dest: &mut [u8]) {
|
||||
randomize(Level::Strong, dest);
|
||||
}
|
||||
pub fn fill_bytes_secure(dest: &mut [u8]) { randomize(Level::Strong, dest); }
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/// The classic Salsa20 stream cipher supporting 20-round and 12-round variants.
|
||||
pub struct Salsa(gcrypt::cipher::Cipher);
|
||||
|
||||
impl Salsa {
|
||||
|
|
|
@ -11,14 +11,10 @@ impl<const FREQ: i64> Default for IntervalGate<FREQ> {
|
|||
|
||||
impl<const FREQ: i64> IntervalGate<FREQ> {
|
||||
#[inline(always)]
|
||||
pub fn new(initial_ts: i64) -> Self {
|
||||
Self(initial_ts)
|
||||
}
|
||||
pub fn new(initial_ts: i64) -> Self { Self(initial_ts) }
|
||||
|
||||
#[inline(always)]
|
||||
pub fn reset(&mut self) {
|
||||
self.0 = 0;
|
||||
}
|
||||
pub fn reset(&mut self) { self.0 = 0; }
|
||||
|
||||
#[inline(always)]
|
||||
pub fn gate(&mut self, time: i64) -> bool {
|
||||
|
@ -35,33 +31,31 @@ impl<const FREQ: i64> IntervalGate<FREQ> {
|
|||
pub struct AtomicIntervalGate<const FREQ: i64>(AtomicI64);
|
||||
|
||||
impl<const FREQ: i64> Default for AtomicIntervalGate<FREQ> {
|
||||
fn default() -> Self {
|
||||
Self(AtomicI64::new(0))
|
||||
}
|
||||
fn default() -> Self { Self(AtomicI64::new(0)) }
|
||||
}
|
||||
|
||||
impl<const FREQ: i64> AtomicIntervalGate<FREQ> {
|
||||
#[inline(always)]
|
||||
pub fn new(initial_ts: i64) -> Self {
|
||||
Self(AtomicI64::new(initial_ts))
|
||||
}
|
||||
pub fn new(initial_ts: i64) -> Self { Self(AtomicI64::new(initial_ts)) }
|
||||
|
||||
#[inline(always)]
|
||||
pub fn reset(&self) {
|
||||
self.0.store(0, Ordering::Relaxed);
|
||||
}
|
||||
pub fn reset(&self) { self.0.store(0, Ordering::Relaxed); }
|
||||
|
||||
#[inline(always)]
|
||||
pub fn gate(&self, time: i64) -> bool {
|
||||
// Note that if two or more threads are using this at once, any thread's time might
|
||||
// end up being the one stored. This is okay since these times should either be the
|
||||
// same or very close, and slight differences won't cause issues with the use cases
|
||||
// for this. This is primarily used to rate gate operations to prevent DOS attacks.
|
||||
if (time - self.0.load(Ordering::Relaxed)) >= FREQ {
|
||||
self.0.store(time, Ordering::Relaxed);
|
||||
true
|
||||
} else {
|
||||
pub fn gate(&self, mut time: i64) -> bool {
|
||||
let prev_time = self.0.load(Ordering::Relaxed);
|
||||
if (time - prev_time) < FREQ {
|
||||
false
|
||||
} else {
|
||||
loop {
|
||||
let pt = self.0.swap(time, Ordering::Relaxed);
|
||||
if pt <= time {
|
||||
break;
|
||||
} else {
|
||||
time = pt;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
pub mod hex;
|
||||
pub mod pool;
|
||||
pub mod gate;
|
||||
pub mod varint;
|
||||
|
||||
pub(crate) const ZEROES: [u8; 64] = [0_u8; 64];
|
||||
|
||||
|
|
53
network-hypervisor/src/util/varint.rs
Normal file
53
network-hypervisor/src/util/varint.rs
Normal file
|
@ -0,0 +1,53 @@
|
|||
use std::io::{Read, Write};
|
||||
|
||||
pub fn write<W: Write>(w: &mut W, mut v: u64) -> std::io::Result<()> {
|
||||
let mut b = [0_u8; 10];
|
||||
let mut i = 10;
|
||||
loop {
|
||||
if v > 0x7f {
|
||||
i -= 1;
|
||||
b[i] = (v as u8) & 0x7f;
|
||||
v >>= 7;
|
||||
} else {
|
||||
i -= 1;
|
||||
b[i] = (v as u8) | 0x80;
|
||||
break;
|
||||
}
|
||||
}
|
||||
w.write_all(&b[i..])
|
||||
}
|
||||
|
||||
pub fn read<R: Read>(r: &mut R) -> std::io::Result<u64> {
|
||||
let mut v = 0_u64;
|
||||
let mut buf = [0_u8; 1];
|
||||
loop {
|
||||
v <<= 7;
|
||||
let _ = r.read_exact(&mut buf)?;
|
||||
let b = buf[0];
|
||||
if b <= 0x7f {
|
||||
v |= b as u64;
|
||||
} else {
|
||||
v |= (b & 0x7f) as u64;
|
||||
return Ok(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn read_from_bytes(r: &[u8], cursor: &mut usize) -> std::io::Result<u64> {
|
||||
let mut v = 0_u64;
|
||||
let mut c = *cursor;
|
||||
while c < r.len() {
|
||||
v <<= 7;
|
||||
let b = unsafe { *r.get_unchecked(c) };
|
||||
c += 1;
|
||||
if b <= 0x7f {
|
||||
v |= b as u64;
|
||||
} else {
|
||||
v |= (b & 0x7f) as u64;
|
||||
*cursor = c;
|
||||
return Ok(v);
|
||||
}
|
||||
}
|
||||
*cursor = c;
|
||||
return Err(std::io::Error::new(std::io::ErrorKind::UnexpectedEof, "incomplete varint"));
|
||||
}
|
|
@ -23,7 +23,6 @@ impl Address {
|
|||
}
|
||||
}
|
||||
|
||||
/// Get an address from a byte slice or return None if it is zero or reserved.
|
||||
#[inline(always)]
|
||||
pub fn from_bytes(b: &[u8]) -> Option<Address> {
|
||||
if b.len() >= ADDRESS_SIZE {
|
||||
|
@ -38,6 +37,16 @@ impl Address {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn from_bytes_fixed(b: &[u8; ADDRESS_SIZE]) -> Option<Address> {
|
||||
let i = (b[0] as u64) << 32 | (b[1] as u64) << 24 | (b[2] as u64) << 16 | (b[3] as u64) << 8 | b[4] as u64;
|
||||
if i != 0 && (i >> 32) != ADDRESS_RESERVED_PREFIX as u64 {
|
||||
Some(Address(unsafe { NonZeroU64::new_unchecked(i) }))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn to_bytes(&self) -> [u8; ADDRESS_SIZE] {
|
||||
let i = self.0.get();
|
||||
|
@ -61,7 +70,7 @@ impl Address {
|
|||
|
||||
#[inline(always)]
|
||||
pub(crate) fn unmarshal<const BL: usize>(buf: &Buffer<BL>, cursor: &mut usize) -> std::io::Result<Option<Self>> {
|
||||
buf.read_bytes_fixed::<{ ADDRESS_SIZE }>(cursor).map(|b| Self::from_bytes(b))
|
||||
buf.read_bytes_fixed::<{ ADDRESS_SIZE }>(cursor).map(|b| Self::from_bytes_fixed(b))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@ impl<const L: usize> Buffer<L> {
|
|||
pub fn new() -> Self { Self(0, [0_u8; L]) }
|
||||
|
||||
/// Get a Buffer initialized with a copy of a byte slice.
|
||||
#[inline(always)]
|
||||
pub fn from_bytes(b: &[u8]) -> std::io::Result<Self> {
|
||||
let l = b.len();
|
||||
if l <= L {
|
||||
|
@ -165,19 +164,9 @@ impl<const L: usize> Buffer<L> {
|
|||
}
|
||||
|
||||
/// Append a variable length integer to this buffer.
|
||||
///
|
||||
/// Varints are encoded as a series of 7-bit bytes terminated by a final 7-bit byte whose
|
||||
/// most significant bit is set. Unlike fixed size integers varints are written in little
|
||||
/// endian order (in 7-bit chunks).
|
||||
///
|
||||
/// They are slower than fixed size values so they should not be used in formats that are
|
||||
/// created or parsed in very speed-critical paths.
|
||||
#[inline(always)]
|
||||
pub fn append_varint(&mut self, mut i: u64) -> std::io::Result<()> {
|
||||
while i >= 0x80 {
|
||||
self.append_u8((i as u8) & 0x7f)?;
|
||||
i >>= 7;
|
||||
}
|
||||
self.append_u8((i as u8) | 0x80)
|
||||
crate::util::varint::write(self, i)
|
||||
}
|
||||
|
||||
/// Append a byte
|
||||
|
@ -317,20 +306,9 @@ impl<const L: usize> Buffer<L> {
|
|||
}
|
||||
|
||||
/// Get the next variable length integer and advance the cursor by its length in bytes.
|
||||
#[inline(always)]
|
||||
pub fn read_varint(&self, cursor: &mut usize) -> std::io::Result<u64> {
|
||||
let mut i = 0_u64;
|
||||
let mut p = 0;
|
||||
loop {
|
||||
let b = self.read_u8(cursor)?;
|
||||
if (b & 0x80) == 0 {
|
||||
i |= (b as u64).wrapping_shl(p);
|
||||
p += 7;
|
||||
} else {
|
||||
i |= ((b & 0x7f) as u64) << p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ok(i)
|
||||
crate::util::varint::read_from_bytes(&(self.1[self.0..]), cursor)
|
||||
}
|
||||
|
||||
/// Get the next u8 and advance the cursor.
|
||||
|
|
|
@ -71,16 +71,7 @@ impl Dictionary {
|
|||
}
|
||||
|
||||
pub fn get_bool(&self, k: &str) -> Option<bool> {
|
||||
self.0.get(k).map_or(None, |v| {
|
||||
if v.is_empty() {
|
||||
Some(false)
|
||||
} else {
|
||||
Some(match v[0] {
|
||||
b'1' | b't' | b'T' | b'y' | b'Y' => true,
|
||||
_ => false
|
||||
})
|
||||
}
|
||||
})
|
||||
self.0.get(k).map_or(None, |v| v.first().map_or(Some(false), |c| Some("1tTyY".contains(*c as char))))
|
||||
}
|
||||
|
||||
pub fn set_str(&mut self, k: &str, v: &str) {
|
||||
|
@ -96,7 +87,7 @@ impl Dictionary {
|
|||
}
|
||||
|
||||
pub fn set_bool(&mut self, k: &str, v: bool) {
|
||||
let _ = self.0.insert(String::from(k), (if v { [b'1'] } else { [b'0'] }).to_vec());
|
||||
let _ = self.0.insert(String::from(k), vec![if v { b'1' } else { b'0' }]);
|
||||
}
|
||||
|
||||
/// Write a dictionary in transport format to a writer.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::cmp::Ordering;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
use crate::vl1::{Address, Endpoint, Identity};
|
||||
use crate::vl1::{Address, Endpoint, Identity, Dictionary};
|
||||
use crate::vl1::buffer::Buffer;
|
||||
use crate::vl1::protocol::PACKET_SIZE_MAX;
|
||||
|
||||
|
@ -15,6 +15,7 @@ pub struct Locator {
|
|||
pub subject: Address,
|
||||
pub signer: Address,
|
||||
pub timestamp: i64,
|
||||
pub metadata: Option<Dictionary>,
|
||||
pub endpoints: Vec<Endpoint>,
|
||||
pub signature: Vec<u8>,
|
||||
}
|
||||
|
@ -34,6 +35,7 @@ impl Locator {
|
|||
subject,
|
||||
signer: signer_identity.address(),
|
||||
timestamp: ts,
|
||||
metadata: None,
|
||||
endpoints: endpoints.to_vec(),
|
||||
signature: Vec::new()
|
||||
};
|
||||
|
@ -81,12 +83,16 @@ impl Locator {
|
|||
fn marshal_internal<const BL: usize>(&self, buf: &mut Buffer<BL>, exclude_signature: bool) -> std::io::Result<()> {
|
||||
self.subject.marshal(buf)?;
|
||||
self.signer.marshal(buf)?;
|
||||
buf.append_u64(self.timestamp as u64)?;
|
||||
buf.append_varint(self.timestamp as u64)?;
|
||||
self.metadata.map_or_else(|| buf.append_varint(0), |d| {
|
||||
let db = d.to_bytes();
|
||||
buf.append_varint(db.len() as u64)?;
|
||||
buf.append_bytes(db.as_slice())
|
||||
})?;
|
||||
buf.append_varint(self.endpoints.len() as u64)?;
|
||||
for e in self.endpoints.iter() {
|
||||
e.marshal(buf)?;
|
||||
}
|
||||
buf.append_varint(0)?; // length of any additional fields
|
||||
if !exclude_signature {
|
||||
buf.append_varint(self.signature.len() as u64)?;
|
||||
buf.append_bytes(self.signature.as_slice())?;
|
||||
|
@ -104,18 +110,26 @@ impl Locator {
|
|||
return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid subject or signer address"));
|
||||
}
|
||||
let timestamp = buf.read_u64(cursor)? as i64;
|
||||
let metadata_size = buf.read_varint(cursor)? as usize;
|
||||
let metadata = if metadata_size > 0 {
|
||||
let md = Dictionary::from_bytes(buf.read_bytes(metadata_size, cursor)?);
|
||||
if md.is_none() {
|
||||
return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid meta-data"));
|
||||
}
|
||||
md
|
||||
} else { None };
|
||||
let endpoint_count = buf.read_varint(cursor)? as usize;
|
||||
let mut endpoints: Vec<Endpoint> = Vec::new();
|
||||
for _ in 0..endpoint_count {
|
||||
endpoints.push(Endpoint::unmarshal(buf, cursor)?);
|
||||
}
|
||||
*cursor += buf.read_varint(cursor)? as usize;
|
||||
let signature_len = buf.read_varint(cursor)? as usize;
|
||||
let signature = buf.read_bytes(signature_len, cursor)?;
|
||||
Ok(Locator {
|
||||
subject: subject.unwrap(),
|
||||
signer: signer.unwrap(),
|
||||
timestamp,
|
||||
metadata,
|
||||
endpoints,
|
||||
signature: signature.to_vec(),
|
||||
})
|
||||
|
|
|
@ -16,12 +16,17 @@ impl MAC {
|
|||
#[inline(always)]
|
||||
pub fn from_bytes(b: &[u8]) -> Option<MAC> {
|
||||
if b.len() >= 6 {
|
||||
NonZeroU64::new((b[0] as u64) << 40 | (b[1] as u64) << 32 | (b[2] as u64) << 24 | (b[3] as u64) << 16 as u64 | (b[4] as u64) << 8 | b[5] as u64).map_or(None, |i| Some(MAC(i)))
|
||||
NonZeroU64::new((b[0] as u64) << 40 | (b[1] as u64) << 32 | (b[2] as u64) << 24 | (b[3] as u64) << 16 as u64 | (b[4] as u64) << 8 | b[5] as u64).map(|i| MAC(i))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn from_bytes_fixed(b: &[u8; 6]) -> Option<MAC> {
|
||||
NonZeroU64::new((b[0] as u64) << 40 | (b[1] as u64) << 32 | (b[2] as u64) << 24 | (b[3] as u64) << 16 as u64 | (b[4] as u64) << 8 | b[5] as u64).map(|i| MAC(i))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn to_bytes(&self) -> [u8; 6] {
|
||||
let i = self.0.get();
|
||||
|
@ -31,7 +36,6 @@ impl MAC {
|
|||
#[inline(always)]
|
||||
pub fn to_u64(&self) -> u64 { self.0.get() }
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn marshal<const BL: usize>(&self, buf: &mut Buffer<BL>) -> std::io::Result<()> {
|
||||
buf.append_and_init_bytes_fixed(|b: &mut [u8; 6]| {
|
||||
let i = self.0.get();
|
||||
|
@ -46,7 +50,7 @@ impl MAC {
|
|||
|
||||
#[inline(always)]
|
||||
pub(crate) fn unmarshal<const BL: usize>(buf: &Buffer<BL>, cursor: &mut usize) -> std::io::Result<Option<Self>> {
|
||||
buf.read_bytes_fixed::<6>(cursor).map(|b| Self::from_bytes(b))
|
||||
buf.read_bytes_fixed::<6>(cursor).map(|b| Self::from_bytes_fixed(b))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -296,13 +296,11 @@ mod tests {
|
|||
#[test]
|
||||
fn default_root_set() {
|
||||
let rs = RootSet::from_bytes(&crate::defaults::ROOT_SET).unwrap();
|
||||
/*
|
||||
rs.roots.iter().for_each(|r| {
|
||||
println!("{}", r.identity.to_string());
|
||||
r.endpoints.iter().for_each(|ep| {
|
||||
println!(" {}", ep.to_string());
|
||||
});
|
||||
});
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue