118 lines
3.3 KiB
Rust
118 lines
3.3 KiB
Rust
//! 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<u8>,
|
|
}
|
|
|
|
impl super::HandshakeParsing for Req {
|
|
fn parse(raw: &[u8]) -> Result<HandshakeData, Error> {
|
|
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<u8>,
|
|
}
|
|
|
|
impl super::HandshakeParsing for Resp {
|
|
fn parse(raw: &[u8]) -> Result<HandshakeData, Error> {
|
|
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],
|
|
}
|