use std::collections::HashMap;
use std::fmt::Debug;
use std::sync::LazyLock;
use crate::attribute::{AttrType, Attribute};
use crate::error::{Error, Result};
use crate::mechanism::{Mechanism, Mechanisms};
use crate::misc::{sizeof, void_ptr};
use crate::pkcs11::*;
#[cfg(feature = "nssdb")]
use crate::pkcs11::vendor::nss::*;
use super::certs::{TrustObject, X509Factory};
use super::key::{
GenericSecretKeyFactory, GenericSecretKeyMechanism, KeyFactory,
PubKeyFactory, SecretKeyFactory,
};
use super::Object;
#[cfg(feature = "nssdb")]
use super::certs::NSSTrustObject;
use bitflags::bitflags;
pub fn incomplete(e: Error) -> Error {
if e.attr_not_found() {
Error::ck_rv(CKR_TEMPLATE_INCOMPLETE)
} else {
e
}
}
bitflags! {
#[derive(Debug, Clone, Copy)]
pub struct OAFlags: u32 {
const Ignored = 0x00000001;
const Sensitive = 0x00000002;
const Defval = 0x00000004;
const RequiredOnCreate = 0x00000008;
const RequiredOnGenerate = 0x00000010;
const AlwaysRequired = 0x00000020;
const SettableOnlyOnCreate = 0x00000080;
const NeverSettable = 0x00000100;
const Unchangeable = 0x00000400;
const ChangeToFalse = 0x00000C00;
const ChangeToTrue = 0x00001400;
const ChangeOnCopy = 0x00002400;
const Ephemeral = 0x00008000;
}
}
#[derive(Debug, Clone)]
pub struct ObjectAttr {
pub(crate) attribute: Attribute,
flags: OAFlags,
}
impl ObjectAttr {
pub fn new(a: Attribute, f: OAFlags) -> ObjectAttr {
ObjectAttr {
attribute: a,
flags: f,
}
}
pub fn get_type(&self) -> CK_ULONG {
self.attribute.get_type()
}
pub fn is(&self, val: OAFlags) -> bool {
if val.is_empty() {
return false;
}
self.flags.contains(val)
}
pub fn has_default(&self) -> bool {
self.flags.contains(OAFlags::Defval)
}
}
#[macro_export]
macro_rules! attr_element {
($id:expr; $flags:expr; $from_type:expr; val $defval:expr) => {
$crate::object::factory::ObjectAttr::new(
$from_type($id, $defval),
$flags,
)
};
}
pub use attr_element;
#[derive(Debug)]
pub struct ObjectFactoryData {
class: CK_OBJECT_CLASS,
attributes: Vec<ObjectAttr>,
sensitive: Vec<CK_ATTRIBUTE_TYPE>,
ephemeral: Vec<CK_ATTRIBUTE_TYPE>,
finalized: bool,
}
impl ObjectFactoryData {
pub fn new(class: CK_OBJECT_CLASS) -> ObjectFactoryData {
ObjectFactoryData {
class: class,
attributes: Vec::new(),
sensitive: Vec::new(),
ephemeral: Vec::new(),
finalized: false,
}
}
pub fn get_class(&self) -> CK_OBJECT_CLASS {
self.class
}
pub fn get_attributes(&self) -> &Vec<ObjectAttr> {
&self.attributes
}
pub fn get_attributes_mut(&mut self) -> &mut Vec<ObjectAttr> {
if self.finalized {
panic!("Attempted modification after finalization");
}
&mut self.attributes
}
pub fn get_sensitive(&self) -> &Vec<CK_ATTRIBUTE_TYPE> {
&self.sensitive
}
pub fn get_ephemeral(&self) -> &Vec<CK_ATTRIBUTE_TYPE> {
&self.ephemeral
}
pub fn finalize(&mut self) {
for a in &self.attributes {
if a.is(OAFlags::Sensitive) {
self.sensitive.push(a.get_type());
}
if a.is(OAFlags::Ephemeral) {
self.ephemeral.push(a.get_type());
}
}
self.finalized = true;
}
}
pub trait ObjectFactory: Debug + Send + Sync {
fn create(&self, _template: &[CK_ATTRIBUTE]) -> Result<Object> {
return Err(CKR_GENERAL_ERROR)?;
}
fn builtin_create(&self, _id: CK_ULONG) -> Result<Object> {
return Err(CKR_GENERAL_ERROR)?;
}
fn copy(&self, obj: &Object, template: &[CK_ATTRIBUTE]) -> Result<Object> {
self.default_copy(obj, template)
}
fn add_common_object_attrs(&mut self) {
let attrs = self.get_data_mut().get_attributes_mut();
attrs.push(attr_element!(
CKA_CLASS; OAFlags::RequiredOnCreate;
Attribute::from_ulong; val 0));
attrs.push(attr_element!(
CKA_UNIQUE_ID; OAFlags::NeverSettable | OAFlags::Unchangeable;
Attribute::from_string; val String::new()));
}
fn add_common_storage_attrs(&mut self, private: bool) {
self.add_common_object_attrs();
let attrs = self.get_data_mut().get_attributes_mut();
attrs.push(attr_element!(
CKA_TOKEN; OAFlags::Defval | OAFlags::ChangeOnCopy;
Attribute::from_bool; val false));
attrs.push(attr_element!(
CKA_PRIVATE; OAFlags::Defval | OAFlags::ChangeOnCopy;
Attribute::from_bool; val private));
attrs.push(attr_element!(
CKA_MODIFIABLE; OAFlags::Defval | OAFlags::ChangeOnCopy;
Attribute::from_bool; val true));
attrs.push(attr_element!(
CKA_LABEL; OAFlags::empty(); Attribute::from_string;
val String::new()));
attrs.push(attr_element!(
CKA_COPYABLE; OAFlags::Defval | OAFlags::ChangeToFalse;
Attribute::from_bool; val true));
attrs.push(attr_element!(
CKA_DESTROYABLE; OAFlags::Defval; Attribute::from_bool;
val true));
}
fn internal_object_create(
&self,
template: &[CK_ATTRIBUTE],
unacceptable_flags: OAFlags,
required_flags: OAFlags,
) -> Result<Object> {
let data = self.get_data();
let mut obj = Object::new(data.get_class());
let attributes = data.get_attributes();
for ck_attr in template {
match attributes.iter().find(|a| a.get_type() == ck_attr.type_) {
Some(attr) => {
if attr.is(unacceptable_flags) {
return Err(CKR_ATTRIBUTE_TYPE_INVALID)?;
}
match obj.get_attr(ck_attr.type_) {
Some(oa) => {
if oa.get_type() != CKA_CLASS
|| (oa.get_type() == CKA_CLASS
&& ck_attr.to_ulong()? != oa.to_ulong()?)
{
return Err(CKR_TEMPLATE_INCONSISTENT)?;
}
}
None => (),
}
if !attr.is(OAFlags::Ignored) {
obj.attributes.push(Attribute::from_ck_attr(ck_attr)?);
}
}
None => {
return Err(CKR_ATTRIBUTE_VALUE_INVALID)?;
}
}
}
for attr in attributes {
match obj.get_attr(attr.get_type()) {
Some(_) => (),
None => {
if attr.has_default() {
obj.attributes.push(attr.attribute.clone());
} else if attr.is(required_flags)
|| attr.is(OAFlags::AlwaysRequired)
{
return Err(CKR_TEMPLATE_INCOMPLETE)?;
}
}
}
}
Ok(obj)
}
fn default_object_create(
&self,
template: &[CK_ATTRIBUTE],
) -> Result<Object> {
let mut obj = self.internal_object_create(
template,
OAFlags::NeverSettable,
OAFlags::RequiredOnCreate,
)?;
obj.generate_unique();
Ok(obj)
}
#[allow(dead_code)]
fn set_attribute_default(
&self,
attr: CK_ATTRIBUTE_TYPE,
obj: &mut Object,
) -> Result<()> {
let attributes = self.get_data().get_attributes();
match attributes.iter().find(|a| a.get_type() == attr) {
Some(defattr) => {
if defattr.has_default() {
obj.set_attr(defattr.attribute.clone())?;
}
}
None => (),
}
Ok(())
}
fn default_copy(
&self,
origin: &Object,
template: &[CK_ATTRIBUTE],
) -> Result<Object> {
let attributes = self.get_data().get_attributes();
for ck_attr in template {
match attributes.iter().find(|a| a.get_type() == ck_attr.type_) {
Some(attr) => {
if attr.is(OAFlags::Unchangeable) {
if attr
.is(OAFlags::ChangeToFalse | OAFlags::ChangeToTrue)
{
let val =
match origin.get_attr_as_bool(ck_attr.type_) {
Ok(a) => a,
Err(_) => false,
};
if val && !attr.is(OAFlags::ChangeToFalse) {
return Err(CKR_ATTRIBUTE_READ_ONLY)?;
}
if !val && !attr.is(OAFlags::ChangeToTrue) {
return Err(CKR_ATTRIBUTE_READ_ONLY)?;
}
}
if !attr.is(OAFlags::ChangeOnCopy) {
return Err(CKR_ATTRIBUTE_READ_ONLY)?;
}
}
}
None => return Err(CKR_TEMPLATE_INCONSISTENT)?,
}
}
let mut obj = origin.blind_copy()?;
for ck_attr in template {
let _ = obj.set_attr(Attribute::from_ck_attr(ck_attr)?)?;
}
match obj.get_attr_as_bool(CKA_EXTRACTABLE) {
Ok(e) => {
let mut val = !e;
match obj.get_attr_as_bool(CKA_NEVER_EXTRACTABLE) {
Ok(ne) => val &= ne,
Err(_) => match origin.get_attr_as_bool(CKA_EXTRACTABLE) {
Ok(oe) => val &= !oe,
Err(_) => val = false,
},
}
let _ = obj.set_attr(Attribute::from_bool(
CKA_NEVER_EXTRACTABLE,
val,
))?;
}
Err(_) => (),
}
match obj.get_attr_as_bool(CKA_SENSITIVE) {
Ok(b) => {
let mut val = b;
match origin.get_attr_as_bool(CKA_ALWAYS_SENSITIVE) {
Ok(ob) => val &= ob,
Err(_) => match origin.get_attr_as_bool(CKA_SENSITIVE) {
Ok(os) => val &= os,
Err(_) => val = false,
},
}
let _ = obj.set_attr(Attribute::from_bool(
CKA_ALWAYS_SENSITIVE,
val,
))?;
}
Err(_) => (),
}
Ok(obj)
}
fn check_set_attributes(&self, template: &[CK_ATTRIBUTE]) -> Result<()> {
let attrs = self.get_data().get_attributes();
for ck_attr in template {
match attrs.iter().find(|a| a.get_type() == ck_attr.type_) {
None => return Err(CKR_ATTRIBUTE_TYPE_INVALID)?,
Some(attr) => {
if attr.is(OAFlags::NeverSettable) {
return Err(CKR_ACTION_PROHIBITED)?;
}
if attr.is(OAFlags::Unchangeable) {
if attr.attribute.get_attrtype() == AttrType::BoolType {
let val = ck_attr.to_bool()?;
if val {
if !attr.is(OAFlags::ChangeToTrue) {
return Err(CKR_ATTRIBUTE_READ_ONLY)?;
}
} else {
if !attr.is(OAFlags::ChangeToFalse) {
return Err(CKR_ATTRIBUTE_READ_ONLY)?;
}
}
} else {
return Err(CKR_ATTRIBUTE_READ_ONLY)?;
}
}
}
}
}
Ok(())
}
fn set_object_attributes(
&self,
obj: &mut Object,
template: &[CK_ATTRIBUTE],
) -> Result<()> {
if !obj.is_modifiable() {
return Err(CKR_ACTION_PROHIBITED)?;
}
self.check_set_attributes(template)?;
for ck_attr in template {
obj.set_attr(Attribute::from_ck_attr(ck_attr)?)?;
}
Ok(())
}
fn get_data(&self) -> &ObjectFactoryData;
fn get_data_mut(&mut self) -> &mut ObjectFactoryData;
fn as_key_factory(&self) -> Result<&dyn KeyFactory> {
Err(CKR_GENERAL_ERROR)?
}
fn as_public_key_factory(&self) -> Result<&dyn PubKeyFactory> {
Err(CKR_GENERAL_ERROR)?
}
fn as_secret_key_factory(&self) -> Result<&dyn SecretKeyFactory> {
Err(CKR_GENERAL_ERROR)?
}
}
#[derive(Debug)]
struct DataFactory {
data: ObjectFactoryData,
}
impl DataFactory {
fn new() -> DataFactory {
let mut factory: DataFactory = DataFactory {
data: ObjectFactoryData::new(CKO_DATA),
};
factory.add_common_storage_attrs(false);
let attributes = factory.data.get_attributes_mut();
attributes.push(attr_element!(
CKA_APPLICATION; OAFlags::Defval; Attribute::from_string;
val String::new()));
attributes.push(attr_element!(
CKA_OBJECT_ID; OAFlags::empty(); Attribute::from_bytes;
val Vec::new()));
attributes.push(attr_element!(
CKA_VALUE; OAFlags::Defval; Attribute::from_bytes;
val Vec::new()));
factory.data.finalize();
factory
}
}
impl ObjectFactory for DataFactory {
fn create(&self, template: &[CK_ATTRIBUTE]) -> Result<Object> {
self.default_object_create(template)
}
fn copy(
&self,
origin: &Object,
template: &[CK_ATTRIBUTE],
) -> Result<Object> {
self.default_copy(origin, template)
}
fn get_data(&self) -> &ObjectFactoryData {
&self.data
}
fn get_data_mut(&mut self) -> &mut ObjectFactoryData {
&mut self.data
}
}
#[cfg(feature = "profiles")]
#[derive(Debug)]
pub struct ProfileFactory {
data: ObjectFactoryData,
}
#[cfg(feature = "profiles")]
impl ProfileFactory {
fn new() -> ProfileFactory {
let mut factory: ProfileFactory = ProfileFactory {
data: ObjectFactoryData::new(CKO_PROFILE),
};
factory.add_common_object_attrs();
let attributes = factory.data.get_attributes_mut();
attributes.push(attr_element!(
CKA_PROFILE_ID; OAFlags::RequiredOnCreate; Attribute::from_ulong;
val CK_UNAVAILABLE_INFORMATION));
factory.data.finalize();
factory
}
}
#[cfg(feature = "profiles")]
impl ObjectFactory for ProfileFactory {
fn create(&self, _template: &[CK_ATTRIBUTE]) -> Result<Object> {
Err(CKR_TEMPLATE_INCOMPLETE)?
}
fn builtin_create(&self, profile_id: CK_PROFILE_ID) -> Result<Object> {
let mut pid = profile_id;
let attr = CK_ATTRIBUTE {
type_: CKA_PROFILE_ID,
pValue: void_ptr!(&mut pid),
ulValueLen: sizeof!(CK_PROFILE_ID),
};
let mut obj = self.internal_object_create(
&[attr],
OAFlags::empty(),
OAFlags::RequiredOnCreate,
)?;
obj.generate_stable_unique(profile_id);
Ok(obj)
}
fn copy(
&self,
_origin: &Object,
_template: &[CK_ATTRIBUTE],
) -> Result<Object> {
Err(CKR_ACTION_PROHIBITED)?
}
fn get_data(&self) -> &ObjectFactoryData {
&self.data
}
fn get_data_mut(&mut self) -> &mut ObjectFactoryData {
&mut self.data
}
}
#[derive(Debug)]
pub struct MechanismFactory {
data: ObjectFactoryData,
}
impl MechanismFactory {
fn new() -> MechanismFactory {
let mut factory: MechanismFactory = MechanismFactory {
data: ObjectFactoryData::new(CKO_MECHANISM),
};
factory.add_common_object_attrs();
let attributes = factory.data.get_attributes_mut();
attributes.push(attr_element!(
CKA_MECHANISM_TYPE; OAFlags::RequiredOnCreate; Attribute::from_ulong;
val CK_UNAVAILABLE_INFORMATION));
factory.data.finalize();
factory
}
}
impl ObjectFactory for MechanismFactory {
fn create(&self, _template: &[CK_ATTRIBUTE]) -> Result<Object> {
Err(CKR_TEMPLATE_INCOMPLETE)?
}
fn builtin_create(
&self,
mechanism_type: CK_MECHANISM_TYPE,
) -> Result<Object> {
let mut mt = mechanism_type;
let attr = CK_ATTRIBUTE {
type_: CKA_MECHANISM_TYPE,
pValue: void_ptr!(&mut mt),
ulValueLen: sizeof!(CK_MECHANISM_TYPE),
};
let mut obj = self.internal_object_create(
&[attr],
OAFlags::empty(),
OAFlags::RequiredOnCreate,
)?;
obj.generate_stable_unique(mechanism_type);
Ok(obj)
}
fn copy(
&self,
_origin: &Object,
_template: &[CK_ATTRIBUTE],
) -> Result<Object> {
Err(CKR_ACTION_PROHIBITED)?
}
fn get_data(&self) -> &ObjectFactoryData {
&self.data
}
fn get_data_mut(&mut self) -> &mut ObjectFactoryData {
&mut self.data
}
}
#[derive(Debug, Eq, Hash, PartialEq)]
pub struct ObjectType {
class: CK_ULONG,
type_: CK_ULONG,
}
impl ObjectType {
pub fn new(class: CK_ULONG, type_: CK_ULONG) -> ObjectType {
ObjectType {
class: class,
type_: type_,
}
}
}
#[derive(Debug)]
pub struct ObjectFactories {
factories: HashMap<ObjectType, &'static Box<dyn ObjectFactory>>,
}
impl ObjectFactories {
pub fn new() -> ObjectFactories {
ObjectFactories {
factories: HashMap::new(),
}
}
pub fn add_factory(
&mut self,
otype: ObjectType,
templ: &'static Box<dyn ObjectFactory>,
) {
self.factories.insert(otype, templ);
}
pub fn get_factory(
&self,
otype: ObjectType,
) -> Result<&Box<dyn ObjectFactory>> {
match self.factories.get(&otype) {
Some(b) => Ok(b),
None => Err(CKR_ATTRIBUTE_VALUE_INVALID)?,
}
}
pub fn create(&self, template: &[CK_ATTRIBUTE]) -> Result<Object> {
let class = match template.iter().find(|a| a.type_ == CKA_CLASS) {
Some(c) => c.to_ulong()?,
None => return Err(CKR_TEMPLATE_INCOMPLETE)?,
};
let type_ = match class {
CKO_DATA | CKO_TRUST | CKO_PROFILE | CKO_MECHANISM => 0,
#[cfg(feature = "nssdb")]
CKO_NSS_TRUST => 0,
CKO_CERTIFICATE => {
match template.iter().find(|a| a.type_ == CKA_CERTIFICATE_TYPE)
{
Some(c) => c.to_ulong()?,
None => return Err(CKR_TEMPLATE_INCOMPLETE)?,
}
}
CKO_PUBLIC_KEY => {
match template.iter().find(|a| a.type_ == CKA_KEY_TYPE) {
Some(k) => k.to_ulong()?,
None => return Err(CKR_TEMPLATE_INCOMPLETE)?,
}
}
CKO_PRIVATE_KEY => {
match template.iter().find(|a| a.type_ == CKA_KEY_TYPE) {
Some(k) => k.to_ulong()?,
None => return Err(CKR_TEMPLATE_INCOMPLETE)?,
}
}
CKO_SECRET_KEY => {
match template.iter().find(|a| a.type_ == CKA_KEY_TYPE) {
Some(k) => k.to_ulong()?,
None => return Err(CKR_TEMPLATE_INCOMPLETE)?,
}
}
_ => return Err(CKR_TEMPLATE_INCONSISTENT)?,
};
self.get_factory(ObjectType::new(class, type_))?
.create(template)
}
pub fn get_object_factory(
&self,
obj: &Object,
) -> Result<&Box<dyn ObjectFactory>> {
let class = obj.get_attr_as_ulong(CKA_CLASS)?;
let type_ = match class {
CKO_CERTIFICATE => obj.get_attr_as_ulong(CKA_CERTIFICATE_TYPE)?,
CKO_PUBLIC_KEY | CKO_PRIVATE_KEY | CKO_SECRET_KEY => {
obj.get_attr_as_ulong(CKA_KEY_TYPE)?
}
_ => 0,
};
self.get_factory(ObjectType::new(class, type_))
}
pub fn check_sensitive(
&self,
obj: &Object,
template: &[CK_ATTRIBUTE],
) -> Result<()> {
let objtype_attrs =
self.get_object_factory(obj)?.get_data().get_attributes();
for ck_attr in template {
match objtype_attrs.iter().find(|a| a.get_type() == ck_attr.type_) {
None => return Err(CKR_ATTRIBUTE_TYPE_INVALID)?,
Some(attr) => {
if attr.is(OAFlags::Sensitive) {
return Err(CKR_ATTRIBUTE_SENSITIVE)?;
}
}
}
}
Ok(())
}
pub fn get_object_attributes(
&self,
obj: &Object,
template: &mut [CK_ATTRIBUTE],
) -> Result<()> {
let sensitive = obj.is_sensitive() || !obj.is_extractable();
let mut result = CKR_OK;
let factory_attrs =
self.get_object_factory(obj)?.get_data().get_attributes();
let obj_attrs = obj.get_attributes();
for ck_attr in template.iter_mut() {
let valid: bool;
match factory_attrs.iter().find(|a| a.get_type() == ck_attr.type_) {
Some(fa) => {
if sensitive && fa.is(OAFlags::Sensitive) {
ck_attr.ulValueLen = CK_UNAVAILABLE_INFORMATION;
if result == CKR_OK {
result = CKR_ATTRIBUTE_SENSITIVE;
}
valid = false;
} else {
valid = true;
}
}
None => {
ck_attr.ulValueLen = CK_UNAVAILABLE_INFORMATION;
if result == CKR_OK {
result = CKR_ATTRIBUTE_TYPE_INVALID;
}
valid = false;
}
}
if !valid {
continue;
}
match obj_attrs.iter().find(|a| a.get_type() == ck_attr.type_) {
Some(oa) => {
let attr_val = oa.get_value();
let attr_len = CK_ULONG::try_from(attr_val.len())?;
if ck_attr.pValue.is_null() {
ck_attr.ulValueLen = attr_len;
} else if ck_attr.ulValueLen == CK_UNAVAILABLE_INFORMATION {
if result == CKR_OK {
result = CKR_TEMPLATE_INCONSISTENT;
}
} else {
if ck_attr.ulValueLen < attr_len {
ck_attr.ulValueLen = CK_UNAVAILABLE_INFORMATION;
if result == CKR_OK {
result = CKR_BUFFER_TOO_SMALL;
}
} else {
ck_attr.ulValueLen = attr_len;
unsafe {
std::ptr::copy_nonoverlapping(
attr_val.as_ptr(),
ck_attr.pValue as *mut _,
attr_val.len(),
);
}
}
}
}
None => {
ck_attr.ulValueLen = CK_UNAVAILABLE_INFORMATION;
if result == CKR_OK {
result = CKR_ATTRIBUTE_TYPE_INVALID;
}
}
}
}
if result == CKR_OK {
Ok(())
} else {
Err(result)?
}
}
pub fn copy(
&self,
obj: &Object,
template: &[CK_ATTRIBUTE],
) -> Result<Object> {
if !obj.is_copyable() {
return Err(CKR_ACTION_PROHIBITED)?;
}
self.get_object_factory(obj)?.copy(obj, template)
}
pub fn get_obj_factory_from_key_template(
&self,
template: &[CK_ATTRIBUTE],
) -> Result<&Box<dyn ObjectFactory>> {
let class = match template.iter().position(|x| x.type_ == CKA_CLASS) {
Some(idx) => template[idx].to_ulong()?,
None => return Err(CKR_TEMPLATE_INCONSISTENT)?,
};
let key_type =
match template.iter().position(|x| x.type_ == CKA_KEY_TYPE) {
Some(idx) => template[idx].to_ulong()?,
None => return Err(CKR_TEMPLATE_INCONSISTENT)?,
};
self.get_factory(ObjectType::new(class, key_type))
}
pub fn derive_key_from_template(
&self,
key: &Object,
template: &[CK_ATTRIBUTE],
) -> Result<Object> {
let factory = self.get_obj_factory_from_key_template(template)?;
factory.as_key_factory()?.key_derive(template, key)
}
}
static DATA_OBJECT_FACTORY: LazyLock<Box<dyn ObjectFactory>> =
LazyLock::new(|| Box::new(DataFactory::new()));
static X509_CERT_FACTORY: LazyLock<Box<dyn ObjectFactory>> =
LazyLock::new(|| Box::new(X509Factory::new()));
static TRUST_OBJECT_FACTORY: LazyLock<Box<dyn ObjectFactory>> =
LazyLock::new(|| Box::new(TrustObject::new()));
#[cfg(feature = "nssdb")]
static NSS_TRUST_OBJECT_FACTORY: LazyLock<Box<dyn ObjectFactory>> =
LazyLock::new(|| Box::new(NSSTrustObject::new()));
#[cfg(feature = "profiles")]
static PROFILE_FACTORY: LazyLock<Box<dyn ObjectFactory>> =
LazyLock::new(|| Box::new(ProfileFactory::new()));
static MECHANISM_FACTORY: LazyLock<Box<dyn ObjectFactory>> =
LazyLock::new(|| Box::new(MechanismFactory::new()));
static GENERIC_SECRET: LazyLock<Box<dyn Mechanism>> = LazyLock::new(|| {
Box::new(GenericSecretKeyMechanism::new(CKK_GENERIC_SECRET))
});
pub(crate) static GENERIC_SECRET_FACTORY: LazyLock<Box<dyn ObjectFactory>> =
LazyLock::new(|| Box::new(GenericSecretKeyFactory::new()));
pub fn register(mechs: &mut Mechanisms, ot: &mut ObjectFactories) {
mechs.add_mechanism(CKM_GENERIC_SECRET_KEY_GEN, &(*GENERIC_SECRET));
ot.add_factory(ObjectType::new(CKO_DATA, 0), &(*DATA_OBJECT_FACTORY));
ot.add_factory(
ObjectType::new(CKO_CERTIFICATE, CKC_X_509),
&(*X509_CERT_FACTORY),
);
ot.add_factory(
ObjectType::new(CKO_SECRET_KEY, CKK_GENERIC_SECRET),
&(*GENERIC_SECRET_FACTORY),
);
ot.add_factory(ObjectType::new(CKO_TRUST, 0), &(*TRUST_OBJECT_FACTORY));
#[cfg(feature = "nssdb")]
ot.add_factory(
ObjectType::new(CKO_NSS_TRUST, 0),
&(*NSS_TRUST_OBJECT_FACTORY),
);
#[cfg(feature = "profiles")]
ot.add_factory(ObjectType::new(CKO_PROFILE, 0), &(*PROFILE_FACTORY));
ot.add_factory(ObjectType::new(CKO_MECHANISM, 0), &(*MECHANISM_FACTORY));
}