dnssec: use the proper enc::asym types

Signed-off-by: Luca Fulchir <luca.fulchir@runesauth.com>
This commit is contained in:
Luca Fulchir 2023-05-28 15:26:17 +02:00
parent e581cb064a
commit 110a346551
Signed by: luca.fulchir
GPG Key ID: 8F6440603D13A78E
6 changed files with 172 additions and 123 deletions

View File

@ -78,7 +78,7 @@ impl Req {
+ KeyID::len() + KeyID::len()
+ KeyExchange::len() + KeyExchange::len()
+ CipherKind::len() + CipherKind::len()
+ self.exchange_key.len() + self.exchange_key.kind().pub_len()
} }
/// return the total length of the cleartext data /// return the total length of the cleartext data
pub fn encrypted_length(&self) -> usize { pub fn encrypted_length(&self) -> usize {
@ -92,7 +92,7 @@ impl Req {
KeyID::len() KeyID::len()
+ KeyExchange::len() + KeyExchange::len()
+ CipherKind::len() + CipherKind::len()
+ self.exchange_key.len() + self.exchange_key.kind().pub_len()
+ self.data.len() + self.data.len()
} }
/// Serialize into raw bytes /// Serialize into raw bytes

View File

@ -200,3 +200,12 @@ impl ConnList {
} }
} }
} }
/*
use ::std::collections::HashMap;
pub(crate) struct AuthServerConnections {
conn_map : HashMap<
pub id: IDSend,
}
*/

View File

@ -23,10 +23,10 @@
//! * Y bytes: pubkey //! * Y bytes: pubkey
//! ] //! ]
use crate::enc::{self, asym::PubKey};
use ::core::num::NonZeroU16; use ::core::num::NonZeroU16;
use ::num_traits::FromPrimitive; use ::num_traits::FromPrimitive;
use ::std::{net::IpAddr, vec::Vec}; use ::std::{net::IpAddr, vec::Vec};
/* /*
* Public key data * Public key data
*/ */
@ -48,92 +48,6 @@ impl TryFrom<&str> for PublicKeyID {
} }
} }
/// Public Key Type
#[derive(::num_derive::FromPrimitive, Debug, Copy, Clone)]
// public enum: use non_exhaustive to force users to add a default case
// so in the future we can expand this easily
#[non_exhaustive]
#[repr(u8)]
pub enum PublicKeyType {
/// ed25519 asymmetric key
Ed25519 = 0,
/// Ephemeral X25519 (Curve25519) key.
/// Used in the directory synchronized handshake
X25519,
}
impl PublicKeyType {
/// Get the size of a public key of this kind
pub fn key_len(&self) -> usize {
match &self {
PublicKeyType::Ed25519 => 32,
PublicKeyType::X25519 => 32, // FIXME: hopefully...
}
}
}
impl TryFrom<&str> for PublicKeyType {
type Error = ::std::io::Error;
fn try_from(raw: &str) -> Result<Self, Self::Error> {
if let Ok(type_u8) = raw.parse::<u8>() {
if let Some(kind) = PublicKeyType::from_u8(type_u8) {
return Ok(kind);
}
}
return Err(::std::io::Error::new(
::std::io::ErrorKind::InvalidData,
"Public Key Type 0 is the only one supported",
));
}
}
/// Public Key, with its type and id
#[derive(Debug, Clone)]
pub struct PublicKey {
/// public key raw data
pub raw: Vec<u8>,
/// type of public key
pub kind: PublicKeyType,
/// id of public key
pub id: PublicKeyID,
}
impl PublicKey {
fn raw_len(&self) -> usize {
let size = 2; // Public Key Type + ID
size + self.raw.len()
}
fn encode_into(&self, raw: &mut Vec<u8>) {
raw.push(self.kind as u8);
raw.push(self.id.0);
raw.extend_from_slice(&self.raw);
}
fn decode_raw(raw: &[u8]) -> Result<(Self, usize), Error> {
if raw.len() < 4 {
return Err(Error::NotEnoughData(0));
}
let kind = PublicKeyType::from_u8(raw[0]).unwrap();
let id = PublicKeyID(raw[1]);
if raw.len() < 2 + kind.key_len() {
return Err(Error::NotEnoughData(2));
}
let mut raw_key = Vec::with_capacity(kind.key_len());
let total_length = 2 + kind.key_len();
raw_key.extend_from_slice(&raw[2..total_length]);
Ok((
Self {
raw: raw_key,
kind,
id,
},
total_length,
))
}
}
/* /*
* Address data * Address data
*/ */
@ -358,7 +272,7 @@ impl Address {
let raw_port = u16::from_le_bytes([raw[1], raw[2]]); let raw_port = u16::from_le_bytes([raw[1], raw[2]]);
// Add publi key ids // Add publickey ids
let num_pubkey_ids = raw[3] as usize; let num_pubkey_ids = raw[3] as usize;
if raw.len() < 3 + num_pubkey_ids { if raw.len() < 3 + num_pubkey_ids {
return Err(Error::NotEnoughData(3)); return Err(Error::NotEnoughData(3));
@ -428,14 +342,14 @@ impl Address {
} }
/* /*
* Actual record puuting it all toghether * Actual record putting it all toghether
*/ */
/// All informations found in the DNSSEC record /// All informations found in the DNSSEC record
#[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<PublicKey>, pub public_keys: Vec<(PublicKeyID, 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>,
@ -461,7 +375,11 @@ impl Record {
let total_size: usize = 1 let total_size: usize = 1
+ self.addresses.iter().map(|a| a.raw_len()).sum::<usize>() + self.addresses.iter().map(|a| a.raw_len()).sum::<usize>()
+ self.public_keys.iter().map(|a| a.raw_len()).sum::<usize>(); + self
.public_keys
.iter()
.map(|(_, key)| 1 + key.kind().pub_len())
.sum::<usize>();
let mut raw = Vec::with_capacity(total_size); let mut raw = Vec::with_capacity(total_size);
@ -475,8 +393,9 @@ impl Record {
for address in self.addresses.iter() { for address in self.addresses.iter() {
address.encode_into(&mut raw); address.encode_into(&mut raw);
} }
for public_key in self.public_keys.iter() { for (public_key_id, public_key) in self.public_keys.iter() {
public_key.encode_into(&mut raw); raw.push(public_key_id.0);
public_key.serialize_into(&mut raw);
} }
Ok(::base85::encode(&raw)) Ok(::base85::encode(&raw))
@ -514,19 +433,21 @@ impl Record {
num_addresses = num_addresses - 1; num_addresses = num_addresses - 1;
} }
while num_public_keys > 0 { while num_public_keys > 0 {
let id = PublicKeyID(raw[bytes_parsed]);
bytes_parsed = bytes_parsed + 1;
let (public_key, bytes) = let (public_key, bytes) =
match PublicKey::decode_raw(&raw[bytes_parsed..]) { match PubKey::deserialize(&raw[bytes_parsed..]) {
Ok(public_key) => public_key, Ok(public_key) => public_key,
Err(Error::UnsupportedData(b)) => { Err(enc::Error::UnsupportedKey(b)) => {
return Err(Error::UnsupportedData(bytes_parsed + b)) return Err(Error::UnsupportedData(bytes_parsed + b))
} }
Err(Error::NotEnoughData(b)) => { Err(enc::Error::NotEnoughData(b)) => {
return Err(Error::NotEnoughData(bytes_parsed + b)) return Err(Error::NotEnoughData(bytes_parsed + b))
} }
Err(e) => return Err(e), _ => return Err(Error::UnknownData(bytes_parsed)),
}; };
bytes_parsed = bytes_parsed + bytes; bytes_parsed = bytes_parsed + bytes;
result.public_keys.push(public_key); result.public_keys.push((id, public_key));
num_public_keys = num_public_keys - 1; num_public_keys = num_public_keys - 1;
} }
if bytes_parsed != raw.len() { if bytes_parsed != raw.len() {

View File

@ -20,18 +20,52 @@ impl KeyID {
} }
} }
/// Capabilities of each key
#[derive(Debug, Clone, Copy)]
pub enum KeyCapabilities {
/// signing *only*
Sign,
/// encrypt *only*
Encrypt,
/// key exchange *only*
Exchange,
/// both sign and encrypt
SignEncrypt,
/// both signing and key exchange
SignExchange,
/// both encrypt and key exchange
EncryptExchange,
/// All: sign, encrypt, Key Exchange
SignEncryptExchage,
}
/// 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)]
#[non_exhaustive]
#[repr(u8)] #[repr(u8)]
pub enum Key { pub enum KeyKind {
/// X25519 Public key /// Ed25519 Public key (sign only)
X25519 = 0, Ed25519 = 0,
/// X25519 Public key (key exchange)
X25519,
} }
impl Key { // FIXME: actually check this
fn pub_len(&self) -> usize { const MIN_KEY_SIZE: usize = 32;
impl KeyKind {
/// return the expected length of the public key
pub fn pub_len(&self) -> usize {
match self { match self {
// FIXME: 99% wrong size // FIXME: 99% wrong size
Key::X25519 => ::ring::signature::ED25519_PUBLIC_KEY_LEN, KeyKind::Ed25519 => ::ring::signature::ED25519_PUBLIC_KEY_LEN,
// FIXME: 99% wrong size
KeyKind::X25519 => ::ring::signature::ED25519_PUBLIC_KEY_LEN,
}
}
/// Get the capabilities of this key type
pub fn capabilities(&self) -> KeyCapabilities {
match self {
KeyKind::Ed25519 => KeyCapabilities::Sign,
KeyKind::X25519 => KeyCapabilities::Exchange,
} }
} }
} }
@ -50,9 +84,80 @@ impl KeyExchange {
} }
} }
/// Kind of key in the handshake /// Kind of public key in the handshake
#[derive(Debug, Copy, Clone)]
#[allow(missing_debug_implementations)]
#[non_exhaustive]
pub enum PubKey {
/// Keys to be used only in key exchanges, not for signing
Exchange(ExchangePubKey),
/// Keys to be used only for signing
Signing,
}
impl PubKey {
/// return the kind of public key
pub fn kind(&self) -> KeyKind {
match self {
// FIXME: lie, we don't fully support this
PubKey::Signing => KeyKind::Ed25519,
PubKey::Exchange(ex) => ex.kind(),
}
}
/// serialize the key into the buffer
/// NOTE: Assumes there is enough space
pub fn serialize_into(&self, out: &mut [u8]) {
assert!(
out.len() >= 1 + self.kind().pub_len(),
"Not enough out buffer",
);
out[0] = self.kind() as u8;
match self {
PubKey::Signing => {
::tracing::error!("serializing ed25519 not supported");
return;
}
PubKey::Exchange(ex) => ex.serialize_into(&mut out[1..]),
}
}
/// Try to deserialize the pubkey from raw bytes
/// on success returns the public key and the number of parsed bytes
pub fn deserialize(raw: &[u8]) -> Result<(Self, usize), Error> {
if raw.len() < 1 + MIN_KEY_SIZE {
return Err(Error::NotEnoughData(0));
}
let kind: KeyKind = match KeyKind::from_u8(raw[0]) {
Some(kind) => kind,
None => return Err(Error::UnsupportedKey(1)),
};
if raw.len() < 1 + kind.pub_len() {
return Err(Error::NotEnoughData(1));
}
match kind {
KeyKind::Ed25519 => {
::tracing::error!("ed25519 keys are not yet supported");
return Err(Error::Parsing);
}
KeyKind::X25519 => {
let pub_key: ::x25519_dalek::PublicKey =
match ::bincode::deserialize(&raw[1..(1 + kind.pub_len())])
{
Ok(pub_key) => pub_key,
Err(_) => return Err(Error::Parsing),
};
Ok((
PubKey::Exchange(ExchangePubKey::X25519(pub_key)),
kind.pub_len(),
))
}
}
}
}
/// Kind of private key in the handshake
#[derive(Clone)] #[derive(Clone)]
#[allow(missing_debug_implementations)] #[allow(missing_debug_implementations)]
#[non_exhaustive]
pub enum PrivKey { pub enum PrivKey {
/// Keys to be used only in key exchanges, not for signing /// Keys to be used only in key exchanges, not for signing
Exchange(ExchangePrivKey), Exchange(ExchangePrivKey),
@ -63,6 +168,7 @@ pub enum PrivKey {
/// Ephemeral private keys /// Ephemeral private keys
#[derive(Clone)] #[derive(Clone)]
#[allow(missing_debug_implementations)] #[allow(missing_debug_implementations)]
#[non_exhaustive]
pub enum ExchangePrivKey { pub enum ExchangePrivKey {
/// X25519(Curve25519) used for key exchange /// X25519(Curve25519) used for key exchange
X25519(::x25519_dalek::StaticSecret), X25519(::x25519_dalek::StaticSecret),
@ -70,9 +176,9 @@ pub enum ExchangePrivKey {
impl ExchangePrivKey { impl ExchangePrivKey {
/// Get the kind of key /// Get the kind of key
pub fn kind(&self) -> Key { pub fn kind(&self) -> KeyKind {
match self { match self {
ExchangePrivKey::X25519(_) => Key::X25519, ExchangePrivKey::X25519(_) => KeyKind::X25519,
} }
} }
/// Run the key exchange between two keys of the same kind /// Run the key exchange between two keys of the same kind
@ -99,30 +205,44 @@ impl ExchangePrivKey {
/// all Ephemeral Public keys /// all Ephemeral Public keys
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
#[non_exhaustive]
pub enum ExchangePubKey { pub enum ExchangePubKey {
/// X25519(Curve25519) used for key exchange /// X25519(Curve25519) used for key exchange
X25519(::x25519_dalek::PublicKey), X25519(::x25519_dalek::PublicKey),
} }
impl ExchangePubKey { impl ExchangePubKey {
/// length of the public key used for key exchange /// Get the kind of key
pub fn len(&self) -> usize { pub fn kind(&self) -> KeyKind {
match self { match self {
ExchangePubKey::X25519(_) => 32, ExchangePubKey::X25519(_) => KeyKind::X25519,
}
}
/// serialize the key into the buffer
/// NOTE: Assumes there is enough space
fn serialize_into(&self, out: &mut [u8]) {
match self {
ExchangePubKey::X25519(pk) => {
let bytes = pk.as_bytes();
assert!(bytes.len() == 32, "x25519 should have been 32 bytes");
out[..32].copy_from_slice(bytes);
}
} }
} }
/// Load public key used for key exchange from it raw bytes /// Load public key used for key exchange from it raw bytes
/// The riesult is "unparsed" since we don't verify /// The riesult is "unparsed" since we don't verify
/// the actual key /// the actual key
pub fn from_slice(raw: &[u8]) -> Result<(Self, usize), Error> { pub fn from_slice(raw: &[u8]) -> Result<(Self, usize), Error> {
// FIXME: get *real* minimum key size
const MIN_KEY_SIZE: usize = 32;
if raw.len() < 1 + MIN_KEY_SIZE { if raw.len() < 1 + MIN_KEY_SIZE {
return Err(Error::NotEnoughData); return Err(Error::NotEnoughData(0));
} }
match Key::from_u8(raw[0]) { match KeyKind::from_u8(raw[0]) {
Some(kind) => match kind { Some(kind) => match kind {
Key::X25519 => { KeyKind::Ed25519 => {
::tracing::error!("ed25519 keys are not yet supported");
return Err(Error::Parsing);
}
KeyKind::X25519 => {
let pub_key: ::x25519_dalek::PublicKey = let pub_key: ::x25519_dalek::PublicKey =
match ::bincode::deserialize( match ::bincode::deserialize(
&raw[1..(1 + kind.pub_len())], &raw[1..(1 + kind.pub_len())],

View File

@ -8,14 +8,13 @@ pub enum Error {
Parsing, Parsing,
/// Not enough data /// Not enough data
#[error("not enough data")] #[error("not enough data")]
NotEnoughData, NotEnoughData(usize),
/// buffer too small /// buffer too small
#[error("buffer too small")] #[error("buffer too small")]
InsufficientBuffer, InsufficientBuffer,
/// Wrong Key type found. /// Unsupported Key type found.
/// You might have passed rsa keys where x25519 was expected #[error("unsupported key type")]
#[error("wrong key type")] UnsupportedKey(usize),
WrongKey,
/// Unsupported key exchange for this key /// Unsupported key exchange for this key
#[error("unsupported key exchange")] #[error("unsupported key exchange")]
UnsupportedKeyExchange, UnsupportedKeyExchange,

View File

@ -70,7 +70,7 @@ pub(crate) struct ThreadTracker {
/// (udp_src_sender_port % total_threads) - 1 /// (udp_src_sender_port % total_threads) - 1
pub(crate) struct HandshakeTracker { pub(crate) struct HandshakeTracker {
thread_id: ThreadTracker, thread_id: ThreadTracker,
key_exchanges: Vec<(asym::Key, asym::KeyExchange)>, key_exchanges: Vec<(asym::KeyKind, asym::KeyExchange)>,
ciphers: Vec<CipherKind>, ciphers: Vec<CipherKind>,
/// ephemeral keys used server side in key exchange /// ephemeral keys used server side in key exchange
keys_srv: Vec<HandshakeServer>, keys_srv: Vec<HandshakeServer>,