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.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub struct ServiceID([u8; 16]);
|
||||
|
||||
impl From<[u8; 16]> for ServiceID {
|
||||
|
|
|
@ -185,7 +185,7 @@ impl ConnList {
|
|||
self.connections[id_in_thread] = Some(conn);
|
||||
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 {
|
||||
let id_in_thread: usize =
|
||||
(raw_id.get() / (self.thread_id.total as u64)) as usize;
|
||||
|
|
115
src/enc/asym.rs
115
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
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum KeyCapabilities {
|
||||
|
@ -56,13 +74,23 @@ impl KeyCapabilities {
|
|||
}
|
||||
|
||||
/// 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]
|
||||
#[repr(u8)]
|
||||
pub enum KeyKind {
|
||||
/// Ed25519 Public key (sign only)
|
||||
#[strum(serialize = "ed25519")]
|
||||
Ed25519 = 0,
|
||||
/// X25519 Public key (key exchange)
|
||||
#[strum(serialize = "x25519")]
|
||||
X25519,
|
||||
}
|
||||
// FIXME: actually check this
|
||||
|
@ -73,8 +101,7 @@ impl KeyKind {
|
|||
match self {
|
||||
// FIXME: 99% wrong size
|
||||
KeyKind::Ed25519 => ::ring::signature::ED25519_PUBLIC_KEY_LEN,
|
||||
// FIXME: 99% wrong size
|
||||
KeyKind::X25519 => ::ring::signature::ED25519_PUBLIC_KEY_LEN,
|
||||
KeyKind::X25519 => 32,
|
||||
}
|
||||
}
|
||||
/// Get the capabilities of this key type
|
||||
|
@ -94,15 +121,30 @@ impl KeyKind {
|
|||
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
|
||||
#[derive(Debug, Copy, Clone, PartialEq, ::num_derive::FromPrimitive)]
|
||||
#[derive(
|
||||
Debug,
|
||||
Copy,
|
||||
Clone,
|
||||
PartialEq,
|
||||
::num_derive::FromPrimitive,
|
||||
::strum_macros::EnumString,
|
||||
::strum_macros::IntoStaticStr,
|
||||
)]
|
||||
#[non_exhaustive]
|
||||
#[repr(u8)]
|
||||
pub enum KeyExchangeKind {
|
||||
/// X25519 Public key
|
||||
#[strum(serialize = "x25519diffiehellman")]
|
||||
X25519DiffieHellman = 0,
|
||||
}
|
||||
impl KeyExchangeKind {
|
||||
|
@ -141,6 +183,13 @@ pub enum 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
|
||||
pub fn kind(&self) -> KeyKind {
|
||||
match self {
|
||||
|
@ -149,6 +198,20 @@ impl PubKey {
|
|||
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
|
||||
/// NOTE: Assumes there is enough space
|
||||
pub fn serialize_into(&self, out: &mut [u8]) {
|
||||
|
@ -211,6 +274,24 @@ pub enum PrivKey {
|
|||
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
|
||||
#[derive(Clone)]
|
||||
#[allow(missing_debug_implementations)]
|
||||
|
@ -221,6 +302,12 @@ pub enum 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
|
||||
pub fn kind(&self) -> KeyKind {
|
||||
match self {
|
||||
|
@ -238,14 +325,20 @@ impl ExchangePrivKey {
|
|||
if exchange != KeyExchangeKind::X25519DiffieHellman {
|
||||
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);
|
||||
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 {
|
||||
/// Get the serialized key length
|
||||
pub fn len(&self) -> usize {
|
||||
match self {
|
||||
ExchangePubKey::X25519(_) => KeyKind::X25519.pub_len(),
|
||||
}
|
||||
}
|
||||
/// Get the kind of key
|
||||
pub fn kind(&self) -> KeyKind {
|
||||
match self {
|
||||
|
|
|
@ -7,11 +7,20 @@ use ::zeroize::Zeroize;
|
|||
use crate::{config::Config, enc::Secret};
|
||||
|
||||
/// 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]
|
||||
#[repr(u8)]
|
||||
pub enum HkdfKind {
|
||||
/// Sha3
|
||||
#[strum(serialize = "sha3")]
|
||||
Sha3 = 0,
|
||||
}
|
||||
impl HkdfKind {
|
||||
|
|
|
@ -27,6 +27,10 @@ impl Random {
|
|||
pub fn fill(&self, out: &mut [u8]) {
|
||||
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
|
||||
|
|
|
@ -8,10 +8,19 @@ use crate::{
|
|||
use ::zeroize::Zeroize;
|
||||
|
||||
/// 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)]
|
||||
pub enum CipherKind {
|
||||
/// XChaCha20_Poly1305
|
||||
#[strum(serialize = "xchacha20poly1305")]
|
||||
XChaCha20Poly1305 = 0,
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ pub(crate) struct ClientConnectInfo {
|
|||
#[derive(Debug)]
|
||||
pub(crate) enum HandshakeAction {
|
||||
/// Parsing finished, all ok, nothing to do
|
||||
None,
|
||||
Nonthing,
|
||||
/// Packet parsed, now go perform authentication
|
||||
AuthNeeded(AuthNeededInfo),
|
||||
/// the client can fully establish a connection with this info
|
||||
|
@ -227,6 +227,9 @@ impl HandshakeTracker {
|
|||
}
|
||||
let hshake =
|
||||
self.hshake_cli.remove(resp.client_key_id).unwrap();
|
||||
if let Some(timeout) = hshake.timeout {
|
||||
timeout.abort();
|
||||
}
|
||||
return Ok(HandshakeAction::ClientConnect(
|
||||
ClientConnectInfo {
|
||||
service_id: hshake.service_id,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! Worker thread implementation
|
||||
use crate::{
|
||||
auth::{Domain, ServiceID, Token, TokenChecker, UserID},
|
||||
auth::{self, Domain, ServiceID, Token, TokenChecker, UserID},
|
||||
config::Config,
|
||||
connection::{
|
||||
self,
|
||||
|
@ -390,13 +390,10 @@ impl Worker {
|
|||
self.handshakes.timeout_client(key_id)
|
||||
{
|
||||
for conn_id in connections.into_iter() {
|
||||
if !conn_id.0.is_handshake() {
|
||||
self.connections.delete(conn_id);
|
||||
}
|
||||
self.connections.remove(conn_id);
|
||||
}
|
||||
};
|
||||
}
|
||||
//TODO: reconf message to add channels
|
||||
Work::Recv(pkt) => {
|
||||
self.recv(pkt).await;
|
||||
}
|
||||
|
@ -545,7 +542,6 @@ impl Worker {
|
|||
return;
|
||||
}
|
||||
self.send_packet(raw_out, udp.src, udp.dst).await;
|
||||
return;
|
||||
}
|
||||
HandshakeAction::ClientConnect(cci) => {
|
||||
let ds_resp;
|
||||
|
@ -573,19 +569,19 @@ impl Worker {
|
|||
let id_recv = conn.id_recv;
|
||||
let cipher = conn.cipher_recv.kind();
|
||||
// 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");
|
||||
self.connections.delete(id_recv);
|
||||
self.connections.remove(id_recv);
|
||||
return;
|
||||
}
|
||||
if id_recv.0 == resp_data.service_connection_id {
|
||||
if cci.service_id == auth::SERVICEID_AUTH {
|
||||
// the user asked a single connection
|
||||
// to the authentication server, without any additional
|
||||
// service. No more connections to setup
|
||||
return;
|
||||
}
|
||||
// create and track the connection to the service
|
||||
// SECURITY:
|
||||
// SECURITY: xor with secrets
|
||||
//FIXME: the Secret should be XORed with the client stored
|
||||
// secret (if any)
|
||||
let hkdf = Hkdf::new(
|
||||
|
@ -603,13 +599,10 @@ impl Worker {
|
|||
service_connection.id_send =
|
||||
IDSend(resp_data.service_connection_id);
|
||||
let _ = self.connections.track(service_connection.into());
|
||||
return;
|
||||
}
|
||||
_ => {}
|
||||
HandshakeAction::Nonthing => {}
|
||||
};
|
||||
}
|
||||
// copy packet, spawn
|
||||
todo!();
|
||||
}
|
||||
async fn send_packet(
|
||||
&self,
|
||||
|
|
Loading…
Reference in New Issue