use heapless::Vec;
use serde::{Deserialize, Serialize};
use serde_indexed::{DeserializeIndexed, SerializeIndexed};
use zeroize::Zeroize;
pub use crate::Bytes;
use crate::{
Error,
config::{MAX_KEY_MATERIAL_LENGTH, MAX_SERIALIZED_KEY_LENGTH},
};
pub type Material = Vec<u8, {MAX_KEY_MATERIAL_LENGTH}>;
pub type SerializedKeyBytes = Vec<u8, {MAX_SERIALIZED_KEY_LENGTH}>;
#[derive(Clone, Debug, /*DeserializeIndexed,*/ Eq, PartialEq, /*SerializeIndexed,*/ Zeroize)]
pub struct Key {
pub flags: Flags,
pub kind: Kind,
pub material: Material,
}
#[derive(Clone, Debug, /*DeserializeIndexed,*/ Eq, PartialEq, /*SerializeIndexed,*/ Zeroize)]
pub struct Info {
pub flags: Flags,
pub kind: Kind,
}
impl Info {
pub fn with_local_flag(mut self) -> Self {
self.flags |= Flags::LOCAL;
self
}
}
impl From<Kind> for Info {
fn from(kind: Kind) -> Self {
Self { flags: Default::default(), kind }
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Zeroize)]
#[repr(u16)]
pub enum Kind {
Shared(usize),
Symmetric(usize),
Symmetric32Nonce(usize),
Ed255,
P256,
X255,
}
bitflags::bitflags! {
#[derive(DeserializeIndexed, SerializeIndexed, Zeroize)]
pub struct Flags: u16 {
const LOCAL = 1 << 0;
const SENSITIVE = 1 << 1;
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Secrecy {
Public,
Secret,
}
impl Key {
pub fn serialize(&self) -> SerializedKeyBytes {
let mut buffer = SerializedKeyBytes::new();
buffer.extend_from_slice(&self.flags.bits().to_be_bytes()).unwrap();
buffer.extend_from_slice(&(self.kind.code()).to_be_bytes()).unwrap();
buffer.extend_from_slice(&self.material).unwrap();
buffer
}
pub fn try_deserialize(bytes: &[u8]) -> Result<Self, Error> {
if bytes.len() < 4 {
return Err(Error::InvalidSerializedKey);
}
let (info, material) = bytes.split_at(4);
let flags_bits = u16::from_be_bytes([info[0], info[1]]);
let flags = Flags::from_bits(flags_bits).ok_or(Error::InvalidSerializedKey)?;
let kind_bits = u16::from_be_bytes([info[2], info[3]]);
let kind = Kind::try_from(kind_bits, material.len()).map_err(|_| Error::InvalidSerializedKey)?;
Ok(Key {
flags,
kind,
material: Material::from_slice(material).map_err(|_| Error::InvalidSerializedKey)?,
})
}
}
impl Default for Flags {
fn default() -> Self {
Flags::SENSITIVE
}
}
impl Kind {
pub fn code(self) -> u16 {
match self {
Kind::Shared(_) => 1,
Kind::Symmetric(_) => 2,
Kind::Symmetric32Nonce(_) => 3,
Kind::Ed255 => 4,
Kind::P256 => 5,
Kind::X255 => 6,
}
}
pub fn try_from(code: u16, length: usize) -> Result<Self, Error> {
Ok(match code {
1 => Self::Shared(length),
2 => Self::Symmetric(length),
3 => Self::Symmetric32Nonce(length - 32),
4 => Self::Ed255,
5 => Self::P256,
6 => Self::X255,
_ => return Err(Error::InvalidSerializedKey),
})
}
}