//! 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 { 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); } } } }