More work on ciphers and hkdf
Signed-off-by: Luca Fulchir <luca.fulchir@runesauth.com>
This commit is contained in:
parent
238a0a5516
commit
a39767d32b
43
Cargo.toml
43
Cargo.toml
|
@ -10,7 +10,7 @@ rust-version = "1.67.0"
|
||||||
homepage = "https://git.runesauth.com/RunesAuth/libFenrir"
|
homepage = "https://git.runesauth.com/RunesAuth/libFenrir"
|
||||||
repository = "https://git.runesauth.com/RunesAuth/libFenrir"
|
repository = "https://git.runesauth.com/RunesAuth/libFenrir"
|
||||||
license = "Apache-2.0 WITH LLVM-exception"
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
license-file = "LICENSE"
|
#license-file = "LICENSE"
|
||||||
keywords = [ "Fenrir", "libFenrir", "authentication" ]
|
keywords = [ "Fenrir", "libFenrir", "authentication" ]
|
||||||
categories = [ "authentication", "cryptography", "network-programming" ]
|
categories = [ "authentication", "cryptography", "network-programming" ]
|
||||||
|
|
||||||
|
@ -26,26 +26,33 @@ crate_type = [ "lib", "cdylib", "staticlib" ]
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# please keep these in alphabetical order
|
# please keep these in alphabetical order
|
||||||
|
|
||||||
arc-swap = { version = "^1.6" }
|
arc-swap = { version = "1.6" }
|
||||||
# base85 repo has no tags, fix on a commit. v1.1.1 points to older, wrong version
|
# base85 repo has no tags, fix on a commit. v1.1.1 points to older, wrong version
|
||||||
base85 = { git = "https://gitlab.com/darkwyrm/base85", rev = "d98efbfd171dd9ba48e30a5c88f94db92fc7b3c6" }
|
base85 = { git = "https://gitlab.com/darkwyrm/base85", rev = "d98efbfd171dd9ba48e30a5c88f94db92fc7b3c6" }
|
||||||
futures = { version = "^0.3" }
|
futures = { version = "0.3" }
|
||||||
libc = { version = "^0.2" }
|
hkdf = { version = "0.12" }
|
||||||
num-traits = { version = "^0.2" }
|
libc = { version = "0.2" }
|
||||||
num-derive = { version = "^0.3" }
|
num-traits = { version = "0.2" }
|
||||||
ring = { version = "^0.16" }
|
num-derive = { version = "0.3" }
|
||||||
bincode = { version = "^1.3" }
|
ring = { version = "0.16" }
|
||||||
strum = { version = "^0.24" }
|
bincode = { version = "1.3" }
|
||||||
strum_macros = { version = "^0.24" }
|
sha3 = { version = "0.10" }
|
||||||
thiserror = { version = "^1.0" }
|
strum = { version = "0.24" }
|
||||||
tokio = { version = "^1", features = ["full"] }
|
strum_macros = { version = "0.24" }
|
||||||
|
thiserror = { version = "1.0" }
|
||||||
|
tokio = { version = "1", features = ["full"] }
|
||||||
# PERF: todo linux-only, behind "iouring" feature
|
# PERF: todo linux-only, behind "iouring" feature
|
||||||
#tokio-uring = { version = "^0.4" }
|
#tokio-uring = { version = "0.4" }
|
||||||
tracing = { version = "^0.1" }
|
tracing = { version = "0.1" }
|
||||||
trust-dns-resolver = { version = "^0.22", features = [ "dnssec-ring" ] }
|
trust-dns-resolver = { version = "0.22", features = [ "dnssec-ring" ] }
|
||||||
trust-dns-client = { version = "^0.22", features = [ "dnssec" ] }
|
trust-dns-client = { version = "0.22", features = [ "dnssec" ] }
|
||||||
trust-dns-proto = { version = "^0.22" }
|
trust-dns-proto = { version = "0.22" }
|
||||||
x25519-dalek = { version = "^1.2", features = [ "serde" ] }
|
x25519-dalek = { version = "1.2", features = [ "serde" ] }
|
||||||
|
# NOTE: can not force newer versions of zeroize:
|
||||||
|
# * zeroize is a dependency of x25519-dalek
|
||||||
|
# * zeroize is not *pure* rust, but uses `alloc`
|
||||||
|
# * rust can have multiple versions as deps, but only if the are pure rust
|
||||||
|
zeroize = { version = "1" }
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,10 @@
|
||||||
use super::{Error, HandshakeData};
|
use super::{Error, HandshakeData};
|
||||||
use crate::{
|
use crate::{
|
||||||
connection::ID,
|
connection::ID,
|
||||||
enc::asym::{ExchangePubKey, KeyID},
|
enc::{
|
||||||
|
asym::{ExchangePubKey, KeyExchange, KeyID},
|
||||||
|
sym::CipherKind,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use ::std::vec::Vec;
|
use ::std::vec::Vec;
|
||||||
|
|
||||||
|
@ -29,6 +32,10 @@ pub enum DirSync {
|
||||||
pub struct Req {
|
pub struct Req {
|
||||||
/// Id of the server key used for the key exchange
|
/// Id of the server key used for the key exchange
|
||||||
pub key_id: KeyID,
|
pub key_id: KeyID,
|
||||||
|
/// Selected key exchange
|
||||||
|
pub exchange: KeyExchange,
|
||||||
|
/// Selected cipher
|
||||||
|
pub cipher: CipherKind,
|
||||||
/// Client ephemeral public key used for key exchanges
|
/// Client ephemeral public key used for key exchanges
|
||||||
pub exchange_key: ExchangePubKey,
|
pub exchange_key: ExchangePubKey,
|
||||||
/// encrypted data
|
/// encrypted data
|
||||||
|
@ -37,19 +44,30 @@ pub struct Req {
|
||||||
|
|
||||||
impl super::HandshakeParsing for Req {
|
impl super::HandshakeParsing for Req {
|
||||||
fn parse(raw: &[u8]) -> Result<HandshakeData, Error> {
|
fn parse(raw: &[u8]) -> Result<HandshakeData, Error> {
|
||||||
const MIN_PKT_LEN: usize = 8;
|
const MIN_PKT_LEN: usize = 10;
|
||||||
if raw.len() < MIN_PKT_LEN {
|
if raw.len() < MIN_PKT_LEN {
|
||||||
return Err(Error::NotEnoughData);
|
return Err(Error::NotEnoughData);
|
||||||
}
|
}
|
||||||
let key_id: KeyID =
|
let key_id: KeyID =
|
||||||
KeyID(u16::from_le_bytes(raw[0..1].try_into().unwrap()));
|
KeyID(u16::from_le_bytes(raw[0..1].try_into().unwrap()));
|
||||||
let (exchange_key, len) = match ExchangePubKey::from_slice(&raw[2..]) {
|
use ::num_traits::FromPrimitive;
|
||||||
|
let exchange: KeyExchange = match KeyExchange::from_u8(raw[2]) {
|
||||||
|
Some(exchange) => exchange,
|
||||||
|
None => return Err(Error::Parsing),
|
||||||
|
};
|
||||||
|
let cipher: CipherKind = match CipherKind::from_u8(raw[3]) {
|
||||||
|
Some(cipher) => cipher,
|
||||||
|
None => return Err(Error::Parsing),
|
||||||
|
};
|
||||||
|
let (exchange_key, len) = match ExchangePubKey::from_slice(&raw[4..]) {
|
||||||
Ok(exchange_key) => exchange_key,
|
Ok(exchange_key) => exchange_key,
|
||||||
Err(e) => return Err(e.into()),
|
Err(e) => return Err(e.into()),
|
||||||
};
|
};
|
||||||
let enc = raw[(2 + len)..].to_vec();
|
let enc = raw[(4 + len)..].to_vec();
|
||||||
Ok(HandshakeData::DirSync(DirSync::Req(Self {
|
Ok(HandshakeData::DirSync(DirSync::Req(Self {
|
||||||
key_id,
|
key_id,
|
||||||
|
exchange,
|
||||||
|
cipher,
|
||||||
exchange_key,
|
exchange_key,
|
||||||
enc,
|
enc,
|
||||||
})))
|
})))
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
pub mod handshake;
|
pub mod handshake;
|
||||||
mod packet;
|
mod packet;
|
||||||
|
|
||||||
use ::num_traits::FromPrimitive;
|
|
||||||
use ::std::vec::Vec;
|
use ::std::vec::Vec;
|
||||||
|
|
||||||
pub use handshake::Handshake;
|
pub use handshake::Handshake;
|
||||||
|
|
|
@ -4,11 +4,36 @@ use ::num_traits::FromPrimitive;
|
||||||
use ::std::vec::Vec;
|
use ::std::vec::Vec;
|
||||||
|
|
||||||
use super::Error;
|
use super::Error;
|
||||||
|
use crate::enc::sym::Secret;
|
||||||
|
|
||||||
/// Public key ID
|
/// Public key ID
|
||||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||||
pub struct KeyID(pub u16);
|
pub struct KeyID(pub u16);
|
||||||
|
|
||||||
|
/// Kind of key used in the handshake
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, ::num_derive::FromPrimitive)]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum Key {
|
||||||
|
/// X25519 Public key
|
||||||
|
X25519 = 0,
|
||||||
|
}
|
||||||
|
impl Key {
|
||||||
|
fn pub_len(&self) -> usize {
|
||||||
|
match self {
|
||||||
|
// FIXME: 99% wrong size
|
||||||
|
Key::X25519 => ::ring::signature::ED25519_PUBLIC_KEY_LEN,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Kind of key exchange
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, ::num_derive::FromPrimitive)]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum KeyExchange {
|
||||||
|
/// X25519 Public key
|
||||||
|
X25519DiffieHellman = 0,
|
||||||
|
}
|
||||||
|
|
||||||
/// Kind of key in the handshake
|
/// Kind of key in the handshake
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
#[allow(missing_debug_implementations)]
|
#[allow(missing_debug_implementations)]
|
||||||
|
@ -28,28 +53,29 @@ pub enum ExchangePrivKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExchangePrivKey {
|
impl ExchangePrivKey {
|
||||||
|
/// Get the kind of key
|
||||||
|
pub fn kind(&self) -> Key {
|
||||||
|
match self {
|
||||||
|
ExchangePrivKey::X25519(_) => Key::X25519,
|
||||||
|
}
|
||||||
|
}
|
||||||
/// Run the key exchange between two keys of the same kind
|
/// Run the key exchange between two keys of the same kind
|
||||||
pub fn key_exchange(
|
pub fn key_exchange(
|
||||||
&self,
|
&self,
|
||||||
|
exchange: KeyExchange,
|
||||||
pub_key: ExchangePubKey,
|
pub_key: ExchangePubKey,
|
||||||
) -> Result<[u8; 32], Error> {
|
) -> Result<Secret, Error> {
|
||||||
todo!();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Kind of key in the key exchange
|
|
||||||
#[derive(Debug, Copy, Clone, ::num_derive::FromPrimitive)]
|
|
||||||
#[repr(u8)]
|
|
||||||
pub enum ExchangePubKeyKind {
|
|
||||||
/// X25519 Public key
|
|
||||||
X25519 = 0,
|
|
||||||
}
|
|
||||||
impl ExchangePubKeyKind {
|
|
||||||
fn len(&self) -> usize {
|
|
||||||
match self {
|
match self {
|
||||||
// FIXME: 99% wrong size
|
ExchangePrivKey::X25519(priv_key) => {
|
||||||
ExchangePubKeyKind::X25519 => {
|
if exchange != KeyExchange::X25519DiffieHellman {
|
||||||
::ring::signature::ED25519_PUBLIC_KEY_LEN
|
return Err(Error::UnsupportedKeyExchange);
|
||||||
|
}
|
||||||
|
if let ExchangePubKey::X25519(inner_pub_key) = pub_key {
|
||||||
|
let shared_secret = priv_key.diffie_hellman(&inner_pub_key);
|
||||||
|
Ok(shared_secret.into())
|
||||||
|
} else {
|
||||||
|
Err(Error::UnsupportedKeyExchange)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,16 +98,17 @@ impl ExchangePubKey {
|
||||||
if raw.len() < 1 + MIN_KEY_SIZE {
|
if raw.len() < 1 + MIN_KEY_SIZE {
|
||||||
return Err(Error::NotEnoughData);
|
return Err(Error::NotEnoughData);
|
||||||
}
|
}
|
||||||
match ExchangePubKeyKind::from_u8(raw[0]) {
|
match Key::from_u8(raw[0]) {
|
||||||
Some(kind) => match kind {
|
Some(kind) => match kind {
|
||||||
ExchangePubKeyKind::X25519 => {
|
Key::X25519 => {
|
||||||
let pub_key: ::x25519_dalek::PublicKey =
|
let pub_key: ::x25519_dalek::PublicKey =
|
||||||
match ::bincode::deserialize(&raw[1..(1 + kind.len())])
|
match ::bincode::deserialize(
|
||||||
{
|
&raw[1..(1 + kind.pub_len())],
|
||||||
|
) {
|
||||||
Ok(pub_key) => pub_key,
|
Ok(pub_key) => pub_key,
|
||||||
Err(_) => return Err(Error::Parsing),
|
Err(_) => return Err(Error::Parsing),
|
||||||
};
|
};
|
||||||
Ok((ExchangePubKey::X25519(pub_key), kind.len()))
|
Ok((ExchangePubKey::X25519(pub_key), kind.pub_len()))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
|
|
|
@ -13,4 +13,10 @@ pub enum Error {
|
||||||
/// You might have passed rsa keys where x25519 was expected
|
/// You might have passed rsa keys where x25519 was expected
|
||||||
#[error("wrong key type")]
|
#[error("wrong key type")]
|
||||||
WrongKey,
|
WrongKey,
|
||||||
|
/// Unsupported key exchange for this key
|
||||||
|
#[error("unsupported key exchange")]
|
||||||
|
UnsupportedKeyExchange,
|
||||||
|
/// Unsupported cipher
|
||||||
|
#[error("unsupported cipher")]
|
||||||
|
UnsupportedCipher,
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
//! Hash-based Key Derivation Function
|
||||||
|
//! We just repackage other crates
|
||||||
|
|
||||||
|
use ::hkdf::Hkdf;
|
||||||
|
use ::sha3::Sha3_256;
|
||||||
|
use ::zeroize::Zeroize;
|
||||||
|
|
||||||
|
use crate::enc::sym::Secret;
|
||||||
|
|
||||||
|
// Hack & tricks:
|
||||||
|
// HKDF are pretty important, but they don't zero out the data.
|
||||||
|
// we can't user #[derive(Zeroing)] either.
|
||||||
|
// So we craete a union with a Zeroing object, and drop manually both.
|
||||||
|
|
||||||
|
#[derive(Zeroize)]
|
||||||
|
#[zeroize(drop)]
|
||||||
|
struct Zeroable([u8; ::core::mem::size_of::<Hkdf<Sha3_256>>()]);
|
||||||
|
|
||||||
|
union HkdfInner {
|
||||||
|
hkdf: ::core::mem::ManuallyDrop<Hkdf<Sha3_256>>,
|
||||||
|
zeroable: ::core::mem::ManuallyDrop<Zeroable>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for HkdfInner {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
unsafe {
|
||||||
|
drop(&mut self.hkdf);
|
||||||
|
drop(&mut self.zeroable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sha3 based HKDF
|
||||||
|
#[allow(missing_debug_implementations)]
|
||||||
|
pub struct HkdfSha3 {
|
||||||
|
_inner: Hkdf<Sha3_256>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HkdfSha3 {
|
||||||
|
/// Instantiate a new HKDF with Sha3-256
|
||||||
|
pub fn new(salt: Option<&[u8]>, key: Secret) -> Self {
|
||||||
|
Self {
|
||||||
|
_inner: Hkdf::<Sha3_256>::new(salt, key.as_ref()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
pub mod asym;
|
pub mod asym;
|
||||||
mod errors;
|
mod errors;
|
||||||
|
pub mod hkdf;
|
||||||
pub mod sym;
|
pub mod sym;
|
||||||
|
|
||||||
pub use errors::Error;
|
pub use errors::Error;
|
||||||
|
|
|
@ -1,5 +1,96 @@
|
||||||
//! Symmetric cypher stuff
|
//! Symmetric cypher stuff
|
||||||
|
|
||||||
|
use ::zeroize::Zeroize;
|
||||||
|
|
||||||
|
/// Secret, used for keys.
|
||||||
|
/// Grants that on drop() we will zero out memory
|
||||||
|
#[derive(Zeroize)]
|
||||||
|
#[zeroize(drop)]
|
||||||
|
#[allow(missing_debug_implementations)]
|
||||||
|
pub struct Secret {
|
||||||
|
secret: [u8; 32],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Secret {
|
||||||
|
/// return a reference to the secret
|
||||||
|
pub fn as_ref(&self) -> &[u8; 32] {
|
||||||
|
&self.secret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<::x25519_dalek::SharedSecret> for Secret {
|
||||||
|
fn from(shared_secret: ::x25519_dalek::SharedSecret) -> Self {
|
||||||
|
Self {
|
||||||
|
secret: shared_secret.to_bytes(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// List of possible Ciphers
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, ::num_derive::FromPrimitive)]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum CipherKind {
|
||||||
|
/// Chaha20_Poly1305
|
||||||
|
Chacha20Poly1305 = 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CipherKind {
|
||||||
|
/// required length of the nonce
|
||||||
|
pub fn nonce_len(&self) -> usize {
|
||||||
|
::ring::aead::CHACHA20_POLY1305.nonce_len()
|
||||||
|
}
|
||||||
|
/// required length of the key
|
||||||
|
pub fn key_len(&self) -> usize {
|
||||||
|
::ring::aead::CHACHA20_POLY1305.key_len()
|
||||||
|
}
|
||||||
|
/// Length of the authentication tag
|
||||||
|
pub fn tag_len(&self) -> usize {
|
||||||
|
::ring::aead::CHACHA20_POLY1305.tag_len()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// actual ciphers
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Cipher {
|
||||||
|
/// Cipher Chaha20_Poly1305
|
||||||
|
Chacha20Poly1305(Chacha20Poly1305),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Cipher {
|
||||||
|
/// Build a new Cipher
|
||||||
|
pub fn new(kind: CipherKind, secret: Secret) -> Self {
|
||||||
|
match kind {
|
||||||
|
CipherKind::Chacha20Poly1305 => {
|
||||||
|
Self::Chacha20Poly1305(Chacha20Poly1305::new(secret))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Chacha20Poly1305 cipher
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Chacha20Poly1305 {
|
||||||
|
cipher: ::ring::aead::OpeningKey<Nonce>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Chacha20Poly1305 {
|
||||||
|
/// Initialize the cipher with the given nonce
|
||||||
|
pub fn with_nonce(key: Secret, nonce: Nonce) -> Self {
|
||||||
|
let unbound_key = ::ring::aead::UnboundKey::new(
|
||||||
|
&::ring::aead::CHACHA20_POLY1305,
|
||||||
|
key.as_ref(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
use ::ring::aead::BoundKey;
|
||||||
|
Self {
|
||||||
|
cipher: ::ring::aead::OpeningKey::<Nonce>::new(unbound_key, nonce),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Initialize a new ChachaPoly20 cipher with a random nonce
|
||||||
|
pub fn new(key: Secret) -> Self {
|
||||||
|
Self::with_nonce(key, Nonce::new())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[allow(missing_debug_implementations)]
|
#[allow(missing_debug_implementations)]
|
||||||
|
@ -11,6 +102,8 @@ struct NonceNum {
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub union Nonce {
|
pub union Nonce {
|
||||||
num: NonceNum,
|
num: NonceNum,
|
||||||
|
// ring::aead::Nonce does not implement 'Copy'
|
||||||
|
// even though it's just [u8;12]
|
||||||
raw: ::core::mem::ManuallyDrop<::ring::aead::Nonce>,
|
raw: ::core::mem::ManuallyDrop<::ring::aead::Nonce>,
|
||||||
easy_from: [u8; 12],
|
easy_from: [u8; 12],
|
||||||
}
|
}
|
||||||
|
@ -48,7 +141,6 @@ impl Nonce {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//impl Copy for Nonce {}
|
|
||||||
impl Clone for Nonce {
|
impl Clone for Nonce {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
|
|
37
src/lib.rs
37
src/lib.rs
|
@ -22,6 +22,7 @@ use ::arc_swap::{ArcSwap, ArcSwapAny};
|
||||||
use ::std::{net::SocketAddr, sync::Arc};
|
use ::std::{net::SocketAddr, sync::Arc};
|
||||||
use ::tokio::{net::UdpSocket, task::JoinHandle};
|
use ::tokio::{net::UdpSocket, task::JoinHandle};
|
||||||
|
|
||||||
|
use crate::enc::{asym, sym::CipherKind};
|
||||||
pub use config::Config;
|
pub use config::Config;
|
||||||
use connection::handshake::{self, Handshake, HandshakeKey};
|
use connection::handshake::{self, Handshake, HandshakeKey};
|
||||||
|
|
||||||
|
@ -40,9 +41,14 @@ pub enum Error {
|
||||||
/// Handshake errors
|
/// Handshake errors
|
||||||
#[error("Handshake: {0:?}")]
|
#[error("Handshake: {0:?}")]
|
||||||
Handshake(#[from] handshake::Error),
|
Handshake(#[from] handshake::Error),
|
||||||
|
/// Key error
|
||||||
|
#[error("key: {0:?}")]
|
||||||
|
Key(#[from] crate::enc::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FenrirInner {
|
struct FenrirInner {
|
||||||
|
key_exchanges: ArcSwapAny<Arc<Vec<(asym::Key, asym::KeyExchange)>>>,
|
||||||
|
ciphers: ArcSwapAny<Arc<Vec<CipherKind>>>,
|
||||||
keys: ArcSwapAny<Arc<Vec<HandshakeKey>>>,
|
keys: ArcSwapAny<Arc<Vec<HandshakeKey>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,21 +82,30 @@ impl FenrirInner {
|
||||||
return Err(handshake::Error::UnknownKeyID.into());
|
return Err(handshake::Error::UnknownKeyID.into());
|
||||||
}
|
}
|
||||||
let ephemeral_key = ephemeral_key.unwrap();
|
let ephemeral_key = ephemeral_key.unwrap();
|
||||||
|
{
|
||||||
|
let exchanges = self.key_exchanges.load();
|
||||||
|
if None
|
||||||
|
== exchanges.iter().find(|&x| {
|
||||||
|
*x == (ephemeral_key.kind(), req.exchange)
|
||||||
|
})
|
||||||
|
{
|
||||||
|
return Err(
|
||||||
|
enc::Error::UnsupportedKeyExchange.into()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let ciphers = self.ciphers.load();
|
||||||
|
if None == ciphers.iter().find(|&x| *x == req.cipher) {
|
||||||
|
return Err(enc::Error::UnsupportedCipher.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
let shared_key = match ephemeral_key
|
let shared_key = match ephemeral_key
|
||||||
.key_exchange(req.exchange_key)
|
.key_exchange(req.exchange, req.exchange_key)
|
||||||
{
|
{
|
||||||
Ok(shared_key) => shared_key,
|
Ok(shared_key) => shared_key,
|
||||||
Err(e) => return Err(handshake::Error::Key(e).into()),
|
Err(e) => return Err(handshake::Error::Key(e).into()),
|
||||||
};
|
};
|
||||||
use crate::enc::sym::Nonce;
|
|
||||||
use ::ring::aead::{self, BoundKey};
|
|
||||||
let alg = aead::UnboundKey::new(
|
|
||||||
&aead::CHACHA20_POLY1305,
|
|
||||||
&shared_key,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let nonce = Nonce::new();
|
|
||||||
let chacha = aead::OpeningKey::new(alg, nonce);
|
|
||||||
todo!();
|
todo!();
|
||||||
}
|
}
|
||||||
DirSync::Resp(resp) => {
|
DirSync::Resp(resp) => {
|
||||||
|
@ -135,6 +150,8 @@ impl Fenrir {
|
||||||
dnssec: None,
|
dnssec: None,
|
||||||
stop_working: sender,
|
stop_working: sender,
|
||||||
_inner: Arc::new(FenrirInner {
|
_inner: Arc::new(FenrirInner {
|
||||||
|
ciphers: ArcSwapAny::new(Arc::new(Vec::new())),
|
||||||
|
key_exchanges: ArcSwapAny::new(Arc::new(Vec::new())),
|
||||||
keys: ArcSwapAny::new(Arc::new(Vec::new())),
|
keys: ArcSwapAny::new(Arc::new(Vec::new())),
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue