use std::sync::LazyLock;
use crate::attribute::{Attribute, CkAttrs};
use crate::ec::{get_oid_from_obj, oid_to_bits};
use crate::error::Result;
use crate::object::*;
use crate::pkcs11::vendor::KRY_UNSPEC;
use crate::pkcs11::*;
pub const KRF_FIPS: CK_ULONG = 1;
const VALIDATION_VERSION: [u8; 2] = [3u8, 0u8];
const VALIDATION_LEVEL: CK_ULONG = 1;
const MODULE_ID: &str = "Kryoptic FIPS Module - v1";
const COUNTRY: &str = "US";
const CERTIFICATE: &str = "Pending";
const CERTIFICATE_URI: &str = "";
const VENDOR_URI: &str = "https://github.com/latchset/kryoptic";
const PROFILE: &str = "";
#[derive(Debug)]
pub struct ValidationFactory {
data: ObjectFactoryData,
}
impl ValidationFactory {
fn new() -> ValidationFactory {
let mut factory: ValidationFactory = ValidationFactory {
data: ObjectFactoryData::new(CKO_VALIDATION),
};
factory.add_common_object_attrs();
let attributes = factory.data.get_attributes_mut();
attributes.push(attr_element!(
CKA_VALIDATION_TYPE; OAFlags::AlwaysRequired
| OAFlags::NeverSettable | OAFlags::Unchangeable;
Attribute::from_ulong; val 0));
attributes.push(attr_element!(
CKA_VALIDATION_VERSION; OAFlags::AlwaysRequired
| OAFlags::NeverSettable | OAFlags::Unchangeable;
Attribute::from_bytes; val Vec::new()));
attributes.push(attr_element!(
CKA_VALIDATION_LEVEL; OAFlags::AlwaysRequired
| OAFlags::NeverSettable | OAFlags::Unchangeable;
Attribute::from_ulong; val 0));
attributes.push(attr_element!(
CKA_VALIDATION_MODULE_ID; OAFlags::AlwaysRequired
| OAFlags::NeverSettable | OAFlags::Unchangeable;
Attribute::from_string; val String::new()));
attributes.push(attr_element!(
CKA_VALIDATION_FLAG; OAFlags::AlwaysRequired
| OAFlags::NeverSettable | OAFlags::Unchangeable;
Attribute::from_ulong; val 0));
attributes.push(attr_element!(
CKA_VALIDATION_AUTHORITY_TYPE; OAFlags::AlwaysRequired
| OAFlags::NeverSettable | OAFlags::Unchangeable;
Attribute::from_ulong; val 0));
attributes.push(attr_element!(
CKA_VALIDATION_COUNTRY; OAFlags::AlwaysRequired
| OAFlags::NeverSettable | OAFlags::Unchangeable;
Attribute::from_string; val String::new()));
attributes.push(attr_element!(
CKA_VALIDATION_CERTIFICATE_IDENTIFIER; OAFlags::AlwaysRequired
| OAFlags::NeverSettable | OAFlags::Unchangeable;
Attribute::from_string; val String::new()));
attributes.push(attr_element!(
CKA_VALIDATION_CERTIFICATE_URI; OAFlags::AlwaysRequired
| OAFlags::NeverSettable | OAFlags::Unchangeable;
Attribute::from_string; val String::new()));
attributes.push(attr_element!(
CKA_VALIDATION_VENDOR_URI; OAFlags::AlwaysRequired
| OAFlags::NeverSettable | OAFlags::Unchangeable;
Attribute::from_string; val String::new()));
attributes.push(attr_element!(
CKA_VALIDATION_PROFILE; OAFlags::AlwaysRequired
| OAFlags::NeverSettable | OAFlags::Unchangeable;
Attribute::from_string; val String::new()));
factory.data.finalize();
factory
}
}
impl ObjectFactory for ValidationFactory {
fn create(&self, _template: &[CK_ATTRIBUTE]) -> Result<Object> {
Err(CKR_TEMPLATE_INCOMPLETE)?
}
fn builtin_create(&self, stable_id: CK_ULONG) -> Result<Object> {
let mut tmpl = CkAttrs::with_capacity(11);
match stable_id {
super::FIPS_VALIDATION_OBJ => {
tmpl.add_ulong(CKA_VALIDATION_TYPE, &CKV_TYPE_SOFTWARE);
tmpl.add_slice(CKA_VALIDATION_VERSION, &VALIDATION_VERSION)?;
tmpl.add_ulong(CKA_VALIDATION_LEVEL, &VALIDATION_LEVEL);
tmpl.add_slice(CKA_VALIDATION_MODULE_ID, MODULE_ID.as_bytes())?;
tmpl.add_ulong(CKA_VALIDATION_FLAG, &KRF_FIPS);
tmpl.add_ulong(
CKA_VALIDATION_AUTHORITY_TYPE,
&CKV_AUTHORITY_TYPE_NIST_CMVP,
);
tmpl.add_slice(CKA_VALIDATION_COUNTRY, COUNTRY.as_bytes())?;
tmpl.add_slice(
CKA_VALIDATION_CERTIFICATE_IDENTIFIER,
CERTIFICATE.as_bytes(),
)?;
tmpl.add_slice(
CKA_VALIDATION_CERTIFICATE_URI,
CERTIFICATE_URI.as_bytes(),
)?;
tmpl.add_slice(
CKA_VALIDATION_VENDOR_URI,
VENDOR_URI.as_bytes(),
)?;
tmpl.add_slice(CKA_VALIDATION_PROFILE, PROFILE.as_bytes())?;
}
_ => return Err(CKR_GENERAL_ERROR)?,
}
let mut obj = self.internal_object_create(
tmpl.as_slice(),
OAFlags::empty(),
OAFlags::RequiredOnCreate,
)?;
obj.generate_stable_unique(stable_id);
Ok(obj)
}
fn copy(
&self,
_origin: &Object,
_template: &[CK_ATTRIBUTE],
) -> Result<Object> {
Err(CKR_TEMPLATE_INCOMPLETE)?
}
fn get_data(&self) -> &ObjectFactoryData {
&self.data
}
fn get_data_mut(&mut self) -> &mut ObjectFactoryData {
&mut self.data
}
}
pub(crate) static VALIDATION_FACTORY: LazyLock<Box<dyn ObjectFactory>> =
LazyLock::new(|| Box::new(ValidationFactory::new()));
macro_rules! btb {
($val:expr) => {
($val + 7) / 8
};
}
macro_rules! step {
($s1:expr) => {
([btb!($s1), 0, 0, 0], (0, 0))
};
($s1:expr, $s2:expr) => {
([btb!($s1), btb!($s2), 0, 0], (0, 0))
};
($s1:expr, $s2:expr, $s3:expr) => {
([btb!($s1), btb!($s2), btb!($s3), 0], (0, 0))
};
($s1:expr, $s2:expr, $s3:expr, $s4:expr) => {
([btb!($s1), btb!($s2), btb!($s3), btb!($s4)], (0, 0))
};
}
macro_rules! range {
($r1:expr, $r2:expr) => {
([0, 0, 0, 0], (btb!($r1), btb!($r2)))
};
}
macro_rules! step_and_range {
() => {
([0, 0, 0, 0], (0, 0))
};
($s1:expr; $r1:expr, $r2:expr) => {
([btb!($s1), 0, 0, 0], (btb!($r1), btb!($r2)))
};
($s1:expr, $s2:expr; $r1:expr, $r2:expr) => {
([btb!($s1), btb!($s2), 0, 0], (btb!($r1), btb!($r2)))
};
($s1:expr, $s2:expr, $s3:expr; $r1:expr, $r2:expr) => {
([btb!($s1), btb!($s2), btb!($s3), 0], (btb!($r1), btb!($r2)))
};
($s1:expr, $s2:expr, $s3:expr, $s4:expr; $r1:expr, $r2:expr) => {
(
[btb!($s1), btb!($s2), btb!($s3), btb!($s4)],
(btb!($r1), btb!($r2)),
)
};
}
macro_rules! restrict {
() => {
(KRY_UNSPEC, step_and_range!())
};
($key:expr) => {
($key, step_and_range!())
};
($key:expr, $sr:expr) => {
($key, $sr)
};
}
fn flag_to_op(flag: CK_FLAGS) -> Result<CK_ATTRIBUTE_TYPE> {
Ok(match flag {
CKF_SIGN => CKA_SIGN,
CKF_VERIFY => CKA_VERIFY,
CKF_ENCRYPT => CKA_ENCRYPT,
CKF_DECRYPT => CKA_DECRYPT,
CKF_WRAP => CKA_WRAP,
CKF_UNWRAP => CKA_UNWRAP,
CKF_DERIVE => CKA_DERIVE,
_ => return Err(CKR_GENERAL_ERROR)?,
})
}
struct FipsKeyType {
keytype: CK_KEY_TYPE,
operations: CK_FLAGS,
sizes: ([usize; 4], (usize, usize)),
}
struct FipsMechanism {
mechanism: CK_MECHANISM_TYPE,
operations: CK_FLAGS,
restrictions: [(CK_KEY_TYPE, ([usize; 4], (usize, usize))); 2],
genflags: CK_FLAGS,
}
struct FipsChecks {
keys: [FipsKeyType; 17],
mechs: [FipsMechanism; 93],
}
const FIPS_CHECKS: FipsChecks = FipsChecks {
keys: [
FipsKeyType {
keytype: CKK_RSA,
operations: CKF_SIGN
| CKF_VERIFY
| CKF_ENCRYPT
| CKF_DECRYPT
| CKF_WRAP
| CKF_UNWRAP,
sizes: range!(2048, 16384),
},
FipsKeyType {
keytype: CKK_RSA,
operations: CKF_VERIFY | CKF_DECRYPT | CKF_UNWRAP,
sizes: step!(1024, 1280, 1536, 1792),
},
FipsKeyType {
keytype: CKK_EC,
operations: CKF_SIGN | CKF_VERIFY | CKF_DERIVE,
sizes: step!(256, 384, 521),
},
FipsKeyType {
keytype: CKK_AES,
operations: CKF_SIGN
| CKF_VERIFY
| CKF_ENCRYPT
| CKF_DECRYPT
| CKF_WRAP
| CKF_UNWRAP,
sizes: step!(128, 192, 256),
},
FipsKeyType {
keytype: CKK_GENERIC_SECRET,
operations: CKF_SIGN | CKF_VERIFY | CKF_DERIVE,
sizes: range!(112, 255 * 64 * 8),
},
FipsKeyType {
keytype: CKK_SHA224_HMAC,
operations: CKF_SIGN | CKF_VERIFY | CKF_DERIVE,
sizes: step!(224),
},
FipsKeyType {
keytype: CKK_SHA256_HMAC,
operations: CKF_SIGN | CKF_VERIFY | CKF_DERIVE,
sizes: step!(256),
},
FipsKeyType {
keytype: CKK_SHA384_HMAC,
operations: CKF_SIGN | CKF_VERIFY | CKF_DERIVE,
sizes: step!(384),
},
FipsKeyType {
keytype: CKK_SHA512_HMAC,
operations: CKF_SIGN | CKF_VERIFY | CKF_DERIVE,
sizes: step!(512),
},
FipsKeyType {
keytype: CKK_SHA3_224_HMAC,
operations: CKF_SIGN | CKF_VERIFY | CKF_DERIVE,
sizes: step!(224),
},
FipsKeyType {
keytype: CKK_SHA3_256_HMAC,
operations: CKF_SIGN | CKF_VERIFY | CKF_DERIVE,
sizes: step!(256),
},
FipsKeyType {
keytype: CKK_SHA3_384_HMAC,
operations: CKF_SIGN | CKF_VERIFY | CKF_DERIVE,
sizes: step!(384),
},
FipsKeyType {
keytype: CKK_SHA3_512_HMAC,
operations: CKF_SIGN | CKF_VERIFY | CKF_DERIVE,
sizes: step!(512),
},
FipsKeyType {
keytype: CKK_EC_EDWARDS,
operations: CKF_SIGN | CKF_VERIFY,
sizes: step!(255, 448),
},
FipsKeyType {
keytype: CKK_HKDF,
operations: CKF_DERIVE,
sizes: range!(112, 512),
},
FipsKeyType {
keytype: CKK_ML_KEM,
operations: CKF_ENCAPSULATE | CKF_DECAPSULATE,
sizes: step!(1632, 2400, 3168),
},
FipsKeyType {
keytype: CKK_ML_DSA,
operations: CKF_SIGN | CKF_VERIFY,
sizes: step!(2560, 4032, 4896),
},
],
mechs: [
FipsMechanism {
mechanism: CKM_RSA_PKCS_KEY_PAIR_GEN,
operations: CKF_GENERATE_KEY_PAIR,
restrictions: [
restrict!(CKK_RSA, range!(2048, 16384)),
restrict!(),
],
genflags: CKF_SIGN
| CKF_VERIFY
| CKF_ENCRYPT
| CKF_DECRYPT
| CKF_WRAP
| CKF_UNWRAP,
},
FipsMechanism {
mechanism: CKM_RSA_PKCS_OAEP,
operations: CKF_ENCRYPT | CKF_DECRYPT,
restrictions: [
restrict!(CKK_RSA, range!(2048, 16384)),
restrict!(),
],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA1_RSA_PKCS,
operations: CKF_VERIFY,
restrictions: [restrict!(CKK_RSA), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA224_RSA_PKCS,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_RSA), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA256_RSA_PKCS,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_RSA), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA384_RSA_PKCS,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_RSA), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA512_RSA_PKCS,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_RSA), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA3_224_RSA_PKCS,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_RSA), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA3_256_RSA_PKCS,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_RSA), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA3_384_RSA_PKCS,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_RSA), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA3_512_RSA_PKCS,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_RSA), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA1_RSA_PKCS_PSS,
operations: CKF_VERIFY,
restrictions: [restrict!(CKK_RSA), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA224_RSA_PKCS_PSS,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_RSA), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA256_RSA_PKCS_PSS,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_RSA), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA384_RSA_PKCS_PSS,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_RSA), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA512_RSA_PKCS_PSS,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_RSA), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA3_224_RSA_PKCS_PSS,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_RSA), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA3_256_RSA_PKCS_PSS,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_RSA), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA3_384_RSA_PKCS_PSS,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_RSA), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA3_512_RSA_PKCS_PSS,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_RSA), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_EC_KEY_PAIR_GEN,
operations: CKF_GENERATE_KEY_PAIR,
restrictions: [restrict!(CKK_EC), restrict!()],
genflags: CKF_SIGN | CKF_VERIFY | CKF_DERIVE,
},
FipsMechanism {
mechanism: CKM_ECDSA_SHA224,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_EC), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_ECDSA_SHA256,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_EC), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_ECDSA_SHA384,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_EC), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_ECDSA_SHA512,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_EC), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_EC_EDWARDS_KEY_PAIR_GEN,
operations: CKF_GENERATE_KEY_PAIR,
restrictions: [restrict!(CKK_EC_EDWARDS), restrict!()],
genflags: CKF_SIGN | CKF_VERIFY,
},
FipsMechanism {
mechanism: CKM_EDDSA,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_EC_EDWARDS), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_AES_KEY_GEN,
operations: CKF_GENERATE,
restrictions: [restrict!(CKK_AES), restrict!()],
genflags: CKF_ENCRYPT
| CKF_DECRYPT
| CKF_SIGN | CKF_VERIFY
| CKF_WRAP
| CKF_UNWRAP
| CKF_DERIVE,
},
FipsMechanism {
mechanism: CKM_AES_ECB,
operations: CKF_ENCRYPT | CKF_DECRYPT,
restrictions: [restrict!(CKK_AES), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_AES_CBC,
operations: CKF_ENCRYPT | CKF_DECRYPT,
restrictions: [restrict!(CKK_AES), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_AES_CBC_PAD,
operations: CKF_ENCRYPT | CKF_DECRYPT,
restrictions: [restrict!(CKK_AES), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_AES_CTR,
operations: CKF_ENCRYPT | CKF_DECRYPT,
restrictions: [restrict!(CKK_AES), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_AES_GCM,
operations: CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP,
restrictions: [restrict!(CKK_AES), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_AES_CTS,
operations: CKF_ENCRYPT | CKF_DECRYPT,
restrictions: [restrict!(CKK_AES), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_AES_CMAC,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_AES), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_AES_CMAC_GENERAL,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_AES), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_AES_KEY_WRAP,
operations: CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP,
restrictions: [restrict!(KRY_UNSPEC), restrict!()],
genflags: CKF_SIGN
| CKF_VERIFY
| CKF_ENCRYPT
| CKF_DECRYPT
| CKF_WRAP
| CKF_UNWRAP
| CKF_DERIVE,
},
FipsMechanism {
mechanism: CKM_AES_KEY_WRAP_KWP,
operations: CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP,
restrictions: [restrict!(KRY_UNSPEC), restrict!()],
genflags: CKF_SIGN
| CKF_VERIFY
| CKF_ENCRYPT
| CKF_DECRYPT
| CKF_WRAP
| CKF_UNWRAP
| CKF_DERIVE,
},
FipsMechanism {
mechanism: CKM_SHA224,
operations: CKF_DIGEST,
restrictions: [restrict!(), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA256,
operations: CKF_DIGEST,
restrictions: [restrict!(), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA384,
operations: CKF_DIGEST,
restrictions: [restrict!(), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA512,
operations: CKF_DIGEST,
restrictions: [restrict!(), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA3_224,
operations: CKF_DIGEST,
restrictions: [restrict!(), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA3_256,
operations: CKF_DIGEST,
restrictions: [restrict!(), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA3_384,
operations: CKF_DIGEST,
restrictions: [restrict!(), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA3_512,
operations: CKF_DIGEST,
restrictions: [restrict!(), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA224_HMAC,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [
restrict!(CKK_SHA224_HMAC, range!(112, 224)),
restrict!(CKK_GENERIC_SECRET, range!(112, 224)),
],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA256_HMAC,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [
restrict!(CKK_SHA256_HMAC, range!(112, 256)),
restrict!(CKK_GENERIC_SECRET, range!(112, 256)),
],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA384_HMAC,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [
restrict!(CKK_SHA384_HMAC, range!(112, 384)),
restrict!(CKK_GENERIC_SECRET, range!(112, 384)),
],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA512_HMAC,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [
restrict!(CKK_SHA512_HMAC, range!(112, 512)),
restrict!(CKK_GENERIC_SECRET, range!(112, 512)),
],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA512_224_HMAC,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [
restrict!(CKK_SHA512_224_HMAC, range!(112, 224)),
restrict!(CKK_GENERIC_SECRET, range!(112, 224)),
],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA512_256_HMAC,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [
restrict!(CKK_SHA512_256_HMAC, range!(112, 256)),
restrict!(CKK_GENERIC_SECRET, range!(112, 256)),
],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA3_224_HMAC,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [
restrict!(CKK_SHA3_224_HMAC, range!(112, 224)),
restrict!(CKK_GENERIC_SECRET, range!(112, 224)),
],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA3_256_HMAC,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [
restrict!(CKK_SHA3_256_HMAC, range!(112, 256)),
restrict!(CKK_GENERIC_SECRET, range!(112, 256)),
],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA3_384_HMAC,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [
restrict!(CKK_SHA3_384_HMAC, range!(112, 384)),
restrict!(CKK_GENERIC_SECRET, range!(112, 384)),
],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA3_512_HMAC,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [
restrict!(CKK_SHA3_512_HMAC, range!(112, 512)),
restrict!(CKK_GENERIC_SECRET, range!(112, 512)),
],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA224_HMAC_GENERAL,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [
restrict!(CKK_SHA224_HMAC, range!(112, 224)),
restrict!(CKK_GENERIC_SECRET, range!(112, 224)),
],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA256_HMAC_GENERAL,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [
restrict!(CKK_SHA256_HMAC, range!(112, 256)),
restrict!(CKK_GENERIC_SECRET, range!(112, 256)),
],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA384_HMAC_GENERAL,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [
restrict!(CKK_SHA384_HMAC, range!(112, 384)),
restrict!(CKK_GENERIC_SECRET, range!(112, 384)),
],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA512_HMAC_GENERAL,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [
restrict!(CKK_SHA512_HMAC, range!(112, 512)),
restrict!(CKK_GENERIC_SECRET, range!(112, 512)),
],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA3_224_HMAC_GENERAL,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [
restrict!(CKK_SHA3_224_HMAC, range!(112, 224)),
restrict!(CKK_GENERIC_SECRET, range!(112, 224)),
],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA3_256_HMAC_GENERAL,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [
restrict!(CKK_SHA3_256_HMAC, range!(112, 256)),
restrict!(CKK_GENERIC_SECRET, range!(112, 256)),
],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA3_384_HMAC_GENERAL,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [
restrict!(CKK_SHA3_384_HMAC, range!(112, 384)),
restrict!(CKK_GENERIC_SECRET, range!(112, 384)),
],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_SHA3_512_HMAC_GENERAL,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [
restrict!(CKK_SHA3_512_HMAC, range!(112, 512)),
restrict!(CKK_GENERIC_SECRET, range!(112, 512)),
],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_TLS_MAC,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [
restrict!(CKK_GENERIC_SECRET, range!(112, 512)),
restrict!(),
],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_PKCS5_PBKD2,
operations: CKF_GENERATE,
restrictions: [
restrict!(KRY_UNSPEC, range!(112, 256)),
restrict!(),
],
genflags: CKF_DERIVE,
},
FipsMechanism {
mechanism: CKM_GENERIC_SECRET_KEY_GEN,
operations: CKF_GENERATE,
restrictions: [
restrict!(CKK_GENERIC_SECRET, range!(112, 255 * 64 * 8)),
restrict!(),
],
genflags: CKF_SIGN | CKF_VERIFY | CKF_DERIVE,
},
FipsMechanism {
mechanism: CKM_HKDF_KEY_GEN,
operations: CKF_GENERATE,
restrictions: [
restrict!(CKK_HKDF, step_and_range!(256, 384, 512; 160, 224)),
restrict!(),
],
genflags: CKF_DERIVE,
},
FipsMechanism {
mechanism: CKM_HKDF_DERIVE,
operations: CKF_DERIVE,
restrictions: [
restrict!(CKK_GENERIC_SECRET, range!(112, 255 * 64 * 8)),
restrict!(CKK_HKDF, range!(112, 255 * 64 * 8)),
],
genflags: CKF_SIGN
| CKF_VERIFY
| CKF_ENCRYPT
| CKF_DECRYPT
| CKF_WRAP
| CKF_UNWRAP
| CKF_DERIVE,
},
FipsMechanism {
mechanism: CKM_HKDF_DATA,
operations: CKF_DERIVE,
restrictions: [
restrict!(KRY_UNSPEC, range!(112, 255 * 64 * 8)),
restrict!(),
],
genflags: CKF_SIGN
| CKF_VERIFY
| CKF_ENCRYPT
| CKF_DECRYPT
| CKF_WRAP
| CKF_UNWRAP
| CKF_DERIVE,
},
FipsMechanism {
mechanism: CKM_TLS12_EXTENDED_MASTER_KEY_DERIVE_DH,
operations: CKF_DERIVE,
restrictions: [
restrict!(CKK_GENERIC_SECRET, step!(48 * 8)),
restrict!(),
],
genflags: CKF_SIGN
| CKF_VERIFY
| CKF_ENCRYPT
| CKF_DECRYPT
| CKF_DERIVE,
},
FipsMechanism {
mechanism: CKM_TLS12_EXTENDED_MASTER_KEY_DERIVE,
operations: CKF_DERIVE,
restrictions: [
restrict!(CKK_GENERIC_SECRET, step!(48 * 8)),
restrict!(),
],
genflags: CKF_SIGN
| CKF_VERIFY
| CKF_ENCRYPT
| CKF_DECRYPT
| CKF_DERIVE,
},
FipsMechanism {
mechanism: CKM_TLS12_KEY_AND_MAC_DERIVE,
operations: CKF_DERIVE,
restrictions: [
restrict!(CKK_GENERIC_SECRET, range!(112, 255 * 64 * 8)),
restrict!(),
],
genflags: CKF_SIGN
| CKF_VERIFY
| CKF_ENCRYPT
| CKF_DECRYPT
| CKF_DERIVE,
},
FipsMechanism {
mechanism: CKM_TLS12_KEY_SAFE_DERIVE,
operations: CKF_DERIVE,
restrictions: [
restrict!(CKK_GENERIC_SECRET, range!(112, 255 * 64 * 8)),
restrict!(),
],
genflags: CKF_SIGN
| CKF_VERIFY
| CKF_ENCRYPT
| CKF_DECRYPT
| CKF_DERIVE,
},
FipsMechanism {
mechanism: CKM_SP800_108_COUNTER_KDF,
operations: CKF_DERIVE,
restrictions: [
restrict!(CKK_AES),
restrict!(KRY_UNSPEC, range!(112, 0x1000000)),
],
genflags: CKF_SIGN
| CKF_VERIFY
| CKF_ENCRYPT
| CKF_DECRYPT
| CKF_WRAP
| CKF_UNWRAP
| CKF_DERIVE,
},
FipsMechanism {
mechanism: CKM_SP800_108_FEEDBACK_KDF,
operations: CKF_DERIVE,
restrictions: [
restrict!(CKK_AES),
restrict!(KRY_UNSPEC, range!(112, 0x1000000)),
],
genflags: CKF_SIGN
| CKF_VERIFY
| CKF_ENCRYPT
| CKF_DECRYPT
| CKF_WRAP
| CKF_UNWRAP
| CKF_DERIVE,
},
FipsMechanism {
mechanism: CKM_CONCATENATE_BASE_AND_KEY,
operations: CKF_DERIVE,
restrictions: [
restrict!(KRY_UNSPEC, range!(112, 255 * 64 * 8)),
restrict!(),
],
genflags: CKF_SIGN
| CKF_VERIFY
| CKF_ENCRYPT
| CKF_DECRYPT
| CKF_WRAP
| CKF_UNWRAP
| CKF_DERIVE,
},
FipsMechanism {
mechanism: CKM_CONCATENATE_BASE_AND_DATA,
operations: CKF_DERIVE,
restrictions: [
restrict!(KRY_UNSPEC, range!(112, 255 * 64 * 8)),
restrict!(),
],
genflags: CKF_SIGN
| CKF_VERIFY
| CKF_ENCRYPT
| CKF_DECRYPT
| CKF_WRAP
| CKF_UNWRAP
| CKF_DERIVE,
},
FipsMechanism {
mechanism: CKM_CONCATENATE_DATA_AND_BASE,
operations: CKF_DERIVE,
restrictions: [
restrict!(KRY_UNSPEC, range!(112, 255 * 64 * 8)),
restrict!(),
],
genflags: CKF_SIGN
| CKF_VERIFY
| CKF_ENCRYPT
| CKF_DECRYPT
| CKF_WRAP
| CKF_UNWRAP
| CKF_DERIVE,
},
FipsMechanism {
mechanism: CKM_XOR_BASE_AND_DATA,
operations: CKF_DERIVE,
restrictions: [
restrict!(KRY_UNSPEC, range!(112, 255 * 64 * 8)),
restrict!(),
],
genflags: CKF_SIGN
| CKF_VERIFY
| CKF_ENCRYPT
| CKF_DECRYPT
| CKF_WRAP
| CKF_UNWRAP
| CKF_DERIVE,
},
FipsMechanism {
mechanism: CKM_ML_KEM_KEY_PAIR_GEN,
operations: CKF_GENERATE_KEY_PAIR,
restrictions: [restrict!(CKK_ML_KEM), restrict!()],
genflags: CKF_ENCAPSULATE | CKF_DECAPSULATE,
},
FipsMechanism {
mechanism: CKM_ML_KEM,
operations: CKF_ENCAPSULATE | CKF_DECAPSULATE,
restrictions: [restrict!(CKK_ML_KEM), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_ML_DSA_KEY_PAIR_GEN,
operations: CKF_GENERATE_KEY_PAIR,
restrictions: [restrict!(CKK_ML_DSA), restrict!()],
genflags: CKF_SIGN | CKF_VERIFY,
},
FipsMechanism {
mechanism: CKM_ML_DSA,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_ML_DSA), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_HASH_ML_DSA,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_ML_DSA), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_HASH_ML_DSA_SHA224,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_ML_DSA), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_HASH_ML_DSA_SHA256,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_ML_DSA), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_HASH_ML_DSA_SHA384,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_ML_DSA), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_HASH_ML_DSA_SHA512,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_ML_DSA), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_HASH_ML_DSA_SHA3_224,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_ML_DSA), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_HASH_ML_DSA_SHA3_256,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_ML_DSA), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_HASH_ML_DSA_SHA3_384,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_ML_DSA), restrict!()],
genflags: 0,
},
FipsMechanism {
mechanism: CKM_HASH_ML_DSA_SHA3_512,
operations: CKF_SIGN | CKF_VERIFY,
restrictions: [restrict!(CKK_ML_DSA), restrict!()],
genflags: 0,
},
],
};
fn size_check(len: usize, sizes: ([usize; 4], (usize, usize))) -> Option<bool> {
let mut size_check: Option<bool> = None;
for size in sizes.0 {
if size != 0 && size_check != Some(true) {
if len == size {
size_check = Some(true);
} else {
size_check = Some(false);
}
}
}
if size_check.is_none() && sizes.1 != (0, 0) {
let (min, max) = sizes.1;
if min != 0 && len < min {
size_check = Some(false);
} else if max != 0 && len > max {
size_check = Some(false);
} else {
size_check = Some(true);
}
}
size_check
}
fn check_key(
obj: &Object,
op: CK_FLAGS,
genflags: Option<CK_FLAGS>,
restrictions: Option<&[(CK_KEY_TYPE, ([usize; 4], (usize, usize))); 2]>,
) -> bool {
let key_type = match obj.get_attr_as_ulong(CKA_KEY_TYPE) {
Ok(k) => k,
Err(_) => return false,
};
let keylen = match key_type {
CKK_RSA => match obj.get_attr_as_bytes(CKA_MODULUS) {
Ok(m) => m.len(),
Err(_) => return false,
},
CKK_EC | CKK_EC_EDWARDS => match get_oid_from_obj(obj) {
Ok(oid) => match oid_to_bits(oid) {
Ok(l) => btb!(l),
Err(_) => return false,
},
Err(_) => return false,
},
_ => {
match obj.get_attr_as_ulong(CKA_VALUE_LEN) {
Ok(l) => usize::try_from(l).unwrap(),
Err(_) => return false,
}
}
};
if let Some(gf) = genflags {
for f in [
CKF_SIGN,
CKF_VERIFY,
CKF_ENCRYPT,
CKF_DECRYPT,
CKF_WRAP,
CKF_UNWRAP,
CKF_DERIVE,
] {
if gf & f == 0 {
let attr = match flag_to_op(f) {
Ok(a) => a,
Err(_) => return false,
};
match obj.get_attr_as_bool(attr) {
Ok(b) => {
if b {
return false;
}
}
Err(_) => (),
}
}
}
}
if let Some(restr) = restrictions {
let mut key_passes = false;
for r in restr {
if r.0 != KRY_UNSPEC && r.0 != key_type {
continue;
}
match size_check(keylen, r.1) {
Some(b) => {
if b {
key_passes = true
} else {
return false;
}
}
None => key_passes = true,
}
}
if !key_passes {
return false;
}
}
for k in &FIPS_CHECKS.keys {
if k.keytype != key_type {
continue;
}
if k.operations & op != 0 {
if match size_check(keylen, k.sizes) {
None => false,
Some(v) => v,
} == true
{
return true;
}
}
}
false
}
fn has_fips_flag(key: &Object) -> bool {
if let Ok(f) = key.get_attr_as_ulong(CKA_OBJECT_VALIDATION_FLAGS) {
if (f & KRF_FIPS) == KRF_FIPS {
return true;
}
}
false
}
fn add_fips_flag(key: &mut Object) {
let flag = match key.get_attr_as_ulong(CKA_OBJECT_VALIDATION_FLAGS) {
Ok(f) => f,
Err(_) => 0,
} | KRF_FIPS;
let _ =
key.set_attr(Attribute::from_ulong(CKA_OBJECT_VALIDATION_FLAGS, flag));
}
pub fn is_key_approved(key: &Object, op: CK_FLAGS) -> bool {
if has_fips_flag(key) {
return true;
}
check_key(key, op, None, None)
}
pub fn add_missing_validation_flag(key: &mut Object) {
if let Ok(_) = key.get_attr_as_ulong(CKA_OBJECT_VALIDATION_FLAGS) {
return;
}
if is_key_approved(key, CK_UNAVAILABLE_INFORMATION) {
add_fips_flag(key);
}
}
pub fn is_approved(
mechanism: CK_MECHANISM_TYPE,
op: CK_FLAGS,
iobj: Option<&Object>,
mut oobj: Option<&mut Object>,
) -> bool {
let checks = match op {
CKF_DIGEST => 0,
CKF_SIGN | CKF_VERIFY | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP => 1,
CKF_GENERATE | CKF_GENERATE_KEY_PAIR => 2,
CKF_UNWRAP | CKF_DERIVE => 3,
_ => return false,
};
for m in &FIPS_CHECKS.mechs {
if mechanism != m.mechanism {
continue;
}
if m.operations & op == 0 {
return false;
}
if checks == 0 {
return true;
}
if checks & 1 == 1 {
let valid_key = if let Some(obj) = iobj {
is_key_approved(obj, op)
} else {
false
};
if !valid_key {
return false;
}
if checks == 1 {
return true;
}
}
if checks & 2 == 2 {
if let Some(ref mut obj) = oobj {
if check_key(
obj,
CK_UNAVAILABLE_INFORMATION,
Some(m.genflags),
Some(&m.restrictions),
) {
add_fips_flag(obj);
return true;
} else {
if mechanism == CKM_HKDF_DATA {
if let Ok(val) = obj.get_attr_as_bytes(CKA_VALUE) {
let len = val.len();
match size_check(len, m.restrictions[0].1) {
Some(true) => return true,
_ => return false,
}
}
}
}
}
}
}
false
}