ConnTrack with ciphers

Signed-off-by: Luca Fulchir <luca.fulchir@runesauth.com>
This commit is contained in:
Luca Fulchir 2023-02-26 10:44:21 +01:00
parent f53ef95c73
commit 7bddc9bf55
Signed by: luca.fulchir
GPG Key ID: 8F6440603D13A78E
3 changed files with 102 additions and 26 deletions

View File

@ -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,
}
}
}

View File

@ -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<Nonce>,
}
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
}
}

View File

@ -305,7 +305,7 @@ impl ConnList {
ids_used: vec![bitmap_id],
}
}
fn reserve_first(&mut self, hkdf: HkdfSha3) -> Arc<Connection> {
fn reserve_first(&mut self, mut conn: Connection) -> Arc<Connection> {
// 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;