diff --git a/README.md b/README.md new file mode 100644 index 000000000..78821f98d --- /dev/null +++ b/README.md @@ -0,0 +1,12 @@ +tetanus: work-in-progress repo for ZeroTier in (mostly) pure Rust +====== + +![Rust](artwork/rust.png) + +--- + +This repository will go away or be mothballed in the future. It's a work in progress and is a bit of a monorepo that will probably get broken up eventually. + +The ZeroTier Rust code is currently sort of unlicensed pending actual release. We haven't decided what license to use yet, but we plan on it being something FOSS-friendlier than the current BSL in the old repo. + +--- diff --git a/aes-gmac-siv/src/impl_openssl.rs b/aes-gmac-siv/src/impl_openssl.rs index 12fcc06bf..d2f640b00 100644 --- a/aes-gmac-siv/src/impl_openssl.rs +++ b/aes-gmac-siv/src/impl_openssl.rs @@ -185,11 +185,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 { - let tmp = self.tmp.as_mut_ptr().cast::(); - *tmp = *self.tag.as_mut_ptr().cast::(); - *tmp.offset(1) = 0; - } + self.tmp[0..8].copy_from_slice(&tag_tmp[0..8]); + self.tmp[8..12].fill(0); let _ = self.gmac.replace(Crypter::new(aes_gcm_by_key_size(self.k0.len()), Mode::Encrypt, self.k0.as_slice(), Some(&self.tmp[0..12])).unwrap()); } @@ -234,7 +231,7 @@ impl AesGmacSiv { unsafe { // tag[8..16] == tmp[0..8] ^ tmp[8..16] let tmp = self.tmp.as_mut_ptr().cast::(); - if *self.tag.as_mut_ptr().cast::().offset(1) == *tmp ^ *tmp.offset(1) { + if *self.tag.as_mut_ptr().cast::().offset(1) == *tmp ^ *tmp.add(1) { Some(&self.tag) } else { None diff --git a/artwork/rust.png b/artwork/rust.png new file mode 100644 index 000000000..5337933bf Binary files /dev/null and b/artwork/rust.png differ diff --git a/zerotier-core-crypto/src/hex.rs b/zerotier-core-crypto/src/hex.rs index 3b2515652..e0eec0d9c 100644 --- a/zerotier-core-crypto/src/hex.rs +++ b/zerotier-core-crypto/src/hex.rs @@ -4,7 +4,7 @@ pub const HEX_CHARS: [u8; 16] = [b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', /// Encode a byte slice to a hexadecimal string. pub fn to_string(b: &[u8]) -> String { - let mut s = String::new(); + let mut s = String::with_capacity(b.len() * 2); s.reserve(b.len() * 2); for c in b { let x = *c as usize; @@ -16,8 +16,7 @@ pub fn to_string(b: &[u8]) -> String { /// Encode an unsigned 64-bit value as a hexadecimal string. pub fn to_string_u64(mut i: u64, skip_leading_zeroes: bool) -> String { - let mut s = String::new(); - s.reserve(16); + let mut s = String::with_capacity(16); for _ in 0..16 { let ii = i >> 60; if ii != 0 || !s.is_empty() || !skip_leading_zeroes { @@ -30,8 +29,7 @@ pub fn to_string_u64(mut i: u64, skip_leading_zeroes: bool) -> String { /// Encode an unsigned 64-bit value as a hexadecimal ASCII string. pub fn to_vec_u64(mut i: u64, skip_leading_zeroes: bool) -> Vec { - let mut s = Vec::new(); - s.reserve(16); + let mut s = Vec::with_capacity(16); for _ in 0..16 { let ii = i >> 60; if ii != 0 || !s.is_empty() || !skip_leading_zeroes { @@ -44,9 +42,7 @@ pub fn to_vec_u64(mut i: u64, skip_leading_zeroes: bool) -> Vec { /// Decode a hex string, ignoring all non-hexadecimal characters. pub fn from_string(s: &str) -> Vec { - let mut b: Vec = Vec::new(); - b.reserve((s.len() / 2) + 1); - + let mut b: Vec = Vec::with_capacity((s.len() / 2) + 1); let mut byte = 0_u8; let mut have_8: bool = false; for cc in s.as_bytes() { @@ -71,13 +67,12 @@ pub fn from_string(s: &str) -> Vec { have_8 = !have_8; } } - b } -/// Encode bytes from 'b' into hex characters in 'dest'. +/// Encode bytes from 'b' into hex characters in 'dest' and return the number of hex characters written. /// This will panic if the destination slice is smaller than twice the length of the source. -pub fn to_hex_bytes(b: &[u8], dest: &mut [u8]) { +pub fn to_hex_bytes(b: &[u8], dest: &mut [u8]) -> usize { let mut j = 0; for c in b { let x = *c as usize; @@ -85,4 +80,5 @@ pub fn to_hex_bytes(b: &[u8], dest: &mut [u8]) { dest[j + 1] = HEX_CHARS[x & 0xf]; j += 2; } + j } diff --git a/zerotier-core-crypto/src/p384.rs b/zerotier-core-crypto/src/p384.rs index c961a3881..94be794a3 100644 --- a/zerotier-core-crypto/src/p384.rs +++ b/zerotier-core-crypto/src/p384.rs @@ -177,6 +177,8 @@ impl P384KeyPair { } /// Perform ECDH key agreement, returning the raw (un-hashed!) ECDH secret. + /// + /// This secret should not be used directly. It should be hashed and perhaps used in a KDF. pub fn agree(&self, other_public: &P384PublicKey) -> Option> { unsafe { let mut s: Secret = Secret::default(); diff --git a/zerotier-core-crypto/src/poly1305.rs b/zerotier-core-crypto/src/poly1305.rs index a1b5449c1..d8fa9c4ab 100644 --- a/zerotier-core-crypto/src/poly1305.rs +++ b/zerotier-core-crypto/src/poly1305.rs @@ -11,12 +11,9 @@ pub const POLY1305_MAC_SIZE: usize = 16; impl Poly1305 { #[inline(always)] - pub fn new(key: &[u8]) -> Option { - if key.len() == 32 { - Some(Self(poly1305::Poly1305::new(poly1305::Key::from_slice(key)))) - } else { - None - } + pub fn new(key: &[u8]) -> Poly1305 { + assert_eq!(key.len(), 32); + Self(poly1305::Poly1305::new(poly1305::Key::from_slice(key))) } #[inline(always)] diff --git a/zerotier-network-hypervisor/src/vl1/peer.rs b/zerotier-network-hypervisor/src/vl1/peer.rs index 9c2fd605d..8e95cfe72 100644 --- a/zerotier-network-hypervisor/src/vl1/peer.rs +++ b/zerotier-network-hypervisor/src/vl1/peer.rs @@ -75,7 +75,8 @@ fn salsa_poly_create(secret: &SymmetricSecret, header: &PacketHeader, packet_siz let mut salsa = Salsa::<12>::new(&key.0, &header.id); let mut poly1305_key = [0_u8; 32]; salsa.crypt_in_place(&mut poly1305_key); - (salsa, Poly1305::new(&poly1305_key).unwrap()) + + (salsa, Poly1305::new(&poly1305_key)) } /// Attempt AEAD packet encryption and MAC validation. Returns message ID on success.