142 lines
3.9 KiB
Rust
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);
|
|
}
|
|
}
|
|
}
|
|
}
|