Build and test fixes.

This commit is contained in:
Adam Ierymenko 2021-11-03 09:52:35 -04:00
parent 9c64f262a3
commit 7318a188b2
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
18 changed files with 73 additions and 65 deletions

View file

@ -4,8 +4,8 @@ version = "0.1.0"
edition = "2018"
[dependencies]
rand_core = "^0"
rand_core = "0.5"
aes-gmac-siv = { path = "../aes-gmac-siv" }
gcrypt = "^0"
x25519-dalek = { version = "^1", features = ["u64_backend"] }
ed25519-dalek = { version = "^1", features = ["u64_backend"] }
gcrypt = "0.7.0"
x25519-dalek = { version = "1.2.0", features = ["u64_backend"] }
ed25519-dalek = { version = "1.0.1", features = ["u64_backend"] }

View file

@ -6,7 +6,6 @@
* https://www.zerotier.com/
*/
use std::convert::TryInto;
use std::mem::MaybeUninit;
use crate::hash::{SHA384, SHA512};
@ -24,7 +23,7 @@ fn hash_int_le(sha: &mut SHA512, i: u64) {
/// Compute balloon memory-hard hash using SHA-512 and SHA-384 for the final.
/// SPACE_COST must be a multiple of 64. This is checked with an assertion.
/// DELTA is usually 3.
pub fn hash<const SPACE_COST: usize, const TIME_COST: usize, const DELTA: usize>(password: &[u8], salt: &[u8]) -> [u8; crate::crypto::hash::SHA384_HASH_SIZE] {
pub fn hash<const SPACE_COST: usize, const TIME_COST: usize, const DELTA: usize>(password: &[u8], salt: &[u8]) -> [u8; crate::hash::SHA384_HASH_SIZE] {
debug_assert_ne!(SPACE_COST, 0);
debug_assert_ne!(TIME_COST, 0);
debug_assert_ne!(DELTA, 0);
@ -129,7 +128,7 @@ mod tests {
let start = std::time::SystemTime::now();
let mut tmp = 0_u8;
for _ in 0..100 {
let foo = crate::crypto::balloon::hash::<16384, 3, 3>(&[1_u8], &[2_u8]);
let foo = crate::balloon::hash::<16384, 3, 3>(&[1_u8], &[2_u8]);
tmp = tmp.wrapping_add(foo[0]);
}
let duration = std::time::SystemTime::now().duration_since(start).unwrap();

View file

@ -6,7 +6,7 @@
* https://www.zerotier.com/
*/
pub(crate) const HEX_CHARS: [u8; 16] = [ b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'a', b'b', b'c', b'd', b'e', b'f'];
pub const HEX_CHARS: [u8; 16] = [ b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'a', b'b', b'c', b'd', b'e', b'f'];
/// Encode a byte slice to a hexadecimal string.
pub fn to_string(b: &[u8]) -> String {

View file

@ -15,6 +15,7 @@ pub mod balloon;
pub mod kbkdf;
pub mod random;
pub mod secret;
pub mod hex;
pub use aes_gmac_siv;
pub use rand_core;

View file

@ -27,7 +27,7 @@ fn dump_sexp(exp: &SExpression) {
} else {
let b = exp.get_bytes(0);
if b.is_some() {
print!("#{}#", crate::util::hex::to_string(b.unwrap()));
print!("#{}#", crate::hex::to_string(b.unwrap()));
} else {
print!("()");
}
@ -51,14 +51,14 @@ fn dump_sexp(exp: &SExpression) {
#[inline(always)]
fn hash_to_data_sexp(msg: &[u8]) -> [u8; 155] {
let h = crate::crypto::hash::SHA512::hash(msg);
let h = crate::hash::SHA512::hash(msg);
let mut d = [0_u8; 155];
d[0..24].copy_from_slice(b"(data(flags raw)(value #");
let mut j = 24;
for i in 0..64 {
let b = h[i] as usize;
d[j] = crate::util::hex::HEX_CHARS[b >> 4];
d[j + 1] = crate::util::hex::HEX_CHARS[b & 0xf];
d[j] = crate::hex::HEX_CHARS[b >> 4];
d[j + 1] = crate::hex::HEX_CHARS[b & 0xf];
j += 2;
}
d[152..155].copy_from_slice(b"#))");
@ -107,8 +107,8 @@ impl P521KeyPair {
public_key: pk_exp,
public_key_bytes: [0_u8; P521_PUBLIC_KEY_SIZE],
},
secret_key_for_ecdsa: SExpression::from_str(format!("(private-key(ecc(curve nistp521)(q #{}#)(d #{}#)))", crate::util::hex::to_string(pk), crate::util::hex::to_string(sk)).as_str()).unwrap(),
secret_key_for_ecdh: SExpression::from_str(format!("(data(flags raw)(value #{}#))", crate::util::hex::to_string(sk)).as_str()).unwrap(),
secret_key_for_ecdsa: SExpression::from_str(format!("(private-key(ecc(curve nistp521)(q #{}#)(d #{}#)))", crate::hex::to_string(pk), crate::hex::to_string(sk)).as_str()).unwrap(),
secret_key_for_ecdh: SExpression::from_str(format!("(data(flags raw)(value #{}#))", crate::hex::to_string(sk)).as_str()).unwrap(),
secret_key_bytes: Secret::default(),
};
kp.public_key.public_key_bytes[((P521_PUBLIC_KEY_SIZE + 1) - pk.len())..P521_PUBLIC_KEY_SIZE].copy_from_slice(&pk[1..]);
@ -132,8 +132,8 @@ impl P521KeyPair {
}
Some(P521KeyPair {
public_key: public_key.unwrap(),
secret_key_for_ecdsa: SExpression::from_str(format!("(private-key(ecc(curve nistp521)(q #04{}#)(d #{}#)))", crate::util::hex::to_string(public_bytes), crate::util::hex::to_string(secret_bytes)).as_str()).unwrap(),
secret_key_for_ecdh: SExpression::from_str(format!("(data(flags raw)(value #{}#))", crate::util::hex::to_string(secret_bytes)).as_str()).unwrap(),
secret_key_for_ecdsa: SExpression::from_str(format!("(private-key(ecc(curve nistp521)(q #04{}#)(d #{}#)))", crate::hex::to_string(public_bytes), crate::hex::to_string(secret_bytes)).as_str()).unwrap(),
secret_key_for_ecdh: SExpression::from_str(format!("(data(flags raw)(value #{}#))", crate::hex::to_string(secret_bytes)).as_str()).unwrap(),
secret_key_bytes: Secret::from_bytes(secret_bytes),
})
}
@ -188,7 +188,7 @@ impl P521PublicKey {
pub fn from_bytes(b: &[u8]) -> Option<P521PublicKey> {
if b.len() == P521_PUBLIC_KEY_SIZE {
Some(P521PublicKey {
public_key: SExpression::from_str(format!("(public-key(ecc(curve nistp521)(q #04{}#)))", crate::util::hex::to_string(b)).as_str()).unwrap(),
public_key: SExpression::from_str(format!("(public-key(ecc(curve nistp521)(q #04{}#)))", crate::hex::to_string(b)).as_str()).unwrap(),
public_key_bytes: b.try_into().unwrap(),
})
} else {
@ -201,7 +201,7 @@ impl P521PublicKey {
pub fn verify(&self, msg: &[u8], signature: &[u8]) -> bool {
if signature.len() == P521_ECDSA_SIGNATURE_SIZE {
let data = SExpression::from_str(unsafe { std::str::from_utf8_unchecked(&hash_to_data_sexp(msg)) }).unwrap();
let sig = SExpression::from_str(format!("(sig-val(ecdsa(r #{}#)(s #{}#)))", crate::util::hex::to_string(&signature[0..66]), crate::util::hex::to_string(&signature[66..132])).as_str()).unwrap();
let sig = SExpression::from_str(format!("(sig-val(ecdsa(r #{}#)(s #{}#)))", crate::hex::to_string(&signature[0..66]), crate::hex::to_string(&signature[66..132])).as_str()).unwrap();
gcrypt::pkey::verify(&self.public_key, &data, &sig).is_ok()
} else {
false

View file

@ -6,8 +6,6 @@
* https://www.zerotier.com/
*/
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).
@ -18,7 +16,7 @@ impl SecureRandom {
pub fn get() -> Self { Self }
}
impl RngCore for SecureRandom {
impl rand_core::RngCore for SecureRandom {
#[inline(always)]
fn next_u32(&mut self) -> u32 {
let mut tmp = 0_u32;
@ -37,13 +35,13 @@ impl RngCore for SecureRandom {
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> {
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> {
randomize(Level::Strong, dest);
Ok(())
}
}
impl CryptoRng for SecureRandom {}
impl rand_core::CryptoRng for SecureRandom {}
#[inline(always)]
pub fn next_u32_secure() -> u32 {

View file

@ -7,7 +7,6 @@
*/
use std::convert::TryInto;
use std::mem::size_of;
use std::ptr::write_volatile;
/// Container for secrets that clears them on drop.

View file

@ -6,11 +6,12 @@
* https://www.zerotier.com/
*/
pub mod hex;
pub mod pool;
pub mod gate;
pub mod varint;
pub use zerotier_core_crypto::hex;
pub(crate) const ZEROES: [u8; 64] = [0_u8; 64];
#[inline(always)]

View file

@ -6,7 +6,6 @@
* https://www.zerotier.com/
*/
use std::mem::size_of;
use std::ptr::NonNull;
use std::sync::{Arc, Weak};

View file

@ -7,55 +7,59 @@
*/
use std::io::{Read, Write};
use crate::vl1::buffer::Buffer;
/// Write a variable length integer, which can consume up to 10 bytes.
pub fn write<W: Write>(w: &mut W, mut v: u64) -> std::io::Result<()> {
let mut b = [0_u8; 10];
let mut i = 10;
let mut i = 0;
loop {
if v > 0x7f {
i -= 1;
b[i] = (v as u8) & 0x7f;
v >>= 7;
i += 1;
v = v.wrapping_shr(7);
} else {
i -= 1;
b[i] = (v as u8) | 0x80;
i += 1;
break;
}
}
w.write_all(&b[i..])
w.write_all(&b[0..i])
}
pub fn read<R: Read>(r: &mut R) -> std::io::Result<u64> {
/// Read a variable length integer, returning the value and the number of bytes written.
pub fn read<R: Read>(r: &mut R) -> std::io::Result<(u64, usize)> {
let mut v = 0_u64;
let mut buf = [0_u8; 1];
let mut pos = 0;
let mut i = 0_usize;
loop {
v <<= 7;
let _ = r.read_exact(&mut buf)?;
let b = buf[0];
i += 1;
if b <= 0x7f {
v |= b as u64;
v |= (b as u64).wrapping_shl(pos);
pos += 7;
} else {
v |= (b & 0x7f) as u64;
return Ok(v);
v |= ((b & 0x7f) as u64).wrapping_shl(pos);
return Ok((v, i));
}
}
}
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);
#[cfg(test)]
mod tests {
use crate::util::varint::*;
#[test]
fn varint() {
let mut t: Vec<u8> = Vec::new();
for i in 0..131072 {
t.clear();
let ii = (u64::MAX / 131072) * i;
assert!(write(&mut t, ii).is_ok());
let mut t2 = t.as_slice();
assert_eq!(read(&mut t2).unwrap().0, ii);
}
}
*cursor = c;
return Err(std::io::Error::new(std::io::ErrorKind::UnexpectedEof, "incomplete varint"));
}

View file

@ -106,6 +106,9 @@ impl<const L: usize> Buffer<L> {
#[inline(always)]
pub unsafe fn set_size_unchecked(&mut self, s: usize) { self.0 = s; }
#[inline(always)]
pub unsafe fn get_unchecked(&self, i: usize) -> u8 { *self.1.get_unchecked(i) }
/// Append a packed structure and call a function to initialize it in place.
/// Anything not initialized will be zero.
#[inline(always)]
@ -327,7 +330,11 @@ 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> {
crate::util::varint::read_from_bytes(&(self.1[self.0..]), cursor)
let mut a = &self.1[*cursor..];
crate::util::varint::read(&mut a).map(|r| {
*cursor += r.1;
r.0
})
}
/// Get the next u8 and advance the cursor.

View file

@ -16,7 +16,7 @@ use crate::util::hex::HEX_CHARS;
/// It also supports binary keys and values which will be minimally escaped but render the result not
/// entirely human readable. Keys are serialized in natural sort order so the result can be consistently
/// checksummed or hashed.
#[derive(Clone)]
#[derive(Clone, PartialEq, Eq)]
pub struct Dictionary(BTreeMap<String, Vec<u8>>);
fn write_escaped<W: Write>(b: &[u8], w: &mut W) -> std::io::Result<()> {

View file

@ -306,9 +306,9 @@ impl Identity {
/// Verify a signature.
pub fn verify(&self, msg: &[u8], signature: &[u8]) -> bool {
self.v1.as_ref().map_or_else(|| {
crate::crypto::c25519::ed25519_verify(&self.ed25519, signature, msg)
zerotier_core_crypto::c25519::ed25519_verify(&self.ed25519, signature, msg)
}, |p521| {
signature.len() == IDENTITY_TYPE_1_SIGNATURE_SIZE && (*p521).1.verify(msg, &signature[0..P521_ECDSA_SIGNATURE_SIZE]) && crate::crypto::c25519::ed25519_verify(&self.ed25519, &signature[P521_ECDSA_SIGNATURE_SIZE..], msg)
signature.len() == IDENTITY_TYPE_1_SIGNATURE_SIZE && (*p521).1.verify(msg, &signature[0..P521_ECDSA_SIGNATURE_SIZE]) && zerotier_core_crypto::c25519::ed25519_verify(&self.ed25519, &signature[P521_ECDSA_SIGNATURE_SIZE..], msg)
})
}

View file

@ -92,11 +92,13 @@ impl Locator {
self.subject.marshal(buf)?;
self.signer.marshal(buf)?;
buf.append_varint(self.timestamp as u64)?;
self.metadata.map_or_else(|| buf.append_varint(0), |d| {
let db = d.to_bytes();
if self.metadata.is_none() {
buf.append_varint(0)?;
} else {
let db = self.metadata.as_ref().unwrap().to_bytes();
buf.append_varint(db.len() as u64)?;
buf.append_bytes(db.as_slice())
})?;
buf.append_bytes(db.as_slice())?;
}
buf.append_varint(self.endpoints.len() as u64)?;
for e in self.endpoints.iter() {
e.marshal(buf)?;

View file

@ -7,7 +7,6 @@
*/
use std::convert::TryInto;
use std::mem::MaybeUninit;
use std::ptr::copy_nonoverlapping;
use std::sync::Arc;
use std::sync::atomic::{AtomicI64, AtomicU64, AtomicU8, Ordering};
@ -449,7 +448,7 @@ impl Peer {
let aes_ctr_iv_position = packet.len();
debug_assert!(packet.append_and_init_bytes_fixed(|iv: &mut [u8; 18]| {
crate::crypto::random::fill_bytes_secure(&mut iv[0..16]);
zerotier_core_crypto::random::fill_bytes_secure(&mut iv[0..16]);
iv[12] &= 0x7f; // mask off MSB of counter in iv to play nice with some AES-CTR implementations
// LEGACY: create a 16-bit encrypted field that specifies zero moons. This is ignored by v2

View file

@ -177,7 +177,7 @@ pub fn compress_packet(src: &[u8], dest: &mut Buffer<{ PACKET_SIZE_MAX }>) -> bo
let d = dest.as_bytes_mut();
d[0..PACKET_VERB_INDEX].copy_from_slice(&src[0..PACKET_VERB_INDEX]);
d[PACKET_VERB_INDEX] = src[PACKET_VERB_INDEX] | VERB_FLAG_COMPRESSED;
lz4_flex::block::compress_into(&src[PACKET_VERB_INDEX + 1..], d, PACKET_VERB_INDEX + 1)
lz4_flex::block::compress_into(&src[PACKET_VERB_INDEX + 1..], &mut d[PACKET_VERB_INDEX + 1..])
};
if cs.is_ok() {
let cs = cs.unwrap();
@ -193,7 +193,7 @@ pub fn compress_packet(src: &[u8], dest: &mut Buffer<{ PACKET_SIZE_MAX }>) -> bo
/// Add HMAC-SHA384 to the end of a packet and set verb flag.
#[inline(always)]
pub fn add_extended_auth(pkt: &mut Buffer<{ PACKET_SIZE_MAX }>, hmac_secret_key: &[u8]) -> std::io::Result<()> {
pkt.append_bytes_fixed(&ztcrypto::hash::SHA384::hmac(hmac_secret_key, pkt.as_bytes_starting_at(PACKET_VERB_INDEX + 1)?))?;
pkt.append_bytes_fixed(&zerotier_core_crypto::hash::SHA384::hmac(hmac_secret_key, pkt.as_bytes_starting_at(PACKET_VERB_INDEX + 1)?))?;
pkt.as_bytes_mut()[PACKET_VERB_INDEX] |= VERB_FLAG_EXTENDED_AUTHENTICATION;
Ok(())
}

View file

@ -16,7 +16,6 @@ use zerotier_core_crypto::hash::SHA384;
use zerotier_core_crypto::p521::*;
use zerotier_core_crypto::secret::Secret;
use crate::error::InvalidFormatError;
use crate::vl1::{Endpoint, Identity};
use crate::vl1::buffer::Buffer;
use crate::vl1::protocol::PACKET_SIZE_MAX;

View file

@ -1298,7 +1298,7 @@ dependencies = [
"aes-gmac-siv",
"ed25519-dalek",
"gcrypt",
"rand_core 0.6.3",
"rand_core 0.5.1",
"x25519-dalek",
]