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()
+ KeyExchange::len()
+ CipherKind::len()
+ self.exchange_key.len()
+ self.exchange_key.kind().pub_len()
}
/// return the total length of the cleartext data
pub fn encrypted_length(&self) -> usize {
@ -92,7 +92,7 @@ impl Req {
KeyID::len()
+ KeyExchange::len()
+ CipherKind::len()
+ self.exchange_key.len()
+ self.exchange_key.kind().pub_len()
+ self.data.len()
}
/// 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
//! ]
use crate::enc::{self, asym::PubKey};
use ::core::num::NonZeroU16;
use ::num_traits::FromPrimitive;
use ::std::{net::IpAddr, vec::Vec};
/*
* 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
*/
@ -358,7 +272,7 @@ impl Address {
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;
if raw.len() < 3 + num_pubkey_ids {
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
#[derive(Debug, Clone)]
pub struct Record {
/// Public keys used by any authentication server
pub public_keys: Vec<PublicKey>,
pub public_keys: Vec<(PublicKeyID, PubKey)>,
/// List of all authentication servers' addresses.
/// Multiple ones can point to the same authentication server
pub addresses: Vec<Address>,
@ -461,7 +375,11 @@ impl Record {
let total_size: usize = 1
+ 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);
@ -475,8 +393,9 @@ impl Record {
for address in self.addresses.iter() {
address.encode_into(&mut raw);
}
for public_key in self.public_keys.iter() {
public_key.encode_into(&mut raw);
for (public_key_id, public_key) in self.public_keys.iter() {
raw.push(public_key_id.0);
public_key.serialize_into(&mut raw);
}
Ok(::base85::encode(&raw))
@ -514,19 +433,21 @@ impl Record {
num_addresses = num_addresses - 1;
}
while num_public_keys > 0 {
let id = PublicKeyID(raw[bytes_parsed]);
bytes_parsed = bytes_parsed + 1;
let (public_key, bytes) =
match PublicKey::decode_raw(&raw[bytes_parsed..]) {
match PubKey::deserialize(&raw[bytes_parsed..]) {
Ok(public_key) => public_key,
Err(Error::UnsupportedData(b)) => {
Err(enc::Error::UnsupportedKey(b)) => {
return Err(Error::UnsupportedData(bytes_parsed + b))
}
Err(Error::NotEnoughData(b)) => {
Err(enc::Error::NotEnoughData(b)) => {
return Err(Error::NotEnoughData(bytes_parsed + b))
}
Err(e) => return Err(e),
_ => return Err(Error::UnknownData(bytes_parsed)),
};
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;
}
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
#[derive(Debug, Copy, Clone, PartialEq, ::num_derive::FromPrimitive)]
#[non_exhaustive]
#[repr(u8)]
pub enum Key {
/// X25519 Public key
X25519 = 0,
pub enum KeyKind {
/// Ed25519 Public key (sign only)
Ed25519 = 0,
/// X25519 Public key (key exchange)
X25519,
}
impl Key {
fn pub_len(&self) -> usize {
// FIXME: actually check this
const MIN_KEY_SIZE: usize = 32;
impl KeyKind {
/// return the expected length of the public key
pub fn pub_len(&self) -> usize {
match self {
// 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)]
#[allow(missing_debug_implementations)]
#[non_exhaustive]
pub enum PrivKey {
/// Keys to be used only in key exchanges, not for signing
Exchange(ExchangePrivKey),
@ -63,6 +168,7 @@ pub enum PrivKey {
/// Ephemeral private keys
#[derive(Clone)]
#[allow(missing_debug_implementations)]
#[non_exhaustive]
pub enum ExchangePrivKey {
/// X25519(Curve25519) used for key exchange
X25519(::x25519_dalek::StaticSecret),
@ -70,9 +176,9 @@ pub enum ExchangePrivKey {
impl ExchangePrivKey {
/// Get the kind of key
pub fn kind(&self) -> Key {
pub fn kind(&self) -> KeyKind {
match self {
ExchangePrivKey::X25519(_) => Key::X25519,
ExchangePrivKey::X25519(_) => KeyKind::X25519,
}
}
/// Run the key exchange between two keys of the same kind
@ -99,30 +205,44 @@ impl ExchangePrivKey {
/// all Ephemeral Public keys
#[derive(Debug, Copy, Clone)]
#[non_exhaustive]
pub enum ExchangePubKey {
/// X25519(Curve25519) used for key exchange
X25519(::x25519_dalek::PublicKey),
}
impl ExchangePubKey {
/// length of the public key used for key exchange
pub fn len(&self) -> usize {
/// Get the kind of key
pub fn kind(&self) -> KeyKind {
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
/// The riesult is "unparsed" since we don't verify
/// the actual key
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 {
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 {
Key::X25519 => {
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())],

View File

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

View File

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