157 lines
4.1 KiB
Rust
157 lines
4.1 KiB
Rust
//! Handhsake handling
|
|
|
|
pub mod dirsync;
|
|
|
|
use crate::{
|
|
connection::{self, ProtocolVersion},
|
|
enc::sym::{HeadLen, TagLen},
|
|
};
|
|
use ::num_traits::FromPrimitive;
|
|
use ::std::{rc::Rc, sync::Arc};
|
|
|
|
/// Handshake errors
|
|
#[derive(::thiserror::Error, Debug, Copy, Clone)]
|
|
pub enum Error {
|
|
/// Error while parsing the handshake packet
|
|
/// TODO: more detailed parsing errors
|
|
#[error("not an handshake packet")]
|
|
Parsing,
|
|
/// No such Key ID
|
|
#[error("unknown key id")]
|
|
UnknownKeyID,
|
|
/// Key error
|
|
#[error("key: {0:?}")]
|
|
Key(#[from] crate::enc::Error),
|
|
/// Not enough data
|
|
#[error("not enough data")]
|
|
NotEnoughData,
|
|
}
|
|
|
|
pub(crate) struct HandshakeServer {
|
|
pub id: crate::enc::asym::KeyID,
|
|
pub key: crate::enc::asym::PrivKey,
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub(crate) struct HandshakeClient {
|
|
pub id: crate::enc::asym::KeyID,
|
|
pub key: crate::enc::asym::PrivKey,
|
|
pub service_id: crate::auth::ServiceID,
|
|
pub service_conn_id: connection::IDRecv,
|
|
pub connection: Rc<crate::connection::Connection>,
|
|
}
|
|
|
|
/// Parsed handshake
|
|
#[derive(Debug, Clone)]
|
|
pub enum HandshakeData {
|
|
/// Directory synchronized handhsake
|
|
DirSync(dirsync::DirSync),
|
|
}
|
|
|
|
impl HandshakeData {
|
|
/// actual length of the handshake data
|
|
pub fn len(&self) -> usize {
|
|
match self {
|
|
HandshakeData::DirSync(d) => d.len(),
|
|
}
|
|
}
|
|
/// Serialize into raw bytes
|
|
/// NOTE: assumes that there is exactly asa much buffer as needed
|
|
pub fn serialize(
|
|
&self,
|
|
head_len: HeadLen,
|
|
tag_len: TagLen,
|
|
out: &mut [u8],
|
|
) {
|
|
match self {
|
|
HandshakeData::DirSync(d) => d.serialize(head_len, tag_len, out),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Kind of handshake
|
|
#[derive(::num_derive::FromPrimitive, Debug, Clone, Copy)]
|
|
#[repr(u8)]
|
|
pub enum Kind {
|
|
/// 1-RTT, Directory synchronized handshake
|
|
/// Request
|
|
DirSyncReq = 0,
|
|
/// 1-RTT, Directory synchronized handshake
|
|
/// Response
|
|
DirSyncResp,
|
|
/*
|
|
/// 2-RTT, Stateful connection
|
|
Stateful,
|
|
...
|
|
/// 3 RTT, Stateless connection
|
|
Stateless,
|
|
....
|
|
*/
|
|
}
|
|
|
|
/// Parsed handshake
|
|
#[derive(Debug, Clone)]
|
|
pub struct Handshake {
|
|
/// Fenrir Protocol version
|
|
pub fenrir_version: ProtocolVersion,
|
|
/// enum for the parsed data
|
|
pub data: HandshakeData,
|
|
}
|
|
|
|
impl Handshake {
|
|
/// Build new handshake from the data
|
|
pub fn new(data: HandshakeData) -> Self {
|
|
Handshake {
|
|
fenrir_version: ProtocolVersion::V0,
|
|
data,
|
|
}
|
|
}
|
|
/// return the total length of the handshake
|
|
pub fn len(&self) -> usize {
|
|
ProtocolVersion::len() + self.data.len()
|
|
}
|
|
const MIN_PKT_LEN: usize = 8;
|
|
/// Parse the packet and return the parsed handshake
|
|
pub fn deserialize(raw: &[u8]) -> Result<Self, Error> {
|
|
if raw.len() < Self::MIN_PKT_LEN {
|
|
return Err(Error::NotEnoughData);
|
|
}
|
|
let fenrir_version = match ProtocolVersion::from_u8(raw[0]) {
|
|
Some(fenrir_version) => fenrir_version,
|
|
None => return Err(Error::Parsing),
|
|
};
|
|
let handshake_kind = match Kind::from_u8(raw[1]) {
|
|
Some(handshake_kind) => handshake_kind,
|
|
None => return Err(Error::Parsing),
|
|
};
|
|
let data = match handshake_kind {
|
|
Kind::DirSyncReq => dirsync::Req::deserialize(&raw[2..])?,
|
|
Kind::DirSyncResp => dirsync::Resp::deserialize(&raw[2..])?,
|
|
};
|
|
Ok(Self {
|
|
fenrir_version,
|
|
data,
|
|
})
|
|
}
|
|
/// serialize the handshake into bytes
|
|
/// NOTE: assumes that there is exactly as much buffer as needed
|
|
pub fn serialize(
|
|
&self,
|
|
head_len: HeadLen,
|
|
tag_len: TagLen,
|
|
out: &mut [u8],
|
|
) {
|
|
assert!(out.len() > 1, "Handshake: not enough buffer to serialize");
|
|
self.fenrir_version.serialize(&mut out[0]);
|
|
self.data.serialize(head_len, tag_len, &mut out[1..]);
|
|
}
|
|
|
|
pub(crate) fn work(&self, keys: &[HandshakeServer]) -> Result<(), Error> {
|
|
todo!()
|
|
}
|
|
}
|
|
|
|
trait HandshakeParsing {
|
|
fn deserialize(raw: &[u8]) -> Result<HandshakeData, Error>;
|
|
}
|