From 7bddc9bf55dbe7babd5dfb8ef96b779a8d145889 Mon Sep 17 00:00:00 2001 From: Luca Fulchir Date: Sun, 26 Feb 2023 10:44:21 +0100 Subject: [PATCH] ConnTrack with ciphers Signed-off-by: Luca Fulchir --- src/connection/mod.rs | 43 ++++++++++++++++++++++++++++++++--- src/enc/sym.rs | 52 +++++++++++++++++++++++++++++++++++++------ src/lib.rs | 33 ++++++++++++++------------- 3 files changed, 102 insertions(+), 26 deletions(-) diff --git a/src/connection/mod.rs b/src/connection/mod.rs index 7220a03..87ee6ba 100644 --- a/src/connection/mod.rs +++ b/src/connection/mod.rs @@ -9,6 +9,11 @@ pub use handshake::Handshake; pub use packet::ConnectionID as ID; pub use packet::{Packet, PacketData}; +use crate::enc::{ + hkdf::HkdfSha3, + sym::{CipherKind, CipherRecv, CipherSend}, +}; + /// Version of the fenrir protocol in use #[derive(::num_derive::FromPrimitive, Debug, Copy, Clone)] #[repr(u8)] @@ -33,11 +38,43 @@ pub struct Connection { /// Connection ID pub id: ID, /// The main hkdf used for all secrets in this connection - pub hkdf: crate::enc::hkdf::HkdfSha3, + pub hkdf: HkdfSha3, + /// Cipher for decrypting data + pub cipher_recv: CipherRecv, + /// Cipher for encrypting data + pub cipher_send: CipherSend, +} + +/// Role: used to set the correct secrets +/// * Server: Connection is Incoming +/// * Client: Connection is Outgoing +#[derive(Debug, Copy, Clone)] +#[repr(u8)] +pub enum Role { + /// Server: we receive the connection + Server = 0, + /// Client: we initate the connection + Client, } impl Connection { - pub(crate) fn new(id: ID, hkdf: crate::enc::hkdf::HkdfSha3) -> Self { - Self { id, hkdf } + pub(crate) fn new(hkdf: HkdfSha3, cipher: CipherKind, role: Role) -> Self { + let (secret_recv, secret_send) = match role { + Role::Server => { + (hkdf.get_secret(b"to_server"), hkdf.get_secret(b"to_client")) + } + Role::Client => { + (hkdf.get_secret(b"to_client"), hkdf.get_secret(b"to_server")) + } + }; + let mut cipher_recv = CipherRecv::new(cipher, secret_recv); + let mut cipher_send = CipherSend::new(cipher, secret_send); + + Self { + id: ID::Handshake, + hkdf, + cipher_recv, + cipher_send, + } } } diff --git a/src/enc/sym.rs b/src/enc/sym.rs index 4e51f5e..28418dc 100644 --- a/src/enc/sym.rs +++ b/src/enc/sym.rs @@ -200,8 +200,15 @@ impl Cipher { } /// Receive only cipher -#[allow(missing_debug_implementations)] pub struct CipherRecv(Cipher); +impl ::core::fmt::Debug for CipherRecv { + fn fmt( + &self, + f: &mut core::fmt::Formatter<'_>, + ) -> Result<(), ::std::fmt::Error> { + ::core::fmt::Debug::fmt("[hidden cipher recv]", f) + } +} impl CipherRecv { /// Build a new Cipher @@ -253,17 +260,24 @@ impl Data { } /// Send only cipher -#[allow(missing_debug_implementations)] pub struct CipherSend { - nonce: Nonce, + nonce: NonceSync, cipher: Cipher, } +impl ::core::fmt::Debug for CipherSend { + fn fmt( + &self, + f: &mut core::fmt::Formatter<'_>, + ) -> Result<(), ::std::fmt::Error> { + ::core::fmt::Debug::fmt("[hidden cipher send]", f) + } +} impl CipherSend { /// Build a new Cipher pub fn new(kind: CipherKind, secret: Secret) -> Self { Self { - nonce: Nonce::new(), + nonce: NonceSync::new(), cipher: Cipher::new(kind, secret), } } @@ -276,9 +290,9 @@ impl CipherSend { } } /// Encrypt the given data - pub fn encrypt(&mut self, aad: AAD, data: &mut Data) -> Result<(), Error> { - self.cipher.encrypt(&self.nonce, aad, data)?; - self.nonce.advance(); + pub fn encrypt(&self, aad: AAD, data: &mut Data) -> Result<(), Error> { + let old_nonce = self.nonce.advance(); + self.cipher.encrypt(&old_nonce, aad, data)?; Ok(()) } } @@ -372,3 +386,27 @@ impl Nonce { } } } + +/// Synchronize the mutex acess with a nonce for multithread safety +#[derive(Debug)] +pub struct NonceSync { + nonce: ::std::sync::Mutex, +} +impl NonceSync { + /// Create a new thread safe nonce + pub fn new() -> Self { + Self { + nonce: ::std::sync::Mutex::new(Nonce::new()), + } + } + /// 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 + } +} diff --git a/src/lib.rs b/src/lib.rs index 391cdff..c63f813 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -305,7 +305,7 @@ impl ConnList { ids_used: vec![bitmap_id], } } - fn reserve_first(&mut self, hkdf: HkdfSha3) -> Arc { + fn reserve_first(&mut self, mut conn: Connection) -> Arc { // uhm... bad things are going on here: // * id must be initialized, but only because: // * rust does not understand that after the `!found` id is always @@ -332,14 +332,15 @@ impl ConnList { self.ids_used.push(new_bitmap); } let new_id = connection::ID::new_u64(id); - let new_conn = Arc::new(connection::Connection::new(new_id, hkdf)); + conn.id = new_id; + let conn = Arc::new(conn); if (self.connections.len() as u64) < id { - self.connections.push(Some(new_conn.clone())); + self.connections.push(Some(conn.clone())); } else { // very probably redundant - self.connections[id as usize] = Some(new_conn.clone()); + self.connections[id as usize] = Some(conn.clone()); } - new_conn + conn } } @@ -656,11 +657,16 @@ impl Fenrir { let srv_secret = enc::sym::Secret::new_rand(&self.rand); + let raw_conn = Connection::new( + authinfo.hkdf, + req.cipher, + connection::Role::Server, + ); // track connection let auth_conn = { let mut lock = self.connections.write().await; - lock.reserve_first(authinfo.hkdf) + lock.reserve_first(raw_conn) }; // TODO: move all the next bits into @@ -672,20 +678,15 @@ impl Fenrir { service_id: srv_conn_id, service_key: srv_secret, }; - // build response - let secret_send = - auth_conn.hkdf.get_secret(b"to_client"); - let mut cipher_send = CipherSend::new( - authinfo.cipher, - secret_send, - ); use crate::enc::sym::AAD; let aad = AAD(&mut []); // no aad for now - let mut data = cipher_send + let mut data = auth_conn + .cipher_send .make_data(dirsync::RespData::len()); - if let Err(e) = - cipher_send.encrypt(aad, &mut data) + if let Err(e) = auth_conn + .cipher_send + .encrypt(aad, &mut data) { ::tracing::error!("can't encrypt: {:?}", e); return;