mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-04-26 17:03:43 +02:00
More refactoring to consolidate protocol V1 stuff.
This commit is contained in:
parent
de506dc48b
commit
75f407c137
4 changed files with 48 additions and 60 deletions
|
@ -6,7 +6,11 @@ use std::mem::MaybeUninit;
|
||||||
use crate::vl1::Address;
|
use crate::vl1::Address;
|
||||||
|
|
||||||
use zerotier_utils::buffer::{Buffer, PooledBufferFactory};
|
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:
|
* 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<AesGmacSiv, AesGmacSivPoolFactory>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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<AesGmacSiv> 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.
|
/// Maximum delta between the message ID of a sent packet and its response.
|
||||||
|
|
|
@ -7,7 +7,6 @@ mod mac;
|
||||||
mod path;
|
mod path;
|
||||||
mod peer;
|
mod peer;
|
||||||
mod rootset;
|
mod rootset;
|
||||||
mod symmetricsecret;
|
|
||||||
|
|
||||||
pub(crate) mod node;
|
pub(crate) mod node;
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,6 @@ use crate::protocol::*;
|
||||||
use crate::vl1::address::Address;
|
use crate::vl1::address::Address;
|
||||||
use crate::vl1::debug_event;
|
use crate::vl1::debug_event;
|
||||||
use crate::vl1::node::*;
|
use crate::vl1::node::*;
|
||||||
use crate::vl1::symmetricsecret::SymmetricSecret;
|
|
||||||
use crate::vl1::{Endpoint, Identity, Path};
|
use crate::vl1::{Endpoint, Identity, Path};
|
||||||
use crate::{VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION};
|
use crate::{VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION};
|
||||||
|
|
||||||
|
@ -28,7 +27,7 @@ pub(crate) const SERVICE_INTERVAL_MS: i64 = 10000;
|
||||||
pub struct Peer<HostSystemImpl: HostSystem> {
|
pub struct Peer<HostSystemImpl: HostSystem> {
|
||||||
pub identity: Identity,
|
pub identity: Identity,
|
||||||
|
|
||||||
static_symmetric_key: SymmetricSecret,
|
v1_proto_static_secret: v1::SymmetricSecret,
|
||||||
paths: Mutex<Vec<PeerPath<HostSystemImpl>>>,
|
paths: Mutex<Vec<PeerPath<HostSystemImpl>>>,
|
||||||
|
|
||||||
pub(crate) last_send_time_ticks: AtomicI64,
|
pub(crate) last_send_time_ticks: AtomicI64,
|
||||||
|
@ -67,7 +66,7 @@ impl<HostSystemImpl: HostSystem> Peer<HostSystemImpl> {
|
||||||
this_node_identity.agree(&id).map(|static_secret| -> Self {
|
this_node_identity.agree(&id).map(|static_secret| -> Self {
|
||||||
Self {
|
Self {
|
||||||
identity: id,
|
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)),
|
paths: Mutex::new(Vec::with_capacity(4)),
|
||||||
last_send_time_ticks: AtomicI64::new(NEVER_HAPPENED_TICKS),
|
last_send_time_ticks: AtomicI64::new(NEVER_HAPPENED_TICKS),
|
||||||
last_receive_time_ticks: AtomicI64::new(NEVER_HAPPENED_TICKS),
|
last_receive_time_ticks: AtomicI64::new(NEVER_HAPPENED_TICKS),
|
||||||
|
@ -294,7 +293,7 @@ impl<HostSystemImpl: HostSystem> Peer<HostSystemImpl> {
|
||||||
v1::CIPHER_AES_GMAC_SIV
|
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_init(&self.v1_proto_next_message_id().to_ne_bytes());
|
||||||
aes_gmac_siv.encrypt_set_aad(&v1::get_packet_aad_bytes(
|
aes_gmac_siv.encrypt_set_aad(&v1::get_packet_aad_bytes(
|
||||||
self.identity.address,
|
self.identity.address,
|
||||||
|
@ -325,7 +324,7 @@ impl<HostSystemImpl: HostSystem> Peer<HostSystemImpl> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let (mut salsa, poly1305_otk) = v1_proto_salsa_poly_create(
|
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::<v1::PacketHeader>(0).unwrap();
|
let header = packet.struct_mut_at::<v1::PacketHeader>(0).unwrap();
|
||||||
header.id = self.v1_proto_next_message_id().to_ne_bytes();
|
header.id = self.v1_proto_next_message_id().to_ne_bytes();
|
||||||
|
@ -412,7 +411,7 @@ impl<HostSystemImpl: HostSystem> Peer<HostSystemImpl> {
|
||||||
assert!(node.identity.write_public(&mut packet, self.identity.p384.is_none()).is_ok());
|
assert!(node.identity.write_public(&mut packet, self.identity.p384.is_none()).is_ok());
|
||||||
|
|
||||||
let (_, poly1305_key) = v1_proto_salsa_poly_create(
|
let (_, poly1305_key) = v1_proto_salsa_poly_create(
|
||||||
&self.static_symmetric_key,
|
&self.v1_proto_static_secret,
|
||||||
packet.struct_at::<v1::PacketHeader>(0).unwrap(),
|
packet.struct_at::<v1::PacketHeader>(0).unwrap(),
|
||||||
packet.len(),
|
packet.len(),
|
||||||
);
|
);
|
||||||
|
@ -468,7 +467,7 @@ impl<HostSystemImpl: HostSystem> Peer<HostSystemImpl> {
|
||||||
let mut payload = PacketBuffer::new();
|
let mut payload = PacketBuffer::new();
|
||||||
|
|
||||||
let message_id = if let Some(message_id2) = v1_proto_try_aead_decrypt(
|
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_frag0_payload_bytes,
|
||||||
packet_header,
|
packet_header,
|
||||||
fragments,
|
fragments,
|
||||||
|
@ -870,7 +869,7 @@ impl<HostSystemImpl: HostSystem> PartialEq for Peer<HostSystemImpl> {
|
||||||
impl<HostSystemImpl: HostSystem> Eq for Peer<HostSystemImpl> {}
|
impl<HostSystemImpl: HostSystem> Eq for Peer<HostSystemImpl> {}
|
||||||
|
|
||||||
fn v1_proto_try_aead_decrypt(
|
fn v1_proto_try_aead_decrypt(
|
||||||
secret: &SymmetricSecret,
|
secret: &v1::SymmetricSecret,
|
||||||
packet_frag0_payload_bytes: &[u8],
|
packet_frag0_payload_bytes: &[u8],
|
||||||
packet_header: &v1::PacketHeader,
|
packet_header: &v1::PacketHeader,
|
||||||
fragments: &[Option<PooledPacketBuffer>],
|
fragments: &[Option<PooledPacketBuffer>],
|
||||||
|
@ -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.
|
// Create a per-packet key from the IV, source, destination, and packet size.
|
||||||
let mut key: Secret<32> = secret.key.first_n_clone();
|
let mut key: Secret<32> = secret.key.first_n_clone();
|
||||||
let hb = header.as_bytes();
|
let hb = header.as_bytes();
|
||||||
|
|
|
@ -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<AesGmacSiv, AesGmacSivPoolFactory>,
|
|
||||||
}
|
|
||||||
|
|
||||||
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<AesGmacSiv> 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();
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue