use std::fmt::Debug;
use std::sync::LazyLock;
use crate::error::Result;
use crate::mechanism::{Derive, Mechanism, Mechanisms};
use crate::object::{
GenericSecretKeyFactory, GenericSecretKeyMechanism, ObjectFactories,
ObjectFactory, ObjectType,
};
use crate::ossl::hkdf::HKDFOperation;
use crate::pkcs11::*;
static HKDF_MECHS: LazyLock<[Box<dyn Mechanism>; 2]> = LazyLock::new(|| {
[
Box::new(HKDFMechanism {
info: CK_MECHANISM_INFO {
ulMinKeySize: 0,
ulMaxKeySize: CK_ULONG::try_from(u32::MAX).unwrap(),
flags: CKF_DERIVE,
},
}),
Box::new(GenericSecretKeyMechanism::new(CKK_HKDF)),
]
});
static HKDF_KEY_FACTORY: LazyLock<Box<dyn ObjectFactory>> =
LazyLock::new(|| Box::new(GenericSecretKeyFactory::new()));
pub fn register(mechs: &mut Mechanisms, ot: &mut ObjectFactories) {
for ckm in &[CKM_HKDF_DERIVE, CKM_HKDF_DATA] {
mechs.add_mechanism(*ckm, &(*HKDF_MECHS)[0]);
}
mechs.add_mechanism(CKM_HKDF_KEY_GEN, &(*HKDF_MECHS)[1]);
ot.add_factory(
ObjectType::new(CKO_SECRET_KEY, CKK_HKDF),
&(*HKDF_KEY_FACTORY),
);
}
#[derive(Debug)]
struct HKDFMechanism {
info: CK_MECHANISM_INFO,
}
impl Mechanism for HKDFMechanism {
fn info(&self) -> &CK_MECHANISM_INFO {
&self.info
}
fn derive_operation(&self, mech: &CK_MECHANISM) -> Result<Box<dyn Derive>> {
if self.info.flags & CKF_DERIVE != CKF_DERIVE {
return Err(CKR_MECHANISM_INVALID)?;
}
match mech.mechanism {
CKM_HKDF_DERIVE | CKM_HKDF_DATA => {
Ok(Box::new(HKDFOperation::new(mech)?))
}
_ => Err(CKR_MECHANISM_INVALID)?,
}
}
}