use crate::{client, device, object, wrap, Capability, Client, Domain};
use getrandom::getrandom;
use std::fmt::{self, Debug};
use zeroize::{Zeroize, Zeroizing};
#[derive(Clone)]
pub struct Key {
pub(crate) import_params: object::import::Params,
pub(crate) delegated_capabilities: Capability,
pub(crate) data: Vec<u8>,
}
impl Key {
pub fn generate_random(key_id: object::Id, algorithm: wrap::Algorithm) -> Self {
let mut bytes = Zeroizing::new(vec![0u8; algorithm.key_len()]);
getrandom(&mut bytes).expect("RNG failure!");
Self::from_bytes(key_id, &bytes).unwrap()
}
pub fn from_bytes(key_id: object::Id, bytes: &[u8]) -> Result<Self, device::Error> {
let alg = match bytes.len() {
16 => wrap::Algorithm::AES128_CCM,
24 => wrap::Algorithm::AES192_CCM,
32 => wrap::Algorithm::AES256_CCM,
other => fail!(
device::ErrorKind::WrongLength,
"expected 16, 24, or 32-byte wrap key (got {})",
other
),
};
let object_params = object::import::Params::new(key_id, alg.into());
Ok(Self {
import_params: object_params,
delegated_capabilities: Default::default(),
data: bytes.to_vec(),
})
}
pub fn label(mut self, label: object::Label) -> Self {
self.import_params.label = label;
self
}
pub fn domains(mut self, domains: Domain) -> Self {
self.import_params.domains = domains;
self
}
pub fn capabilities(mut self, capabilities: Capability) -> Self {
self.import_params.capabilities = capabilities;
self
}
pub fn delegated_capabilities(mut self, capabilities: Capability) -> Self {
self.delegated_capabilities = capabilities;
self
}
pub fn create(&self, client: &Client) -> Result<(), client::Error> {
let algorithm = self.import_params.algorithm.wrap().unwrap();
client.put_wrap_key(
self.import_params.id,
self.import_params.label.clone(),
self.import_params.domains,
self.import_params.capabilities,
self.delegated_capabilities,
algorithm,
self.data.clone(),
)?;
Ok(())
}
}
impl Debug for Key {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"yubihsm:wrap::Key {{ import_params: {:?}, delegated_capabilities: {:?}, data: ... }}",
self.import_params, self.delegated_capabilities
)
}
}
impl Drop for Key {
fn drop(&mut self) {
self.data.zeroize();
}
}