ConnTrack with ciphers
Signed-off-by: Luca Fulchir <luca.fulchir@runesauth.com>
This commit is contained in:
parent
f53ef95c73
commit
7bddc9bf55
|
@ -9,6 +9,11 @@ pub use handshake::Handshake;
|
||||||
pub use packet::ConnectionID as ID;
|
pub use packet::ConnectionID as ID;
|
||||||
pub use packet::{Packet, PacketData};
|
pub use packet::{Packet, PacketData};
|
||||||
|
|
||||||
|
use crate::enc::{
|
||||||
|
hkdf::HkdfSha3,
|
||||||
|
sym::{CipherKind, CipherRecv, CipherSend},
|
||||||
|
};
|
||||||
|
|
||||||
/// Version of the fenrir protocol in use
|
/// Version of the fenrir protocol in use
|
||||||
#[derive(::num_derive::FromPrimitive, Debug, Copy, Clone)]
|
#[derive(::num_derive::FromPrimitive, Debug, Copy, Clone)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
|
@ -33,11 +38,43 @@ pub struct Connection {
|
||||||
/// Connection ID
|
/// Connection ID
|
||||||
pub id: ID,
|
pub id: ID,
|
||||||
/// The main hkdf used for all secrets in this connection
|
/// 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 {
|
impl Connection {
|
||||||
pub(crate) fn new(id: ID, hkdf: crate::enc::hkdf::HkdfSha3) -> Self {
|
pub(crate) fn new(hkdf: HkdfSha3, cipher: CipherKind, role: Role) -> Self {
|
||||||
Self { id, hkdf }
|
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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -200,8 +200,15 @@ impl Cipher {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Receive only cipher
|
/// Receive only cipher
|
||||||
#[allow(missing_debug_implementations)]
|
|
||||||
pub struct CipherRecv(Cipher);
|
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 {
|
impl CipherRecv {
|
||||||
/// Build a new Cipher
|
/// Build a new Cipher
|
||||||
|
@ -253,17 +260,24 @@ impl Data {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send only cipher
|
/// Send only cipher
|
||||||
#[allow(missing_debug_implementations)]
|
|
||||||
pub struct CipherSend {
|
pub struct CipherSend {
|
||||||
nonce: Nonce,
|
nonce: NonceSync,
|
||||||
cipher: Cipher,
|
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 {
|
impl CipherSend {
|
||||||
/// Build a new Cipher
|
/// Build a new Cipher
|
||||||
pub fn new(kind: CipherKind, secret: Secret) -> Self {
|
pub fn new(kind: CipherKind, secret: Secret) -> Self {
|
||||||
Self {
|
Self {
|
||||||
nonce: Nonce::new(),
|
nonce: NonceSync::new(),
|
||||||
cipher: Cipher::new(kind, secret),
|
cipher: Cipher::new(kind, secret),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -276,9 +290,9 @@ impl CipherSend {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Encrypt the given data
|
/// Encrypt the given data
|
||||||
pub fn encrypt(&mut self, aad: AAD, data: &mut Data) -> Result<(), Error> {
|
pub fn encrypt(&self, aad: AAD, data: &mut Data) -> Result<(), Error> {
|
||||||
self.cipher.encrypt(&self.nonce, aad, data)?;
|
let old_nonce = self.nonce.advance();
|
||||||
self.nonce.advance();
|
self.cipher.encrypt(&old_nonce, aad, data)?;
|
||||||
Ok(())
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
33
src/lib.rs
33
src/lib.rs
|
@ -305,7 +305,7 @@ impl ConnList {
|
||||||
ids_used: vec![bitmap_id],
|
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:
|
// uhm... bad things are going on here:
|
||||||
// * id must be initialized, but only because:
|
// * id must be initialized, but only because:
|
||||||
// * rust does not understand that after the `!found` id is always
|
// * rust does not understand that after the `!found` id is always
|
||||||
|
@ -332,14 +332,15 @@ impl ConnList {
|
||||||
self.ids_used.push(new_bitmap);
|
self.ids_used.push(new_bitmap);
|
||||||
}
|
}
|
||||||
let new_id = connection::ID::new_u64(id);
|
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 {
|
if (self.connections.len() as u64) < id {
|
||||||
self.connections.push(Some(new_conn.clone()));
|
self.connections.push(Some(conn.clone()));
|
||||||
} else {
|
} else {
|
||||||
// very probably redundant
|
// 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 =
|
let srv_secret =
|
||||||
enc::sym::Secret::new_rand(&self.rand);
|
enc::sym::Secret::new_rand(&self.rand);
|
||||||
|
|
||||||
|
let raw_conn = Connection::new(
|
||||||
|
authinfo.hkdf,
|
||||||
|
req.cipher,
|
||||||
|
connection::Role::Server,
|
||||||
|
);
|
||||||
// track connection
|
// track connection
|
||||||
let auth_conn = {
|
let auth_conn = {
|
||||||
let mut lock =
|
let mut lock =
|
||||||
self.connections.write().await;
|
self.connections.write().await;
|
||||||
lock.reserve_first(authinfo.hkdf)
|
lock.reserve_first(raw_conn)
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: move all the next bits into
|
// TODO: move all the next bits into
|
||||||
|
@ -672,20 +678,15 @@ impl Fenrir {
|
||||||
service_id: srv_conn_id,
|
service_id: srv_conn_id,
|
||||||
service_key: srv_secret,
|
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;
|
use crate::enc::sym::AAD;
|
||||||
let aad = AAD(&mut []); // no aad for now
|
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());
|
.make_data(dirsync::RespData::len());
|
||||||
|
|
||||||
if let Err(e) =
|
if let Err(e) = auth_conn
|
||||||
cipher_send.encrypt(aad, &mut data)
|
.cipher_send
|
||||||
|
.encrypt(aad, &mut data)
|
||||||
{
|
{
|
||||||
::tracing::error!("can't encrypt: {:?}", e);
|
::tracing::error!("can't encrypt: {:?}", e);
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in New Issue