Helpers for dnssec
Signed-off-by: Luca Fulchir <luca.fulchir@runesauth.com>
This commit is contained in:
parent
3e09b9cee0
commit
6da5464c68
|
@ -106,8 +106,10 @@ impl Domain {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reserve the first service ID for the authentication service
|
||||||
|
pub const SERVICEID_AUTH: ServiceID = ServiceID([0; 16]);
|
||||||
/// The Service ID is a UUID associated with the service.
|
/// The Service ID is a UUID associated with the service.
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||||
pub struct ServiceID([u8; 16]);
|
pub struct ServiceID([u8; 16]);
|
||||||
|
|
||||||
impl From<[u8; 16]> for ServiceID {
|
impl From<[u8; 16]> for ServiceID {
|
||||||
|
|
|
@ -185,7 +185,7 @@ impl ConnList {
|
||||||
self.connections[id_in_thread] = Some(conn);
|
self.connections[id_in_thread] = Some(conn);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
pub(crate) fn delete(&mut self, id: IDRecv) {
|
pub(crate) fn remove(&mut self, id: IDRecv) {
|
||||||
if let IDRecv(ID::ID(raw_id)) = id {
|
if let IDRecv(ID::ID(raw_id)) = id {
|
||||||
let id_in_thread: usize =
|
let id_in_thread: usize =
|
||||||
(raw_id.get() / (self.thread_id.total as u64)) as usize;
|
(raw_id.get() / (self.thread_id.total as u64)) as usize;
|
||||||
|
|
121
src/enc/asym.rs
121
src/enc/asym.rs
|
@ -25,6 +25,24 @@ impl KeyID {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TryFrom<&str> for KeyID {
|
||||||
|
type Error = ::std::io::Error;
|
||||||
|
fn try_from(raw: &str) -> Result<Self, Self::Error> {
|
||||||
|
if let Ok(id_u16) = raw.parse::<u16>() {
|
||||||
|
return Ok(KeyID(id_u16));
|
||||||
|
}
|
||||||
|
return Err(::std::io::Error::new(
|
||||||
|
::std::io::ErrorKind::InvalidData,
|
||||||
|
"KeyID must be between 0 and 65535",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl ::std::fmt::Display for KeyID {
|
||||||
|
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
||||||
|
write!(f, "{}", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Capabilities of each key
|
/// Capabilities of each key
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum KeyCapabilities {
|
pub enum KeyCapabilities {
|
||||||
|
@ -56,13 +74,23 @@ impl KeyCapabilities {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Kind of key used in the handshake
|
/// Kind of key used in the handshake
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, ::num_derive::FromPrimitive)]
|
#[derive(
|
||||||
|
Debug,
|
||||||
|
Copy,
|
||||||
|
Clone,
|
||||||
|
PartialEq,
|
||||||
|
::num_derive::FromPrimitive,
|
||||||
|
::strum_macros::EnumString,
|
||||||
|
::strum_macros::IntoStaticStr,
|
||||||
|
)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum KeyKind {
|
pub enum KeyKind {
|
||||||
/// Ed25519 Public key (sign only)
|
/// Ed25519 Public key (sign only)
|
||||||
|
#[strum(serialize = "ed25519")]
|
||||||
Ed25519 = 0,
|
Ed25519 = 0,
|
||||||
/// X25519 Public key (key exchange)
|
/// X25519 Public key (key exchange)
|
||||||
|
#[strum(serialize = "x25519")]
|
||||||
X25519,
|
X25519,
|
||||||
}
|
}
|
||||||
// FIXME: actually check this
|
// FIXME: actually check this
|
||||||
|
@ -73,8 +101,7 @@ impl KeyKind {
|
||||||
match self {
|
match self {
|
||||||
// FIXME: 99% wrong size
|
// FIXME: 99% wrong size
|
||||||
KeyKind::Ed25519 => ::ring::signature::ED25519_PUBLIC_KEY_LEN,
|
KeyKind::Ed25519 => ::ring::signature::ED25519_PUBLIC_KEY_LEN,
|
||||||
// FIXME: 99% wrong size
|
KeyKind::X25519 => 32,
|
||||||
KeyKind::X25519 => ::ring::signature::ED25519_PUBLIC_KEY_LEN,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Get the capabilities of this key type
|
/// Get the capabilities of this key type
|
||||||
|
@ -94,15 +121,30 @@ impl KeyKind {
|
||||||
KeyKind::X25519 => &X25519_KEY_EXCHANGES,
|
KeyKind::X25519 => &X25519_KEY_EXCHANGES,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// generate new keypair
|
||||||
|
pub fn new_keypair(
|
||||||
|
&self,
|
||||||
|
rnd: &Random,
|
||||||
|
) -> Result<(PrivKey, PubKey), Error> {
|
||||||
|
PubKey::new_keypair(*self, rnd)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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,
|
||||||
|
::strum_macros::EnumString,
|
||||||
|
::strum_macros::IntoStaticStr,
|
||||||
|
)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum KeyExchangeKind {
|
pub enum KeyExchangeKind {
|
||||||
/// X25519 Public key
|
/// X25519 Public key
|
||||||
|
#[strum(serialize = "x25519diffiehellman")]
|
||||||
X25519DiffieHellman = 0,
|
X25519DiffieHellman = 0,
|
||||||
}
|
}
|
||||||
impl KeyExchangeKind {
|
impl KeyExchangeKind {
|
||||||
|
@ -141,6 +183,13 @@ pub enum PubKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PubKey {
|
impl PubKey {
|
||||||
|
/// Get the serialized key length
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
match self {
|
||||||
|
PubKey::Exchange(ex) => ex.len(),
|
||||||
|
PubKey::Signing => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
/// return the kind of public key
|
/// return the kind of public key
|
||||||
pub fn kind(&self) -> KeyKind {
|
pub fn kind(&self) -> KeyKind {
|
||||||
match self {
|
match self {
|
||||||
|
@ -149,6 +198,20 @@ impl PubKey {
|
||||||
PubKey::Exchange(ex) => ex.kind(),
|
PubKey::Exchange(ex) => ex.kind(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// generate new keypair
|
||||||
|
fn new_keypair(
|
||||||
|
kind: KeyKind,
|
||||||
|
rnd: &Random,
|
||||||
|
) -> Result<(PrivKey, PubKey), Error> {
|
||||||
|
match kind {
|
||||||
|
KeyKind::Ed25519 => todo!(),
|
||||||
|
KeyKind::X25519 => {
|
||||||
|
let (priv_key, pub_key) =
|
||||||
|
KeyExchangeKind::X25519DiffieHellman.new_keypair(rnd)?;
|
||||||
|
Ok((PrivKey::Exchange(priv_key), PubKey::Exchange(pub_key)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
/// serialize the key into the buffer
|
/// serialize the key into the buffer
|
||||||
/// NOTE: Assumes there is enough space
|
/// NOTE: Assumes there is enough space
|
||||||
pub fn serialize_into(&self, out: &mut [u8]) {
|
pub fn serialize_into(&self, out: &mut [u8]) {
|
||||||
|
@ -211,6 +274,24 @@ pub enum PrivKey {
|
||||||
Signing,
|
Signing,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PrivKey {
|
||||||
|
/// Get the serialized key length
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
match self {
|
||||||
|
PrivKey::Exchange(ex) => ex.len(),
|
||||||
|
PrivKey::Signing => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// serialize the key into the buffer
|
||||||
|
/// NOTE: Assumes there is enough space
|
||||||
|
pub fn serialize_into(&self, out: &mut [u8]) {
|
||||||
|
match self {
|
||||||
|
PrivKey::Exchange(ex) => ex.serialize_into(out),
|
||||||
|
PrivKey::Signing => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Ephemeral private keys
|
/// Ephemeral private keys
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
#[allow(missing_debug_implementations)]
|
#[allow(missing_debug_implementations)]
|
||||||
|
@ -221,6 +302,12 @@ pub enum ExchangePrivKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExchangePrivKey {
|
impl ExchangePrivKey {
|
||||||
|
/// Get the serialized key length
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
match self {
|
||||||
|
ExchangePrivKey::X25519(_) => KeyKind::X25519.pub_len(),
|
||||||
|
}
|
||||||
|
}
|
||||||
/// Get the kind of key
|
/// Get the kind of key
|
||||||
pub fn kind(&self) -> KeyKind {
|
pub fn kind(&self) -> KeyKind {
|
||||||
match self {
|
match self {
|
||||||
|
@ -238,12 +325,18 @@ impl ExchangePrivKey {
|
||||||
if exchange != KeyExchangeKind::X25519DiffieHellman {
|
if exchange != KeyExchangeKind::X25519DiffieHellman {
|
||||||
return Err(Error::UnsupportedKeyExchange);
|
return Err(Error::UnsupportedKeyExchange);
|
||||||
}
|
}
|
||||||
if let ExchangePubKey::X25519(inner_pub_key) = pub_key {
|
let ExchangePubKey::X25519(inner_pub_key) = pub_key;
|
||||||
let shared_secret = priv_key.diffie_hellman(&inner_pub_key);
|
let shared_secret = priv_key.diffie_hellman(&inner_pub_key);
|
||||||
Ok(shared_secret.into())
|
Ok(shared_secret.into())
|
||||||
} else {
|
}
|
||||||
Err(Error::UnsupportedKeyExchange)
|
}
|
||||||
}
|
}
|
||||||
|
/// serialize the key into the buffer
|
||||||
|
/// NOTE: Assumes there is enough space
|
||||||
|
pub fn serialize_into(&self, out: &mut [u8]) {
|
||||||
|
match self {
|
||||||
|
ExchangePrivKey::X25519(key) => {
|
||||||
|
out[..32].copy_from_slice(&key.to_bytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -258,6 +351,12 @@ pub enum ExchangePubKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExchangePubKey {
|
impl ExchangePubKey {
|
||||||
|
/// Get the serialized key length
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
match self {
|
||||||
|
ExchangePubKey::X25519(_) => KeyKind::X25519.pub_len(),
|
||||||
|
}
|
||||||
|
}
|
||||||
/// Get the kind of key
|
/// Get the kind of key
|
||||||
pub fn kind(&self) -> KeyKind {
|
pub fn kind(&self) -> KeyKind {
|
||||||
match self {
|
match self {
|
||||||
|
|
|
@ -7,11 +7,20 @@ use ::zeroize::Zeroize;
|
||||||
use crate::{config::Config, enc::Secret};
|
use crate::{config::Config, enc::Secret};
|
||||||
|
|
||||||
/// Kind of HKDF
|
/// Kind of HKDF
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, ::num_derive::FromPrimitive)]
|
#[derive(
|
||||||
|
Debug,
|
||||||
|
Copy,
|
||||||
|
Clone,
|
||||||
|
PartialEq,
|
||||||
|
::num_derive::FromPrimitive,
|
||||||
|
::strum_macros::EnumString,
|
||||||
|
::strum_macros::IntoStaticStr,
|
||||||
|
)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum HkdfKind {
|
pub enum HkdfKind {
|
||||||
/// Sha3
|
/// Sha3
|
||||||
|
#[strum(serialize = "sha3")]
|
||||||
Sha3 = 0,
|
Sha3 = 0,
|
||||||
}
|
}
|
||||||
impl HkdfKind {
|
impl HkdfKind {
|
||||||
|
|
|
@ -27,6 +27,10 @@ impl Random {
|
||||||
pub fn fill(&self, out: &mut [u8]) {
|
pub fn fill(&self, out: &mut [u8]) {
|
||||||
self.rnd.fill(out);
|
self.rnd.fill(out);
|
||||||
}
|
}
|
||||||
|
/// return the underlying ring SystemRandom
|
||||||
|
pub fn ring_rnd(&self) -> &::ring::rand::SystemRandom {
|
||||||
|
&self.rnd
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fake debug implementation to avoid leaking secrets
|
// Fake debug implementation to avoid leaking secrets
|
||||||
|
|
|
@ -8,10 +8,19 @@ use crate::{
|
||||||
use ::zeroize::Zeroize;
|
use ::zeroize::Zeroize;
|
||||||
|
|
||||||
/// List of possible Ciphers
|
/// List of possible Ciphers
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, ::num_derive::FromPrimitive)]
|
#[derive(
|
||||||
|
Debug,
|
||||||
|
Copy,
|
||||||
|
Clone,
|
||||||
|
PartialEq,
|
||||||
|
::num_derive::FromPrimitive,
|
||||||
|
::strum_macros::EnumString,
|
||||||
|
::strum_macros::IntoStaticStr,
|
||||||
|
)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum CipherKind {
|
pub enum CipherKind {
|
||||||
/// XChaCha20_Poly1305
|
/// XChaCha20_Poly1305
|
||||||
|
#[strum(serialize = "xchacha20poly1305")]
|
||||||
XChaCha20Poly1305 = 0,
|
XChaCha20Poly1305 = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ pub(crate) struct ClientConnectInfo {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) enum HandshakeAction {
|
pub(crate) enum HandshakeAction {
|
||||||
/// Parsing finished, all ok, nothing to do
|
/// Parsing finished, all ok, nothing to do
|
||||||
None,
|
Nonthing,
|
||||||
/// Packet parsed, now go perform authentication
|
/// Packet parsed, now go perform authentication
|
||||||
AuthNeeded(AuthNeededInfo),
|
AuthNeeded(AuthNeededInfo),
|
||||||
/// the client can fully establish a connection with this info
|
/// the client can fully establish a connection with this info
|
||||||
|
@ -227,6 +227,9 @@ impl HandshakeTracker {
|
||||||
}
|
}
|
||||||
let hshake =
|
let hshake =
|
||||||
self.hshake_cli.remove(resp.client_key_id).unwrap();
|
self.hshake_cli.remove(resp.client_key_id).unwrap();
|
||||||
|
if let Some(timeout) = hshake.timeout {
|
||||||
|
timeout.abort();
|
||||||
|
}
|
||||||
return Ok(HandshakeAction::ClientConnect(
|
return Ok(HandshakeAction::ClientConnect(
|
||||||
ClientConnectInfo {
|
ClientConnectInfo {
|
||||||
service_id: hshake.service_id,
|
service_id: hshake.service_id,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! Worker thread implementation
|
//! Worker thread implementation
|
||||||
use crate::{
|
use crate::{
|
||||||
auth::{Domain, ServiceID, Token, TokenChecker, UserID},
|
auth::{self, Domain, ServiceID, Token, TokenChecker, UserID},
|
||||||
config::Config,
|
config::Config,
|
||||||
connection::{
|
connection::{
|
||||||
self,
|
self,
|
||||||
|
@ -390,13 +390,10 @@ impl Worker {
|
||||||
self.handshakes.timeout_client(key_id)
|
self.handshakes.timeout_client(key_id)
|
||||||
{
|
{
|
||||||
for conn_id in connections.into_iter() {
|
for conn_id in connections.into_iter() {
|
||||||
if !conn_id.0.is_handshake() {
|
self.connections.remove(conn_id);
|
||||||
self.connections.delete(conn_id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
//TODO: reconf message to add channels
|
|
||||||
Work::Recv(pkt) => {
|
Work::Recv(pkt) => {
|
||||||
self.recv(pkt).await;
|
self.recv(pkt).await;
|
||||||
}
|
}
|
||||||
|
@ -545,7 +542,6 @@ impl Worker {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.send_packet(raw_out, udp.src, udp.dst).await;
|
self.send_packet(raw_out, udp.src, udp.dst).await;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
HandshakeAction::ClientConnect(cci) => {
|
HandshakeAction::ClientConnect(cci) => {
|
||||||
let ds_resp;
|
let ds_resp;
|
||||||
|
@ -573,19 +569,19 @@ impl Worker {
|
||||||
let id_recv = conn.id_recv;
|
let id_recv = conn.id_recv;
|
||||||
let cipher = conn.cipher_recv.kind();
|
let cipher = conn.cipher_recv.kind();
|
||||||
// track the connection to the authentication server
|
// track the connection to the authentication server
|
||||||
if self.connections.track(Rc::new(conn)).is_err() {
|
if self.connections.track(conn.into()).is_err() {
|
||||||
::tracing::error!("Could not track new connection");
|
::tracing::error!("Could not track new connection");
|
||||||
self.connections.delete(id_recv);
|
self.connections.remove(id_recv);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if id_recv.0 == resp_data.service_connection_id {
|
if cci.service_id == auth::SERVICEID_AUTH {
|
||||||
// the user asked a single connection
|
// the user asked a single connection
|
||||||
// to the authentication server, without any additional
|
// to the authentication server, without any additional
|
||||||
// service. No more connections to setup
|
// service. No more connections to setup
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// create and track the connection to the service
|
// create and track the connection to the service
|
||||||
// SECURITY:
|
// SECURITY: xor with secrets
|
||||||
//FIXME: the Secret should be XORed with the client stored
|
//FIXME: the Secret should be XORed with the client stored
|
||||||
// secret (if any)
|
// secret (if any)
|
||||||
let hkdf = Hkdf::new(
|
let hkdf = Hkdf::new(
|
||||||
|
@ -603,13 +599,10 @@ impl Worker {
|
||||||
service_connection.id_send =
|
service_connection.id_send =
|
||||||
IDSend(resp_data.service_connection_id);
|
IDSend(resp_data.service_connection_id);
|
||||||
let _ = self.connections.track(service_connection.into());
|
let _ = self.connections.track(service_connection.into());
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
_ => {}
|
HandshakeAction::Nonthing => {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// copy packet, spawn
|
|
||||||
todo!();
|
|
||||||
}
|
}
|
||||||
async fn send_packet(
|
async fn send_packet(
|
||||||
&self,
|
&self,
|
||||||
|
|
Loading…
Reference in New Issue