libFenrir/src/enc/asym.rs
Luca Fulchir 1259996201
Connect boilerplate, cleanup
Signed-off-by: Luca Fulchir <luca.fulchir@runesauth.com>
2023-05-27 10:57:15 +02:00

142 lines
3.9 KiB
Rust

//! Asymmetric key handling and wrappers
use ::num_traits::FromPrimitive;
use super::Error;
use crate::enc::sym::Secret;
/// Public key ID
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct KeyID(pub u16);
impl KeyID {
/// Length of the Key ID in bytes
pub const fn len() -> usize {
2
}
/// Serialize into raw bytes
pub fn serialize(&self, out: &mut [u8; KeyID::len()]) {
out.copy_from_slice(&self.0.to_le_bytes());
}
}
/// Kind of key used in the handshake
#[derive(Debug, Copy, Clone, PartialEq, ::num_derive::FromPrimitive)]
#[repr(u8)]
pub enum Key {
/// X25519 Public key
X25519 = 0,
}
impl Key {
fn pub_len(&self) -> usize {
match self {
// FIXME: 99% wrong size
Key::X25519 => ::ring::signature::ED25519_PUBLIC_KEY_LEN,
}
}
}
/// Kind of key exchange
#[derive(Debug, Copy, Clone, PartialEq, ::num_derive::FromPrimitive)]
#[repr(u8)]
pub enum KeyExchange {
/// X25519 Public key
X25519DiffieHellman = 0,
}
impl KeyExchange {
/// The serialize length of the field
pub fn len() -> usize {
1
}
}
/// Kind of key in the handshake
#[derive(Clone)]
#[allow(missing_debug_implementations)]
pub enum PrivKey {
/// Keys to be used only in key exchanges, not for signing
Exchange(ExchangePrivKey),
/// Keys to be used only for signing
Signing,
}
/// Ephemeral private keys
#[derive(Clone)]
#[allow(missing_debug_implementations)]
pub enum ExchangePrivKey {
/// X25519(Curve25519) used for key exchange
X25519(::x25519_dalek::StaticSecret),
}
impl ExchangePrivKey {
/// Get the kind of key
pub fn kind(&self) -> Key {
match self {
ExchangePrivKey::X25519(_) => Key::X25519,
}
}
/// Run the key exchange between two keys of the same kind
pub fn key_exchange(
&self,
exchange: KeyExchange,
pub_key: ExchangePubKey,
) -> Result<Secret, Error> {
match self {
ExchangePrivKey::X25519(priv_key) => {
if exchange != KeyExchange::X25519DiffieHellman {
return Err(Error::UnsupportedKeyExchange);
}
if 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)
}
}
}
}
}
/// all Ephemeral Public keys
#[derive(Debug, Copy, Clone)]
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 {
match self {
ExchangePubKey::X25519(_) => 32,
}
}
/// 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);
}
match Key::from_u8(raw[0]) {
Some(kind) => match kind {
Key::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((ExchangePubKey::X25519(pub_key), kind.pub_len()))
}
},
None => {
return Err(Error::Parsing);
}
}
}
}