//! Directory synchronized handshake //! 1-RTT connection //! //! The simplest, fastest handshake supported by Fenrir //! Downside: It does not offer protection from DDos, //! no perfect forward secrecy //! //! To grant a form of perfect forward secrecy, the server should periodically //! change the DNSSEC public/private keys use super::{Error, HandshakeData}; use crate::{ connection::ID, enc::{ asym::{ExchangePubKey, KeyExchange, KeyID}, sym::CipherKind, }, }; use ::std::vec::Vec; /// Parsed handshake #[derive(Debug, Clone)] pub enum DirSync { /// Directory synchronized handshake: client request Req(Req), /// Directory synchronized handshake: server response Resp(Resp), } /// Client request of a directory synchronized handshake #[derive(Debug, Clone)] pub struct Req { /// Id of the server key used for the key exchange pub key_id: KeyID, /// Selected key exchange pub exchange: KeyExchange, /// Selected cipher pub cipher: CipherKind, /// Client ephemeral public key used for key exchanges pub exchange_key: ExchangePubKey, /// encrypted data pub enc: Vec, } impl super::HandshakeParsing for Req { fn parse(raw: &[u8]) -> Result { const MIN_PKT_LEN: usize = 10; if raw.len() < MIN_PKT_LEN { return Err(Error::NotEnoughData); } let key_id: KeyID = KeyID(u16::from_le_bytes(raw[0..1].try_into().unwrap())); use ::num_traits::FromPrimitive; let exchange: KeyExchange = match KeyExchange::from_u8(raw[2]) { Some(exchange) => exchange, None => return Err(Error::Parsing), }; let cipher: CipherKind = match CipherKind::from_u8(raw[3]) { Some(cipher) => cipher, None => return Err(Error::Parsing), }; let (exchange_key, len) = match ExchangePubKey::from_slice(&raw[4..]) { Ok(exchange_key) => exchange_key, Err(e) => return Err(e.into()), }; let enc = raw[(4 + len)..].to_vec(); Ok(HandshakeData::DirSync(DirSync::Req(Self { key_id, exchange, cipher, exchange_key, enc, }))) } } /// Decrypted request data #[derive(Debug, Clone, Copy)] pub struct ReqData { /// Random nonce, the client can use this to track multiple key exchanges pub nonce: [u8; 16], /// Client key id so the client can use and rotate keys pub client_key_id: KeyID, /// Authentication token pub token: [u8; 32], /// Receiving connection id for the client pub id: ID, // TODO: service info } /// Server response in a directory synchronized handshake #[derive(Debug, Clone)] pub struct Resp { /// Tells the client with which key the exchange was done pub client_key_id: KeyID, /// encrypted data pub enc: Vec, } impl super::HandshakeParsing for Resp { fn parse(raw: &[u8]) -> Result { todo!() } } /// Decrypted response data #[derive(Debug, Clone, Copy)] pub struct RespData { /// Client nonce, copied from the request client_nonce: [u8; 16], /// Server Connection ID id: ID, /// Service Connection ID service_id: ID, /// Service encryption key service_key: [u8; 32], }