More work on key exhcnage negotiation
Signed-off-by: Luca Fulchir <luca.fulchir@runesauth.com>
This commit is contained in:
parent
1bae4c9953
commit
ac213a6528
|
@ -1,6 +1,10 @@
|
||||||
//!
|
//!
|
||||||
//! Configuration to initialize the Fenrir networking library
|
//! Configuration to initialize the Fenrir networking library
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
connection::handshake::HandshakeID,
|
||||||
|
enc::{asym::KeyExchange, hkdf::HkdfKind, sym::CipherKind},
|
||||||
|
};
|
||||||
use ::std::{
|
use ::std::{
|
||||||
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
|
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
|
||||||
num::NonZeroUsize,
|
num::NonZeroUsize,
|
||||||
|
@ -18,6 +22,14 @@ pub struct Config {
|
||||||
pub listen: Vec<SocketAddr>,
|
pub listen: Vec<SocketAddr>,
|
||||||
/// List of DNS resolvers to use
|
/// List of DNS resolvers to use
|
||||||
pub resolvers: Vec<SocketAddr>,
|
pub resolvers: Vec<SocketAddr>,
|
||||||
|
/// Supported handshakes
|
||||||
|
pub handshakes: Vec<HandshakeID>,
|
||||||
|
/// Supported key exchanges
|
||||||
|
pub key_exchanges: Vec<KeyExchange>,
|
||||||
|
/// Supported Hkdfs
|
||||||
|
pub hkdfs: Vec<HkdfKind>,
|
||||||
|
/// Supported Ciphers
|
||||||
|
pub ciphers: Vec<CipherKind>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
|
@ -34,6 +46,10 @@ impl Default for Config {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
resolvers: Vec::new(),
|
resolvers: Vec::new(),
|
||||||
|
handshakes: [HandshakeID::DirectorySynchronized].to_vec(),
|
||||||
|
key_exchanges: [KeyExchange::X25519DiffieHellman].to_vec(),
|
||||||
|
hkdfs: [HkdfKind::Sha3].to_vec(),
|
||||||
|
ciphers: [CipherKind::XChaCha20Poly1305].to_vec(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,13 +14,41 @@ use crate::{
|
||||||
connection::{ProtocolVersion, ID},
|
connection::{ProtocolVersion, ID},
|
||||||
enc::{
|
enc::{
|
||||||
asym::{ExchangePubKey, KeyExchange, KeyID},
|
asym::{ExchangePubKey, KeyExchange, KeyID},
|
||||||
|
hkdf::HkdfKind,
|
||||||
sym::{CipherKind, HeadLen, Secret, TagLen},
|
sym::{CipherKind, HeadLen, Secret, TagLen},
|
||||||
|
Random,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use ::arrayref::array_mut_ref;
|
use ::arrayref::array_mut_ref;
|
||||||
|
|
||||||
type Nonce = [u8; 16];
|
// TODO: merge with crate::enc::sym::Nonce
|
||||||
|
/// random nonce
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct Nonce([u8; 16]);
|
||||||
|
|
||||||
|
impl Nonce {
|
||||||
|
/// Create a new random Nonce
|
||||||
|
pub fn new(rnd: &Random) -> Self {
|
||||||
|
use ::core::mem::MaybeUninit;
|
||||||
|
let mut out: MaybeUninit<[u8; 16]>;
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
unsafe {
|
||||||
|
out = MaybeUninit::uninit();
|
||||||
|
let _ = rnd.fill(out.assume_init_mut());
|
||||||
|
Self(out.assume_init())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Length of the serialized Nonce
|
||||||
|
pub const fn len() -> usize {
|
||||||
|
16
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<&[u8; 16]> for Nonce {
|
||||||
|
fn from(raw: &[u8; 16]) -> Self {
|
||||||
|
Self(raw.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Parsed handshake
|
/// Parsed handshake
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -61,6 +89,8 @@ pub struct Req {
|
||||||
pub key_id: KeyID,
|
pub key_id: KeyID,
|
||||||
/// Selected key exchange
|
/// Selected key exchange
|
||||||
pub exchange: KeyExchange,
|
pub exchange: KeyExchange,
|
||||||
|
/// Selected hkdf
|
||||||
|
pub hkdf: HkdfKind,
|
||||||
/// Selected cipher
|
/// Selected cipher
|
||||||
pub cipher: CipherKind,
|
pub cipher: CipherKind,
|
||||||
/// Client ephemeral public key used for key exchanges
|
/// Client ephemeral public key used for key exchanges
|
||||||
|
@ -77,6 +107,7 @@ impl Req {
|
||||||
ProtocolVersion::len()
|
ProtocolVersion::len()
|
||||||
+ KeyID::len()
|
+ KeyID::len()
|
||||||
+ KeyExchange::len()
|
+ KeyExchange::len()
|
||||||
|
+ HkdfKind::len()
|
||||||
+ CipherKind::len()
|
+ CipherKind::len()
|
||||||
+ self.exchange_key.kind().pub_len()
|
+ self.exchange_key.kind().pub_len()
|
||||||
}
|
}
|
||||||
|
@ -91,6 +122,7 @@ impl Req {
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
KeyID::len()
|
KeyID::len()
|
||||||
+ KeyExchange::len()
|
+ KeyExchange::len()
|
||||||
|
+ HkdfKind::len()
|
||||||
+ CipherKind::len()
|
+ CipherKind::len()
|
||||||
+ self.exchange_key.kind().pub_len()
|
+ self.exchange_key.kind().pub_len()
|
||||||
+ self.data.len()
|
+ self.data.len()
|
||||||
|
@ -121,18 +153,23 @@ impl super::HandshakeParsing for Req {
|
||||||
Some(exchange) => exchange,
|
Some(exchange) => exchange,
|
||||||
None => return Err(Error::Parsing),
|
None => return Err(Error::Parsing),
|
||||||
};
|
};
|
||||||
let cipher: CipherKind = match CipherKind::from_u8(raw[3]) {
|
let hkdf: HkdfKind = match HkdfKind::from_u8(raw[3]) {
|
||||||
|
Some(exchange) => exchange,
|
||||||
|
None => return Err(Error::Parsing),
|
||||||
|
};
|
||||||
|
let cipher: CipherKind = match CipherKind::from_u8(raw[4]) {
|
||||||
Some(cipher) => cipher,
|
Some(cipher) => cipher,
|
||||||
None => return Err(Error::Parsing),
|
None => return Err(Error::Parsing),
|
||||||
};
|
};
|
||||||
let (exchange_key, len) = match ExchangePubKey::from_slice(&raw[4..]) {
|
let (exchange_key, len) = match ExchangePubKey::from_slice(&raw[5..]) {
|
||||||
Ok(exchange_key) => exchange_key,
|
Ok(exchange_key) => exchange_key,
|
||||||
Err(e) => return Err(e.into()),
|
Err(e) => return Err(e.into()),
|
||||||
};
|
};
|
||||||
let data = ReqInner::CipherText(raw.len() - (4 + len));
|
let data = ReqInner::CipherText(raw.len() - (5 + len));
|
||||||
Ok(HandshakeData::DirSync(DirSync::Req(Self {
|
Ok(HandshakeData::DirSync(DirSync::Req(Self {
|
||||||
key_id,
|
key_id,
|
||||||
exchange,
|
exchange,
|
||||||
|
hkdf,
|
||||||
cipher,
|
cipher,
|
||||||
exchange_key,
|
exchange_key,
|
||||||
data,
|
data,
|
||||||
|
@ -253,7 +290,7 @@ pub struct ReqData {
|
||||||
impl ReqData {
|
impl ReqData {
|
||||||
/// actual length of the request data
|
/// actual length of the request data
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.nonce.len() + KeyID::len() + ID::len() + self.auth.len()
|
Nonce::len() + KeyID::len() + ID::len() + self.auth.len()
|
||||||
}
|
}
|
||||||
/// Minimum byte length of the request data
|
/// Minimum byte length of the request data
|
||||||
pub const MIN_PKT_LEN: usize =
|
pub const MIN_PKT_LEN: usize =
|
||||||
|
@ -265,7 +302,8 @@ impl ReqData {
|
||||||
}
|
}
|
||||||
let mut start = 0;
|
let mut start = 0;
|
||||||
let mut end = 16;
|
let mut end = 16;
|
||||||
let nonce: Nonce = raw[start..end].try_into().unwrap();
|
let raw_sized: &[u8; 16] = raw[start..end].try_into().unwrap();
|
||||||
|
let nonce: Nonce = raw_sized.into();
|
||||||
start = end;
|
start = end;
|
||||||
end = end + KeyID::len();
|
end = end + KeyID::len();
|
||||||
let client_key_id =
|
let client_key_id =
|
||||||
|
@ -440,7 +478,7 @@ impl RespData {
|
||||||
assert!(out.len() == Self::len(), "wrong buffer size");
|
assert!(out.len() == Self::len(), "wrong buffer size");
|
||||||
let mut start = 0;
|
let mut start = 0;
|
||||||
let mut end = Self::NONCE_LEN;
|
let mut end = Self::NONCE_LEN;
|
||||||
out[start..end].copy_from_slice(&self.client_nonce);
|
out[start..end].copy_from_slice(&self.client_nonce.0);
|
||||||
start = end;
|
start = end;
|
||||||
end = end + Self::NONCE_LEN;
|
end = end + Self::NONCE_LEN;
|
||||||
self.id.serialize(&mut out[start..end]);
|
self.id.serialize(&mut out[start..end]);
|
||||||
|
|
|
@ -27,6 +27,37 @@ pub enum Error {
|
||||||
NotEnoughData,
|
NotEnoughData,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// List of possible handshakes
|
||||||
|
#[derive(::num_derive::FromPrimitive, Debug, Clone, Copy, PartialEq)]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum HandshakeID {
|
||||||
|
/// 1-RTT Directory synchronized handshake. Fast, no forward secrecy
|
||||||
|
DirectorySynchronized = 0,
|
||||||
|
/// 2-RTT Stateful exchange. Little DDos protection
|
||||||
|
Stateful,
|
||||||
|
/// 3-RTT stateless exchange. Forward secrecy and ddos protection
|
||||||
|
Stateless,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<&str> for HandshakeID {
|
||||||
|
type Error = ::std::io::Error;
|
||||||
|
// TODO: from actual names, not only numeric
|
||||||
|
fn try_from(raw: &str) -> Result<Self, Self::Error> {
|
||||||
|
if let Ok(handshake_u8) = raw.parse::<u8>() {
|
||||||
|
if handshake_u8 >= 1 {
|
||||||
|
if let Some(handshake) = HandshakeID::from_u8(handshake_u8 - 1)
|
||||||
|
{
|
||||||
|
return Ok(handshake);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Err(::std::io::Error::new(
|
||||||
|
::std::io::ErrorKind::InvalidData,
|
||||||
|
"Unknown handshake ID",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) struct HandshakeServer {
|
pub(crate) struct HandshakeServer {
|
||||||
pub id: crate::enc::asym::KeyID,
|
pub id: crate::enc::asym::KeyID,
|
||||||
pub key: crate::enc::asym::PrivKey,
|
pub key: crate::enc::asym::PrivKey,
|
||||||
|
|
|
@ -19,15 +19,15 @@
|
||||||
//! * 2..4 priority (for failover)
|
//! * 2..4 priority (for failover)
|
||||||
//! * 5..7 weight between priority
|
//! * 5..7 weight between priority
|
||||||
//! * 1 byte: divided in half:
|
//! * 1 byte: divided in half:
|
||||||
//! * half: num of public key ids
|
//! * half: num of public key indexes
|
||||||
//! * half: num of handhskae ids
|
//! * half: num of handshake ids
|
||||||
//! * 2 bytes: UDP port
|
//! * 2 bytes: UDP port
|
||||||
//! * [ 1 byte per public key id ]
|
//! * [ HALF byte per public key idx ] (index on the list of public keys)
|
||||||
//! * [ 1 byte per handshake id ]
|
//! * [ 1 byte per handshake id ]
|
||||||
//! * X bytes: IP
|
//! * X bytes: IP
|
||||||
//! ]
|
//! ]
|
||||||
//! [ # list of pubkeys
|
//! [ # list of pubkeys (max: 16)
|
||||||
//! * 1 byte: pubkey id
|
//! * 2 byte: pubkey id
|
||||||
//! * 1 byte: pubkey length
|
//! * 1 byte: pubkey length
|
||||||
//! * 1 byte: pubkey type
|
//! * 1 byte: pubkey type
|
||||||
//! * Y bytes: pubkey
|
//! * Y bytes: pubkey
|
||||||
|
@ -42,11 +42,14 @@
|
||||||
//! * 1 byte for each cipher
|
//! * 1 byte for each cipher
|
||||||
//! ]
|
//! ]
|
||||||
|
|
||||||
use crate::enc::{
|
use crate::{
|
||||||
self,
|
connection::handshake::HandshakeID,
|
||||||
asym::{KeyExchange, PubKey},
|
enc::{
|
||||||
hkdf::HkdfKind,
|
self,
|
||||||
sym::CipherKind,
|
asym::{KeyExchange, KeyID, PubKey},
|
||||||
|
hkdf::HkdfKind,
|
||||||
|
sym::CipherKind,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use ::core::num::NonZeroU16;
|
use ::core::num::NonZeroU16;
|
||||||
use ::num_traits::FromPrimitive;
|
use ::num_traits::FromPrimitive;
|
||||||
|
@ -55,22 +58,12 @@ use ::std::{net::IpAddr, vec::Vec};
|
||||||
* Public key data
|
* Public key data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/// Public Key ID
|
/// Public Key Index.
|
||||||
|
/// this points to the index of the public key in the array of public keys.
|
||||||
|
/// needed to have one byte less in the list of public keys
|
||||||
|
/// supported by and address
|
||||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||||
pub struct PublicKeyID(u8);
|
pub struct PubKeyIdx(pub u8);
|
||||||
|
|
||||||
impl TryFrom<&str> for PublicKeyID {
|
|
||||||
type Error = ::std::io::Error;
|
|
||||||
fn try_from(raw: &str) -> Result<Self, Self::Error> {
|
|
||||||
if let Ok(id_u8) = raw.parse::<u8>() {
|
|
||||||
return Ok(PublicKeyID(id_u8));
|
|
||||||
}
|
|
||||||
return Err(::std::io::Error::new(
|
|
||||||
::std::io::ErrorKind::InvalidData,
|
|
||||||
"Public Key ID must be between 0 and 256",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Address data
|
* Address data
|
||||||
|
@ -168,37 +161,6 @@ impl TryFrom<&str> for AddressWeight {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// List of possible handshakes
|
|
||||||
#[derive(::num_derive::FromPrimitive, Debug, Clone, Copy)]
|
|
||||||
#[repr(u8)]
|
|
||||||
pub enum HandshakeID {
|
|
||||||
/// 1-RTT Directory synchronized handshake. Fast, no forward secrecy
|
|
||||||
DirectorySynchronized = 0,
|
|
||||||
/// 2-RTT Stateful exchange. Little DDos protection
|
|
||||||
Stateful,
|
|
||||||
/// 3-RTT stateless exchange. Forward secrecy and ddos protection
|
|
||||||
Stateless,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<&str> for HandshakeID {
|
|
||||||
type Error = ::std::io::Error;
|
|
||||||
// TODO: from actual names, not only numeric
|
|
||||||
fn try_from(raw: &str) -> Result<Self, Self::Error> {
|
|
||||||
if let Ok(handshake_u8) = raw.parse::<u8>() {
|
|
||||||
if handshake_u8 >= 1 {
|
|
||||||
if let Some(handshake) = HandshakeID::from_u8(handshake_u8 - 1)
|
|
||||||
{
|
|
||||||
return Ok(handshake);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Err(::std::io::Error::new(
|
|
||||||
::std::io::ErrorKind::InvalidData,
|
|
||||||
"Unknown handshake ID",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Authentication server address information:
|
/// Authentication server address information:
|
||||||
/// * ip
|
/// * ip
|
||||||
/// * udp port
|
/// * udp port
|
||||||
|
@ -220,14 +182,16 @@ pub struct Address {
|
||||||
/// List of supported handshakes
|
/// List of supported handshakes
|
||||||
pub handshake_ids: Vec<HandshakeID>,
|
pub handshake_ids: Vec<HandshakeID>,
|
||||||
/// Public key IDs used by this address
|
/// Public key IDs used by this address
|
||||||
pub public_key_ids: Vec<PublicKeyID>,
|
pub public_key_idx: Vec<PubKeyIdx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Address {
|
impl Address {
|
||||||
fn raw_len(&self) -> usize {
|
fn raw_len(&self) -> usize {
|
||||||
// UDP port + Priority + Weight + pubkey_len + handshake_len
|
// UDP port + Priority + Weight + pubkey_len + handshake_len
|
||||||
let mut size = 6;
|
let mut size = 6;
|
||||||
size = size + self.public_key_ids.len() + self.handshake_ids.len();
|
let num_pubkey_idx = self.public_key_idx.len();
|
||||||
|
let idx_bytes = (num_pubkey_idx / 2) + (num_pubkey_idx % 2);
|
||||||
|
size = size + idx_bytes + self.handshake_ids.len();
|
||||||
size + match self.ip {
|
size + match self.ip {
|
||||||
IpAddr::V4(_) => size + 4,
|
IpAddr::V4(_) => size + 4,
|
||||||
IpAddr::V6(_) => size + 16,
|
IpAddr::V6(_) => size + 16,
|
||||||
|
@ -244,7 +208,7 @@ impl Address {
|
||||||
bitfield |= self.weight as u8;
|
bitfield |= self.weight as u8;
|
||||||
|
|
||||||
raw.push(bitfield);
|
raw.push(bitfield);
|
||||||
let len_combined: u8 = self.public_key_ids.len() as u8;
|
let len_combined: u8 = self.public_key_idx.len() as u8;
|
||||||
let len_combined = len_combined << 4;
|
let len_combined = len_combined << 4;
|
||||||
let len_combined = len_combined | self.handshake_ids.len() as u8;
|
let len_combined = len_combined | self.handshake_ids.len() as u8;
|
||||||
raw.push(len_combined);
|
raw.push(len_combined);
|
||||||
|
@ -256,8 +220,18 @@ impl Address {
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
for id in self.public_key_ids.iter() {
|
// pair every idx, since the max is 16
|
||||||
raw.push(id.0);
|
for chunk in self.public_key_idx.chunks(2) {
|
||||||
|
let second = {
|
||||||
|
if chunk.len() == 2 {
|
||||||
|
chunk[1].0
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let tmp = chunk[0].0 << 4;
|
||||||
|
let tmp = tmp | second;
|
||||||
|
raw.push(tmp);
|
||||||
}
|
}
|
||||||
for id in self.handshake_ids.iter() {
|
for id in self.handshake_ids.iter() {
|
||||||
raw.push(*id as u8);
|
raw.push(*id as u8);
|
||||||
|
@ -301,21 +275,29 @@ impl Address {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add publickey ids
|
// Add publickey ids
|
||||||
let num_pubkey_ids = (raw[3] >> 4) as usize;
|
let num_pubkey_idx = (raw[3] >> 4) as usize;
|
||||||
let num_handshake_ids = (raw[3] & 0x0F) as usize;
|
let num_handshake_ids = (raw[3] & 0x0F) as usize;
|
||||||
if raw.len() <= 3 + num_pubkey_ids + num_handshake_ids {
|
if raw.len() <= 3 + num_pubkey_idx + num_handshake_ids {
|
||||||
return Err(Error::NotEnoughData(3));
|
return Err(Error::NotEnoughData(3));
|
||||||
}
|
}
|
||||||
let mut bytes_parsed = 4;
|
let mut bytes_parsed = 4;
|
||||||
let mut public_key_ids = Vec::with_capacity(num_pubkey_ids);
|
let mut public_key_idx = Vec::with_capacity(num_pubkey_idx);
|
||||||
for raw_pubkey_id in
|
let idx_bytes = (num_pubkey_idx / 2) + (num_pubkey_idx % 2);
|
||||||
raw[bytes_parsed..(bytes_parsed + num_pubkey_ids)].iter()
|
let mut idx_added = 0;
|
||||||
|
for raw_pubkey_idx_pair in
|
||||||
|
raw[bytes_parsed..(bytes_parsed + idx_bytes)].iter()
|
||||||
{
|
{
|
||||||
public_key_ids.push(PublicKeyID(*raw_pubkey_id));
|
let first = PubKeyIdx(raw_pubkey_idx_pair >> 4);
|
||||||
|
let second = PubKeyIdx(raw_pubkey_idx_pair & 0x0F);
|
||||||
|
public_key_idx.push(first);
|
||||||
|
if num_pubkey_idx - idx_added >= 2 {
|
||||||
|
public_key_idx.push(second);
|
||||||
|
}
|
||||||
|
idx_added = idx_added + 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add handshake ids
|
// add handshake ids
|
||||||
bytes_parsed = bytes_parsed + num_pubkey_ids;
|
bytes_parsed = bytes_parsed + idx_bytes;
|
||||||
let mut handshake_ids = Vec::with_capacity(num_handshake_ids);
|
let mut handshake_ids = Vec::with_capacity(num_handshake_ids);
|
||||||
for raw_handshake_id in
|
for raw_handshake_id in
|
||||||
raw[bytes_parsed..(bytes_parsed + num_handshake_ids)].iter()
|
raw[bytes_parsed..(bytes_parsed + num_handshake_ids)].iter()
|
||||||
|
@ -358,7 +340,7 @@ impl Address {
|
||||||
port,
|
port,
|
||||||
priority,
|
priority,
|
||||||
weight,
|
weight,
|
||||||
public_key_ids,
|
public_key_idx,
|
||||||
handshake_ids,
|
handshake_ids,
|
||||||
},
|
},
|
||||||
bytes_parsed,
|
bytes_parsed,
|
||||||
|
@ -374,7 +356,7 @@ impl Address {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Record {
|
pub struct Record {
|
||||||
/// Public keys used by any authentication server
|
/// Public keys used by any authentication server
|
||||||
pub public_keys: Vec<(PublicKeyID, PubKey)>,
|
pub public_keys: Vec<(KeyID, PubKey)>,
|
||||||
/// List of all authentication servers' addresses.
|
/// List of all authentication servers' addresses.
|
||||||
/// Multiple ones can point to the same authentication server
|
/// Multiple ones can point to the same authentication server
|
||||||
pub addresses: Vec<Address>,
|
pub addresses: Vec<Address>,
|
||||||
|
@ -443,7 +425,8 @@ impl Record {
|
||||||
address.encode_into(&mut raw);
|
address.encode_into(&mut raw);
|
||||||
}
|
}
|
||||||
for (public_key_id, public_key) in self.public_keys.iter() {
|
for (public_key_id, public_key) in self.public_keys.iter() {
|
||||||
raw.push(public_key_id.0);
|
let key_id_bytes = public_key_id.0.to_le_bytes();
|
||||||
|
raw.extend_from_slice(&key_id_bytes);
|
||||||
raw.push(public_key.kind().pub_len() as u8);
|
raw.push(public_key.kind().pub_len() as u8);
|
||||||
raw.push(public_key.kind() as u8);
|
raw.push(public_key.kind() as u8);
|
||||||
public_key.serialize_into(&mut raw);
|
public_key.serialize_into(&mut raw);
|
||||||
|
@ -462,8 +445,8 @@ impl Record {
|
||||||
}
|
}
|
||||||
/// Decode from base85 to the actual object
|
/// Decode from base85 to the actual object
|
||||||
pub fn decode(raw: &[u8]) -> Result<Self, Error> {
|
pub fn decode(raw: &[u8]) -> Result<Self, Error> {
|
||||||
// bare minimum for 1 address, 1 key, 1 key exchange and 1 cipher
|
// bare minimum for lengths, (1 address), (1 key), cipher negotiation
|
||||||
const MIN_RAW_LENGTH: usize = 1 + 1 + 1 + 8 + 9 + 1 + 1;
|
const MIN_RAW_LENGTH: usize = 3 + (6 + 4) + (4 + 32) + 1 + 1 + 1;
|
||||||
if raw.len() <= MIN_RAW_LENGTH {
|
if raw.len() <= MIN_RAW_LENGTH {
|
||||||
return Err(Error::NotEnoughData(0));
|
return Err(Error::NotEnoughData(0));
|
||||||
}
|
}
|
||||||
|
@ -499,11 +482,14 @@ impl Record {
|
||||||
num_addresses = num_addresses - 1;
|
num_addresses = num_addresses - 1;
|
||||||
}
|
}
|
||||||
while num_public_keys > 0 {
|
while num_public_keys > 0 {
|
||||||
if bytes_parsed + 2 >= raw.len() {
|
if bytes_parsed + 3 >= raw.len() {
|
||||||
return Err(Error::NotEnoughData(bytes_parsed));
|
return Err(Error::NotEnoughData(bytes_parsed));
|
||||||
}
|
}
|
||||||
let id = PublicKeyID(raw[bytes_parsed]);
|
|
||||||
bytes_parsed = bytes_parsed + 1;
|
let raw_key_id =
|
||||||
|
u16::from_le_bytes([raw[bytes_parsed], raw[bytes_parsed + 1]]);
|
||||||
|
let id = KeyID(raw_key_id);
|
||||||
|
bytes_parsed = bytes_parsed + 2;
|
||||||
let pubkey_length = raw[bytes_parsed] as usize;
|
let pubkey_length = raw[bytes_parsed] as usize;
|
||||||
bytes_parsed = bytes_parsed + 1;
|
bytes_parsed = bytes_parsed + 1;
|
||||||
if pubkey_length + bytes_parsed >= raw.len() {
|
if pubkey_length + bytes_parsed >= raw.len() {
|
||||||
|
@ -590,6 +576,13 @@ impl Record {
|
||||||
result.ciphers.push(cipher);
|
result.ciphers.push(cipher);
|
||||||
num_ciphers = num_ciphers - 1;
|
num_ciphers = num_ciphers - 1;
|
||||||
}
|
}
|
||||||
|
for addr in result.addresses.iter() {
|
||||||
|
for idx in addr.public_key_idx.iter() {
|
||||||
|
if idx.0 as usize >= result.public_keys.len() {
|
||||||
|
return Err(Error::Max16PublicKeys);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if bytes_parsed != raw.len() {
|
if bytes_parsed != raw.len() {
|
||||||
Err(Error::UnknownData(bytes_parsed))
|
Err(Error::UnknownData(bytes_parsed))
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -3,7 +3,10 @@
|
||||||
use ::num_traits::FromPrimitive;
|
use ::num_traits::FromPrimitive;
|
||||||
|
|
||||||
use super::Error;
|
use super::Error;
|
||||||
use crate::enc::{sym::Secret, Random};
|
use crate::{
|
||||||
|
config::Config,
|
||||||
|
enc::{sym::Secret, Random},
|
||||||
|
};
|
||||||
|
|
||||||
/// Public key ID
|
/// Public key ID
|
||||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||||
|
@ -68,8 +71,19 @@ impl KeyKind {
|
||||||
KeyKind::X25519 => KeyCapabilities::Exchange,
|
KeyKind::X25519 => KeyCapabilities::Exchange,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// Returns the key exchanges supported by this key
|
||||||
|
pub fn key_exchanges(&self) -> &'static [KeyExchange] {
|
||||||
|
const EMPTY: [KeyExchange; 0] = [];
|
||||||
|
const X25519_KEY_EXCHANGES: [KeyExchange; 1] =
|
||||||
|
[KeyExchange::X25519DiffieHellman];
|
||||||
|
match self {
|
||||||
|
KeyKind::Ed25519 => &EMPTY,
|
||||||
|
KeyKind::X25519 => &X25519_KEY_EXCHANGES,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: rename in KeyExchangeKind
|
||||||
/// Kind of key exchange
|
/// Kind of key exchange
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, ::num_derive::FromPrimitive)]
|
#[derive(Debug, Copy, Clone, PartialEq, ::num_derive::FromPrimitive)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
@ -279,7 +293,28 @@ impl ExchangePubKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Build a new pair of private/public key pair
|
/// Select the best key exchange from our supported list
|
||||||
pub fn new_keypair(kind: KeyKind, rnd: &Random) -> (PrivKey, PubKey) {
|
/// and the other endpoint supported list.
|
||||||
todo!()
|
/// Give priority to our list
|
||||||
|
pub fn server_select_key_exchange(
|
||||||
|
cfg: &Config,
|
||||||
|
client_supported: &Vec<KeyExchange>,
|
||||||
|
) -> Option<KeyExchange> {
|
||||||
|
cfg.key_exchanges
|
||||||
|
.iter()
|
||||||
|
.find(|k| client_supported.contains(k))
|
||||||
|
.copied()
|
||||||
|
}
|
||||||
|
/// Select the best key exchange from our supported list
|
||||||
|
/// and the other endpoint supported list.
|
||||||
|
/// Give priority to the server list
|
||||||
|
/// This is used only in the Directory Synchronized handshake
|
||||||
|
pub fn client_select_key_exchange(
|
||||||
|
cfg: &Config,
|
||||||
|
server_supported: &Vec<KeyExchange>,
|
||||||
|
) -> Option<KeyExchange> {
|
||||||
|
server_supported
|
||||||
|
.iter()
|
||||||
|
.find(|k| cfg.key_exchanges.contains(k))
|
||||||
|
.copied()
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
use ::sha3::Sha3_256;
|
use ::sha3::Sha3_256;
|
||||||
use ::zeroize::Zeroize;
|
use ::zeroize::Zeroize;
|
||||||
|
|
||||||
use crate::enc::sym::Secret;
|
use crate::{config::Config, enc::sym::Secret};
|
||||||
|
|
||||||
/// Kind of HKDF
|
/// Kind of HKDF
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, ::num_derive::FromPrimitive)]
|
#[derive(Debug, Copy, Clone, PartialEq, ::num_derive::FromPrimitive)]
|
||||||
|
@ -14,6 +14,12 @@ pub enum HkdfKind {
|
||||||
/// Sha3
|
/// Sha3
|
||||||
Sha3 = 0,
|
Sha3 = 0,
|
||||||
}
|
}
|
||||||
|
impl HkdfKind {
|
||||||
|
/// Length of the serialized type
|
||||||
|
pub const fn len() -> usize {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Generic wrapper on Hkdfs
|
/// Generic wrapper on Hkdfs
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -52,6 +58,8 @@ impl Hkdf {
|
||||||
// we can't use #[derive(Zeroing)] either.
|
// we can't use #[derive(Zeroing)] either.
|
||||||
// So we craete a union with a Zeroing object, and drop both manually.
|
// So we craete a union with a Zeroing object, and drop both manually.
|
||||||
|
|
||||||
|
// TODO: move this to Hkdf instead of Sha3
|
||||||
|
|
||||||
#[derive(Zeroize)]
|
#[derive(Zeroize)]
|
||||||
#[zeroize(drop)]
|
#[zeroize(drop)]
|
||||||
struct Zeroable([u8; ::core::mem::size_of::<::hkdf::Hkdf<Sha3_256>>()]);
|
struct Zeroable([u8; ::core::mem::size_of::<::hkdf::Hkdf<Sha3_256>>()]);
|
||||||
|
@ -89,7 +97,7 @@ pub struct HkdfSha3 {
|
||||||
|
|
||||||
impl HkdfSha3 {
|
impl HkdfSha3 {
|
||||||
/// Instantiate a new HKDF with Sha3-256
|
/// Instantiate a new HKDF with Sha3-256
|
||||||
pub fn new(salt: &[u8], key: Secret) -> Self {
|
pub(crate) fn new(salt: &[u8], key: Secret) -> Self {
|
||||||
let hkdf = ::hkdf::Hkdf::<Sha3_256>::new(Some(salt), key.as_ref());
|
let hkdf = ::hkdf::Hkdf::<Sha3_256>::new(Some(salt), key.as_ref());
|
||||||
Self {
|
Self {
|
||||||
inner: HkdfInner {
|
inner: HkdfInner {
|
||||||
|
@ -98,7 +106,7 @@ impl HkdfSha3 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Get a secret generated from the key and a given context
|
/// Get a secret generated from the key and a given context
|
||||||
pub fn get_secret(&self, context: &[u8]) -> Secret {
|
pub(crate) fn get_secret(&self, context: &[u8]) -> Secret {
|
||||||
let mut out: [u8; 32] = [0; 32];
|
let mut out: [u8; 32] = [0; 32];
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -117,3 +125,29 @@ impl ::core::fmt::Debug for HkdfSha3 {
|
||||||
::core::fmt::Debug::fmt("[hidden hkdf]", f)
|
::core::fmt::Debug::fmt("[hidden hkdf]", f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Select the best hkdf from our supported list
|
||||||
|
/// and the other endpoint supported list.
|
||||||
|
/// Give priority to our list
|
||||||
|
pub fn server_select_hkdf(
|
||||||
|
cfg: &Config,
|
||||||
|
client_supported: &Vec<HkdfKind>,
|
||||||
|
) -> Option<HkdfKind> {
|
||||||
|
cfg.hkdfs
|
||||||
|
.iter()
|
||||||
|
.find(|h| client_supported.contains(h))
|
||||||
|
.copied()
|
||||||
|
}
|
||||||
|
/// Select the best hkdf from our supported list
|
||||||
|
/// and the other endpoint supported list.
|
||||||
|
/// Give priority to the server list
|
||||||
|
/// this is used only in the directory synchronized handshake
|
||||||
|
pub fn client_select_hkdf(
|
||||||
|
cfg: &Config,
|
||||||
|
server_supported: &Vec<HkdfKind>,
|
||||||
|
) -> Option<HkdfKind> {
|
||||||
|
server_supported
|
||||||
|
.iter()
|
||||||
|
.find(|h| cfg.hkdfs.contains(h))
|
||||||
|
.copied()
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//! Symmetric cypher stuff
|
//! Symmetric cypher stuff
|
||||||
|
|
||||||
use super::Error;
|
use super::Error;
|
||||||
use crate::enc::Random;
|
use crate::{config::Config, enc::Random};
|
||||||
use ::zeroize::Zeroize;
|
use ::zeroize::Zeroize;
|
||||||
|
|
||||||
/// Secret, used for keys.
|
/// Secret, used for keys.
|
||||||
|
@ -299,7 +299,7 @@ impl XChaCha20Poly1305 {
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// TODO: For efficiency "Nonce" should become a reference.
|
// TODO: Merge crate::{enc::sym::Nonce, connection::handshake::dirsync::Nonce}
|
||||||
//
|
//
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
@ -387,3 +387,28 @@ impl NonceSync {
|
||||||
old_nonce
|
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> {
|
||||||
|
cfg.ciphers
|
||||||
|
.iter()
|
||||||
|
.find(|c| client_supported.contains(c))
|
||||||
|
.copied()
|
||||||
|
}
|
||||||
|
/// Select the best cipher from our supported list
|
||||||
|
/// and the other endpoint supported list.
|
||||||
|
/// Give priority to the server list
|
||||||
|
/// This is used only in the Directory synchronized handshake
|
||||||
|
pub fn client_select_cipher(
|
||||||
|
cfg: &Config,
|
||||||
|
server_supported: &Vec<CipherKind>,
|
||||||
|
) -> Option<CipherKind> {
|
||||||
|
server_supported
|
||||||
|
.iter()
|
||||||
|
.find(|c| cfg.ciphers.contains(c))
|
||||||
|
.copied()
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
//! Worker thread implementation
|
//! Worker thread implementation
|
||||||
use crate::{
|
use crate::{
|
||||||
auth::{ServiceID, TokenChecker},
|
auth::{ServiceID, TokenChecker},
|
||||||
|
config::Config,
|
||||||
connection::{
|
connection::{
|
||||||
self,
|
self,
|
||||||
handshake::{
|
handshake::{
|
||||||
|
@ -12,9 +13,9 @@ use crate::{
|
||||||
},
|
},
|
||||||
dnssec,
|
dnssec,
|
||||||
enc::{
|
enc::{
|
||||||
asym::PubKey,
|
asym::{self, PubKey},
|
||||||
hkdf::{Hkdf, HkdfKind},
|
hkdf::{self, Hkdf, HkdfKind},
|
||||||
sym::Secret,
|
sym::{self, Secret},
|
||||||
Random,
|
Random,
|
||||||
},
|
},
|
||||||
inner::{HandshakeAction, HandshakeTracker, ThreadTracker},
|
inner::{HandshakeAction, HandshakeTracker, ThreadTracker},
|
||||||
|
@ -53,6 +54,7 @@ pub(crate) enum WorkAnswer {
|
||||||
|
|
||||||
/// Actual worker implementation.
|
/// Actual worker implementation.
|
||||||
pub(crate) struct Worker {
|
pub(crate) struct Worker {
|
||||||
|
cfg: Config,
|
||||||
thread_id: ThreadTracker,
|
thread_id: ThreadTracker,
|
||||||
// PERF: rand uses syscalls. how to do that async?
|
// PERF: rand uses syscalls. how to do that async?
|
||||||
rand: Random,
|
rand: Random,
|
||||||
|
@ -67,6 +69,7 @@ pub(crate) struct Worker {
|
||||||
|
|
||||||
impl Worker {
|
impl Worker {
|
||||||
pub(crate) async fn new_and_loop(
|
pub(crate) async fn new_and_loop(
|
||||||
|
cfg: Config,
|
||||||
thread_id: ThreadTracker,
|
thread_id: ThreadTracker,
|
||||||
stop_working: ::tokio::sync::broadcast::Receiver<bool>,
|
stop_working: ::tokio::sync::broadcast::Receiver<bool>,
|
||||||
token_check: Option<Arc<Mutex<TokenChecker>>>,
|
token_check: Option<Arc<Mutex<TokenChecker>>>,
|
||||||
|
@ -75,6 +78,7 @@ impl Worker {
|
||||||
) -> ::std::io::Result<()> {
|
) -> ::std::io::Result<()> {
|
||||||
// TODO: get a channel to send back information, and send the error
|
// TODO: get a channel to send back information, and send the error
|
||||||
let mut worker = Self::new(
|
let mut worker = Self::new(
|
||||||
|
cfg,
|
||||||
thread_id,
|
thread_id,
|
||||||
stop_working,
|
stop_working,
|
||||||
token_check,
|
token_check,
|
||||||
|
@ -86,6 +90,7 @@ impl Worker {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
pub(crate) async fn new(
|
pub(crate) async fn new(
|
||||||
|
cfg: Config,
|
||||||
thread_id: ThreadTracker,
|
thread_id: ThreadTracker,
|
||||||
stop_working: ::tokio::sync::broadcast::Receiver<bool>,
|
stop_working: ::tokio::sync::broadcast::Receiver<bool>,
|
||||||
token_check: Option<Arc<Mutex<TokenChecker>>>,
|
token_check: Option<Arc<Mutex<TokenChecker>>>,
|
||||||
|
@ -126,6 +131,7 @@ impl Worker {
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
cfg,
|
||||||
thread_id,
|
thread_id,
|
||||||
rand: Random::new(),
|
rand: Random::new(),
|
||||||
stop_working,
|
stop_working,
|
||||||
|
@ -156,19 +162,52 @@ impl Worker {
|
||||||
let _ = sender.send(conn_num);
|
let _ = sender.send(conn_num);
|
||||||
}
|
}
|
||||||
Work::Connect((send_res, dnssec_record, _service_id)) => {
|
Work::Connect((send_res, dnssec_record, _service_id)) => {
|
||||||
|
// PERF: geolocation
|
||||||
|
|
||||||
|
// Find the first destination with a coherent
|
||||||
|
// pubkey/key exchange
|
||||||
let destination =
|
let destination =
|
||||||
dnssec_record.addresses.iter().find_map(|addr| {
|
dnssec_record.addresses.iter().find_map(|addr| {
|
||||||
let maybe_key =
|
if addr
|
||||||
dnssec_record.public_keys.iter().find(
|
.handshake_ids
|
||||||
|(id, _)| addr.public_key_ids.contains(id),
|
.iter()
|
||||||
);
|
.find(|h_srv| {
|
||||||
match maybe_key {
|
self.cfg.handshakes.contains(h_srv)
|
||||||
Some(key) => Some((addr, key)),
|
})
|
||||||
None => None,
|
.is_none()
|
||||||
|
{
|
||||||
|
// skip servers with no corresponding
|
||||||
|
// handshake types
|
||||||
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for idx in addr.public_key_idx.iter() {
|
||||||
|
let key_supported_k_x =
|
||||||
|
dnssec_record.public_keys[idx.0 as usize]
|
||||||
|
.1
|
||||||
|
.kind()
|
||||||
|
.key_exchanges();
|
||||||
|
match self
|
||||||
|
.cfg
|
||||||
|
.key_exchanges
|
||||||
|
.iter()
|
||||||
|
.find(|x| key_supported_k_x.contains(x))
|
||||||
|
{
|
||||||
|
Some(exchange) => {
|
||||||
|
return Some((
|
||||||
|
addr,
|
||||||
|
dnssec_record.public_keys
|
||||||
|
[idx.0 as usize],
|
||||||
|
exchange,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
None => return None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return None;
|
||||||
});
|
});
|
||||||
let (addr, key) = match destination {
|
let (addr, key, exchange) = match destination {
|
||||||
Some((addr, key)) => (addr, key),
|
Some((addr, key, exchange)) => (addr, key, exchange),
|
||||||
None => {
|
None => {
|
||||||
let _ =
|
let _ =
|
||||||
send_res.send(Err(crate::Error::Resolution(
|
send_res.send(Err(crate::Error::Resolution(
|
||||||
|
@ -178,8 +217,29 @@ impl Worker {
|
||||||
continue 'mainloop;
|
continue 'mainloop;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
use crate::enc::asym;
|
let hkdf = match hkdf::client_select_hkdf(
|
||||||
let exchange = asym::KeyExchange::X25519DiffieHellman;
|
&self.cfg,
|
||||||
|
&dnssec_record.hkdfs,
|
||||||
|
) {
|
||||||
|
Some(hkdf) => hkdf,
|
||||||
|
None => {
|
||||||
|
let _ = send_res
|
||||||
|
.send(Err(crate::Error::HandshakeNegotiation));
|
||||||
|
continue 'mainloop;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let cipher = match sym::client_select_cipher(
|
||||||
|
&self.cfg,
|
||||||
|
&dnssec_record.ciphers,
|
||||||
|
) {
|
||||||
|
Some(cipher) => cipher,
|
||||||
|
None => {
|
||||||
|
let _ = send_res
|
||||||
|
.send(Err(crate::Error::HandshakeNegotiation));
|
||||||
|
continue 'mainloop;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let (priv_key, pub_key) =
|
let (priv_key, pub_key) =
|
||||||
match exchange.new_keypair(&self.rand) {
|
match exchange.new_keypair(&self.rand) {
|
||||||
Ok(pair) => pair,
|
Ok(pair) => pair,
|
||||||
|
@ -187,10 +247,15 @@ impl Worker {
|
||||||
};
|
};
|
||||||
// build request
|
// build request
|
||||||
/*
|
/*
|
||||||
|
let req_data = dirsync::ReqData {
|
||||||
|
nonce: dirsync::Nonce::new(&self.rand),
|
||||||
|
client_key_id:
|
||||||
|
};
|
||||||
let req = dirsync::Req {
|
let req = dirsync::Req {
|
||||||
key_id: key.0,
|
key_id: key.0,
|
||||||
exchange: exchange,
|
exchange,
|
||||||
cipher: 42,
|
hkdf,
|
||||||
|
cipher,
|
||||||
exchange_key: client_pub_key,
|
exchange_key: client_pub_key,
|
||||||
data: 42,
|
data: 42,
|
||||||
};
|
};
|
||||||
|
|
|
@ -62,6 +62,9 @@ pub enum Error {
|
||||||
/// Resolution problems. wrong or incomplete DNSSEC data
|
/// Resolution problems. wrong or incomplete DNSSEC data
|
||||||
#[error("DNSSEC resolution: {0}")]
|
#[error("DNSSEC resolution: {0}")]
|
||||||
Resolution(String),
|
Resolution(String),
|
||||||
|
/// No common cryptographic primitives
|
||||||
|
#[error("No common cryptographic primitives")]
|
||||||
|
HandshakeNegotiation,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Instance of a fenrir endpoint
|
/// Instance of a fenrir endpoint
|
||||||
|
@ -381,6 +384,7 @@ impl Fenrir {
|
||||||
::tracing::debug!("Spawning thread {}", core);
|
::tracing::debug!("Spawning thread {}", core);
|
||||||
let th_topology = hw_topology.clone();
|
let th_topology = hw_topology.clone();
|
||||||
let th_tokio_rt = tokio_rt.clone();
|
let th_tokio_rt = tokio_rt.clone();
|
||||||
|
let th_config = self.cfg.clone();
|
||||||
let (work_send, work_recv) = ::async_channel::unbounded::<Work>();
|
let (work_send, work_recv) = ::async_channel::unbounded::<Work>();
|
||||||
let th_stop_working = self.stop_working.subscribe();
|
let th_stop_working = self.stop_working.subscribe();
|
||||||
let th_token_check = self.token_check.clone();
|
let th_token_check = self.token_check.clone();
|
||||||
|
@ -417,6 +421,7 @@ impl Fenrir {
|
||||||
let _ = tk_local.block_on(
|
let _ = tk_local.block_on(
|
||||||
&th_tokio_rt,
|
&th_tokio_rt,
|
||||||
Worker::new_and_loop(
|
Worker::new_and_loop(
|
||||||
|
th_config,
|
||||||
thread_id,
|
thread_id,
|
||||||
th_stop_working,
|
th_stop_working,
|
||||||
th_token_check,
|
th_token_check,
|
||||||
|
|
Loading…
Reference in New Issue