From 08025de8f505b065d8841c4999d2c5dbbd9c56c3 Mon Sep 17 00:00:00 2001 From: Luca Fulchir Date: Mon, 19 Jun 2023 19:26:21 +0200 Subject: [PATCH] Rename lots of stuff to properly use namespaces Signed-off-by: Luca Fulchir --- src/config/mod.rs | 17 +++-- src/connection/handshake/dirsync.rs | 108 ++++++++++++++-------------- src/connection/handshake/mod.rs | 33 ++++----- src/connection/handshake/tests.rs | 31 ++++---- src/connection/handshake/tracker.rs | 79 ++++++++++---------- src/connection/mod.rs | 4 +- src/connection/packet.rs | 10 +-- src/dnssec/record.rs | 17 +++-- src/dnssec/tests.rs | 8 +-- src/enc/asym.rs | 66 ++++++++--------- src/enc/hkdf.rs | 28 ++++---- src/enc/sym.rs | 107 ++++++++++----------------- src/enc/tests.rs | 24 ++++--- src/inner/worker.rs | 37 +++++----- src/tests.rs | 11 ++- 15 files changed, 269 insertions(+), 311 deletions(-) diff --git a/src/config/mod.rs b/src/config/mod.rs index f196ac9..392bdcc 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -2,11 +2,10 @@ //! Configuration to initialize the Fenrir networking library use crate::{ - connection::handshake::HandshakeID, + connection::handshake, enc::{ asym::{KeyExchangeKind, KeyID, PrivKey, PubKey}, - hkdf::HkdfKind, - sym::CipherKind, + hkdf, sym, }, }; use ::std::{ @@ -44,13 +43,13 @@ pub struct Config { /// List of DNS resolvers to use pub resolvers: Vec, /// Supported handshakes - pub handshakes: Vec, + pub handshakes: Vec, /// Supported key exchanges pub key_exchanges: Vec, /// Supported Hkdfs - pub hkdfs: Vec, + pub hkdfs: Vec, /// Supported Ciphers - pub ciphers: Vec, + pub ciphers: Vec, /// list of authentication servers /// clients will have this empty pub servers: Vec, @@ -73,10 +72,10 @@ impl Default for Config { ), ], resolvers: Vec::new(), - handshakes: [HandshakeID::DirectorySynchronized].to_vec(), + handshakes: [handshake::ID::DirectorySynchronized].to_vec(), key_exchanges: [KeyExchangeKind::X25519DiffieHellman].to_vec(), - hkdfs: [HkdfKind::Sha3].to_vec(), - ciphers: [CipherKind::XChaCha20Poly1305].to_vec(), + hkdfs: [hkdf::Kind::Sha3].to_vec(), + ciphers: [sym::Kind::XChaCha20Poly1305].to_vec(), servers: Vec::new(), server_keys: Vec::new(), } diff --git a/src/connection/handshake/dirsync.rs b/src/connection/handshake/dirsync.rs index 0be2dd4..676af37 100644 --- a/src/connection/handshake/dirsync.rs +++ b/src/connection/handshake/dirsync.rs @@ -8,14 +8,14 @@ //! To grant a form of perfect forward secrecy, the server should periodically //! change the DNSSEC public/private keys -use super::{Error, HandshakeData}; +use super::Error; use crate::{ auth, - connection::{ProtocolVersion, ID}, + connection::{handshake, ProtocolVersion, ID}, enc::{ asym::{ExchangePubKey, KeyExchangeKind, KeyID}, - hkdf::HkdfKind, - sym::{CipherKind, HeadLen, TagLen}, + hkdf, + sym::{self, NonceLen, TagLen}, Random, Secret, }, }; @@ -59,7 +59,7 @@ pub enum DirSync { impl DirSync { /// actual length of the dirsync handshake data - pub fn len(&self, head_len: HeadLen, tag_len: TagLen) -> usize { + pub fn len(&self, head_len: NonceLen, tag_len: TagLen) -> usize { match self { DirSync::Req(req) => req.len(), DirSync::Resp(resp) => resp.len(head_len, tag_len), @@ -69,7 +69,7 @@ impl DirSync { /// NOTE: assumes that there is exactly asa much buffer as needed pub fn serialize( &self, - head_len: HeadLen, + head_len: NonceLen, tag_len: TagLen, out: &mut [u8], ) { @@ -88,13 +88,13 @@ pub struct Req { /// Selected key exchange pub exchange: KeyExchangeKind, /// Selected hkdf - pub hkdf: HkdfKind, + pub hkdf: hkdf::Kind, /// Selected cipher - pub cipher: CipherKind, + pub cipher: sym::Kind, /// Client ephemeral public key used for key exchanges pub exchange_key: ExchangePubKey, /// encrypted data - pub data: ReqInner, + pub data: ReqState, // SECURITY: TODO: Add padding to min: 1200 bytes // to avoid amplification attaks // also: 1200 < 1280 to allow better vpn compatibility @@ -105,30 +105,30 @@ impl Req { /// NOTE: starts from the beginning of the fenrir packet pub fn encrypted_offset(&self) -> usize { ProtocolVersion::len() - + crate::handshake::HandshakeID::len() + + handshake::ID::len() + KeyID::len() + KeyExchangeKind::len() - + HkdfKind::len() - + CipherKind::len() + + hkdf::Kind::len() + + sym::Kind::len() + self.exchange_key.kind().pub_len() } /// return the total length of the cleartext data pub fn encrypted_length( &self, - head_len: HeadLen, + head_len: NonceLen, tag_len: TagLen, ) -> usize { match &self.data { - ReqInner::ClearText(data) => data.len() + head_len.0 + tag_len.0, - ReqInner::CipherText(length) => *length, + ReqState::ClearText(data) => data.len() + head_len.0 + tag_len.0, + ReqState::CipherText(length) => *length, } } /// actual length of the directory synchronized request pub fn len(&self) -> usize { KeyID::len() + KeyExchangeKind::len() - + HkdfKind::len() - + CipherKind::len() + + hkdf::Kind::len() + + sym::Kind::len() + self.exchange_key.kind().pub_len() + self.cipher.nonce_len().0 + self.data.len() @@ -138,7 +138,7 @@ impl Req { /// NOTE: assumes that there is exactly as much buffer as needed pub fn serialize( &self, - head_len: HeadLen, + head_len: NonceLen, tag_len: TagLen, out: &mut [u8], ) { @@ -150,7 +150,7 @@ impl Req { let written_next = 5 + key_len; self.exchange_key.serialize_into(&mut out[5..written_next]); let written = written_next; - if let ReqInner::ClearText(data) = &self.data { + if let ReqState::ClearText(data) = &self.data { let from = written + head_len.0; let to = out.len() - tag_len.0; data.serialize(&mut out[from..to]); @@ -160,8 +160,8 @@ impl Req { } } -impl super::HandshakeParsing for Req { - fn deserialize(raw: &[u8]) -> Result { +impl handshake::Parsing for Req { + fn deserialize(raw: &[u8]) -> Result { const MIN_PKT_LEN: usize = 10; if raw.len() < MIN_PKT_LEN { return Err(Error::NotEnoughData); @@ -173,25 +173,25 @@ impl super::HandshakeParsing for Req { Some(exchange) => exchange, None => return Err(Error::Parsing), }; - let hkdf: HkdfKind = match HkdfKind::from_u8(raw[3]) { + let hkdf: hkdf::Kind = match hkdf::Kind::from_u8(raw[3]) { Some(exchange) => exchange, None => return Err(Error::Parsing), }; - let cipher: CipherKind = match CipherKind::from_u8(raw[4]) { + let cipher: sym::Kind = match sym::Kind::from_u8(raw[4]) { Some(cipher) => cipher, None => return Err(Error::Parsing), }; const CURR_SIZE: usize = KeyID::len() + KeyExchangeKind::len() - + HkdfKind::len() - + CipherKind::len(); + + hkdf::Kind::len() + + sym::Kind::len(); let (exchange_key, len) = match ExchangePubKey::deserialize(&raw[CURR_SIZE..]) { Ok(exchange_key) => exchange_key, Err(e) => return Err(e.into()), }; - let data = ReqInner::CipherText(raw.len() - (CURR_SIZE + len)); - Ok(HandshakeData::DirSync(DirSync::Req(Self { + let data = ReqState::CipherText(raw.len() - (CURR_SIZE + len)); + Ok(handshake::Data::DirSync(DirSync::Req(Self { key_id, exchange, hkdf, @@ -204,18 +204,18 @@ impl super::HandshakeParsing for Req { /// Quick way to avoid mixing cipher and clear text #[derive(Debug, Clone, PartialEq)] -pub enum ReqInner { +pub enum ReqState { /// Data is still encrytped, we only keep the length CipherText(usize), /// Client data, decrypted and parsed ClearText(ReqData), } -impl ReqInner { +impl ReqState { /// The length of the data pub fn len(&self) -> usize { match self { - ReqInner::CipherText(len) => *len, - ReqInner::ClearText(data) => data.len(), + ReqState::CipherText(len) => *len, + ReqState::ClearText(data) => data.len(), } } /// parse the cleartext @@ -224,10 +224,10 @@ impl ReqInner { raw: &[u8], ) -> Result<(), Error> { let clear = match self { - ReqInner::CipherText(len) => { + ReqState::CipherText(len) => { assert!( *len > raw.len(), - "DirSync::ReqInner::CipherText length mismatch" + "DirSync::ReqState::CipherText length mismatch" ); match ReqData::deserialize(raw) { Ok(clear) => clear, @@ -236,7 +236,7 @@ impl ReqInner { } _ => return Err(Error::Parsing), }; - *self = ReqInner::ClearText(clear); + *self = ReqState::ClearText(clear); Ok(()) } } @@ -386,18 +386,18 @@ impl ReqData { /// Quick way to avoid mixing cipher and clear text #[derive(Debug, Clone, PartialEq)] -pub enum RespInner { +pub enum RespState { /// Server data, still in ciphertext CipherText(usize), /// Parsed, cleartext server data ClearText(RespData), } -impl RespInner { +impl RespState { /// The length of the data pub fn len(&self) -> usize { match self { - RespInner::CipherText(len) => *len, - RespInner::ClearText(_) => RespData::len(), + RespState::CipherText(len) => *len, + RespState::ClearText(_) => RespData::len(), } } /// parse the cleartext @@ -406,10 +406,10 @@ impl RespInner { raw: &[u8], ) -> Result<(), Error> { let clear = match self { - RespInner::CipherText(len) => { + RespState::CipherText(len) => { assert!( *len > raw.len(), - "DirSync::RespInner::CipherText length mismatch" + "DirSync::RespState::CipherText length mismatch" ); match RespData::deserialize(raw) { Ok(clear) => clear, @@ -418,12 +418,12 @@ impl RespInner { } _ => return Err(Error::Parsing), }; - *self = RespInner::ClearText(clear); + *self = RespState::ClearText(clear); Ok(()) } /// Serialize the still cleartext data pub fn serialize(&self, out: &mut [u8]) { - if let RespInner::ClearText(clear) = &self { + if let RespState::ClearText(clear) = &self { clear.serialize(out); } } @@ -435,20 +435,20 @@ pub struct Resp { /// Tells the client with which key the exchange was done pub client_key_id: KeyID, /// actual response data, might be encrypted - pub data: RespInner, + pub data: RespState, } -impl super::HandshakeParsing for Resp { - fn deserialize(raw: &[u8]) -> Result { +impl handshake::Parsing for Resp { + fn deserialize(raw: &[u8]) -> Result { const MIN_PKT_LEN: usize = 68; if raw.len() < MIN_PKT_LEN { return Err(Error::NotEnoughData); } let client_key_id: KeyID = KeyID(u16::from_le_bytes(raw[0..KeyID::len()].try_into().unwrap())); - Ok(HandshakeData::DirSync(DirSync::Resp(Self { + Ok(handshake::Data::DirSync(DirSync::Resp(Self { client_key_id, - data: RespInner::CipherText(raw[KeyID::len()..].len()), + data: RespState::CipherText(raw[KeyID::len()..].len()), }))) } } @@ -457,32 +457,30 @@ impl Resp { /// return the offset of the encrypted data /// NOTE: starts from the beginning of the fenrir packet pub fn encrypted_offset(&self) -> usize { - ProtocolVersion::len() - + crate::connection::handshake::HandshakeID::len() - + KeyID::len() + ProtocolVersion::len() + handshake::ID::len() + KeyID::len() } /// return the total length of the cleartext data pub fn encrypted_length( &self, - head_len: HeadLen, + head_len: NonceLen, tag_len: TagLen, ) -> usize { match &self.data { - RespInner::ClearText(_data) => { + RespState::ClearText(_data) => { RespData::len() + head_len.0 + tag_len.0 } - RespInner::CipherText(len) => *len, + RespState::CipherText(len) => *len, } } /// Total length of the response handshake - pub fn len(&self, head_len: HeadLen, tag_len: TagLen) -> usize { + pub fn len(&self, head_len: NonceLen, tag_len: TagLen) -> usize { KeyID::len() + head_len.0 + self.data.len() + tag_len.0 } /// Serialize into raw bytes /// NOTE: assumes that there is exactly as much buffer as needed pub fn serialize( &self, - head_len: HeadLen, + head_len: NonceLen, _tag_len: TagLen, out: &mut [u8], ) { diff --git a/src/connection/handshake/mod.rs b/src/connection/handshake/mod.rs index b5204a1..6c0e53d 100644 --- a/src/connection/handshake/mod.rs +++ b/src/connection/handshake/mod.rs @@ -4,10 +4,11 @@ pub mod dirsync; #[cfg(test)] mod tests; pub(crate) mod tracker; +pub(crate) use tracker::{Action, Tracker}; use crate::{ connection::ProtocolVersion, - enc::sym::{HeadLen, TagLen}, + enc::sym::{NonceLen, TagLen}, }; use ::num_traits::FromPrimitive; @@ -56,7 +57,7 @@ pub enum Error { ::strum_macros::IntoStaticStr, )] #[repr(u8)] -pub enum HandshakeID { +pub enum ID { /// 1-RTT Directory synchronized handshake. Fast, no forward secrecy #[strum(serialize = "directory_synchronized")] DirectorySynchronized = 0, @@ -67,7 +68,7 @@ pub enum HandshakeID { #[strum(serialize = "stateless")] Stateless, } -impl HandshakeID { +impl ID { /// The length of the serialized field pub const fn len() -> usize { 1 @@ -75,28 +76,28 @@ impl HandshakeID { } /// Parsed handshake #[derive(Debug, Clone, PartialEq)] -pub enum HandshakeData { +pub enum Data { /// Directory synchronized handhsake DirSync(dirsync::DirSync), } -impl HandshakeData { +impl Data { /// actual length of the handshake data - pub fn len(&self, head_len: HeadLen, tag_len: TagLen) -> usize { + pub fn len(&self, head_len: NonceLen, tag_len: TagLen) -> usize { match self { - HandshakeData::DirSync(d) => d.len(head_len, tag_len), + Data::DirSync(d) => d.len(head_len, tag_len), } } /// Serialize into raw bytes /// NOTE: assumes that there is exactly asa much buffer as needed pub fn serialize( &self, - head_len: HeadLen, + head_len: NonceLen, tag_len: TagLen, out: &mut [u8], ) { match self { - HandshakeData::DirSync(d) => d.serialize(head_len, tag_len, out), + Data::DirSync(d) => d.serialize(head_len, tag_len, out), } } } @@ -133,19 +134,19 @@ pub struct Handshake { /// Fenrir Protocol version pub fenrir_version: ProtocolVersion, /// enum for the parsed data - pub data: HandshakeData, + pub data: Data, } impl Handshake { /// Build new handshake from the data - pub fn new(data: HandshakeData) -> Self { + pub fn new(data: Data) -> Self { Handshake { fenrir_version: ProtocolVersion::V0, data, } } /// return the total length of the handshake - pub fn len(&self, head_len: HeadLen, tag_len: TagLen) -> usize { + pub fn len(&self, head_len: NonceLen, tag_len: TagLen) -> usize { ProtocolVersion::len() + HandshakeKind::len() + self.data.len(head_len, tag_len) @@ -179,13 +180,13 @@ impl Handshake { /// NOTE: assumes that there is exactly as much buffer as needed pub fn serialize( &self, - head_len: HeadLen, + head_len: NonceLen, tag_len: TagLen, out: &mut [u8], ) { out[0] = self.fenrir_version as u8; out[1] = match &self.data { - HandshakeData::DirSync(d) => match d { + Data::DirSync(d) => match d { dirsync::DirSync::Req(_) => HandshakeKind::DirSyncReq, dirsync::DirSync::Resp(_) => HandshakeKind::DirSyncResp, }, @@ -194,6 +195,6 @@ impl Handshake { } } -trait HandshakeParsing { - fn deserialize(raw: &[u8]) -> Result; +trait Parsing { + fn deserialize(raw: &[u8]) -> Result; } diff --git a/src/connection/handshake/tests.rs b/src/connection/handshake/tests.rs index 83cacfd..d8eff42 100644 --- a/src/connection/handshake/tests.rs +++ b/src/connection/handshake/tests.rs @@ -1,13 +1,16 @@ use crate::{ auth, - connection::{handshake::*, ID}, + connection::{ + handshake::{self, dirsync, Handshake}, + ID, + }, enc::{self, asym::KeyID}, }; #[test] fn test_handshake_dirsync_req() { let rand = enc::Random::new(); - let cipher = enc::sym::CipherKind::XChaCha20Poly1305; + let cipher = enc::sym::Kind::XChaCha20Poly1305; let (_, exchange_key) = match enc::asym::KeyExchangeKind::X25519DiffieHellman.new_keypair(&rand) @@ -19,7 +22,7 @@ fn test_handshake_dirsync_req() { } }; - let data = dirsync::ReqInner::ClearText(dirsync::ReqData { + let data = dirsync::ReqState::ClearText(dirsync::ReqData { nonce: dirsync::Nonce::new(&rand), client_key_id: KeyID(2424), id: ID::ID(::core::num::NonZeroU64::new(424242).unwrap()), @@ -31,16 +34,16 @@ fn test_handshake_dirsync_req() { }, }); - let h_req = Handshake::new(HandshakeData::DirSync(dirsync::DirSync::Req( - dirsync::Req { + let h_req = Handshake::new(handshake::Data::DirSync( + dirsync::DirSync::Req(dirsync::Req { key_id: KeyID(4224), exchange: enc::asym::KeyExchangeKind::X25519DiffieHellman, - hkdf: enc::hkdf::HkdfKind::Sha3, - cipher: enc::sym::CipherKind::XChaCha20Poly1305, + hkdf: enc::hkdf::Kind::Sha3, + cipher: enc::sym::Kind::XChaCha20Poly1305, exchange_key, data, - }, - ))); + }), + )); let mut bytes = Vec::::with_capacity( h_req.len(cipher.nonce_len(), cipher.tag_len()), @@ -55,7 +58,7 @@ fn test_handshake_dirsync_req() { return; } }; - if let HandshakeData::DirSync(dirsync::DirSync::Req(r_a)) = + if let handshake::Data::DirSync(dirsync::DirSync::Req(r_a)) = &mut deserialized.data { let enc_start = r_a.encrypted_offset() + cipher.nonce_len().0; @@ -74,11 +77,11 @@ fn test_handshake_dirsync_req() { #[test] fn test_handshake_dirsync_reqsp() { let rand = enc::Random::new(); - let cipher = enc::sym::CipherKind::XChaCha20Poly1305; + let cipher = enc::sym::Kind::XChaCha20Poly1305; let service_key = enc::Secret::new_rand(&rand); - let data = dirsync::RespInner::ClearText(dirsync::RespData { + let data = dirsync::RespState::ClearText(dirsync::RespData { client_nonce: dirsync::Nonce::new(&rand), id: ID::ID(::core::num::NonZeroU64::new(424242).unwrap()), service_connection_id: ID::ID( @@ -87,7 +90,7 @@ fn test_handshake_dirsync_reqsp() { service_key, }); - let h_resp = Handshake::new(HandshakeData::DirSync( + let h_resp = Handshake::new(handshake::Data::DirSync( dirsync::DirSync::Resp(dirsync::Resp { client_key_id: KeyID(4444), data, @@ -107,7 +110,7 @@ fn test_handshake_dirsync_reqsp() { return; } }; - if let HandshakeData::DirSync(dirsync::DirSync::Resp(r_a)) = + if let handshake::Data::DirSync(dirsync::DirSync::Resp(r_a)) = &mut deserialized.data { let enc_start = r_a.encrypted_offset() + cipher.nonce_len().0; diff --git a/src/connection/handshake/tracker.rs b/src/connection/handshake/tracker.rs index 5da29bb..30a6a8f 100644 --- a/src/connection/handshake/tracker.rs +++ b/src/connection/handshake/tracker.rs @@ -3,22 +3,21 @@ use crate::{ auth::{Domain, ServiceID}, connection::{ - self, handshake::{self, Error, Handshake}, Conn, IDRecv, IDSend, }, enc::{ self, asym::{self, KeyID, PrivKey, PubKey}, - hkdf::{Hkdf, HkdfKind}, - sym::{CipherKind, CipherRecv}, + hkdf::{self, Hkdf}, + sym::{self, CipherRecv}, }, inner::ThreadTracker, }; use ::tokio::sync::oneshot; -pub(crate) struct HandshakeServer { +pub(crate) struct Server { pub id: KeyID, pub key: PrivKey, pub domains: Vec, @@ -26,7 +25,7 @@ pub(crate) struct HandshakeServer { pub(crate) type ConnectAnswer = Result<(KeyID, IDSend), crate::Error>; -pub(crate) struct HandshakeClient { +pub(crate) struct Client { pub service_id: ServiceID, pub service_conn_id: IDRecv, pub connection: Conn, @@ -37,13 +36,13 @@ pub(crate) struct HandshakeClient { /// Tracks the keys used by the client and the handshake /// they are associated with -pub(crate) struct HandshakeClientList { +pub(crate) struct ClientList { used: Vec<::bitmaps::Bitmap<1024>>, // index = KeyID keys: Vec>, - list: Vec>, + list: Vec>, } -impl HandshakeClientList { +impl ClientList { pub(crate) fn new() -> Self { Self { used: [::bitmaps::Bitmap::<1024>::new()].to_vec(), @@ -51,13 +50,13 @@ impl HandshakeClientList { list: Vec::with_capacity(16), } } - pub(crate) fn get(&self, id: KeyID) -> Option<&HandshakeClient> { + pub(crate) fn get(&self, id: KeyID) -> Option<&Client> { if id.0 as usize >= self.list.len() { return None; } self.list[id.0 as usize].as_ref() } - pub(crate) fn remove(&mut self, id: KeyID) -> Option { + pub(crate) fn remove(&mut self, id: KeyID) -> Option { if id.0 as usize >= self.list.len() { return None; } @@ -82,8 +81,7 @@ impl HandshakeClientList { connection: Conn, answer: oneshot::Sender, srv_key_id: KeyID, - ) -> Result<(KeyID, &mut HandshakeClient), oneshot::Sender> - { + ) -> Result<(KeyID, &mut Client), oneshot::Sender> { let maybe_free_key_idx = self.used.iter().enumerate().find_map(|(idx, bmap)| { match bmap.first_false_index() { @@ -112,7 +110,7 @@ impl HandshakeClientList { self.list.push(None); } self.keys[free_key_idx] = Some((priv_key, pub_key)); - self.list[free_key_idx] = Some(HandshakeClient { + self.list[free_key_idx] = Some(Client { service_id, service_conn_id, connection, @@ -153,7 +151,7 @@ pub(crate) struct ClientConnectInfo { } /// Intermediate actions to be taken while parsing the handshake #[derive(Debug)] -pub(crate) enum HandshakeAction { +pub(crate) enum Action { /// Parsing finished, all ok, nothing to do Nothing, /// Packet parsed, now go perform authentication @@ -167,20 +165,20 @@ pub(crate) enum HandshakeAction { /// Each of them will handle a subset of all handshakes. /// Each handshake is routed to a different tracker by checking /// core = (udp_src_sender_port % total_threads) - 1 -pub(crate) struct HandshakeTracker { +pub(crate) struct Tracker { thread_id: ThreadTracker, key_exchanges: Vec, - ciphers: Vec, + ciphers: Vec, /// ephemeral keys used server side in key exchange - keys_srv: Vec, + keys_srv: Vec, /// ephemeral keys used client side in key exchange - hshake_cli: HandshakeClientList, + hshake_cli: ClientList, } -impl HandshakeTracker { +impl Tracker { pub(crate) fn new( thread_id: ThreadTracker, - ciphers: Vec, + ciphers: Vec, key_exchanges: Vec, ) -> Self { Self { @@ -188,7 +186,7 @@ impl HandshakeTracker { ciphers, key_exchanges, keys_srv: Vec::new(), - hshake_cli: HandshakeClientList::new(), + hshake_cli: ClientList::new(), } } pub(crate) fn add_server_key( @@ -199,7 +197,7 @@ impl HandshakeTracker { if self.keys_srv.iter().find(|&k| k.id == id).is_some() { return Err(()); } - self.keys_srv.push(HandshakeServer { + self.keys_srv.push(Server { id, key, domains: Vec::new(), @@ -236,8 +234,7 @@ impl HandshakeTracker { connection: Conn, answer: oneshot::Sender, srv_key_id: KeyID, - ) -> Result<(KeyID, &mut HandshakeClient), oneshot::Sender> - { + ) -> Result<(KeyID, &mut Client), oneshot::Sender> { self.hshake_cli.add( priv_key, pub_key, @@ -248,10 +245,7 @@ impl HandshakeTracker { srv_key_id, ) } - pub(crate) fn remove_client( - &mut self, - key_id: KeyID, - ) -> Option { + pub(crate) fn remove_client(&mut self, key_id: KeyID) -> Option { self.hshake_cli.remove(key_id) } pub(crate) fn timeout_client( @@ -269,10 +263,10 @@ impl HandshakeTracker { &mut self, mut handshake: Handshake, handshake_raw: &mut [u8], - ) -> Result { - use connection::handshake::{dirsync::DirSync, HandshakeData}; + ) -> Result { + use handshake::dirsync::DirSync; match handshake.data { - HandshakeData::DirSync(ref mut ds) => match ds { + handshake::Data::DirSync(ref mut ds) => match ds { DirSync::Req(ref mut req) => { if !self.key_exchanges.contains(&req.exchange) { return Err(enc::Error::UnsupportedKeyExchange.into()); @@ -310,7 +304,8 @@ impl HandshakeTracker { Ok(shared_key) => shared_key, Err(e) => return Err(handshake::Error::Key(e).into()), }; - let hkdf = Hkdf::new(HkdfKind::Sha3, b"fenrir", shared_key); + let hkdf = + Hkdf::new(hkdf::Kind::Sha3, b"fenrir", shared_key); let secret_recv = hkdf.get_secret(b"to_server"); let cipher_recv = CipherRecv::new(req.cipher, secret_recv); use crate::enc::sym::AAD; @@ -334,7 +329,7 @@ impl HandshakeTracker { } } - return Ok(HandshakeAction::AuthNeeded(AuthNeededInfo { + return Ok(Action::AuthNeeded(AuthNeededInfo { handshake, hkdf, })); @@ -374,16 +369,14 @@ impl HandshakeTracker { if let Some(timeout) = hshake.timeout { timeout.abort(); } - return Ok(HandshakeAction::ClientConnect( - ClientConnectInfo { - service_id: hshake.service_id, - service_connection_id: hshake.service_conn_id, - handshake, - connection: hshake.connection, - answer: hshake.answer, - srv_key_id: hshake.srv_key_id, - }, - )); + return Ok(Action::ClientConnect(ClientConnectInfo { + service_id: hshake.service_id, + service_connection_id: hshake.service_conn_id, + handshake, + connection: hshake.connection, + answer: hshake.answer, + srv_key_id: hshake.srv_key_id, + })); } }, } diff --git a/src/connection/mod.rs b/src/connection/mod.rs index 2889381..f6c0a86 100644 --- a/src/connection/mod.rs +++ b/src/connection/mod.rs @@ -14,7 +14,7 @@ use crate::{ enc::{ asym::PubKey, hkdf::Hkdf, - sym::{CipherKind, CipherRecv, CipherSend}, + sym::{self, CipherRecv, CipherSend}, Random, }, inner::ThreadTracker, @@ -163,7 +163,7 @@ pub enum Role { impl Conn { pub(crate) fn new( hkdf: Hkdf, - cipher: CipherKind, + cipher: sym::Kind, role: Role, rand: &Random, ) -> Self { diff --git a/src/connection/packet.rs b/src/connection/packet.rs index 545c882..d501fd4 100644 --- a/src/connection/packet.rs +++ b/src/connection/packet.rs @@ -3,7 +3,7 @@ use crate::{ connection, - enc::sym::{HeadLen, TagLen}, + enc::sym::{NonceLen, TagLen}, }; /// Enumerate the possible data in a fenrir packet @@ -17,7 +17,7 @@ pub enum Data { impl Data { /// total length of the data in bytes - pub fn len(&self, head_len: HeadLen, tag_len: TagLen) -> usize { + pub fn len(&self, head_len: NonceLen, tag_len: TagLen) -> usize { match self { Data::Handshake(h) => h.len(head_len, tag_len), Data::Raw(len) => *len, @@ -27,7 +27,7 @@ impl Data { /// NOTE: assumes that there is exactly asa much buffer as needed pub fn serialize( &self, - head_len: HeadLen, + head_len: NonceLen, tag_len: TagLen, out: &mut [u8], ) { @@ -69,14 +69,14 @@ impl Packet { }) } /// get the total length of the packet - pub fn len(&self, head_len: HeadLen, tag_len: TagLen) -> usize { + pub fn len(&self, head_len: NonceLen, tag_len: TagLen) -> usize { connection::ID::len() + self.data.len(head_len, tag_len) } /// serialize packet into buffer /// NOTE: assumes that there is exactly asa much buffer as needed pub fn serialize( &self, - head_len: HeadLen, + head_len: NonceLen, tag_len: TagLen, out: &mut [u8], ) { diff --git a/src/dnssec/record.rs b/src/dnssec/record.rs index a995cea..638ec68 100644 --- a/src/dnssec/record.rs +++ b/src/dnssec/record.rs @@ -43,12 +43,11 @@ //! ] use crate::{ - connection::handshake::HandshakeID, + connection::handshake, enc::{ self, asym::{KeyExchangeKind, KeyID, PubKey}, - hkdf::HkdfKind, - sym::CipherKind, + hkdf, sym, }, }; use ::core::num::NonZeroU16; @@ -180,7 +179,7 @@ pub struct Address { /// Weight of this address in the priority group pub weight: AddressWeight, /// List of supported handshakes - pub handshake_ids: Vec, + pub handshake_ids: Vec, /// Public key IDs used by this address pub public_key_idx: Vec, } @@ -331,7 +330,7 @@ impl Address { for raw_handshake_id in raw[bytes_parsed..(bytes_parsed + num_handshake_ids)].iter() { - match HandshakeID::from_u8(*raw_handshake_id) { + match handshake::ID::from_u8(*raw_handshake_id) { Some(h_id) => handshake_ids.push(h_id), None => { ::tracing::warn!( @@ -392,9 +391,9 @@ pub struct Record { /// List of supported key exchanges pub key_exchanges: Vec, /// List of supported key exchanges - pub hkdfs: Vec, + pub hkdfs: Vec, /// List of supported ciphers - pub ciphers: Vec, + pub ciphers: Vec, } impl Record { @@ -597,7 +596,7 @@ impl Record { num_key_exchanges = num_key_exchanges - 1; } while num_hkdfs > 0 { - let hkdf = match HkdfKind::from_u8(raw[bytes_parsed]) { + let hkdf = match hkdf::Kind::from_u8(raw[bytes_parsed]) { Some(hkdf) => hkdf, None => { // continue parsing. This could be a new hkdf type @@ -615,7 +614,7 @@ impl Record { num_hkdfs = num_hkdfs - 1; } while num_ciphers > 0 { - let cipher = match CipherKind::from_u8(raw[bytes_parsed]) { + let cipher = match sym::Kind::from_u8(raw[bytes_parsed]) { Some(cipher) => cipher, None => { // continue parsing. This could be a new cipher type diff --git a/src/dnssec/tests.rs b/src/dnssec/tests.rs index ff450ae..04cbb18 100644 --- a/src/dnssec/tests.rs +++ b/src/dnssec/tests.rs @@ -12,7 +12,7 @@ fn test_dnssec_serialization() { return; } }; - use crate::{connection::handshake::HandshakeID, enc}; + use crate::{connection::handshake, enc}; let record = Record { public_keys: [( @@ -25,14 +25,14 @@ fn test_dnssec_serialization() { port: Some(::core::num::NonZeroU16::new(31337).unwrap()), priority: record::AddressPriority::P1, weight: record::AddressWeight::W1, - handshake_ids: [HandshakeID::DirectorySynchronized].to_vec(), + handshake_ids: [handshake::ID::DirectorySynchronized].to_vec(), public_key_idx: [record::PubKeyIdx(0)].to_vec(), }] .to_vec(), key_exchanges: [enc::asym::KeyExchangeKind::X25519DiffieHellman] .to_vec(), - hkdfs: [enc::hkdf::HkdfKind::Sha3].to_vec(), - ciphers: [enc::sym::CipherKind::XChaCha20Poly1305].to_vec(), + hkdfs: [enc::hkdf::Kind::Sha3].to_vec(), + ciphers: [enc::sym::Kind::XChaCha20Poly1305].to_vec(), }; let encoded = match record.encode() { Ok(encoded) => encoded, diff --git a/src/enc/asym.rs b/src/enc/asym.rs index 47a3b5a..4958a38 100644 --- a/src/enc/asym.rs +++ b/src/enc/asym.rs @@ -45,7 +45,7 @@ impl ::std::fmt::Display for KeyID { /// Capabilities of each key #[derive(Debug, Clone, Copy)] -pub enum KeyCapabilities { +pub enum Capabilities { /// signing *only* Sign, /// encrypt *only* @@ -61,13 +61,13 @@ pub enum KeyCapabilities { /// All: sign, encrypt, Key Exchange SignEncryptExchage, } -impl KeyCapabilities { +impl Capabilities { /// Check if this key supports eky exchage pub fn has_exchange(&self) -> bool { match self { - KeyCapabilities::Exchange - | KeyCapabilities::SignExchange - | KeyCapabilities::SignEncryptExchage => true, + Capabilities::Exchange + | Capabilities::SignExchange + | Capabilities::SignEncryptExchage => true, _ => false, } } @@ -85,7 +85,7 @@ impl KeyCapabilities { )] #[non_exhaustive] #[repr(u8)] -pub enum KeyKind { +pub enum Kind { /// Ed25519 Public key (sign only) #[strum(serialize = "ed25519")] Ed25519 = 0, @@ -93,25 +93,25 @@ pub enum KeyKind { #[strum(serialize = "x25519")] X25519, } -impl KeyKind { +impl Kind { /// Length of the serialized field pub const fn len() -> usize { 1 } /// return the expected length of the public key pub fn pub_len(&self) -> usize { - KeyKind::len() + Kind::len() + match self { // FIXME: 99% wrong size - KeyKind::Ed25519 => ::ring::signature::ED25519_PUBLIC_KEY_LEN, - KeyKind::X25519 => 32, + Kind::Ed25519 => ::ring::signature::ED25519_PUBLIC_KEY_LEN, + Kind::X25519 => 32, } } /// Get the capabilities of this key type - pub fn capabilities(&self) -> KeyCapabilities { + pub fn capabilities(&self) -> Capabilities { match self { - KeyKind::Ed25519 => KeyCapabilities::Sign, - KeyKind::X25519 => KeyCapabilities::Exchange, + Kind::Ed25519 => Capabilities::Sign, + Kind::X25519 => Capabilities::Exchange, } } /// Returns the key exchanges supported by this key @@ -120,8 +120,8 @@ impl KeyKind { const X25519_KEY_EXCHANGES: [KeyExchangeKind; 1] = [KeyExchangeKind::X25519DiffieHellman]; match self { - KeyKind::Ed25519 => &EMPTY, - KeyKind::X25519 => &X25519_KEY_EXCHANGES, + Kind::Ed25519 => &EMPTY, + Kind::X25519 => &X25519_KEY_EXCHANGES, } } /// generate new keypair @@ -193,21 +193,21 @@ impl PubKey { } } /// return the kind of public key - pub fn kind(&self) -> KeyKind { + pub fn kind(&self) -> Kind { match self { // FIXME: lie, we don't fully support this - PubKey::Signing => KeyKind::Ed25519, + PubKey::Signing => Kind::Ed25519, PubKey::Exchange(ex) => ex.kind(), } } /// generate new keypair fn new_keypair( - kind: KeyKind, + kind: Kind, rnd: &Random, ) -> Result<(PrivKey, PubKey), Error> { match kind { - KeyKind::Ed25519 => todo!(), - KeyKind::X25519 => { + Kind::Ed25519 => todo!(), + Kind::X25519 => { let (priv_key, pub_key) = KeyExchangeKind::X25519DiffieHellman.new_keypair(rnd)?; Ok((PrivKey::Exchange(priv_key), PubKey::Exchange(pub_key))) @@ -231,7 +231,7 @@ impl PubKey { if raw.len() < 1 { return Err(Error::NotEnoughData(0)); } - let kind: KeyKind = match KeyKind::from_u8(raw[0]) { + let kind: Kind = match Kind::from_u8(raw[0]) { Some(kind) => kind, None => return Err(Error::UnsupportedKey(1)), }; @@ -239,11 +239,11 @@ impl PubKey { return Err(Error::NotEnoughData(1)); } match kind { - KeyKind::Ed25519 => { + Kind::Ed25519 => { ::tracing::error!("ed25519 keys are not yet supported"); return Err(Error::Parsing); } - KeyKind::X25519 => { + Kind::X25519 => { let pub_key: ::x25519_dalek::PublicKey = //match ::bincode::deserialize(&raw[1..(1 + kind.pub_len())]) match ::bincode::deserialize(&raw[1..]) @@ -284,7 +284,7 @@ impl PrivKey { } } /// return the kind of public key - pub fn kind(&self) -> KeyKind { + pub fn kind(&self) -> Kind { match self { PrivKey::Signing => todo!(), PrivKey::Exchange(ex) => ex.kind(), @@ -322,13 +322,13 @@ impl ExchangePrivKey { /// Get the serialized key length pub fn len(&self) -> usize { match self { - ExchangePrivKey::X25519(_) => KeyKind::X25519.pub_len(), + ExchangePrivKey::X25519(_) => Kind::X25519.pub_len(), } } /// Get the kind of key - pub fn kind(&self) -> KeyKind { + pub fn kind(&self) -> Kind { match self { - ExchangePrivKey::X25519(_) => KeyKind::X25519, + ExchangePrivKey::X25519(_) => Kind::X25519, } } /// Run the key exchange between two keys of the same kind @@ -372,13 +372,13 @@ impl ExchangePubKey { /// Get the serialized key length pub fn len(&self) -> usize { match self { - ExchangePubKey::X25519(_) => KeyKind::X25519.pub_len(), + ExchangePubKey::X25519(_) => Kind::X25519.pub_len(), } } /// Get the kind of key - pub fn kind(&self) -> KeyKind { + pub fn kind(&self) -> Kind { match self { - ExchangePubKey::X25519(_) => KeyKind::X25519, + ExchangePubKey::X25519(_) => Kind::X25519, } } /// serialize the key into the buffer @@ -396,13 +396,13 @@ impl ExchangePubKey { /// The riesult is "unparsed" since we don't verify /// the actual key pub fn deserialize(raw: &[u8]) -> Result<(Self, usize), Error> { - match KeyKind::from_u8(raw[0]) { + match Kind::from_u8(raw[0]) { Some(kind) => match kind { - KeyKind::Ed25519 => { + Kind::Ed25519 => { ::tracing::error!("ed25519 keys are not yet supported"); return Err(Error::Parsing); } - KeyKind::X25519 => { + Kind::X25519 => { let pub_key: ::x25519_dalek::PublicKey = match ::bincode::deserialize( &raw[1..(1 + kind.pub_len())], diff --git a/src/enc/hkdf.rs b/src/enc/hkdf.rs index e52e236..7ba885b 100644 --- a/src/enc/hkdf.rs +++ b/src/enc/hkdf.rs @@ -18,12 +18,12 @@ use crate::{config::Config, enc::Secret}; )] #[non_exhaustive] #[repr(u8)] -pub enum HkdfKind { +pub enum Kind { /// Sha3 #[strum(serialize = "sha3")] Sha3 = 0, } -impl HkdfKind { +impl Kind { /// Length of the serialized type pub const fn len() -> usize { 1 @@ -34,7 +34,7 @@ impl HkdfKind { #[derive(Clone)] pub enum Hkdf { /// Sha3 based - Sha3(HkdfSha3), + Sha3(Sha3), } // Fake debug implementation to avoid leaking secrets @@ -49,9 +49,9 @@ impl ::core::fmt::Debug for Hkdf { impl Hkdf { /// New Hkdf - pub fn new(kind: HkdfKind, salt: &[u8], key: Secret) -> Self { + pub fn new(kind: Kind, salt: &[u8], key: Secret) -> Self { match kind { - HkdfKind::Sha3 => Self::Sha3(HkdfSha3::new(salt, key)), + Kind::Sha3 => Self::Sha3(Sha3::new(salt, key)), } } /// Get a secret generated from the key and a given context @@ -61,9 +61,9 @@ impl Hkdf { } } /// get the kind of this Hkdf - pub fn kind(&self) -> HkdfKind { + pub fn kind(&self) -> Kind { match self { - Hkdf::Sha3(_) => HkdfKind::Sha3, + Hkdf::Sha3(_) => Kind::Sha3, } } } @@ -106,11 +106,11 @@ impl Clone for HkdfInner { /// Sha3 based HKDF #[derive(Clone)] -pub struct HkdfSha3 { +pub struct Sha3 { inner: HkdfInner, } -impl HkdfSha3 { +impl Sha3 { /// Instantiate a new HKDF with Sha3-256 pub(crate) fn new(salt: &[u8], key: Secret) -> Self { let hkdf = ::hkdf::Hkdf::::new(Some(salt), key.as_ref()); @@ -132,7 +132,7 @@ impl HkdfSha3 { } // Fake debug implementation to avoid leaking secrets -impl ::core::fmt::Debug for HkdfSha3 { +impl ::core::fmt::Debug for Sha3 { fn fmt( &self, f: &mut core::fmt::Formatter<'_>, @@ -146,8 +146,8 @@ impl ::core::fmt::Debug for HkdfSha3 { /// Give priority to our list pub fn server_select_hkdf( cfg: &Config, - client_supported: &Vec, -) -> Option { + client_supported: &Vec, +) -> Option { cfg.hkdfs .iter() .find(|h| client_supported.contains(h)) @@ -159,8 +159,8 @@ pub fn server_select_hkdf( /// this is used only in the directory synchronized handshake pub fn client_select_hkdf( cfg: &Config, - server_supported: &Vec, -) -> Option { + server_supported: &Vec, +) -> Option { server_supported .iter() .find(|h| cfg.hkdfs.contains(h)) diff --git a/src/enc/sym.rs b/src/enc/sym.rs index d4204e0..14d712d 100644 --- a/src/enc/sym.rs +++ b/src/enc/sym.rs @@ -17,20 +17,20 @@ use crate::{ ::strum_macros::IntoStaticStr, )] #[repr(u8)] -pub enum CipherKind { +pub enum Kind { /// XChaCha20_Poly1305 #[strum(serialize = "xchacha20poly1305")] XChaCha20Poly1305 = 0, } -impl CipherKind { +impl Kind { /// length of the serialized id for the cipher kind field pub const fn len() -> usize { 1 } /// required length of the nonce - pub fn nonce_len(&self) -> HeadLen { - HeadLen(Nonce::len()) + pub fn nonce_len(&self) -> NonceLen { + Nonce::len() } /// required length of the key pub fn key_len(&self) -> usize { @@ -48,21 +48,10 @@ impl CipherKind { #[derive(Debug)] pub struct AAD<'a>(pub &'a [u8]); -/// Cipher direction, to make sure we don't reuse the same cipher -/// for both decrypting and encrypting -#[derive(Debug, Copy, Clone)] -#[repr(u8)] -pub enum CipherDirection { - /// Receive, to decrypt only - Recv = 0, - /// Send, to encrypt only - Send, -} - /// strong typedef for header length /// aka: nonce length in the encrypted data) #[derive(Debug, Copy, Clone)] -pub struct HeadLen(pub usize); +pub struct NonceLen(pub usize); /// strong typedef for the Tag length /// aka: cryptographic authentication tag length at the end /// of the encrypted data @@ -77,21 +66,21 @@ enum Cipher { impl Cipher { /// Build a new Cipher - fn new(kind: CipherKind, secret: Secret) -> Self { + fn new(kind: Kind, secret: Secret) -> Self { match kind { - CipherKind::XChaCha20Poly1305 => { + Kind::XChaCha20Poly1305 => { Self::XChaCha20Poly1305(XChaCha20Poly1305::new(secret)) } } } - pub fn kind(&self) -> CipherKind { + pub fn kind(&self) -> Kind { match self { - Cipher::XChaCha20Poly1305(_) => CipherKind::XChaCha20Poly1305, + Cipher::XChaCha20Poly1305(_) => Kind::XChaCha20Poly1305, } } - fn nonce_len(&self) -> HeadLen { + fn nonce_len(&self) -> NonceLen { match self { - Cipher::XChaCha20Poly1305(_) => HeadLen(Nonce::len()), + Cipher::XChaCha20Poly1305(_) => Nonce::len(), } } fn tag_len(&self) -> TagLen { @@ -117,7 +106,7 @@ impl Cipher { return Err(Error::NotEnoughData(raw_data.len())); } let (nonce_bytes, data_and_tag) = - raw_data.split_at_mut(Nonce::len()); + raw_data.split_at_mut(Nonce::len().0); let (data_notag, tag_bytes) = data_and_tag.split_at_mut( data_and_tag.len() - ::ring::aead::CHACHA20_POLY1305.tag_len(), @@ -137,20 +126,20 @@ impl Cipher { }; //data.drain(..Nonce::len()); //data.truncate(final_len); - Ok(&raw_data[Nonce::len()..Nonce::len() + final_len]) + Ok(&raw_data[Nonce::len().0..Nonce::len().0 + final_len]) } } } fn overhead(&self) -> usize { match self { Cipher::XChaCha20Poly1305(_) => { - let cipher = CipherKind::XChaCha20Poly1305; + let cipher = Kind::XChaCha20Poly1305; cipher.nonce_len().0 + cipher.tag_len().0 } } } fn encrypt( - &self, + &mut self, nonce: &Nonce, aad: AAD, data: &mut [u8], @@ -162,13 +151,13 @@ impl Cipher { let tag_len: usize = ::ring::aead::CHACHA20_POLY1305.tag_len(); let data_len_notag = data.len() - tag_len; // write nonce - data[..Nonce::len()].copy_from_slice(nonce.as_bytes()); + data[..Nonce::len().0].copy_from_slice(nonce.as_bytes()); // encrypt data match cipher.cipher.encrypt_in_place_detached( nonce.as_bytes().into(), aad.0, - &mut data[Nonce::len()..data_len_notag], + &mut data[Nonce::len().0..data_len_notag], ) { Ok(tag) => { data[data_len_notag..].copy_from_slice(tag.as_slice()); @@ -194,11 +183,11 @@ impl ::core::fmt::Debug for CipherRecv { impl CipherRecv { /// Build a new Cipher - pub fn new(kind: CipherKind, secret: Secret) -> Self { + pub fn new(kind: Kind, secret: Secret) -> Self { Self(Cipher::new(kind, secret)) } /// Get the length of the nonce for this cipher - pub fn nonce_len(&self) -> HeadLen { + pub fn nonce_len(&self) -> NonceLen { self.0.nonce_len() } /// Get the length of the nonce for this cipher @@ -215,14 +204,14 @@ impl CipherRecv { self.0.decrypt(aad, data) } /// return the underlying cipher id - pub fn kind(&self) -> CipherKind { + pub fn kind(&self) -> Kind { self.0.kind() } } /// Send only cipher pub struct CipherSend { - nonce: NonceSync, + nonce: Nonce, cipher: Cipher, } impl ::core::fmt::Debug for CipherSend { @@ -236,20 +225,20 @@ impl ::core::fmt::Debug for CipherSend { impl CipherSend { /// Build a new Cipher - pub fn new(kind: CipherKind, secret: Secret, rand: &Random) -> Self { + pub fn new(kind: Kind, secret: Secret, rand: &Random) -> Self { Self { - nonce: NonceSync::new(rand), + nonce: Nonce::new(rand), cipher: Cipher::new(kind, secret), } } /// Encrypt the given data - pub fn encrypt(&self, aad: AAD, data: &mut [u8]) -> Result<(), Error> { + pub fn encrypt(&mut self, aad: AAD, data: &mut [u8]) -> Result<(), Error> { let old_nonce = self.nonce.advance(); self.cipher.encrypt(&old_nonce, aad, data)?; Ok(()) } /// return the underlying cipher id - pub fn kind(&self) -> CipherKind { + pub fn kind(&self) -> Kind { self.cipher.kind() } } @@ -285,7 +274,7 @@ struct NonceNum { #[repr(C)] pub union Nonce { num: NonceNum, - raw: [u8; Self::len()], + raw: [u8; Self::len().0], } impl ::core::fmt::Debug for Nonce { @@ -303,17 +292,17 @@ impl ::core::fmt::Debug for Nonce { impl Nonce { /// Generate a new random Nonce pub fn new(rand: &Random) -> Self { - let mut raw = [0; Self::len()]; + let mut raw = [0; Self::len().0]; rand.fill(&mut raw); Self { raw } } /// Length of this nonce in bytes - pub const fn len() -> usize { + pub const fn len() -> NonceLen { // FIXME: was:12. xchacha20poly1305 requires 24. // but we should change keys much earlier than that, and our // nonces are not random, but sequential. // we should change keys every 2^30 bytes to be sure (stream max window) - return 24; + return NonceLen(24); } /// Get reference to the nonce bytes pub fn as_bytes(&self) -> &[u8] { @@ -323,11 +312,12 @@ impl Nonce { } } /// Create Nonce from array - pub fn from_slice(raw: [u8; Self::len()]) -> Self { + pub fn from_slice(raw: [u8; Self::len().0]) -> Self { Self { raw } } /// Go to the next nonce - pub fn advance(&mut self) { + pub fn advance(&mut self) -> Self { + let old_nonce = self.clone(); #[allow(unsafe_code)] unsafe { let old_low = self.num.low; @@ -336,40 +326,17 @@ impl Nonce { self.num.high = self.num.high; } } - } -} - -/// Synchronize the mutex acess with a nonce for multithread safety -// TODO: remove mutex, not needed anymore -#[derive(Debug)] -pub struct NonceSync { - nonce: ::std::sync::Mutex, -} -impl NonceSync { - /// Create a new thread safe nonce - pub fn new(rand: &Random) -> Self { - Self { - nonce: ::std::sync::Mutex::new(Nonce::new(rand)), - } - } - /// Advance the nonce and return the *old* value - pub fn advance(&self) -> Nonce { - let old_nonce: Nonce; - { - let mut nonce = self.nonce.lock().unwrap(); - old_nonce = *nonce; - nonce.advance(); - } old_nonce } } + /// Select the best cipher from our supported list /// and the other endpoint supported list. /// Give priority to our list pub fn server_select_cipher( cfg: &Config, - client_supported: &Vec, -) -> Option { + client_supported: &Vec, +) -> Option { cfg.ciphers .iter() .find(|c| client_supported.contains(c)) @@ -381,8 +348,8 @@ pub fn server_select_cipher( /// This is used only in the Directory synchronized handshake pub fn client_select_cipher( cfg: &Config, - server_supported: &Vec, -) -> Option { + server_supported: &Vec, +) -> Option { server_supported .iter() .find(|c| cfg.ciphers.contains(c)) diff --git a/src/enc/tests.rs b/src/enc/tests.rs index ead07ee..af2ddef 100644 --- a/src/enc/tests.rs +++ b/src/enc/tests.rs @@ -1,24 +1,26 @@ use crate::{ - auth, - connection::{handshake::*, ID}, + connection::{ + handshake::{self, *}, + ID, + }, enc::{self, asym::KeyID}, }; #[test] fn test_simple_encrypt_decrypt() { let rand = enc::Random::new(); - let cipher = enc::sym::CipherKind::XChaCha20Poly1305; + let cipher = enc::sym::Kind::XChaCha20Poly1305; let secret = enc::Secret::new_rand(&rand); let secret2 = secret.clone(); - let cipher_send = enc::sym::CipherSend::new(cipher, secret, &rand); + let mut cipher_send = enc::sym::CipherSend::new(cipher, secret, &rand); let cipher_recv = enc::sym::CipherRecv::new(cipher, secret2); let mut data = Vec::new(); let tot_len = cipher_recv.nonce_len().0 + 1234 + cipher_recv.tag_len().0; data.resize(tot_len, 0); rand.fill(&mut data); - data[..enc::sym::Nonce::len()].copy_from_slice(&[0; 24]); + data[..enc::sym::Nonce::len().0].copy_from_slice(&[0; 24]); let last = data.len() - cipher_recv.tag_len().0; data[last..].copy_from_slice(&[0; 16]); let orig = data.clone(); @@ -31,7 +33,7 @@ fn test_simple_encrypt_decrypt() { if cipher_recv.decrypt(aad2, &mut data).is_err() { assert!(false, "Decrypt failed"); } - data[..enc::sym::Nonce::len()].copy_from_slice(&[0; 24]); + data[..enc::sym::Nonce::len().0].copy_from_slice(&[0; 24]); let last = data.len() - cipher_recv.tag_len().0; data[last..].copy_from_slice(&[0; 16]); assert!(orig == data, "DIFFERENT!\n{:?}\n{:?}\n", orig, data); @@ -40,18 +42,18 @@ fn test_simple_encrypt_decrypt() { #[test] fn test_encrypt_decrypt() { let rand = enc::Random::new(); - let cipher = enc::sym::CipherKind::XChaCha20Poly1305; + let cipher = enc::sym::Kind::XChaCha20Poly1305; let secret = enc::Secret::new_rand(&rand); let secret2 = secret.clone(); - let cipher_send = enc::sym::CipherSend::new(cipher, secret, &rand); + let mut cipher_send = enc::sym::CipherSend::new(cipher, secret, &rand); let cipher_recv = enc::sym::CipherRecv::new(cipher, secret2); let nonce_len = cipher_recv.nonce_len(); let tag_len = cipher_recv.tag_len(); let service_key = enc::Secret::new_rand(&rand); - let data = dirsync::RespInner::ClearText(dirsync::RespData { + let data = dirsync::RespState::ClearText(dirsync::RespData { client_nonce: dirsync::Nonce::new(&rand), id: ID::ID(::core::num::NonZeroU64::new(424242).unwrap()), service_connection_id: ID::ID( @@ -68,7 +70,7 @@ fn test_encrypt_decrypt() { let encrypt_to = encrypt_from + resp.encrypted_length(nonce_len, tag_len); let h_resp = - Handshake::new(HandshakeData::DirSync(dirsync::DirSync::Resp(resp))); + Handshake::new(handshake::Data::DirSync(dirsync::DirSync::Resp(resp))); let mut bytes = Vec::::with_capacity( h_resp.len(cipher.nonce_len(), cipher.tag_len()), @@ -117,7 +119,7 @@ fn test_encrypt_decrypt() { } }; // reparse - if let HandshakeData::DirSync(dirsync::DirSync::Resp(r_a)) = + if let handshake::Data::DirSync(dirsync::DirSync::Resp(r_a)) = &mut deserialized.data { let enc_start = r_a.encrypted_offset() + cipher.nonce_len().0; diff --git a/src/inner/worker.rs b/src/inner/worker.rs index cdd5d75..80176ca 100644 --- a/src/inner/worker.rs +++ b/src/inner/worker.rs @@ -7,8 +7,7 @@ use crate::{ handshake::{ self, dirsync::{self, DirSync}, - tracker::{HandshakeAction, HandshakeTracker}, - Handshake, HandshakeData, + Handshake, }, packet::{self, Packet}, socket::{UdpClient, UdpServer}, @@ -17,7 +16,7 @@ use crate::{ dnssec, enc::{ asym::{self, KeyID, PrivKey, PubKey}, - hkdf::{self, Hkdf, HkdfKind}, + hkdf::{self, Hkdf}, sym, Random, Secret, }, inner::ThreadTracker, @@ -69,7 +68,7 @@ pub struct Worker { queue_timeouts_send: mpsc::UnboundedSender, thread_channels: Vec<::async_channel::Sender>, connections: ConnList, - handshakes: HandshakeTracker, + handshakes: handshake::Tracker, } #[allow(unsafe_code)] @@ -86,7 +85,7 @@ impl Worker { ) -> ::std::io::Result { let (queue_timeouts_send, queue_timeouts_recv) = mpsc::unbounded_channel(); - let mut handshakes = HandshakeTracker::new( + let mut handshakes = handshake::Tracker::new( thread_id, cfg.ciphers.clone(), cfg.key_exchanges.clone(), @@ -345,7 +344,7 @@ impl Worker { hkdf: hkdf_selected, cipher: cipher_selected, exchange_key: pub_key, - data: dirsync::ReqInner::ClearText(req_data), + data: dirsync::ReqState::ClearText(req_data), }; let encrypt_start = connection::ID::len() + req.encrypted_offset(); @@ -354,7 +353,7 @@ impl Worker { cipher_selected.nonce_len(), cipher_selected.tag_len(), ); - let h_req = Handshake::new(HandshakeData::DirSync( + let h_req = Handshake::new(handshake::Data::DirSync( DirSync::Req(req), )); let packet = Packet { @@ -450,9 +449,9 @@ impl Worker { } }; match action { - HandshakeAction::AuthNeeded(authinfo) => { + handshake::Action::AuthNeeded(authinfo) => { let req; - if let HandshakeData::DirSync(DirSync::Req(r)) = + if let handshake::Data::DirSync(DirSync::Req(r)) = authinfo.handshake.data { req = r; @@ -460,9 +459,9 @@ impl Worker { ::tracing::error!("AuthInfo on non DS::Req"); return; } - use dirsync::ReqInner; + use dirsync::ReqState; let req_data = match req.data { - ReqInner::ClearText(req_data) => req_data, + ReqState::ClearText(req_data) => req_data, _ => { ::tracing::error!("AuthNeeded: expected ClearText"); assert!(false, "AuthNeeded: unreachable"); @@ -538,17 +537,17 @@ impl Worker { // no aad for now let aad = AAD(&mut []); - use dirsync::RespInner; + use dirsync::RespState; let resp = dirsync::Resp { client_key_id: req_data.client_key_id, - data: RespInner::ClearText(resp_data), + data: RespState::ClearText(resp_data), }; let encrypt_from = connection::ID::len() + resp.encrypted_offset(); let encrypt_until = encrypt_from + resp.encrypted_length(head_len, tag_len); let resp_handshake = Handshake::new( - HandshakeData::DirSync(DirSync::Resp(resp)), + handshake::Data::DirSync(DirSync::Resp(resp)), ); let packet = Packet { id: connection::ID::new_handshake(), @@ -568,9 +567,9 @@ impl Worker { } self.send_packet(raw_out, udp.src, udp.dst).await; } - HandshakeAction::ClientConnect(cci) => { + handshake::Action::ClientConnect(cci) => { let ds_resp; - if let HandshakeData::DirSync(DirSync::Resp(resp)) = + if let handshake::Data::DirSync(DirSync::Resp(resp)) = cci.handshake.data { ds_resp = resp; @@ -580,7 +579,7 @@ impl Worker { } // track connection let resp_data; - if let dirsync::RespInner::ClearText(r_data) = ds_resp.data + if let dirsync::RespState::ClearText(r_data) = ds_resp.data { resp_data = r_data; } else { @@ -609,7 +608,7 @@ impl Worker { //FIXME: the Secret should be XORed with the client // stored secret (if any) let hkdf = Hkdf::new( - HkdfKind::Sha3, + hkdf::Kind::Sha3, cci.service_id.as_bytes(), resp_data.service_key, ); @@ -628,7 +627,7 @@ impl Worker { let _ = cci.answer.send(Ok((cci.srv_key_id, auth_srv_conn))); } - HandshakeAction::Nothing => {} + handshake::Action::Nothing => {} }; } } diff --git a/src/tests.rs b/src/tests.rs index acf57cc..4e2a0b6 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -62,10 +62,7 @@ async fn test_connection_dirsync() { rt.block_on(local_thread); }); - use crate::{ - connection::handshake::HandshakeID, - dnssec::{record, Record}, - }; + use crate::dnssec::{record, Record}; let port: u16 = server.addresses()[0].port(); @@ -76,14 +73,14 @@ async fn test_connection_dirsync() { port: Some(::core::num::NonZeroU16::new(port).unwrap()), priority: record::AddressPriority::P1, weight: record::AddressWeight::W1, - handshake_ids: [HandshakeID::DirectorySynchronized].to_vec(), + handshake_ids: [handshake::ID::DirectorySynchronized].to_vec(), public_key_idx: [record::PubKeyIdx(0)].to_vec(), }] .to_vec(), key_exchanges: [enc::asym::KeyExchangeKind::X25519DiffieHellman] .to_vec(), - hkdfs: [enc::hkdf::HkdfKind::Sha3].to_vec(), - ciphers: [enc::sym::CipherKind::XChaCha20Poly1305].to_vec(), + hkdfs: [enc::hkdf::Kind::Sha3].to_vec(), + ciphers: [enc::sym::Kind::XChaCha20Poly1305].to_vec(), }; ::tokio::time::sleep(::std::time::Duration::from_millis(500)).await;