DirSync response serialization
Signed-off-by: Luca Fulchir <luca.fulchir@runesauth.com>
This commit is contained in:
parent
59394959bd
commit
4157c207a3
|
@ -27,6 +27,7 @@ crate_type = [ "lib", "cdylib", "staticlib" ]
|
|||
# please keep these in alphabetical order
|
||||
|
||||
arc-swap = { version = "1.6" }
|
||||
arrayref = { version = "0.3" }
|
||||
async-channel = { version = "1.8" }
|
||||
# base85 repo has no tags, fix on a commit. v1.1.1 points to older, wrong version
|
||||
base85 = { git = "https://gitlab.com/darkwyrm/base85", rev = "d98efbfd171dd9ba48e30a5c88f94db92fc7b3c6" }
|
||||
|
|
|
@ -17,6 +17,8 @@ use crate::{
|
|||
sym::{CipherKind, Secret},
|
||||
},
|
||||
};
|
||||
|
||||
use ::arrayref::array_mut_ref;
|
||||
use ::std::{collections::VecDeque, num::NonZeroU64, vec::Vec};
|
||||
|
||||
type Nonce = [u8; 16];
|
||||
|
@ -30,6 +32,24 @@ pub enum DirSync {
|
|||
Resp(Resp),
|
||||
}
|
||||
|
||||
impl DirSync {
|
||||
/// actual length of the dirsync handshake data
|
||||
pub fn len(&self) -> usize {
|
||||
match self {
|
||||
DirSync::Req(req) => req.len(),
|
||||
DirSync::Resp(resp) => resp.len(),
|
||||
}
|
||||
}
|
||||
/// Serialize into raw bytes
|
||||
/// NOTE: assumes that there is exactly asa much buffer as needed
|
||||
pub fn serialize(&self, out: &mut [u8]) {
|
||||
match self {
|
||||
DirSync::Req(req) => req.serialize(out),
|
||||
DirSync::Resp(resp) => resp.serialize(out),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Client request of a directory synchronized handshake
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Req {
|
||||
|
@ -50,6 +70,20 @@ impl Req {
|
|||
pub fn set_data(&mut self, data: ReqData) {
|
||||
self.data = ReqInner::Data(data);
|
||||
}
|
||||
/// actual length of the directory synchronized request
|
||||
pub fn len(&self) -> usize {
|
||||
KeyID::len()
|
||||
+ KeyExchange::len()
|
||||
+ CipherKind::len()
|
||||
+ self.exchange_key.len()
|
||||
+ self.data.len()
|
||||
}
|
||||
/// Serialize into raw bytes
|
||||
/// NOTE: assumes that there is exactly asa much buffer as needed
|
||||
pub fn serialize(&self, out: &mut [u8]) {
|
||||
//assert!(out.len() > , ": not enough buffer to serialize");
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl super::HandshakeParsing for Req {
|
||||
|
@ -76,7 +110,7 @@ impl super::HandshakeParsing for Req {
|
|||
let mut vec = VecDeque::with_capacity(raw.len() - (4 + len));
|
||||
vec.extend(raw[(4 + len)..].iter().copied());
|
||||
let _ = vec.make_contiguous();
|
||||
let data = ReqInner::Ciphertext(vec);
|
||||
let data = ReqInner::CipherText(vec);
|
||||
Ok(HandshakeData::DirSync(DirSync::Req(Self {
|
||||
key_id,
|
||||
exchange,
|
||||
|
@ -91,17 +125,25 @@ impl super::HandshakeParsing for Req {
|
|||
#[derive(Debug, Clone)]
|
||||
pub enum ReqInner {
|
||||
/// Client data, still in ciphertext
|
||||
Ciphertext(VecDeque<u8>),
|
||||
CipherText(VecDeque<u8>),
|
||||
/// Client data, decrypted but unprocessed
|
||||
Cleartext(VecDeque<u8>),
|
||||
ClearText(VecDeque<u8>),
|
||||
/// Parsed client data
|
||||
Data(ReqData),
|
||||
}
|
||||
impl ReqInner {
|
||||
/// The length of the data
|
||||
pub fn len(&self) -> usize {
|
||||
match self {
|
||||
ReqInner::CipherText(c) => c.len(),
|
||||
ReqInner::ClearText(c) => c.len(),
|
||||
ReqInner::Data(d) => d.len(),
|
||||
}
|
||||
}
|
||||
/// Get the ciptertext, or panic
|
||||
pub fn ciphertext<'a>(&'a mut self) -> &'a mut VecDeque<u8> {
|
||||
match self {
|
||||
ReqInner::Ciphertext(data) => data,
|
||||
ReqInner::CipherText(data) => data,
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
|
@ -109,13 +151,13 @@ impl ReqInner {
|
|||
pub fn mark_as_cleartext(&mut self) {
|
||||
let mut newdata: VecDeque<u8>;
|
||||
match self {
|
||||
ReqInner::Ciphertext(data) => {
|
||||
ReqInner::CipherText(data) => {
|
||||
newdata = VecDeque::new();
|
||||
::core::mem::swap(&mut newdata, data);
|
||||
}
|
||||
_ => return,
|
||||
}
|
||||
*self = ReqInner::Cleartext(newdata);
|
||||
*self = ReqInner::ClearText(newdata);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,6 +237,10 @@ pub struct ReqData {
|
|||
pub auth: AuthInfo,
|
||||
}
|
||||
impl ReqData {
|
||||
/// actual length of the request data
|
||||
pub fn len(&self) -> usize {
|
||||
self.nonce.len() + KeyID::len() + ID::len() + self.auth.len()
|
||||
}
|
||||
/// Minimum byte length of the request data
|
||||
pub const MIN_PKT_LEN: usize =
|
||||
16 + KeyID::len() + ID::len() + AuthInfo::MIN_PKT_LEN;
|
||||
|
@ -202,7 +248,7 @@ impl ReqData {
|
|||
pub fn deserialize(raw: &ReqInner) -> Result<Self, Error> {
|
||||
let raw = match raw {
|
||||
// raw is VecDeque, assume everything is on the first slice
|
||||
ReqInner::Cleartext(raw) => raw.as_slices().0,
|
||||
ReqInner::ClearText(raw) => raw.as_slices().0,
|
||||
_ => return Err(Error::Parsing),
|
||||
};
|
||||
if raw.len() < Self::MIN_PKT_LEN {
|
||||
|
@ -249,6 +295,23 @@ impl super::HandshakeParsing for Resp {
|
|||
}
|
||||
}
|
||||
|
||||
impl Resp {
|
||||
/// Total length of the response handshake
|
||||
pub fn len(&self) -> usize {
|
||||
KeyID::len() + self.enc.len()
|
||||
}
|
||||
/// Serialize into raw bytes
|
||||
/// NOTE: assumes that there is exactly asa much buffer as needed
|
||||
pub fn serialize(&self, out: &mut [u8]) {
|
||||
assert!(
|
||||
out.len() == KeyID::len() + self.enc.len(),
|
||||
"DirSync Resp: not enough buffer to serialize"
|
||||
);
|
||||
self.client_key_id.serialize(array_mut_ref![out, 0, 2]);
|
||||
out[2..].copy_from_slice(&self.enc[..]);
|
||||
}
|
||||
}
|
||||
|
||||
/// Decrypted response data
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RespData {
|
||||
|
@ -269,6 +332,7 @@ impl RespData {
|
|||
Self::NONCE_LEN + ID::len() + ID::len() + 32
|
||||
}
|
||||
/// Serialize the data into a buffer
|
||||
/// NOTE: assumes that there is exactly asa much buffer as needed
|
||||
pub fn serialize(&self, out: &mut [u8]) {
|
||||
assert!(out.len() == Self::len(), "wrong buffer size");
|
||||
let mut start = 0;
|
||||
|
|
|
@ -36,6 +36,22 @@ pub enum HandshakeData {
|
|||
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, out: &mut [u8]) {
|
||||
match self {
|
||||
HandshakeData::DirSync(d) => d.serialize(out),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Kind of handshake
|
||||
#[derive(::num_derive::FromPrimitive, Debug, Clone, Copy)]
|
||||
#[repr(u8)]
|
||||
|
@ -66,6 +82,17 @@ pub struct Handshake {
|
|||
}
|
||||
|
||||
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> {
|
||||
|
@ -89,6 +116,14 @@ impl Handshake {
|
|||
data,
|
||||
})
|
||||
}
|
||||
/// serialize the handshake into bytes
|
||||
/// NOTE: assumes that there is exactly asa much buffer as needed
|
||||
pub fn serialize(&self, out: &mut [u8]) {
|
||||
assert!(out.len() > 1, "Handshake: not enough buffer to serialize");
|
||||
self.fenrir_version.serialize(&mut out[0]);
|
||||
self.data.serialize(&mut out[1..]);
|
||||
}
|
||||
|
||||
pub(crate) fn work(&self, keys: &[HandshakeKey]) -> Result<(), Error> {
|
||||
todo!()
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use ::std::vec::Vec;
|
|||
|
||||
pub use handshake::Handshake;
|
||||
pub use packet::ConnectionID as ID;
|
||||
pub use packet::Packet;
|
||||
pub use packet::{Packet, PacketData};
|
||||
|
||||
/// Version of the fenrir protocol in use
|
||||
#[derive(::num_derive::FromPrimitive, Debug, Copy, Clone)]
|
||||
|
@ -16,3 +16,13 @@ pub enum ProtocolVersion {
|
|||
/// First Fenrir Protocol Version
|
||||
V0 = 0,
|
||||
}
|
||||
impl ProtocolVersion {
|
||||
/// actual length of the protocol version field
|
||||
pub const fn len() -> usize {
|
||||
1
|
||||
}
|
||||
/// Serialize into raw bytes
|
||||
pub fn serialize(&self, out: &mut u8) {
|
||||
*out = *self as u8;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,10 @@ pub enum ConnectionID {
|
|||
}
|
||||
|
||||
impl ConnectionID {
|
||||
/// Set the conenction id to handshake
|
||||
pub fn new_handshake() -> Self {
|
||||
Self::Handshake
|
||||
}
|
||||
/// New random service ID
|
||||
pub fn new_rand(rand: &::ring::rand::SystemRandom) -> Self {
|
||||
use ::ring::rand::SecureRandom;
|
||||
|
@ -67,9 +71,52 @@ impl From<[u8; 8]> for ConnectionID {
|
|||
}
|
||||
}
|
||||
|
||||
/// Enumerate the possible data in a fenrir packet
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum PacketData {
|
||||
/// A parsed handshake packet
|
||||
Handshake(super::Handshake),
|
||||
}
|
||||
|
||||
impl PacketData {
|
||||
/// total length of the data in bytes
|
||||
pub fn len(&self) -> usize {
|
||||
match self {
|
||||
PacketData::Handshake(h) => h.len(),
|
||||
}
|
||||
}
|
||||
/// serialize data into bytes
|
||||
/// NOTE: assumes that there is exactly asa much buffer as needed
|
||||
pub fn serialize(&self, out: &mut [u8]) {
|
||||
assert!(self.len() == out.len(), "PacketData: wrong buffer length");
|
||||
match self {
|
||||
PacketData::Handshake(h) => h.serialize(out),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Fenrir packet structure
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Packet {
|
||||
/// Id of the Fenrir connection.
|
||||
id: ConnectionID,
|
||||
pub id: ConnectionID,
|
||||
/// actual data inside the packet
|
||||
pub data: PacketData,
|
||||
}
|
||||
|
||||
impl Packet {
|
||||
/// get the total length of the packet
|
||||
pub fn len(&self) -> usize {
|
||||
ConnectionID::len() + self.data.len()
|
||||
}
|
||||
/// serialize packet into buffer
|
||||
/// NOTE: assumes that there is exactly asa much buffer as needed
|
||||
pub fn serialize(&self, out: &mut [u8]) {
|
||||
assert!(
|
||||
out.len() > ConnectionID::len(),
|
||||
"Packet: not enough buffer to serialize"
|
||||
);
|
||||
self.id.serialize(&mut out[0..ConnectionID::len()]);
|
||||
self.data.serialize(&mut out[ConnectionID::len()..]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,10 @@ impl KeyID {
|
|||
pub const fn len() -> usize {
|
||||
2
|
||||
}
|
||||
/// Serialize into raw bytes
|
||||
pub fn serialize(&self, out: &mut [u8; KeyID::len()]) {
|
||||
out.copy_from_slice(&self.0.to_le_bytes());
|
||||
}
|
||||
}
|
||||
|
||||
/// Kind of key used in the handshake
|
||||
|
@ -40,6 +44,12 @@ pub enum KeyExchange {
|
|||
/// X25519 Public key
|
||||
X25519DiffieHellman = 0,
|
||||
}
|
||||
impl KeyExchange {
|
||||
/// The serialize length of the field
|
||||
pub fn len() -> usize {
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
/// Kind of key in the handshake
|
||||
#[derive(Clone)]
|
||||
|
@ -96,12 +106,18 @@ pub enum ExchangePubKey {
|
|||
}
|
||||
|
||||
impl ExchangePubKey {
|
||||
/// length of the public key used for key exchange
|
||||
pub fn len(&self) -> usize {
|
||||
match self {
|
||||
ExchangePubKey::X25519(_) => 32,
|
||||
}
|
||||
}
|
||||
/// Load public key used for key exchange from it raw bytes
|
||||
/// The riesult is "unparsed" since we don't verify
|
||||
/// the actual key
|
||||
pub fn from_slice(raw: &[u8]) -> Result<(Self, usize), Error> {
|
||||
// FIXME: get *real* minimum key size
|
||||
const MIN_KEY_SIZE: usize = 8;
|
||||
const MIN_KEY_SIZE: usize = 32;
|
||||
if raw.len() < 1 + MIN_KEY_SIZE {
|
||||
return Err(Error::NotEnoughData);
|
||||
}
|
||||
|
|
|
@ -54,6 +54,10 @@ pub enum CipherKind {
|
|||
}
|
||||
|
||||
impl CipherKind {
|
||||
/// length of the serialized id for the cipher kind field
|
||||
pub fn len() -> usize {
|
||||
1
|
||||
}
|
||||
/// required length of the nonce
|
||||
pub fn nonce_len(&self) -> usize {
|
||||
// TODO: how the hell do I take this from ::chacha20poly1305?
|
||||
|
|
23
src/lib.rs
23
src/lib.rs
|
@ -333,10 +333,7 @@ impl Fenrir {
|
|||
fn stop_sync(&mut self) {
|
||||
let _ = self.stop_working.send(true);
|
||||
let mut toempty_sockets = self.sockets.rm_all();
|
||||
let task = ::tokio::task::spawn(Self::stop_sockets(toempty_sockets));
|
||||
//let mut toempty_socket = Vec::new();
|
||||
//::std::mem::swap(&mut self.sockets, &mut toempty_socket);
|
||||
//let task = ::tokio::task::spawn(Self::stop_sockets(toempty_socket));
|
||||
let task = ::tokio::task::spawn(toempty_sockets.stop_all());
|
||||
let _ = ::futures::executor::block_on(task);
|
||||
self.dnssec = None;
|
||||
}
|
||||
|
@ -345,15 +342,10 @@ impl Fenrir {
|
|||
pub async fn stop(&mut self) {
|
||||
let _ = self.stop_working.send(true);
|
||||
let mut toempty_sockets = self.sockets.rm_all();
|
||||
Self::stop_sockets(toempty_sockets).await;
|
||||
toempty_sockets.stop_all().await;
|
||||
self.dnssec = None;
|
||||
}
|
||||
|
||||
/// actually do the work of stopping resolvers and listeners
|
||||
async fn stop_sockets(sockets: SocketList) {
|
||||
sockets.stop_all().await;
|
||||
}
|
||||
|
||||
/// Enable some common socket options. This is just the unsafe part
|
||||
fn enable_sock_opt(
|
||||
fd: ::std::os::fd::RawFd,
|
||||
|
@ -611,6 +603,17 @@ impl Fenrir {
|
|||
client_key_id: req_data.client_key_id,
|
||||
enc: data.get_raw(),
|
||||
};
|
||||
let resp_handshake = Handshake::new(
|
||||
HandshakeData::DirSync(DirSync::Resp(resp)),
|
||||
);
|
||||
use connection::{Packet, PacketData, ID};
|
||||
let packet = Packet {
|
||||
id: ID::new_handshake(),
|
||||
data: PacketData::Handshake(resp_handshake),
|
||||
};
|
||||
let mut raw_out =
|
||||
Vec::<u8>::with_capacity(packet.len());
|
||||
packet.serialize(&mut raw_out);
|
||||
todo!()
|
||||
}
|
||||
_ => {
|
||||
|
|
Loading…
Reference in New Issue