dnssec: use the proper enc::asym types
Signed-off-by: Luca Fulchir <luca.fulchir@runesauth.com>
This commit is contained in:
parent
e581cb064a
commit
110a346551
|
@ -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
|
||||
|
|
|
@ -200,3 +200,12 @@ impl ConnList {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
use ::std::collections::HashMap;
|
||||
|
||||
pub(crate) struct AuthServerConnections {
|
||||
conn_map : HashMap<
|
||||
pub id: IDSend,
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -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() {
|
||||
|
|
154
src/enc/asym.rs
154
src/enc/asym.rs
|
@ -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())],
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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>,
|
||||
|
|
Loading…
Reference in New Issue