Rename lots of stuff to properly use namespaces
Signed-off-by: Luca Fulchir <luca.fulchir@runesauth.com>
This commit is contained in:
parent
cd7be0ff69
commit
bf877cf86e
|
@ -2,11 +2,10 @@
|
|||
//! Configuration to initialize the Fenrir networking library
|
||||
|
||||
use crate::{
|
||||
connection::handshake::HandshakeID,
|
||||
connection::handshake,
|
||||
enc::{
|
||||
asym::{KeyExchangeKind, KeyID, PrivKey, PubKey},
|
||||
hkdf::HkdfKind,
|
||||
sym::CipherKind,
|
||||
hkdf, sym,
|
||||
},
|
||||
};
|
||||
use ::std::{
|
||||
|
@ -44,13 +43,13 @@ pub struct Config {
|
|||
/// List of DNS resolvers to use
|
||||
pub resolvers: Vec<SocketAddr>,
|
||||
/// Supported handshakes
|
||||
pub handshakes: Vec<HandshakeID>,
|
||||
pub handshakes: Vec<handshake::ID>,
|
||||
/// Supported key exchanges
|
||||
pub key_exchanges: Vec<KeyExchangeKind>,
|
||||
/// Supported Hkdfs
|
||||
pub hkdfs: Vec<HkdfKind>,
|
||||
pub hkdfs: Vec<hkdf::Kind>,
|
||||
/// Supported Ciphers
|
||||
pub ciphers: Vec<CipherKind>,
|
||||
pub ciphers: Vec<sym::Kind>,
|
||||
/// list of authentication servers
|
||||
/// clients will have this empty
|
||||
pub servers: Vec<AuthServer>,
|
||||
|
@ -73,10 +72,10 @@ impl Default for Config {
|
|||
),
|
||||
],
|
||||
resolvers: Vec::new(),
|
||||
handshakes: [HandshakeID::DirectorySynchronized].to_vec(),
|
||||
handshakes: [handshake::ID::DirectorySynchronized].to_vec(),
|
||||
key_exchanges: [KeyExchangeKind::X25519DiffieHellman].to_vec(),
|
||||
hkdfs: [HkdfKind::Sha3].to_vec(),
|
||||
ciphers: [CipherKind::XChaCha20Poly1305].to_vec(),
|
||||
hkdfs: [hkdf::Kind::Sha3].to_vec(),
|
||||
ciphers: [sym::Kind::XChaCha20Poly1305].to_vec(),
|
||||
servers: Vec::new(),
|
||||
server_keys: Vec::new(),
|
||||
}
|
||||
|
|
|
@ -8,14 +8,14 @@
|
|||
//! To grant a form of perfect forward secrecy, the server should periodically
|
||||
//! change the DNSSEC public/private keys
|
||||
|
||||
use super::{Error, HandshakeData};
|
||||
use super::Error;
|
||||
use crate::{
|
||||
auth,
|
||||
connection::{ProtocolVersion, ID},
|
||||
connection::{handshake, ProtocolVersion, ID},
|
||||
enc::{
|
||||
asym::{ExchangePubKey, KeyExchangeKind, KeyID},
|
||||
hkdf::HkdfKind,
|
||||
sym::{CipherKind, HeadLen, TagLen},
|
||||
hkdf,
|
||||
sym::{self, NonceLen, TagLen},
|
||||
Random, Secret,
|
||||
},
|
||||
};
|
||||
|
@ -59,7 +59,7 @@ pub enum DirSync {
|
|||
|
||||
impl DirSync {
|
||||
/// actual length of the dirsync handshake data
|
||||
pub fn len(&self, head_len: HeadLen, tag_len: TagLen) -> usize {
|
||||
pub fn len(&self, head_len: NonceLen, tag_len: TagLen) -> usize {
|
||||
match self {
|
||||
DirSync::Req(req) => req.len(),
|
||||
DirSync::Resp(resp) => resp.len(head_len, tag_len),
|
||||
|
@ -69,7 +69,7 @@ impl DirSync {
|
|||
/// NOTE: assumes that there is exactly asa much buffer as needed
|
||||
pub fn serialize(
|
||||
&self,
|
||||
head_len: HeadLen,
|
||||
head_len: NonceLen,
|
||||
tag_len: TagLen,
|
||||
out: &mut [u8],
|
||||
) {
|
||||
|
@ -88,13 +88,13 @@ pub struct Req {
|
|||
/// Selected key exchange
|
||||
pub exchange: KeyExchangeKind,
|
||||
/// Selected hkdf
|
||||
pub hkdf: HkdfKind,
|
||||
pub hkdf: hkdf::Kind,
|
||||
/// Selected cipher
|
||||
pub cipher: CipherKind,
|
||||
pub cipher: sym::Kind,
|
||||
/// Client ephemeral public key used for key exchanges
|
||||
pub exchange_key: ExchangePubKey,
|
||||
/// encrypted data
|
||||
pub data: ReqInner,
|
||||
pub data: ReqState,
|
||||
// SECURITY: TODO: Add padding to min: 1200 bytes
|
||||
// to avoid amplification attaks
|
||||
// also: 1200 < 1280 to allow better vpn compatibility
|
||||
|
@ -105,30 +105,30 @@ impl Req {
|
|||
/// NOTE: starts from the beginning of the fenrir packet
|
||||
pub fn encrypted_offset(&self) -> usize {
|
||||
ProtocolVersion::len()
|
||||
+ crate::handshake::HandshakeID::len()
|
||||
+ handshake::ID::len()
|
||||
+ KeyID::len()
|
||||
+ KeyExchangeKind::len()
|
||||
+ HkdfKind::len()
|
||||
+ CipherKind::len()
|
||||
+ hkdf::Kind::len()
|
||||
+ sym::Kind::len()
|
||||
+ self.exchange_key.kind().pub_len()
|
||||
}
|
||||
/// return the total length of the cleartext data
|
||||
pub fn encrypted_length(
|
||||
&self,
|
||||
head_len: HeadLen,
|
||||
head_len: NonceLen,
|
||||
tag_len: TagLen,
|
||||
) -> usize {
|
||||
match &self.data {
|
||||
ReqInner::ClearText(data) => data.len() + head_len.0 + tag_len.0,
|
||||
ReqInner::CipherText(length) => *length,
|
||||
ReqState::ClearText(data) => data.len() + head_len.0 + tag_len.0,
|
||||
ReqState::CipherText(length) => *length,
|
||||
}
|
||||
}
|
||||
/// actual length of the directory synchronized request
|
||||
pub fn len(&self) -> usize {
|
||||
KeyID::len()
|
||||
+ KeyExchangeKind::len()
|
||||
+ HkdfKind::len()
|
||||
+ CipherKind::len()
|
||||
+ hkdf::Kind::len()
|
||||
+ sym::Kind::len()
|
||||
+ self.exchange_key.kind().pub_len()
|
||||
+ self.cipher.nonce_len().0
|
||||
+ self.data.len()
|
||||
|
@ -138,7 +138,7 @@ impl Req {
|
|||
/// NOTE: assumes that there is exactly as much buffer as needed
|
||||
pub fn serialize(
|
||||
&self,
|
||||
head_len: HeadLen,
|
||||
head_len: NonceLen,
|
||||
tag_len: TagLen,
|
||||
out: &mut [u8],
|
||||
) {
|
||||
|
@ -150,7 +150,7 @@ impl Req {
|
|||
let written_next = 5 + key_len;
|
||||
self.exchange_key.serialize_into(&mut out[5..written_next]);
|
||||
let written = written_next;
|
||||
if let ReqInner::ClearText(data) = &self.data {
|
||||
if let ReqState::ClearText(data) = &self.data {
|
||||
let from = written + head_len.0;
|
||||
let to = out.len() - tag_len.0;
|
||||
data.serialize(&mut out[from..to]);
|
||||
|
@ -160,8 +160,8 @@ impl Req {
|
|||
}
|
||||
}
|
||||
|
||||
impl super::HandshakeParsing for Req {
|
||||
fn deserialize(raw: &[u8]) -> Result<HandshakeData, Error> {
|
||||
impl handshake::Parsing for Req {
|
||||
fn deserialize(raw: &[u8]) -> Result<handshake::Data, Error> {
|
||||
const MIN_PKT_LEN: usize = 10;
|
||||
if raw.len() < MIN_PKT_LEN {
|
||||
return Err(Error::NotEnoughData);
|
||||
|
@ -173,25 +173,25 @@ impl super::HandshakeParsing for Req {
|
|||
Some(exchange) => exchange,
|
||||
None => return Err(Error::Parsing),
|
||||
};
|
||||
let hkdf: HkdfKind = match HkdfKind::from_u8(raw[3]) {
|
||||
let hkdf: hkdf::Kind = match hkdf::Kind::from_u8(raw[3]) {
|
||||
Some(exchange) => exchange,
|
||||
None => return Err(Error::Parsing),
|
||||
};
|
||||
let cipher: CipherKind = match CipherKind::from_u8(raw[4]) {
|
||||
let cipher: sym::Kind = match sym::Kind::from_u8(raw[4]) {
|
||||
Some(cipher) => cipher,
|
||||
None => return Err(Error::Parsing),
|
||||
};
|
||||
const CURR_SIZE: usize = KeyID::len()
|
||||
+ KeyExchangeKind::len()
|
||||
+ HkdfKind::len()
|
||||
+ CipherKind::len();
|
||||
+ hkdf::Kind::len()
|
||||
+ sym::Kind::len();
|
||||
let (exchange_key, len) =
|
||||
match ExchangePubKey::deserialize(&raw[CURR_SIZE..]) {
|
||||
Ok(exchange_key) => exchange_key,
|
||||
Err(e) => return Err(e.into()),
|
||||
};
|
||||
let data = ReqInner::CipherText(raw.len() - (CURR_SIZE + len));
|
||||
Ok(HandshakeData::DirSync(DirSync::Req(Self {
|
||||
let data = ReqState::CipherText(raw.len() - (CURR_SIZE + len));
|
||||
Ok(handshake::Data::DirSync(DirSync::Req(Self {
|
||||
key_id,
|
||||
exchange,
|
||||
hkdf,
|
||||
|
@ -204,18 +204,18 @@ impl super::HandshakeParsing for Req {
|
|||
|
||||
/// Quick way to avoid mixing cipher and clear text
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum ReqInner {
|
||||
pub enum ReqState {
|
||||
/// Data is still encrytped, we only keep the length
|
||||
CipherText(usize),
|
||||
/// Client data, decrypted and parsed
|
||||
ClearText(ReqData),
|
||||
}
|
||||
impl ReqInner {
|
||||
impl ReqState {
|
||||
/// The length of the data
|
||||
pub fn len(&self) -> usize {
|
||||
match self {
|
||||
ReqInner::CipherText(len) => *len,
|
||||
ReqInner::ClearText(data) => data.len(),
|
||||
ReqState::CipherText(len) => *len,
|
||||
ReqState::ClearText(data) => data.len(),
|
||||
}
|
||||
}
|
||||
/// parse the cleartext
|
||||
|
@ -224,10 +224,10 @@ impl ReqInner {
|
|||
raw: &[u8],
|
||||
) -> Result<(), Error> {
|
||||
let clear = match self {
|
||||
ReqInner::CipherText(len) => {
|
||||
ReqState::CipherText(len) => {
|
||||
assert!(
|
||||
*len > raw.len(),
|
||||
"DirSync::ReqInner::CipherText length mismatch"
|
||||
"DirSync::ReqState::CipherText length mismatch"
|
||||
);
|
||||
match ReqData::deserialize(raw) {
|
||||
Ok(clear) => clear,
|
||||
|
@ -236,7 +236,7 @@ impl ReqInner {
|
|||
}
|
||||
_ => return Err(Error::Parsing),
|
||||
};
|
||||
*self = ReqInner::ClearText(clear);
|
||||
*self = ReqState::ClearText(clear);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -386,18 +386,18 @@ impl ReqData {
|
|||
|
||||
/// Quick way to avoid mixing cipher and clear text
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum RespInner {
|
||||
pub enum RespState {
|
||||
/// Server data, still in ciphertext
|
||||
CipherText(usize),
|
||||
/// Parsed, cleartext server data
|
||||
ClearText(RespData),
|
||||
}
|
||||
impl RespInner {
|
||||
impl RespState {
|
||||
/// The length of the data
|
||||
pub fn len(&self) -> usize {
|
||||
match self {
|
||||
RespInner::CipherText(len) => *len,
|
||||
RespInner::ClearText(_) => RespData::len(),
|
||||
RespState::CipherText(len) => *len,
|
||||
RespState::ClearText(_) => RespData::len(),
|
||||
}
|
||||
}
|
||||
/// parse the cleartext
|
||||
|
@ -406,10 +406,10 @@ impl RespInner {
|
|||
raw: &[u8],
|
||||
) -> Result<(), Error> {
|
||||
let clear = match self {
|
||||
RespInner::CipherText(len) => {
|
||||
RespState::CipherText(len) => {
|
||||
assert!(
|
||||
*len > raw.len(),
|
||||
"DirSync::RespInner::CipherText length mismatch"
|
||||
"DirSync::RespState::CipherText length mismatch"
|
||||
);
|
||||
match RespData::deserialize(raw) {
|
||||
Ok(clear) => clear,
|
||||
|
@ -418,12 +418,12 @@ impl RespInner {
|
|||
}
|
||||
_ => return Err(Error::Parsing),
|
||||
};
|
||||
*self = RespInner::ClearText(clear);
|
||||
*self = RespState::ClearText(clear);
|
||||
Ok(())
|
||||
}
|
||||
/// Serialize the still cleartext data
|
||||
pub fn serialize(&self, out: &mut [u8]) {
|
||||
if let RespInner::ClearText(clear) = &self {
|
||||
if let RespState::ClearText(clear) = &self {
|
||||
clear.serialize(out);
|
||||
}
|
||||
}
|
||||
|
@ -435,20 +435,20 @@ pub struct Resp {
|
|||
/// Tells the client with which key the exchange was done
|
||||
pub client_key_id: KeyID,
|
||||
/// actual response data, might be encrypted
|
||||
pub data: RespInner,
|
||||
pub data: RespState,
|
||||
}
|
||||
|
||||
impl super::HandshakeParsing for Resp {
|
||||
fn deserialize(raw: &[u8]) -> Result<HandshakeData, Error> {
|
||||
impl handshake::Parsing for Resp {
|
||||
fn deserialize(raw: &[u8]) -> Result<handshake::Data, Error> {
|
||||
const MIN_PKT_LEN: usize = 68;
|
||||
if raw.len() < MIN_PKT_LEN {
|
||||
return Err(Error::NotEnoughData);
|
||||
}
|
||||
let client_key_id: KeyID =
|
||||
KeyID(u16::from_le_bytes(raw[0..KeyID::len()].try_into().unwrap()));
|
||||
Ok(HandshakeData::DirSync(DirSync::Resp(Self {
|
||||
Ok(handshake::Data::DirSync(DirSync::Resp(Self {
|
||||
client_key_id,
|
||||
data: RespInner::CipherText(raw[KeyID::len()..].len()),
|
||||
data: RespState::CipherText(raw[KeyID::len()..].len()),
|
||||
})))
|
||||
}
|
||||
}
|
||||
|
@ -457,32 +457,30 @@ impl Resp {
|
|||
/// return the offset of the encrypted data
|
||||
/// NOTE: starts from the beginning of the fenrir packet
|
||||
pub fn encrypted_offset(&self) -> usize {
|
||||
ProtocolVersion::len()
|
||||
+ crate::connection::handshake::HandshakeID::len()
|
||||
+ KeyID::len()
|
||||
ProtocolVersion::len() + handshake::ID::len() + KeyID::len()
|
||||
}
|
||||
/// return the total length of the cleartext data
|
||||
pub fn encrypted_length(
|
||||
&self,
|
||||
head_len: HeadLen,
|
||||
head_len: NonceLen,
|
||||
tag_len: TagLen,
|
||||
) -> usize {
|
||||
match &self.data {
|
||||
RespInner::ClearText(_data) => {
|
||||
RespState::ClearText(_data) => {
|
||||
RespData::len() + head_len.0 + tag_len.0
|
||||
}
|
||||
RespInner::CipherText(len) => *len,
|
||||
RespState::CipherText(len) => *len,
|
||||
}
|
||||
}
|
||||
/// Total length of the response handshake
|
||||
pub fn len(&self, head_len: HeadLen, tag_len: TagLen) -> usize {
|
||||
pub fn len(&self, head_len: NonceLen, tag_len: TagLen) -> usize {
|
||||
KeyID::len() + head_len.0 + self.data.len() + tag_len.0
|
||||
}
|
||||
/// Serialize into raw bytes
|
||||
/// NOTE: assumes that there is exactly as much buffer as needed
|
||||
pub fn serialize(
|
||||
&self,
|
||||
head_len: HeadLen,
|
||||
head_len: NonceLen,
|
||||
_tag_len: TagLen,
|
||||
out: &mut [u8],
|
||||
) {
|
||||
|
|
|
@ -4,10 +4,11 @@ pub mod dirsync;
|
|||
#[cfg(test)]
|
||||
mod tests;
|
||||
pub(crate) mod tracker;
|
||||
pub(crate) use tracker::{Action, Tracker};
|
||||
|
||||
use crate::{
|
||||
connection::ProtocolVersion,
|
||||
enc::sym::{HeadLen, TagLen},
|
||||
enc::sym::{NonceLen, TagLen},
|
||||
};
|
||||
use ::num_traits::FromPrimitive;
|
||||
|
||||
|
@ -56,7 +57,7 @@ pub enum Error {
|
|||
::strum_macros::IntoStaticStr,
|
||||
)]
|
||||
#[repr(u8)]
|
||||
pub enum HandshakeID {
|
||||
pub enum ID {
|
||||
/// 1-RTT Directory synchronized handshake. Fast, no forward secrecy
|
||||
#[strum(serialize = "directory_synchronized")]
|
||||
DirectorySynchronized = 0,
|
||||
|
@ -67,7 +68,7 @@ pub enum HandshakeID {
|
|||
#[strum(serialize = "stateless")]
|
||||
Stateless,
|
||||
}
|
||||
impl HandshakeID {
|
||||
impl ID {
|
||||
/// The length of the serialized field
|
||||
pub const fn len() -> usize {
|
||||
1
|
||||
|
@ -75,28 +76,28 @@ impl HandshakeID {
|
|||
}
|
||||
/// Parsed handshake
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum HandshakeData {
|
||||
pub enum Data {
|
||||
/// Directory synchronized handhsake
|
||||
DirSync(dirsync::DirSync),
|
||||
}
|
||||
|
||||
impl HandshakeData {
|
||||
impl Data {
|
||||
/// actual length of the handshake data
|
||||
pub fn len(&self, head_len: HeadLen, tag_len: TagLen) -> usize {
|
||||
pub fn len(&self, head_len: NonceLen, tag_len: TagLen) -> usize {
|
||||
match self {
|
||||
HandshakeData::DirSync(d) => d.len(head_len, tag_len),
|
||||
Data::DirSync(d) => d.len(head_len, tag_len),
|
||||
}
|
||||
}
|
||||
/// Serialize into raw bytes
|
||||
/// NOTE: assumes that there is exactly asa much buffer as needed
|
||||
pub fn serialize(
|
||||
&self,
|
||||
head_len: HeadLen,
|
||||
head_len: NonceLen,
|
||||
tag_len: TagLen,
|
||||
out: &mut [u8],
|
||||
) {
|
||||
match self {
|
||||
HandshakeData::DirSync(d) => d.serialize(head_len, tag_len, out),
|
||||
Data::DirSync(d) => d.serialize(head_len, tag_len, out),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -133,19 +134,19 @@ pub struct Handshake {
|
|||
/// Fenrir Protocol version
|
||||
pub fenrir_version: ProtocolVersion,
|
||||
/// enum for the parsed data
|
||||
pub data: HandshakeData,
|
||||
pub data: Data,
|
||||
}
|
||||
|
||||
impl Handshake {
|
||||
/// Build new handshake from the data
|
||||
pub fn new(data: HandshakeData) -> Self {
|
||||
pub fn new(data: Data) -> Self {
|
||||
Handshake {
|
||||
fenrir_version: ProtocolVersion::V0,
|
||||
data,
|
||||
}
|
||||
}
|
||||
/// return the total length of the handshake
|
||||
pub fn len(&self, head_len: HeadLen, tag_len: TagLen) -> usize {
|
||||
pub fn len(&self, head_len: NonceLen, tag_len: TagLen) -> usize {
|
||||
ProtocolVersion::len()
|
||||
+ HandshakeKind::len()
|
||||
+ self.data.len(head_len, tag_len)
|
||||
|
@ -179,13 +180,13 @@ impl Handshake {
|
|||
/// NOTE: assumes that there is exactly as much buffer as needed
|
||||
pub fn serialize(
|
||||
&self,
|
||||
head_len: HeadLen,
|
||||
head_len: NonceLen,
|
||||
tag_len: TagLen,
|
||||
out: &mut [u8],
|
||||
) {
|
||||
out[0] = self.fenrir_version as u8;
|
||||
out[1] = match &self.data {
|
||||
HandshakeData::DirSync(d) => match d {
|
||||
Data::DirSync(d) => match d {
|
||||
dirsync::DirSync::Req(_) => HandshakeKind::DirSyncReq,
|
||||
dirsync::DirSync::Resp(_) => HandshakeKind::DirSyncResp,
|
||||
},
|
||||
|
@ -194,6 +195,6 @@ impl Handshake {
|
|||
}
|
||||
}
|
||||
|
||||
trait HandshakeParsing {
|
||||
fn deserialize(raw: &[u8]) -> Result<HandshakeData, Error>;
|
||||
trait Parsing {
|
||||
fn deserialize(raw: &[u8]) -> Result<Data, Error>;
|
||||
}
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
use crate::{
|
||||
auth,
|
||||
connection::{handshake::*, ID},
|
||||
connection::{
|
||||
handshake::{self, dirsync, Handshake},
|
||||
ID,
|
||||
},
|
||||
enc::{self, asym::KeyID},
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn test_handshake_dirsync_req() {
|
||||
let rand = enc::Random::new();
|
||||
let cipher = enc::sym::CipherKind::XChaCha20Poly1305;
|
||||
let cipher = enc::sym::Kind::XChaCha20Poly1305;
|
||||
|
||||
let (_, exchange_key) =
|
||||
match enc::asym::KeyExchangeKind::X25519DiffieHellman.new_keypair(&rand)
|
||||
|
@ -19,7 +22,7 @@ fn test_handshake_dirsync_req() {
|
|||
}
|
||||
};
|
||||
|
||||
let data = dirsync::ReqInner::ClearText(dirsync::ReqData {
|
||||
let data = dirsync::ReqState::ClearText(dirsync::ReqData {
|
||||
nonce: dirsync::Nonce::new(&rand),
|
||||
client_key_id: KeyID(2424),
|
||||
id: ID::ID(::core::num::NonZeroU64::new(424242).unwrap()),
|
||||
|
@ -31,16 +34,16 @@ fn test_handshake_dirsync_req() {
|
|||
},
|
||||
});
|
||||
|
||||
let h_req = Handshake::new(HandshakeData::DirSync(dirsync::DirSync::Req(
|
||||
dirsync::Req {
|
||||
let h_req = Handshake::new(handshake::Data::DirSync(
|
||||
dirsync::DirSync::Req(dirsync::Req {
|
||||
key_id: KeyID(4224),
|
||||
exchange: enc::asym::KeyExchangeKind::X25519DiffieHellman,
|
||||
hkdf: enc::hkdf::HkdfKind::Sha3,
|
||||
cipher: enc::sym::CipherKind::XChaCha20Poly1305,
|
||||
hkdf: enc::hkdf::Kind::Sha3,
|
||||
cipher: enc::sym::Kind::XChaCha20Poly1305,
|
||||
exchange_key,
|
||||
data,
|
||||
},
|
||||
)));
|
||||
}),
|
||||
));
|
||||
|
||||
let mut bytes = Vec::<u8>::with_capacity(
|
||||
h_req.len(cipher.nonce_len(), cipher.tag_len()),
|
||||
|
@ -55,7 +58,7 @@ fn test_handshake_dirsync_req() {
|
|||
return;
|
||||
}
|
||||
};
|
||||
if let HandshakeData::DirSync(dirsync::DirSync::Req(r_a)) =
|
||||
if let handshake::Data::DirSync(dirsync::DirSync::Req(r_a)) =
|
||||
&mut deserialized.data
|
||||
{
|
||||
let enc_start = r_a.encrypted_offset() + cipher.nonce_len().0;
|
||||
|
@ -74,11 +77,11 @@ fn test_handshake_dirsync_req() {
|
|||
#[test]
|
||||
fn test_handshake_dirsync_reqsp() {
|
||||
let rand = enc::Random::new();
|
||||
let cipher = enc::sym::CipherKind::XChaCha20Poly1305;
|
||||
let cipher = enc::sym::Kind::XChaCha20Poly1305;
|
||||
|
||||
let service_key = enc::Secret::new_rand(&rand);
|
||||
|
||||
let data = dirsync::RespInner::ClearText(dirsync::RespData {
|
||||
let data = dirsync::RespState::ClearText(dirsync::RespData {
|
||||
client_nonce: dirsync::Nonce::new(&rand),
|
||||
id: ID::ID(::core::num::NonZeroU64::new(424242).unwrap()),
|
||||
service_connection_id: ID::ID(
|
||||
|
@ -87,7 +90,7 @@ fn test_handshake_dirsync_reqsp() {
|
|||
service_key,
|
||||
});
|
||||
|
||||
let h_resp = Handshake::new(HandshakeData::DirSync(
|
||||
let h_resp = Handshake::new(handshake::Data::DirSync(
|
||||
dirsync::DirSync::Resp(dirsync::Resp {
|
||||
client_key_id: KeyID(4444),
|
||||
data,
|
||||
|
@ -107,7 +110,7 @@ fn test_handshake_dirsync_reqsp() {
|
|||
return;
|
||||
}
|
||||
};
|
||||
if let HandshakeData::DirSync(dirsync::DirSync::Resp(r_a)) =
|
||||
if let handshake::Data::DirSync(dirsync::DirSync::Resp(r_a)) =
|
||||
&mut deserialized.data
|
||||
{
|
||||
let enc_start = r_a.encrypted_offset() + cipher.nonce_len().0;
|
||||
|
|
|
@ -3,22 +3,21 @@
|
|||
use crate::{
|
||||
auth::{Domain, ServiceID},
|
||||
connection::{
|
||||
self,
|
||||
handshake::{self, Error, Handshake},
|
||||
Conn, IDRecv, IDSend,
|
||||
},
|
||||
enc::{
|
||||
self,
|
||||
asym::{self, KeyID, PrivKey, PubKey},
|
||||
hkdf::{Hkdf, HkdfKind},
|
||||
sym::{CipherKind, CipherRecv},
|
||||
hkdf::{self, Hkdf},
|
||||
sym::{self, CipherRecv},
|
||||
},
|
||||
inner::ThreadTracker,
|
||||
};
|
||||
|
||||
use ::tokio::sync::oneshot;
|
||||
|
||||
pub(crate) struct HandshakeServer {
|
||||
pub(crate) struct Server {
|
||||
pub id: KeyID,
|
||||
pub key: PrivKey,
|
||||
pub domains: Vec<Domain>,
|
||||
|
@ -26,7 +25,7 @@ pub(crate) struct HandshakeServer {
|
|||
|
||||
pub(crate) type ConnectAnswer = Result<(KeyID, IDSend), crate::Error>;
|
||||
|
||||
pub(crate) struct HandshakeClient {
|
||||
pub(crate) struct Client {
|
||||
pub service_id: ServiceID,
|
||||
pub service_conn_id: IDRecv,
|
||||
pub connection: Conn,
|
||||
|
@ -37,13 +36,13 @@ pub(crate) struct HandshakeClient {
|
|||
|
||||
/// Tracks the keys used by the client and the handshake
|
||||
/// they are associated with
|
||||
pub(crate) struct HandshakeClientList {
|
||||
pub(crate) struct ClientList {
|
||||
used: Vec<::bitmaps::Bitmap<1024>>, // index = KeyID
|
||||
keys: Vec<Option<(PrivKey, PubKey)>>,
|
||||
list: Vec<Option<HandshakeClient>>,
|
||||
list: Vec<Option<Client>>,
|
||||
}
|
||||
|
||||
impl HandshakeClientList {
|
||||
impl ClientList {
|
||||
pub(crate) fn new() -> Self {
|
||||
Self {
|
||||
used: [::bitmaps::Bitmap::<1024>::new()].to_vec(),
|
||||
|
@ -51,13 +50,13 @@ impl HandshakeClientList {
|
|||
list: Vec::with_capacity(16),
|
||||
}
|
||||
}
|
||||
pub(crate) fn get(&self, id: KeyID) -> Option<&HandshakeClient> {
|
||||
pub(crate) fn get(&self, id: KeyID) -> Option<&Client> {
|
||||
if id.0 as usize >= self.list.len() {
|
||||
return None;
|
||||
}
|
||||
self.list[id.0 as usize].as_ref()
|
||||
}
|
||||
pub(crate) fn remove(&mut self, id: KeyID) -> Option<HandshakeClient> {
|
||||
pub(crate) fn remove(&mut self, id: KeyID) -> Option<Client> {
|
||||
if id.0 as usize >= self.list.len() {
|
||||
return None;
|
||||
}
|
||||
|
@ -82,8 +81,7 @@ impl HandshakeClientList {
|
|||
connection: Conn,
|
||||
answer: oneshot::Sender<ConnectAnswer>,
|
||||
srv_key_id: KeyID,
|
||||
) -> Result<(KeyID, &mut HandshakeClient), oneshot::Sender<ConnectAnswer>>
|
||||
{
|
||||
) -> Result<(KeyID, &mut Client), oneshot::Sender<ConnectAnswer>> {
|
||||
let maybe_free_key_idx =
|
||||
self.used.iter().enumerate().find_map(|(idx, bmap)| {
|
||||
match bmap.first_false_index() {
|
||||
|
@ -112,7 +110,7 @@ impl HandshakeClientList {
|
|||
self.list.push(None);
|
||||
}
|
||||
self.keys[free_key_idx] = Some((priv_key, pub_key));
|
||||
self.list[free_key_idx] = Some(HandshakeClient {
|
||||
self.list[free_key_idx] = Some(Client {
|
||||
service_id,
|
||||
service_conn_id,
|
||||
connection,
|
||||
|
@ -153,7 +151,7 @@ pub(crate) struct ClientConnectInfo {
|
|||
}
|
||||
/// Intermediate actions to be taken while parsing the handshake
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum HandshakeAction {
|
||||
pub(crate) enum Action {
|
||||
/// Parsing finished, all ok, nothing to do
|
||||
Nothing,
|
||||
/// Packet parsed, now go perform authentication
|
||||
|
@ -167,20 +165,20 @@ pub(crate) enum HandshakeAction {
|
|||
/// Each of them will handle a subset of all handshakes.
|
||||
/// Each handshake is routed to a different tracker by checking
|
||||
/// core = (udp_src_sender_port % total_threads) - 1
|
||||
pub(crate) struct HandshakeTracker {
|
||||
pub(crate) struct Tracker {
|
||||
thread_id: ThreadTracker,
|
||||
key_exchanges: Vec<asym::KeyExchangeKind>,
|
||||
ciphers: Vec<CipherKind>,
|
||||
ciphers: Vec<sym::Kind>,
|
||||
/// ephemeral keys used server side in key exchange
|
||||
keys_srv: Vec<HandshakeServer>,
|
||||
keys_srv: Vec<Server>,
|
||||
/// ephemeral keys used client side in key exchange
|
||||
hshake_cli: HandshakeClientList,
|
||||
hshake_cli: ClientList,
|
||||
}
|
||||
|
||||
impl HandshakeTracker {
|
||||
impl Tracker {
|
||||
pub(crate) fn new(
|
||||
thread_id: ThreadTracker,
|
||||
ciphers: Vec<CipherKind>,
|
||||
ciphers: Vec<sym::Kind>,
|
||||
key_exchanges: Vec<asym::KeyExchangeKind>,
|
||||
) -> Self {
|
||||
Self {
|
||||
|
@ -188,7 +186,7 @@ impl HandshakeTracker {
|
|||
ciphers,
|
||||
key_exchanges,
|
||||
keys_srv: Vec::new(),
|
||||
hshake_cli: HandshakeClientList::new(),
|
||||
hshake_cli: ClientList::new(),
|
||||
}
|
||||
}
|
||||
pub(crate) fn add_server_key(
|
||||
|
@ -199,7 +197,7 @@ impl HandshakeTracker {
|
|||
if self.keys_srv.iter().find(|&k| k.id == id).is_some() {
|
||||
return Err(());
|
||||
}
|
||||
self.keys_srv.push(HandshakeServer {
|
||||
self.keys_srv.push(Server {
|
||||
id,
|
||||
key,
|
||||
domains: Vec::new(),
|
||||
|
@ -236,8 +234,7 @@ impl HandshakeTracker {
|
|||
connection: Conn,
|
||||
answer: oneshot::Sender<ConnectAnswer>,
|
||||
srv_key_id: KeyID,
|
||||
) -> Result<(KeyID, &mut HandshakeClient), oneshot::Sender<ConnectAnswer>>
|
||||
{
|
||||
) -> Result<(KeyID, &mut Client), oneshot::Sender<ConnectAnswer>> {
|
||||
self.hshake_cli.add(
|
||||
priv_key,
|
||||
pub_key,
|
||||
|
@ -248,10 +245,7 @@ impl HandshakeTracker {
|
|||
srv_key_id,
|
||||
)
|
||||
}
|
||||
pub(crate) fn remove_client(
|
||||
&mut self,
|
||||
key_id: KeyID,
|
||||
) -> Option<HandshakeClient> {
|
||||
pub(crate) fn remove_client(&mut self, key_id: KeyID) -> Option<Client> {
|
||||
self.hshake_cli.remove(key_id)
|
||||
}
|
||||
pub(crate) fn timeout_client(
|
||||
|
@ -269,10 +263,10 @@ impl HandshakeTracker {
|
|||
&mut self,
|
||||
mut handshake: Handshake,
|
||||
handshake_raw: &mut [u8],
|
||||
) -> Result<HandshakeAction, Error> {
|
||||
use connection::handshake::{dirsync::DirSync, HandshakeData};
|
||||
) -> Result<Action, Error> {
|
||||
use handshake::dirsync::DirSync;
|
||||
match handshake.data {
|
||||
HandshakeData::DirSync(ref mut ds) => match ds {
|
||||
handshake::Data::DirSync(ref mut ds) => match ds {
|
||||
DirSync::Req(ref mut req) => {
|
||||
if !self.key_exchanges.contains(&req.exchange) {
|
||||
return Err(enc::Error::UnsupportedKeyExchange.into());
|
||||
|
@ -310,7 +304,8 @@ impl HandshakeTracker {
|
|||
Ok(shared_key) => shared_key,
|
||||
Err(e) => return Err(handshake::Error::Key(e).into()),
|
||||
};
|
||||
let hkdf = Hkdf::new(HkdfKind::Sha3, b"fenrir", shared_key);
|
||||
let hkdf =
|
||||
Hkdf::new(hkdf::Kind::Sha3, b"fenrir", shared_key);
|
||||
let secret_recv = hkdf.get_secret(b"to_server");
|
||||
let cipher_recv = CipherRecv::new(req.cipher, secret_recv);
|
||||
use crate::enc::sym::AAD;
|
||||
|
@ -334,7 +329,7 @@ impl HandshakeTracker {
|
|||
}
|
||||
}
|
||||
|
||||
return Ok(HandshakeAction::AuthNeeded(AuthNeededInfo {
|
||||
return Ok(Action::AuthNeeded(AuthNeededInfo {
|
||||
handshake,
|
||||
hkdf,
|
||||
}));
|
||||
|
@ -374,16 +369,14 @@ impl HandshakeTracker {
|
|||
if let Some(timeout) = hshake.timeout {
|
||||
timeout.abort();
|
||||
}
|
||||
return Ok(HandshakeAction::ClientConnect(
|
||||
ClientConnectInfo {
|
||||
service_id: hshake.service_id,
|
||||
service_connection_id: hshake.service_conn_id,
|
||||
handshake,
|
||||
connection: hshake.connection,
|
||||
answer: hshake.answer,
|
||||
srv_key_id: hshake.srv_key_id,
|
||||
},
|
||||
));
|
||||
return Ok(Action::ClientConnect(ClientConnectInfo {
|
||||
service_id: hshake.service_id,
|
||||
service_connection_id: hshake.service_conn_id,
|
||||
handshake,
|
||||
connection: hshake.connection,
|
||||
answer: hshake.answer,
|
||||
srv_key_id: hshake.srv_key_id,
|
||||
}));
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ use crate::{
|
|||
enc::{
|
||||
asym::PubKey,
|
||||
hkdf::Hkdf,
|
||||
sym::{CipherKind, CipherRecv, CipherSend},
|
||||
sym::{self, CipherRecv, CipherSend},
|
||||
Random,
|
||||
},
|
||||
inner::ThreadTracker,
|
||||
|
@ -163,7 +163,7 @@ pub enum Role {
|
|||
impl Conn {
|
||||
pub(crate) fn new(
|
||||
hkdf: Hkdf,
|
||||
cipher: CipherKind,
|
||||
cipher: sym::Kind,
|
||||
role: Role,
|
||||
rand: &Random,
|
||||
) -> Self {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
use crate::{
|
||||
connection,
|
||||
enc::sym::{HeadLen, TagLen},
|
||||
enc::sym::{NonceLen, TagLen},
|
||||
};
|
||||
|
||||
/// Enumerate the possible data in a fenrir packet
|
||||
|
@ -17,7 +17,7 @@ pub enum Data {
|
|||
|
||||
impl Data {
|
||||
/// total length of the data in bytes
|
||||
pub fn len(&self, head_len: HeadLen, tag_len: TagLen) -> usize {
|
||||
pub fn len(&self, head_len: NonceLen, tag_len: TagLen) -> usize {
|
||||
match self {
|
||||
Data::Handshake(h) => h.len(head_len, tag_len),
|
||||
Data::Raw(len) => *len,
|
||||
|
@ -27,7 +27,7 @@ impl Data {
|
|||
/// NOTE: assumes that there is exactly asa much buffer as needed
|
||||
pub fn serialize(
|
||||
&self,
|
||||
head_len: HeadLen,
|
||||
head_len: NonceLen,
|
||||
tag_len: TagLen,
|
||||
out: &mut [u8],
|
||||
) {
|
||||
|
@ -69,14 +69,14 @@ impl Packet {
|
|||
})
|
||||
}
|
||||
/// get the total length of the packet
|
||||
pub fn len(&self, head_len: HeadLen, tag_len: TagLen) -> usize {
|
||||
pub fn len(&self, head_len: NonceLen, tag_len: TagLen) -> usize {
|
||||
connection::ID::len() + self.data.len(head_len, tag_len)
|
||||
}
|
||||
/// serialize packet into buffer
|
||||
/// NOTE: assumes that there is exactly asa much buffer as needed
|
||||
pub fn serialize(
|
||||
&self,
|
||||
head_len: HeadLen,
|
||||
head_len: NonceLen,
|
||||
tag_len: TagLen,
|
||||
out: &mut [u8],
|
||||
) {
|
||||
|
|
|
@ -43,12 +43,11 @@
|
|||
//! ]
|
||||
|
||||
use crate::{
|
||||
connection::handshake::HandshakeID,
|
||||
connection::handshake,
|
||||
enc::{
|
||||
self,
|
||||
asym::{KeyExchangeKind, KeyID, PubKey},
|
||||
hkdf::HkdfKind,
|
||||
sym::CipherKind,
|
||||
hkdf, sym,
|
||||
},
|
||||
};
|
||||
use ::core::num::NonZeroU16;
|
||||
|
@ -180,7 +179,7 @@ pub struct Address {
|
|||
/// Weight of this address in the priority group
|
||||
pub weight: AddressWeight,
|
||||
/// List of supported handshakes
|
||||
pub handshake_ids: Vec<HandshakeID>,
|
||||
pub handshake_ids: Vec<handshake::ID>,
|
||||
/// Public key IDs used by this address
|
||||
pub public_key_idx: Vec<PubKeyIdx>,
|
||||
}
|
||||
|
@ -331,7 +330,7 @@ impl Address {
|
|||
for raw_handshake_id in
|
||||
raw[bytes_parsed..(bytes_parsed + num_handshake_ids)].iter()
|
||||
{
|
||||
match HandshakeID::from_u8(*raw_handshake_id) {
|
||||
match handshake::ID::from_u8(*raw_handshake_id) {
|
||||
Some(h_id) => handshake_ids.push(h_id),
|
||||
None => {
|
||||
::tracing::warn!(
|
||||
|
@ -392,9 +391,9 @@ pub struct Record {
|
|||
/// List of supported key exchanges
|
||||
pub key_exchanges: Vec<KeyExchangeKind>,
|
||||
/// List of supported key exchanges
|
||||
pub hkdfs: Vec<HkdfKind>,
|
||||
pub hkdfs: Vec<hkdf::Kind>,
|
||||
/// List of supported ciphers
|
||||
pub ciphers: Vec<CipherKind>,
|
||||
pub ciphers: Vec<sym::Kind>,
|
||||
}
|
||||
|
||||
impl Record {
|
||||
|
@ -597,7 +596,7 @@ impl Record {
|
|||
num_key_exchanges = num_key_exchanges - 1;
|
||||
}
|
||||
while num_hkdfs > 0 {
|
||||
let hkdf = match HkdfKind::from_u8(raw[bytes_parsed]) {
|
||||
let hkdf = match hkdf::Kind::from_u8(raw[bytes_parsed]) {
|
||||
Some(hkdf) => hkdf,
|
||||
None => {
|
||||
// continue parsing. This could be a new hkdf type
|
||||
|
@ -615,7 +614,7 @@ impl Record {
|
|||
num_hkdfs = num_hkdfs - 1;
|
||||
}
|
||||
while num_ciphers > 0 {
|
||||
let cipher = match CipherKind::from_u8(raw[bytes_parsed]) {
|
||||
let cipher = match sym::Kind::from_u8(raw[bytes_parsed]) {
|
||||
Some(cipher) => cipher,
|
||||
None => {
|
||||
// continue parsing. This could be a new cipher type
|
||||
|
|
|
@ -12,7 +12,7 @@ fn test_dnssec_serialization() {
|
|||
return;
|
||||
}
|
||||
};
|
||||
use crate::{connection::handshake::HandshakeID, enc};
|
||||
use crate::{connection::handshake, enc};
|
||||
|
||||
let record = Record {
|
||||
public_keys: [(
|
||||
|
@ -25,14 +25,14 @@ fn test_dnssec_serialization() {
|
|||
port: Some(::core::num::NonZeroU16::new(31337).unwrap()),
|
||||
priority: record::AddressPriority::P1,
|
||||
weight: record::AddressWeight::W1,
|
||||
handshake_ids: [HandshakeID::DirectorySynchronized].to_vec(),
|
||||
handshake_ids: [handshake::ID::DirectorySynchronized].to_vec(),
|
||||
public_key_idx: [record::PubKeyIdx(0)].to_vec(),
|
||||
}]
|
||||
.to_vec(),
|
||||
key_exchanges: [enc::asym::KeyExchangeKind::X25519DiffieHellman]
|
||||
.to_vec(),
|
||||
hkdfs: [enc::hkdf::HkdfKind::Sha3].to_vec(),
|
||||
ciphers: [enc::sym::CipherKind::XChaCha20Poly1305].to_vec(),
|
||||
hkdfs: [enc::hkdf::Kind::Sha3].to_vec(),
|
||||
ciphers: [enc::sym::Kind::XChaCha20Poly1305].to_vec(),
|
||||
};
|
||||
let encoded = match record.encode() {
|
||||
Ok(encoded) => encoded,
|
||||
|
|
|
@ -45,7 +45,7 @@ impl ::std::fmt::Display for KeyID {
|
|||
|
||||
/// Capabilities of each key
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum KeyCapabilities {
|
||||
pub enum Capabilities {
|
||||
/// signing *only*
|
||||
Sign,
|
||||
/// encrypt *only*
|
||||
|
@ -61,13 +61,13 @@ pub enum KeyCapabilities {
|
|||
/// All: sign, encrypt, Key Exchange
|
||||
SignEncryptExchage,
|
||||
}
|
||||
impl KeyCapabilities {
|
||||
impl Capabilities {
|
||||
/// Check if this key supports eky exchage
|
||||
pub fn has_exchange(&self) -> bool {
|
||||
match self {
|
||||
KeyCapabilities::Exchange
|
||||
| KeyCapabilities::SignExchange
|
||||
| KeyCapabilities::SignEncryptExchage => true,
|
||||
Capabilities::Exchange
|
||||
| Capabilities::SignExchange
|
||||
| Capabilities::SignEncryptExchage => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ impl KeyCapabilities {
|
|||
)]
|
||||
#[non_exhaustive]
|
||||
#[repr(u8)]
|
||||
pub enum KeyKind {
|
||||
pub enum Kind {
|
||||
/// Ed25519 Public key (sign only)
|
||||
#[strum(serialize = "ed25519")]
|
||||
Ed25519 = 0,
|
||||
|
@ -93,25 +93,25 @@ pub enum KeyKind {
|
|||
#[strum(serialize = "x25519")]
|
||||
X25519,
|
||||
}
|
||||
impl KeyKind {
|
||||
impl Kind {
|
||||
/// Length of the serialized field
|
||||
pub const fn len() -> usize {
|
||||
1
|
||||
}
|
||||
/// return the expected length of the public key
|
||||
pub fn pub_len(&self) -> usize {
|
||||
KeyKind::len()
|
||||
Kind::len()
|
||||
+ match self {
|
||||
// FIXME: 99% wrong size
|
||||
KeyKind::Ed25519 => ::ring::signature::ED25519_PUBLIC_KEY_LEN,
|
||||
KeyKind::X25519 => 32,
|
||||
Kind::Ed25519 => ::ring::signature::ED25519_PUBLIC_KEY_LEN,
|
||||
Kind::X25519 => 32,
|
||||
}
|
||||
}
|
||||
/// Get the capabilities of this key type
|
||||
pub fn capabilities(&self) -> KeyCapabilities {
|
||||
pub fn capabilities(&self) -> Capabilities {
|
||||
match self {
|
||||
KeyKind::Ed25519 => KeyCapabilities::Sign,
|
||||
KeyKind::X25519 => KeyCapabilities::Exchange,
|
||||
Kind::Ed25519 => Capabilities::Sign,
|
||||
Kind::X25519 => Capabilities::Exchange,
|
||||
}
|
||||
}
|
||||
/// Returns the key exchanges supported by this key
|
||||
|
@ -120,8 +120,8 @@ impl KeyKind {
|
|||
const X25519_KEY_EXCHANGES: [KeyExchangeKind; 1] =
|
||||
[KeyExchangeKind::X25519DiffieHellman];
|
||||
match self {
|
||||
KeyKind::Ed25519 => &EMPTY,
|
||||
KeyKind::X25519 => &X25519_KEY_EXCHANGES,
|
||||
Kind::Ed25519 => &EMPTY,
|
||||
Kind::X25519 => &X25519_KEY_EXCHANGES,
|
||||
}
|
||||
}
|
||||
/// generate new keypair
|
||||
|
@ -193,21 +193,21 @@ impl PubKey {
|
|||
}
|
||||
}
|
||||
/// return the kind of public key
|
||||
pub fn kind(&self) -> KeyKind {
|
||||
pub fn kind(&self) -> Kind {
|
||||
match self {
|
||||
// FIXME: lie, we don't fully support this
|
||||
PubKey::Signing => KeyKind::Ed25519,
|
||||
PubKey::Signing => Kind::Ed25519,
|
||||
PubKey::Exchange(ex) => ex.kind(),
|
||||
}
|
||||
}
|
||||
/// generate new keypair
|
||||
fn new_keypair(
|
||||
kind: KeyKind,
|
||||
kind: Kind,
|
||||
rnd: &Random,
|
||||
) -> Result<(PrivKey, PubKey), Error> {
|
||||
match kind {
|
||||
KeyKind::Ed25519 => todo!(),
|
||||
KeyKind::X25519 => {
|
||||
Kind::Ed25519 => todo!(),
|
||||
Kind::X25519 => {
|
||||
let (priv_key, pub_key) =
|
||||
KeyExchangeKind::X25519DiffieHellman.new_keypair(rnd)?;
|
||||
Ok((PrivKey::Exchange(priv_key), PubKey::Exchange(pub_key)))
|
||||
|
@ -231,7 +231,7 @@ impl PubKey {
|
|||
if raw.len() < 1 {
|
||||
return Err(Error::NotEnoughData(0));
|
||||
}
|
||||
let kind: KeyKind = match KeyKind::from_u8(raw[0]) {
|
||||
let kind: Kind = match Kind::from_u8(raw[0]) {
|
||||
Some(kind) => kind,
|
||||
None => return Err(Error::UnsupportedKey(1)),
|
||||
};
|
||||
|
@ -239,11 +239,11 @@ impl PubKey {
|
|||
return Err(Error::NotEnoughData(1));
|
||||
}
|
||||
match kind {
|
||||
KeyKind::Ed25519 => {
|
||||
Kind::Ed25519 => {
|
||||
::tracing::error!("ed25519 keys are not yet supported");
|
||||
return Err(Error::Parsing);
|
||||
}
|
||||
KeyKind::X25519 => {
|
||||
Kind::X25519 => {
|
||||
let pub_key: ::x25519_dalek::PublicKey =
|
||||
//match ::bincode::deserialize(&raw[1..(1 + kind.pub_len())])
|
||||
match ::bincode::deserialize(&raw[1..])
|
||||
|
@ -284,7 +284,7 @@ impl PrivKey {
|
|||
}
|
||||
}
|
||||
/// return the kind of public key
|
||||
pub fn kind(&self) -> KeyKind {
|
||||
pub fn kind(&self) -> Kind {
|
||||
match self {
|
||||
PrivKey::Signing => todo!(),
|
||||
PrivKey::Exchange(ex) => ex.kind(),
|
||||
|
@ -322,13 +322,13 @@ impl ExchangePrivKey {
|
|||
/// Get the serialized key length
|
||||
pub fn len(&self) -> usize {
|
||||
match self {
|
||||
ExchangePrivKey::X25519(_) => KeyKind::X25519.pub_len(),
|
||||
ExchangePrivKey::X25519(_) => Kind::X25519.pub_len(),
|
||||
}
|
||||
}
|
||||
/// Get the kind of key
|
||||
pub fn kind(&self) -> KeyKind {
|
||||
pub fn kind(&self) -> Kind {
|
||||
match self {
|
||||
ExchangePrivKey::X25519(_) => KeyKind::X25519,
|
||||
ExchangePrivKey::X25519(_) => Kind::X25519,
|
||||
}
|
||||
}
|
||||
/// Run the key exchange between two keys of the same kind
|
||||
|
@ -372,13 +372,13 @@ impl ExchangePubKey {
|
|||
/// Get the serialized key length
|
||||
pub fn len(&self) -> usize {
|
||||
match self {
|
||||
ExchangePubKey::X25519(_) => KeyKind::X25519.pub_len(),
|
||||
ExchangePubKey::X25519(_) => Kind::X25519.pub_len(),
|
||||
}
|
||||
}
|
||||
/// Get the kind of key
|
||||
pub fn kind(&self) -> KeyKind {
|
||||
pub fn kind(&self) -> Kind {
|
||||
match self {
|
||||
ExchangePubKey::X25519(_) => KeyKind::X25519,
|
||||
ExchangePubKey::X25519(_) => Kind::X25519,
|
||||
}
|
||||
}
|
||||
/// serialize the key into the buffer
|
||||
|
@ -396,13 +396,13 @@ impl ExchangePubKey {
|
|||
/// The riesult is "unparsed" since we don't verify
|
||||
/// the actual key
|
||||
pub fn deserialize(raw: &[u8]) -> Result<(Self, usize), Error> {
|
||||
match KeyKind::from_u8(raw[0]) {
|
||||
match Kind::from_u8(raw[0]) {
|
||||
Some(kind) => match kind {
|
||||
KeyKind::Ed25519 => {
|
||||
Kind::Ed25519 => {
|
||||
::tracing::error!("ed25519 keys are not yet supported");
|
||||
return Err(Error::Parsing);
|
||||
}
|
||||
KeyKind::X25519 => {
|
||||
Kind::X25519 => {
|
||||
let pub_key: ::x25519_dalek::PublicKey =
|
||||
match ::bincode::deserialize(
|
||||
&raw[1..(1 + kind.pub_len())],
|
||||
|
|
|
@ -18,12 +18,12 @@ use crate::{config::Config, enc::Secret};
|
|||
)]
|
||||
#[non_exhaustive]
|
||||
#[repr(u8)]
|
||||
pub enum HkdfKind {
|
||||
pub enum Kind {
|
||||
/// Sha3
|
||||
#[strum(serialize = "sha3")]
|
||||
Sha3 = 0,
|
||||
}
|
||||
impl HkdfKind {
|
||||
impl Kind {
|
||||
/// Length of the serialized type
|
||||
pub const fn len() -> usize {
|
||||
1
|
||||
|
@ -34,7 +34,7 @@ impl HkdfKind {
|
|||
#[derive(Clone)]
|
||||
pub enum Hkdf {
|
||||
/// Sha3 based
|
||||
Sha3(HkdfSha3),
|
||||
Sha3(Sha3),
|
||||
}
|
||||
|
||||
// Fake debug implementation to avoid leaking secrets
|
||||
|
@ -49,9 +49,9 @@ impl ::core::fmt::Debug for Hkdf {
|
|||
|
||||
impl Hkdf {
|
||||
/// New Hkdf
|
||||
pub fn new(kind: HkdfKind, salt: &[u8], key: Secret) -> Self {
|
||||
pub fn new(kind: Kind, salt: &[u8], key: Secret) -> Self {
|
||||
match kind {
|
||||
HkdfKind::Sha3 => Self::Sha3(HkdfSha3::new(salt, key)),
|
||||
Kind::Sha3 => Self::Sha3(Sha3::new(salt, key)),
|
||||
}
|
||||
}
|
||||
/// Get a secret generated from the key and a given context
|
||||
|
@ -61,9 +61,9 @@ impl Hkdf {
|
|||
}
|
||||
}
|
||||
/// get the kind of this Hkdf
|
||||
pub fn kind(&self) -> HkdfKind {
|
||||
pub fn kind(&self) -> Kind {
|
||||
match self {
|
||||
Hkdf::Sha3(_) => HkdfKind::Sha3,
|
||||
Hkdf::Sha3(_) => Kind::Sha3,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -106,11 +106,11 @@ impl Clone for HkdfInner {
|
|||
|
||||
/// Sha3 based HKDF
|
||||
#[derive(Clone)]
|
||||
pub struct HkdfSha3 {
|
||||
pub struct Sha3 {
|
||||
inner: HkdfInner,
|
||||
}
|
||||
|
||||
impl HkdfSha3 {
|
||||
impl Sha3 {
|
||||
/// Instantiate a new HKDF with Sha3-256
|
||||
pub(crate) fn new(salt: &[u8], key: Secret) -> Self {
|
||||
let hkdf = ::hkdf::Hkdf::<Sha3_256>::new(Some(salt), key.as_ref());
|
||||
|
@ -132,7 +132,7 @@ impl HkdfSha3 {
|
|||
}
|
||||
|
||||
// Fake debug implementation to avoid leaking secrets
|
||||
impl ::core::fmt::Debug for HkdfSha3 {
|
||||
impl ::core::fmt::Debug for Sha3 {
|
||||
fn fmt(
|
||||
&self,
|
||||
f: &mut core::fmt::Formatter<'_>,
|
||||
|
@ -146,8 +146,8 @@ impl ::core::fmt::Debug for HkdfSha3 {
|
|||
/// Give priority to our list
|
||||
pub fn server_select_hkdf(
|
||||
cfg: &Config,
|
||||
client_supported: &Vec<HkdfKind>,
|
||||
) -> Option<HkdfKind> {
|
||||
client_supported: &Vec<Kind>,
|
||||
) -> Option<Kind> {
|
||||
cfg.hkdfs
|
||||
.iter()
|
||||
.find(|h| client_supported.contains(h))
|
||||
|
@ -159,8 +159,8 @@ pub fn server_select_hkdf(
|
|||
/// this is used only in the directory synchronized handshake
|
||||
pub fn client_select_hkdf(
|
||||
cfg: &Config,
|
||||
server_supported: &Vec<HkdfKind>,
|
||||
) -> Option<HkdfKind> {
|
||||
server_supported: &Vec<Kind>,
|
||||
) -> Option<Kind> {
|
||||
server_supported
|
||||
.iter()
|
||||
.find(|h| cfg.hkdfs.contains(h))
|
||||
|
|
107
src/enc/sym.rs
107
src/enc/sym.rs
|
@ -17,20 +17,20 @@ use crate::{
|
|||
::strum_macros::IntoStaticStr,
|
||||
)]
|
||||
#[repr(u8)]
|
||||
pub enum CipherKind {
|
||||
pub enum Kind {
|
||||
/// XChaCha20_Poly1305
|
||||
#[strum(serialize = "xchacha20poly1305")]
|
||||
XChaCha20Poly1305 = 0,
|
||||
}
|
||||
|
||||
impl CipherKind {
|
||||
impl Kind {
|
||||
/// length of the serialized id for the cipher kind field
|
||||
pub const fn len() -> usize {
|
||||
1
|
||||
}
|
||||
/// required length of the nonce
|
||||
pub fn nonce_len(&self) -> HeadLen {
|
||||
HeadLen(Nonce::len())
|
||||
pub fn nonce_len(&self) -> NonceLen {
|
||||
Nonce::len()
|
||||
}
|
||||
/// required length of the key
|
||||
pub fn key_len(&self) -> usize {
|
||||
|
@ -48,21 +48,10 @@ impl CipherKind {
|
|||
#[derive(Debug)]
|
||||
pub struct AAD<'a>(pub &'a [u8]);
|
||||
|
||||
/// Cipher direction, to make sure we don't reuse the same cipher
|
||||
/// for both decrypting and encrypting
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[repr(u8)]
|
||||
pub enum CipherDirection {
|
||||
/// Receive, to decrypt only
|
||||
Recv = 0,
|
||||
/// Send, to encrypt only
|
||||
Send,
|
||||
}
|
||||
|
||||
/// strong typedef for header length
|
||||
/// aka: nonce length in the encrypted data)
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct HeadLen(pub usize);
|
||||
pub struct NonceLen(pub usize);
|
||||
/// strong typedef for the Tag length
|
||||
/// aka: cryptographic authentication tag length at the end
|
||||
/// of the encrypted data
|
||||
|
@ -77,21 +66,21 @@ enum Cipher {
|
|||
|
||||
impl Cipher {
|
||||
/// Build a new Cipher
|
||||
fn new(kind: CipherKind, secret: Secret) -> Self {
|
||||
fn new(kind: Kind, secret: Secret) -> Self {
|
||||
match kind {
|
||||
CipherKind::XChaCha20Poly1305 => {
|
||||
Kind::XChaCha20Poly1305 => {
|
||||
Self::XChaCha20Poly1305(XChaCha20Poly1305::new(secret))
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn kind(&self) -> CipherKind {
|
||||
pub fn kind(&self) -> Kind {
|
||||
match self {
|
||||
Cipher::XChaCha20Poly1305(_) => CipherKind::XChaCha20Poly1305,
|
||||
Cipher::XChaCha20Poly1305(_) => Kind::XChaCha20Poly1305,
|
||||
}
|
||||
}
|
||||
fn nonce_len(&self) -> HeadLen {
|
||||
fn nonce_len(&self) -> NonceLen {
|
||||
match self {
|
||||
Cipher::XChaCha20Poly1305(_) => HeadLen(Nonce::len()),
|
||||
Cipher::XChaCha20Poly1305(_) => Nonce::len(),
|
||||
}
|
||||
}
|
||||
fn tag_len(&self) -> TagLen {
|
||||
|
@ -117,7 +106,7 @@ impl Cipher {
|
|||
return Err(Error::NotEnoughData(raw_data.len()));
|
||||
}
|
||||
let (nonce_bytes, data_and_tag) =
|
||||
raw_data.split_at_mut(Nonce::len());
|
||||
raw_data.split_at_mut(Nonce::len().0);
|
||||
let (data_notag, tag_bytes) = data_and_tag.split_at_mut(
|
||||
data_and_tag.len()
|
||||
- ::ring::aead::CHACHA20_POLY1305.tag_len(),
|
||||
|
@ -137,20 +126,20 @@ impl Cipher {
|
|||
};
|
||||
//data.drain(..Nonce::len());
|
||||
//data.truncate(final_len);
|
||||
Ok(&raw_data[Nonce::len()..Nonce::len() + final_len])
|
||||
Ok(&raw_data[Nonce::len().0..Nonce::len().0 + final_len])
|
||||
}
|
||||
}
|
||||
}
|
||||
fn overhead(&self) -> usize {
|
||||
match self {
|
||||
Cipher::XChaCha20Poly1305(_) => {
|
||||
let cipher = CipherKind::XChaCha20Poly1305;
|
||||
let cipher = Kind::XChaCha20Poly1305;
|
||||
cipher.nonce_len().0 + cipher.tag_len().0
|
||||
}
|
||||
}
|
||||
}
|
||||
fn encrypt(
|
||||
&self,
|
||||
&mut self,
|
||||
nonce: &Nonce,
|
||||
aad: AAD,
|
||||
data: &mut [u8],
|
||||
|
@ -162,13 +151,13 @@ impl Cipher {
|
|||
let tag_len: usize = ::ring::aead::CHACHA20_POLY1305.tag_len();
|
||||
let data_len_notag = data.len() - tag_len;
|
||||
// write nonce
|
||||
data[..Nonce::len()].copy_from_slice(nonce.as_bytes());
|
||||
data[..Nonce::len().0].copy_from_slice(nonce.as_bytes());
|
||||
|
||||
// encrypt data
|
||||
match cipher.cipher.encrypt_in_place_detached(
|
||||
nonce.as_bytes().into(),
|
||||
aad.0,
|
||||
&mut data[Nonce::len()..data_len_notag],
|
||||
&mut data[Nonce::len().0..data_len_notag],
|
||||
) {
|
||||
Ok(tag) => {
|
||||
data[data_len_notag..].copy_from_slice(tag.as_slice());
|
||||
|
@ -194,11 +183,11 @@ impl ::core::fmt::Debug for CipherRecv {
|
|||
|
||||
impl CipherRecv {
|
||||
/// Build a new Cipher
|
||||
pub fn new(kind: CipherKind, secret: Secret) -> Self {
|
||||
pub fn new(kind: Kind, secret: Secret) -> Self {
|
||||
Self(Cipher::new(kind, secret))
|
||||
}
|
||||
/// Get the length of the nonce for this cipher
|
||||
pub fn nonce_len(&self) -> HeadLen {
|
||||
pub fn nonce_len(&self) -> NonceLen {
|
||||
self.0.nonce_len()
|
||||
}
|
||||
/// Get the length of the nonce for this cipher
|
||||
|
@ -215,14 +204,14 @@ impl CipherRecv {
|
|||
self.0.decrypt(aad, data)
|
||||
}
|
||||
/// return the underlying cipher id
|
||||
pub fn kind(&self) -> CipherKind {
|
||||
pub fn kind(&self) -> Kind {
|
||||
self.0.kind()
|
||||
}
|
||||
}
|
||||
|
||||
/// Send only cipher
|
||||
pub struct CipherSend {
|
||||
nonce: NonceSync,
|
||||
nonce: Nonce,
|
||||
cipher: Cipher,
|
||||
}
|
||||
impl ::core::fmt::Debug for CipherSend {
|
||||
|
@ -236,20 +225,20 @@ impl ::core::fmt::Debug for CipherSend {
|
|||
|
||||
impl CipherSend {
|
||||
/// Build a new Cipher
|
||||
pub fn new(kind: CipherKind, secret: Secret, rand: &Random) -> Self {
|
||||
pub fn new(kind: Kind, secret: Secret, rand: &Random) -> Self {
|
||||
Self {
|
||||
nonce: NonceSync::new(rand),
|
||||
nonce: Nonce::new(rand),
|
||||
cipher: Cipher::new(kind, secret),
|
||||
}
|
||||
}
|
||||
/// Encrypt the given data
|
||||
pub fn encrypt(&self, aad: AAD, data: &mut [u8]) -> Result<(), Error> {
|
||||
pub fn encrypt(&mut self, aad: AAD, data: &mut [u8]) -> Result<(), Error> {
|
||||
let old_nonce = self.nonce.advance();
|
||||
self.cipher.encrypt(&old_nonce, aad, data)?;
|
||||
Ok(())
|
||||
}
|
||||
/// return the underlying cipher id
|
||||
pub fn kind(&self) -> CipherKind {
|
||||
pub fn kind(&self) -> Kind {
|
||||
self.cipher.kind()
|
||||
}
|
||||
}
|
||||
|
@ -285,7 +274,7 @@ struct NonceNum {
|
|||
#[repr(C)]
|
||||
pub union Nonce {
|
||||
num: NonceNum,
|
||||
raw: [u8; Self::len()],
|
||||
raw: [u8; Self::len().0],
|
||||
}
|
||||
|
||||
impl ::core::fmt::Debug for Nonce {
|
||||
|
@ -303,17 +292,17 @@ impl ::core::fmt::Debug for Nonce {
|
|||
impl Nonce {
|
||||
/// Generate a new random Nonce
|
||||
pub fn new(rand: &Random) -> Self {
|
||||
let mut raw = [0; Self::len()];
|
||||
let mut raw = [0; Self::len().0];
|
||||
rand.fill(&mut raw);
|
||||
Self { raw }
|
||||
}
|
||||
/// Length of this nonce in bytes
|
||||
pub const fn len() -> usize {
|
||||
pub const fn len() -> NonceLen {
|
||||
// FIXME: was:12. xchacha20poly1305 requires 24.
|
||||
// but we should change keys much earlier than that, and our
|
||||
// nonces are not random, but sequential.
|
||||
// we should change keys every 2^30 bytes to be sure (stream max window)
|
||||
return 24;
|
||||
return NonceLen(24);
|
||||
}
|
||||
/// Get reference to the nonce bytes
|
||||
pub fn as_bytes(&self) -> &[u8] {
|
||||
|
@ -323,11 +312,12 @@ impl Nonce {
|
|||
}
|
||||
}
|
||||
/// Create Nonce from array
|
||||
pub fn from_slice(raw: [u8; Self::len()]) -> Self {
|
||||
pub fn from_slice(raw: [u8; Self::len().0]) -> Self {
|
||||
Self { raw }
|
||||
}
|
||||
/// Go to the next nonce
|
||||
pub fn advance(&mut self) {
|
||||
pub fn advance(&mut self) -> Self {
|
||||
let old_nonce = self.clone();
|
||||
#[allow(unsafe_code)]
|
||||
unsafe {
|
||||
let old_low = self.num.low;
|
||||
|
@ -336,40 +326,17 @@ impl Nonce {
|
|||
self.num.high = self.num.high;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Synchronize the mutex acess with a nonce for multithread safety
|
||||
// TODO: remove mutex, not needed anymore
|
||||
#[derive(Debug)]
|
||||
pub struct NonceSync {
|
||||
nonce: ::std::sync::Mutex<Nonce>,
|
||||
}
|
||||
impl NonceSync {
|
||||
/// Create a new thread safe nonce
|
||||
pub fn new(rand: &Random) -> Self {
|
||||
Self {
|
||||
nonce: ::std::sync::Mutex::new(Nonce::new(rand)),
|
||||
}
|
||||
}
|
||||
/// 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
|
||||
}
|
||||
}
|
||||
|
||||
/// Select the best cipher from our supported list
|
||||
/// and the other endpoint supported list.
|
||||
/// Give priority to our list
|
||||
pub fn server_select_cipher(
|
||||
cfg: &Config,
|
||||
client_supported: &Vec<CipherKind>,
|
||||
) -> Option<CipherKind> {
|
||||
client_supported: &Vec<Kind>,
|
||||
) -> Option<Kind> {
|
||||
cfg.ciphers
|
||||
.iter()
|
||||
.find(|c| client_supported.contains(c))
|
||||
|
@ -381,8 +348,8 @@ pub fn server_select_cipher(
|
|||
/// This is used only in the Directory synchronized handshake
|
||||
pub fn client_select_cipher(
|
||||
cfg: &Config,
|
||||
server_supported: &Vec<CipherKind>,
|
||||
) -> Option<CipherKind> {
|
||||
server_supported: &Vec<Kind>,
|
||||
) -> Option<Kind> {
|
||||
server_supported
|
||||
.iter()
|
||||
.find(|c| cfg.ciphers.contains(c))
|
||||
|
|
|
@ -1,24 +1,26 @@
|
|||
use crate::{
|
||||
auth,
|
||||
connection::{handshake::*, ID},
|
||||
connection::{
|
||||
handshake::{self, *},
|
||||
ID,
|
||||
},
|
||||
enc::{self, asym::KeyID},
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn test_simple_encrypt_decrypt() {
|
||||
let rand = enc::Random::new();
|
||||
let cipher = enc::sym::CipherKind::XChaCha20Poly1305;
|
||||
let cipher = enc::sym::Kind::XChaCha20Poly1305;
|
||||
let secret = enc::Secret::new_rand(&rand);
|
||||
let secret2 = secret.clone();
|
||||
|
||||
let cipher_send = enc::sym::CipherSend::new(cipher, secret, &rand);
|
||||
let mut cipher_send = enc::sym::CipherSend::new(cipher, secret, &rand);
|
||||
let cipher_recv = enc::sym::CipherRecv::new(cipher, secret2);
|
||||
|
||||
let mut data = Vec::new();
|
||||
let tot_len = cipher_recv.nonce_len().0 + 1234 + cipher_recv.tag_len().0;
|
||||
data.resize(tot_len, 0);
|
||||
rand.fill(&mut data);
|
||||
data[..enc::sym::Nonce::len()].copy_from_slice(&[0; 24]);
|
||||
data[..enc::sym::Nonce::len().0].copy_from_slice(&[0; 24]);
|
||||
let last = data.len() - cipher_recv.tag_len().0;
|
||||
data[last..].copy_from_slice(&[0; 16]);
|
||||
let orig = data.clone();
|
||||
|
@ -31,7 +33,7 @@ fn test_simple_encrypt_decrypt() {
|
|||
if cipher_recv.decrypt(aad2, &mut data).is_err() {
|
||||
assert!(false, "Decrypt failed");
|
||||
}
|
||||
data[..enc::sym::Nonce::len()].copy_from_slice(&[0; 24]);
|
||||
data[..enc::sym::Nonce::len().0].copy_from_slice(&[0; 24]);
|
||||
let last = data.len() - cipher_recv.tag_len().0;
|
||||
data[last..].copy_from_slice(&[0; 16]);
|
||||
assert!(orig == data, "DIFFERENT!\n{:?}\n{:?}\n", orig, data);
|
||||
|
@ -40,18 +42,18 @@ fn test_simple_encrypt_decrypt() {
|
|||
#[test]
|
||||
fn test_encrypt_decrypt() {
|
||||
let rand = enc::Random::new();
|
||||
let cipher = enc::sym::CipherKind::XChaCha20Poly1305;
|
||||
let cipher = enc::sym::Kind::XChaCha20Poly1305;
|
||||
let secret = enc::Secret::new_rand(&rand);
|
||||
let secret2 = secret.clone();
|
||||
|
||||
let cipher_send = enc::sym::CipherSend::new(cipher, secret, &rand);
|
||||
let mut cipher_send = enc::sym::CipherSend::new(cipher, secret, &rand);
|
||||
let cipher_recv = enc::sym::CipherRecv::new(cipher, secret2);
|
||||
let nonce_len = cipher_recv.nonce_len();
|
||||
let tag_len = cipher_recv.tag_len();
|
||||
|
||||
let service_key = enc::Secret::new_rand(&rand);
|
||||
|
||||
let data = dirsync::RespInner::ClearText(dirsync::RespData {
|
||||
let data = dirsync::RespState::ClearText(dirsync::RespData {
|
||||
client_nonce: dirsync::Nonce::new(&rand),
|
||||
id: ID::ID(::core::num::NonZeroU64::new(424242).unwrap()),
|
||||
service_connection_id: ID::ID(
|
||||
|
@ -68,7 +70,7 @@ fn test_encrypt_decrypt() {
|
|||
let encrypt_to = encrypt_from + resp.encrypted_length(nonce_len, tag_len);
|
||||
|
||||
let h_resp =
|
||||
Handshake::new(HandshakeData::DirSync(dirsync::DirSync::Resp(resp)));
|
||||
Handshake::new(handshake::Data::DirSync(dirsync::DirSync::Resp(resp)));
|
||||
|
||||
let mut bytes = Vec::<u8>::with_capacity(
|
||||
h_resp.len(cipher.nonce_len(), cipher.tag_len()),
|
||||
|
@ -117,7 +119,7 @@ fn test_encrypt_decrypt() {
|
|||
}
|
||||
};
|
||||
// reparse
|
||||
if let HandshakeData::DirSync(dirsync::DirSync::Resp(r_a)) =
|
||||
if let handshake::Data::DirSync(dirsync::DirSync::Resp(r_a)) =
|
||||
&mut deserialized.data
|
||||
{
|
||||
let enc_start = r_a.encrypted_offset() + cipher.nonce_len().0;
|
||||
|
|
|
@ -7,8 +7,7 @@ use crate::{
|
|||
handshake::{
|
||||
self,
|
||||
dirsync::{self, DirSync},
|
||||
tracker::{HandshakeAction, HandshakeTracker},
|
||||
Handshake, HandshakeData,
|
||||
Handshake,
|
||||
},
|
||||
packet::{self, Packet},
|
||||
socket::{UdpClient, UdpServer},
|
||||
|
@ -17,7 +16,7 @@ use crate::{
|
|||
dnssec,
|
||||
enc::{
|
||||
asym::{self, KeyID, PrivKey, PubKey},
|
||||
hkdf::{self, Hkdf, HkdfKind},
|
||||
hkdf::{self, Hkdf},
|
||||
sym, Random, Secret,
|
||||
},
|
||||
inner::ThreadTracker,
|
||||
|
@ -69,7 +68,7 @@ pub struct Worker {
|
|||
queue_timeouts_send: mpsc::UnboundedSender<Work>,
|
||||
thread_channels: Vec<::async_channel::Sender<Work>>,
|
||||
connections: ConnList,
|
||||
handshakes: HandshakeTracker,
|
||||
handshakes: handshake::Tracker,
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
|
@ -86,7 +85,7 @@ impl Worker {
|
|||
) -> ::std::io::Result<Self> {
|
||||
let (queue_timeouts_send, queue_timeouts_recv) =
|
||||
mpsc::unbounded_channel();
|
||||
let mut handshakes = HandshakeTracker::new(
|
||||
let mut handshakes = handshake::Tracker::new(
|
||||
thread_id,
|
||||
cfg.ciphers.clone(),
|
||||
cfg.key_exchanges.clone(),
|
||||
|
@ -345,7 +344,7 @@ impl Worker {
|
|||
hkdf: hkdf_selected,
|
||||
cipher: cipher_selected,
|
||||
exchange_key: pub_key,
|
||||
data: dirsync::ReqInner::ClearText(req_data),
|
||||
data: dirsync::ReqState::ClearText(req_data),
|
||||
};
|
||||
let encrypt_start =
|
||||
connection::ID::len() + req.encrypted_offset();
|
||||
|
@ -354,7 +353,7 @@ impl Worker {
|
|||
cipher_selected.nonce_len(),
|
||||
cipher_selected.tag_len(),
|
||||
);
|
||||
let h_req = Handshake::new(HandshakeData::DirSync(
|
||||
let h_req = Handshake::new(handshake::Data::DirSync(
|
||||
DirSync::Req(req),
|
||||
));
|
||||
let packet = Packet {
|
||||
|
@ -450,9 +449,9 @@ impl Worker {
|
|||
}
|
||||
};
|
||||
match action {
|
||||
HandshakeAction::AuthNeeded(authinfo) => {
|
||||
handshake::Action::AuthNeeded(authinfo) => {
|
||||
let req;
|
||||
if let HandshakeData::DirSync(DirSync::Req(r)) =
|
||||
if let handshake::Data::DirSync(DirSync::Req(r)) =
|
||||
authinfo.handshake.data
|
||||
{
|
||||
req = r;
|
||||
|
@ -460,9 +459,9 @@ impl Worker {
|
|||
::tracing::error!("AuthInfo on non DS::Req");
|
||||
return;
|
||||
}
|
||||
use dirsync::ReqInner;
|
||||
use dirsync::ReqState;
|
||||
let req_data = match req.data {
|
||||
ReqInner::ClearText(req_data) => req_data,
|
||||
ReqState::ClearText(req_data) => req_data,
|
||||
_ => {
|
||||
::tracing::error!("AuthNeeded: expected ClearText");
|
||||
assert!(false, "AuthNeeded: unreachable");
|
||||
|
@ -538,17 +537,17 @@ impl Worker {
|
|||
// no aad for now
|
||||
let aad = AAD(&mut []);
|
||||
|
||||
use dirsync::RespInner;
|
||||
use dirsync::RespState;
|
||||
let resp = dirsync::Resp {
|
||||
client_key_id: req_data.client_key_id,
|
||||
data: RespInner::ClearText(resp_data),
|
||||
data: RespState::ClearText(resp_data),
|
||||
};
|
||||
let encrypt_from =
|
||||
connection::ID::len() + resp.encrypted_offset();
|
||||
let encrypt_until =
|
||||
encrypt_from + resp.encrypted_length(head_len, tag_len);
|
||||
let resp_handshake = Handshake::new(
|
||||
HandshakeData::DirSync(DirSync::Resp(resp)),
|
||||
handshake::Data::DirSync(DirSync::Resp(resp)),
|
||||
);
|
||||
let packet = Packet {
|
||||
id: connection::ID::new_handshake(),
|
||||
|
@ -568,9 +567,9 @@ impl Worker {
|
|||
}
|
||||
self.send_packet(raw_out, udp.src, udp.dst).await;
|
||||
}
|
||||
HandshakeAction::ClientConnect(cci) => {
|
||||
handshake::Action::ClientConnect(cci) => {
|
||||
let ds_resp;
|
||||
if let HandshakeData::DirSync(DirSync::Resp(resp)) =
|
||||
if let handshake::Data::DirSync(DirSync::Resp(resp)) =
|
||||
cci.handshake.data
|
||||
{
|
||||
ds_resp = resp;
|
||||
|
@ -580,7 +579,7 @@ impl Worker {
|
|||
}
|
||||
// track connection
|
||||
let resp_data;
|
||||
if let dirsync::RespInner::ClearText(r_data) = ds_resp.data
|
||||
if let dirsync::RespState::ClearText(r_data) = ds_resp.data
|
||||
{
|
||||
resp_data = r_data;
|
||||
} else {
|
||||
|
@ -609,7 +608,7 @@ impl Worker {
|
|||
//FIXME: the Secret should be XORed with the client
|
||||
// stored secret (if any)
|
||||
let hkdf = Hkdf::new(
|
||||
HkdfKind::Sha3,
|
||||
hkdf::Kind::Sha3,
|
||||
cci.service_id.as_bytes(),
|
||||
resp_data.service_key,
|
||||
);
|
||||
|
@ -628,7 +627,7 @@ impl Worker {
|
|||
let _ =
|
||||
cci.answer.send(Ok((cci.srv_key_id, auth_srv_conn)));
|
||||
}
|
||||
HandshakeAction::Nothing => {}
|
||||
handshake::Action::Nothing => {}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
11
src/tests.rs
11
src/tests.rs
|
@ -62,10 +62,7 @@ async fn test_connection_dirsync() {
|
|||
rt.block_on(local_thread);
|
||||
});
|
||||
|
||||
use crate::{
|
||||
connection::handshake::HandshakeID,
|
||||
dnssec::{record, Record},
|
||||
};
|
||||
use crate::dnssec::{record, Record};
|
||||
|
||||
let port: u16 = server.addresses()[0].port();
|
||||
|
||||
|
@ -76,14 +73,14 @@ async fn test_connection_dirsync() {
|
|||
port: Some(::core::num::NonZeroU16::new(port).unwrap()),
|
||||
priority: record::AddressPriority::P1,
|
||||
weight: record::AddressWeight::W1,
|
||||
handshake_ids: [HandshakeID::DirectorySynchronized].to_vec(),
|
||||
handshake_ids: [handshake::ID::DirectorySynchronized].to_vec(),
|
||||
public_key_idx: [record::PubKeyIdx(0)].to_vec(),
|
||||
}]
|
||||
.to_vec(),
|
||||
key_exchanges: [enc::asym::KeyExchangeKind::X25519DiffieHellman]
|
||||
.to_vec(),
|
||||
hkdfs: [enc::hkdf::HkdfKind::Sha3].to_vec(),
|
||||
ciphers: [enc::sym::CipherKind::XChaCha20Poly1305].to_vec(),
|
||||
hkdfs: [enc::hkdf::Kind::Sha3].to_vec(),
|
||||
ciphers: [enc::sym::Kind::XChaCha20Poly1305].to_vec(),
|
||||
};
|
||||
|
||||
::tokio::time::sleep(::std::time::Duration::from_millis(500)).await;
|
||||
|
|
Loading…
Reference in New Issue