From 75f407c137f5770334a4facbe4cbd5ed07191f2e Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 29 Sep 2022 14:03:38 -0400 Subject: [PATCH] More refactoring to consolidate protocol V1 stuff. --- network-hypervisor/src/protocol.rs | 41 +++++++++++++++- network-hypervisor/src/vl1/mod.rs | 1 - network-hypervisor/src/vl1/peer.rs | 17 +++---- network-hypervisor/src/vl1/symmetricsecret.rs | 49 ------------------- 4 files changed, 48 insertions(+), 60 deletions(-) delete mode 100644 network-hypervisor/src/vl1/symmetricsecret.rs diff --git a/network-hypervisor/src/protocol.rs b/network-hypervisor/src/protocol.rs index ab16ac2b5..6c697969d 100644 --- a/network-hypervisor/src/protocol.rs +++ b/network-hypervisor/src/protocol.rs @@ -6,7 +6,11 @@ use std::mem::MaybeUninit; use crate::vl1::Address; use zerotier_utils::buffer::{Buffer, PooledBufferFactory}; -use zerotier_utils::pool::{Pool, Pooled}; +use zerotier_utils::pool::{Pool, PoolFactory, Pooled}; + +use zerotier_crypto::aes_gmac_siv::AesGmacSiv; +use zerotier_crypto::hash::hmac_sha384; +use zerotier_crypto::secret::Secret; /* * Legacy V1 protocol versions: @@ -482,6 +486,41 @@ pub(crate) mod v1 { } } } + + /// A V1 symmetric secret with master key and sub-keys for AES-GMAC-SIV + pub(crate) struct SymmetricSecret { + pub key: Secret<64>, + pub aes_gmac_siv: Pool, + } + + fn zt_kbkdf_hmac_sha384(key: &[u8], label: u8) -> Secret<48> { + Secret(hmac_sha384(key, &[0, 0, 0, 0, b'Z', b'T', label, 0, 0, 0, 0, 0x01, 0x80])) + } + + impl SymmetricSecret { + /// Create a new symmetric secret, deriving all sub-keys and such. + pub fn new(key: Secret<64>) -> SymmetricSecret { + let aes_factory = AesGmacSivPoolFactory( + zt_kbkdf_hmac_sha384(&key.0[..48], v1::KBKDF_KEY_USAGE_LABEL_AES_GMAC_SIV_K0).first_n_clone(), + zt_kbkdf_hmac_sha384(&key.0[..48], v1::KBKDF_KEY_USAGE_LABEL_AES_GMAC_SIV_K1).first_n_clone(), + ); + SymmetricSecret { key, aes_gmac_siv: Pool::new(2, aes_factory) } + } + } + + pub(crate) struct AesGmacSivPoolFactory(Secret<32>, Secret<32>); + + impl PoolFactory for AesGmacSivPoolFactory { + #[inline(always)] + fn create(&self) -> AesGmacSiv { + AesGmacSiv::new(self.0.as_bytes(), self.1.as_bytes()) + } + + #[inline(always)] + fn reset(&self, obj: &mut AesGmacSiv) { + obj.reset(); + } + } } /// Maximum delta between the message ID of a sent packet and its response. diff --git a/network-hypervisor/src/vl1/mod.rs b/network-hypervisor/src/vl1/mod.rs index cc303cb38..d49654c48 100644 --- a/network-hypervisor/src/vl1/mod.rs +++ b/network-hypervisor/src/vl1/mod.rs @@ -7,7 +7,6 @@ mod mac; mod path; mod peer; mod rootset; -mod symmetricsecret; pub(crate) mod node; diff --git a/network-hypervisor/src/vl1/peer.rs b/network-hypervisor/src/vl1/peer.rs index e1ff660a3..553bfa03c 100644 --- a/network-hypervisor/src/vl1/peer.rs +++ b/network-hypervisor/src/vl1/peer.rs @@ -19,7 +19,6 @@ use crate::protocol::*; use crate::vl1::address::Address; use crate::vl1::debug_event; use crate::vl1::node::*; -use crate::vl1::symmetricsecret::SymmetricSecret; use crate::vl1::{Endpoint, Identity, Path}; use crate::{VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION}; @@ -28,7 +27,7 @@ pub(crate) const SERVICE_INTERVAL_MS: i64 = 10000; pub struct Peer { pub identity: Identity, - static_symmetric_key: SymmetricSecret, + v1_proto_static_secret: v1::SymmetricSecret, paths: Mutex>>, pub(crate) last_send_time_ticks: AtomicI64, @@ -67,7 +66,7 @@ impl Peer { this_node_identity.agree(&id).map(|static_secret| -> Self { Self { identity: id, - static_symmetric_key: SymmetricSecret::new(static_secret), + v1_proto_static_secret: v1::SymmetricSecret::new(static_secret), paths: Mutex::new(Vec::with_capacity(4)), last_send_time_ticks: AtomicI64::new(NEVER_HAPPENED_TICKS), last_receive_time_ticks: AtomicI64::new(NEVER_HAPPENED_TICKS), @@ -294,7 +293,7 @@ impl Peer { v1::CIPHER_AES_GMAC_SIV }; - let mut aes_gmac_siv = self.static_symmetric_key.aes_gmac_siv.get(); + let mut aes_gmac_siv = self.v1_proto_static_secret.aes_gmac_siv.get(); aes_gmac_siv.encrypt_init(&self.v1_proto_next_message_id().to_ne_bytes()); aes_gmac_siv.encrypt_set_aad(&v1::get_packet_aad_bytes( self.identity.address, @@ -325,7 +324,7 @@ impl Peer { }; let (mut salsa, poly1305_otk) = v1_proto_salsa_poly_create( - &self.static_symmetric_key, + &self.v1_proto_static_secret, { let header = packet.struct_mut_at::(0).unwrap(); header.id = self.v1_proto_next_message_id().to_ne_bytes(); @@ -412,7 +411,7 @@ impl Peer { assert!(node.identity.write_public(&mut packet, self.identity.p384.is_none()).is_ok()); let (_, poly1305_key) = v1_proto_salsa_poly_create( - &self.static_symmetric_key, + &self.v1_proto_static_secret, packet.struct_at::(0).unwrap(), packet.len(), ); @@ -468,7 +467,7 @@ impl Peer { let mut payload = PacketBuffer::new(); let message_id = if let Some(message_id2) = v1_proto_try_aead_decrypt( - &self.static_symmetric_key, + &self.v1_proto_static_secret, packet_frag0_payload_bytes, packet_header, fragments, @@ -870,7 +869,7 @@ impl PartialEq for Peer { impl Eq for Peer {} fn v1_proto_try_aead_decrypt( - secret: &SymmetricSecret, + secret: &v1::SymmetricSecret, packet_frag0_payload_bytes: &[u8], packet_header: &v1::PacketHeader, fragments: &[Option], @@ -952,7 +951,7 @@ fn v1_proto_try_aead_decrypt( } } -fn v1_proto_salsa_poly_create(secret: &SymmetricSecret, header: &v1::PacketHeader, packet_size: usize) -> (Salsa<12>, [u8; 32]) { +fn v1_proto_salsa_poly_create(secret: &v1::SymmetricSecret, header: &v1::PacketHeader, packet_size: usize) -> (Salsa<12>, [u8; 32]) { // Create a per-packet key from the IV, source, destination, and packet size. let mut key: Secret<32> = secret.key.first_n_clone(); let hb = header.as_bytes(); diff --git a/network-hypervisor/src/vl1/symmetricsecret.rs b/network-hypervisor/src/vl1/symmetricsecret.rs deleted file mode 100644 index 056821d15..000000000 --- a/network-hypervisor/src/vl1/symmetricsecret.rs +++ /dev/null @@ -1,49 +0,0 @@ -// (c) 2020-2022 ZeroTier, Inc. -- currently propritery pending actual release and licensing. See LICENSE.md. - -use zerotier_crypto::aes_gmac_siv::AesGmacSiv; -use zerotier_crypto::hash::hmac_sha384; -use zerotier_crypto::secret::Secret; - -use crate::protocol::*; - -use zerotier_utils::pool::{Pool, PoolFactory}; - -/// A symmetric secret key negotiated between peers. -/// -/// This contains the key and several sub-keys and ciphers keyed with sub-keys. -pub(crate) struct SymmetricSecret { - /// Master key from which other keys are derived. - pub key: Secret<64>, - - /// Pool of keyed AES-GMAC-SIV engines (pooled to avoid AES re-init every time). - pub aes_gmac_siv: Pool, -} - -fn zt_kbkdf_hmac_sha384(key: &[u8], label: u8) -> Secret<48> { - Secret(hmac_sha384(key, &[0, 0, 0, 0, b'Z', b'T', label, 0, 0, 0, 0, 0x01, 0x80])) -} - -impl SymmetricSecret { - /// Create a new symmetric secret, deriving all sub-keys and such. - pub fn new(key: Secret<64>) -> SymmetricSecret { - let aes_factory = AesGmacSivPoolFactory( - zt_kbkdf_hmac_sha384(&key.0[..48], v1::KBKDF_KEY_USAGE_LABEL_AES_GMAC_SIV_K0).first_n_clone(), - zt_kbkdf_hmac_sha384(&key.0[..48], v1::KBKDF_KEY_USAGE_LABEL_AES_GMAC_SIV_K1).first_n_clone(), - ); - SymmetricSecret { key, aes_gmac_siv: Pool::new(2, aes_factory) } - } -} - -pub(crate) struct AesGmacSivPoolFactory(Secret<32>, Secret<32>); - -impl PoolFactory for AesGmacSivPoolFactory { - #[inline(always)] - fn create(&self) -> AesGmacSiv { - AesGmacSiv::new(self.0.as_bytes(), self.1.as_bytes()) - } - - #[inline(always)] - fn reset(&self, obj: &mut AesGmacSiv) { - obj.reset(); - } -}