use std::fmt::Debug;
use std::sync::LazyLock;
use crate::attribute::{Attribute, CkAttrs};
use crate::error::Result;
use crate::kasn1::{pkcs, DerEncBigUint, PrivateKeyInfo};
use crate::mechanism::*;
use crate::object::*;
use crate::ossl::rsa::*;
use crate::pkcs11::*;
use asn1;
static RSA_MECHS: LazyLock<[Box<dyn Mechanism>; 4]> = LazyLock::new(|| {
[
Box::new(RsaPKCSMechanism {
info: CK_MECHANISM_INFO {
ulMinKeySize: CK_ULONG::try_from(MIN_RSA_SIZE_BITS).unwrap(),
ulMaxKeySize: CK_ULONG::try_from(MAX_RSA_SIZE_BITS).unwrap(),
flags: CKF_ENCRYPT
| CKF_DECRYPT
| CKF_SIGN
| CKF_VERIFY
| CKF_WRAP
| CKF_UNWRAP,
},
}),
Box::new(RsaPKCSMechanism {
info: CK_MECHANISM_INFO {
ulMinKeySize: CK_ULONG::try_from(MIN_RSA_SIZE_BITS).unwrap(),
ulMaxKeySize: CK_ULONG::try_from(MAX_RSA_SIZE_BITS).unwrap(),
flags: CKF_SIGN | CKF_VERIFY,
},
}),
Box::new(RsaPKCSMechanism {
info: CK_MECHANISM_INFO {
ulMinKeySize: CK_ULONG::try_from(MIN_RSA_SIZE_BITS).unwrap(),
ulMaxKeySize: CK_ULONG::try_from(MAX_RSA_SIZE_BITS).unwrap(),
flags: CKF_GENERATE_KEY_PAIR,
},
}),
Box::new(RsaPKCSMechanism {
info: CK_MECHANISM_INFO {
ulMinKeySize: CK_ULONG::try_from(MIN_RSA_SIZE_BITS).unwrap(),
ulMaxKeySize: CK_ULONG::try_from(MAX_RSA_SIZE_BITS).unwrap(),
flags: CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP,
},
}),
]
});
static PUBLIC_KEY_FACTORY: LazyLock<Box<dyn ObjectFactory>> =
LazyLock::new(|| Box::new(RSAPubFactory::new()));
static PRIVATE_KEY_FACTORY: LazyLock<Box<dyn ObjectFactory>> =
LazyLock::new(|| Box::new(RSAPrivFactory::new()));
pub fn register(mechs: &mut Mechanisms, ot: &mut ObjectFactories) {
for ckm in &[CKM_RSA_X_509, CKM_RSA_PKCS] {
mechs.add_mechanism(*ckm, &RSA_MECHS[0]);
}
for ckm in &[
#[cfg(not(feature = "no_sha1"))]
CKM_SHA1_RSA_PKCS,
CKM_SHA224_RSA_PKCS,
CKM_SHA256_RSA_PKCS,
CKM_SHA384_RSA_PKCS,
CKM_SHA512_RSA_PKCS,
CKM_SHA3_224_RSA_PKCS,
CKM_SHA3_256_RSA_PKCS,
CKM_SHA3_384_RSA_PKCS,
CKM_SHA3_512_RSA_PKCS,
CKM_RSA_PKCS_PSS,
#[cfg(not(feature = "no_sha1"))]
CKM_SHA1_RSA_PKCS_PSS,
CKM_SHA224_RSA_PKCS_PSS,
CKM_SHA256_RSA_PKCS_PSS,
CKM_SHA384_RSA_PKCS_PSS,
CKM_SHA512_RSA_PKCS_PSS,
CKM_SHA3_224_RSA_PKCS_PSS,
CKM_SHA3_256_RSA_PKCS_PSS,
CKM_SHA3_384_RSA_PKCS_PSS,
CKM_SHA3_512_RSA_PKCS_PSS,
] {
mechs.add_mechanism(*ckm, &RSA_MECHS[1]);
}
mechs.add_mechanism(CKM_RSA_PKCS_KEY_PAIR_GEN, &RSA_MECHS[2]);
mechs.add_mechanism(CKM_RSA_PKCS_OAEP, &RSA_MECHS[3]);
ot.add_factory(
ObjectType::new(CKO_PUBLIC_KEY, CKK_RSA),
&PUBLIC_KEY_FACTORY,
);
ot.add_factory(
ObjectType::new(CKO_PRIVATE_KEY, CKK_RSA),
&PRIVATE_KEY_FACTORY,
);
}
#[allow(unused_macros)]
macro_rules! bytes_attr_not_empty {
($obj:expr; $id:expr) => {
match $obj.get_attr_as_bytes($id) {
Ok(e) => {
if e.len() == 0 {
return Err(CKR_ATTRIBUTE_VALUE_INVALID)?;
}
}
Err(e) => {
if e.attr_not_found() {
return Err(CKR_TEMPLATE_INCOMPLETE)?;
} else {
return Err(e);
}
}
}
};
}
fn rsa_check_import(obj: &Object) -> Result<()> {
let modulus = match obj.get_attr_as_bytes(CKA_MODULUS) {
Ok(m) => m,
Err(_) => return Err(CKR_TEMPLATE_INCOMPLETE)?,
};
match obj.get_attr_as_ulong(CKA_MODULUS_BITS) {
Ok(b) => {
let len = usize::try_from((b + 7) / 8)?;
if modulus.len() != len {
return Err(CKR_TEMPLATE_INCONSISTENT)?;
}
}
Err(e) => {
if !e.attr_not_found() {
return Err(e);
}
}
}
if modulus.len() < MIN_RSA_SIZE_BYTES {
return Err(CKR_ATTRIBUTE_VALUE_INVALID)?;
}
match obj.get_attr_as_ulong(CKA_CLASS) {
Ok(c) => match c {
CKO_PUBLIC_KEY => {
bytes_attr_not_empty!(obj; CKA_PUBLIC_EXPONENT);
}
CKO_PRIVATE_KEY => {
bytes_attr_not_empty!(obj; CKA_PUBLIC_EXPONENT);
bytes_attr_not_empty!(obj; CKA_PRIVATE_EXPONENT);
}
_ => return Err(CKR_ATTRIBUTE_VALUE_INVALID)?,
},
Err(_) => return Err(CKR_TEMPLATE_INCOMPLETE)?,
}
Ok(())
}
fn rsa_check_public_key_info(obj: &mut Object) -> Result<()> {
let modulus = obj.get_attr_as_bytes(CKA_MODULUS)?;
let pubexp = obj.get_attr_as_bytes(CKA_PUBLIC_EXPONENT)?;
let rsa_pub_key = pkcs::RsaPublicKey::new(modulus, pubexp)?.serialize()?;
obj.ensure_bytes(
CKA_PUBLIC_KEY_INFO,
pkcs::SubjectPublicKeyInfo::new(pkcs::RSA_ALG, &rsa_pub_key)?
.serialize()?,
)?;
Ok(())
}
#[derive(Debug)]
pub struct RSAPubFactory {
data: ObjectFactoryData,
}
impl RSAPubFactory {
pub fn new() -> RSAPubFactory {
let mut factory: RSAPubFactory = RSAPubFactory {
data: ObjectFactoryData::new(CKO_PUBLIC_KEY),
};
factory.add_common_public_key_attrs();
let attributes = factory.data.get_attributes_mut();
attributes.push(attr_element!(
CKA_MODULUS; OAFlags::RequiredOnCreate | OAFlags::Unchangeable;
Attribute::from_bytes; val Vec::new()));
attributes.push(attr_element!(
CKA_MODULUS_BITS; OAFlags::RequiredOnGenerate
| OAFlags::Unchangeable; Attribute::from_ulong; val 0));
attributes.push(attr_element!(
CKA_PUBLIC_EXPONENT; OAFlags::RequiredOnCreate
| OAFlags::Unchangeable; Attribute::from_bytes; val Vec::new()));
factory.data.finalize();
factory
}
}
impl ObjectFactory for RSAPubFactory {
fn create(&self, template: &[CK_ATTRIBUTE]) -> Result<Object> {
let mut obj = self.key_create(template)?;
rsa_check_import(&mut obj)?;
rsa_check_public_key_info(&mut obj)?;
Ok(obj)
}
fn get_data(&self) -> &ObjectFactoryData {
&self.data
}
fn get_data_mut(&mut self) -> &mut ObjectFactoryData {
&mut self.data
}
fn as_key_factory(&self) -> Result<&dyn KeyFactory> {
Ok(self)
}
fn as_public_key_factory(&self) -> Result<&dyn PubKeyFactory> {
Ok(self)
}
}
impl KeyFactory for RSAPubFactory {}
impl PubKeyFactory for RSAPubFactory {
fn pub_from_private(
&self,
key: &Object,
template: CkAttrs,
) -> Result<Object> {
let mut template: CkAttrs<'_> = template;
if let Some(modulus) = key.get_attr(CKA_MODULUS) {
template.add_slice(CKA_MODULUS, modulus.get_value().as_slice())?;
} else {
return Err(CKR_KEY_UNEXTRACTABLE)?;
}
if let Some(pubexp) = key.get_attr(CKA_PUBLIC_EXPONENT) {
template.add_slice(
CKA_PUBLIC_EXPONENT,
pubexp.get_value().as_slice(),
)?;
} else {
return Err(CKR_KEY_UNEXTRACTABLE)?;
}
self.create(template.as_slice())
}
}
type Version = u64;
#[derive(asn1::Asn1Read, asn1::Asn1Write)]
struct OtherPrimeInfo<'a> {
prime: DerEncBigUint<'a>,
exponent: DerEncBigUint<'a>,
coefficient: DerEncBigUint<'a>,
}
#[derive(asn1::Asn1Read, asn1::Asn1Write)]
struct RSAPrivateKey<'a> {
version: Version,
modulus: DerEncBigUint<'a>,
public_exponent: DerEncBigUint<'a>,
private_exponent: DerEncBigUint<'a>,
prime1: DerEncBigUint<'a>,
prime2: DerEncBigUint<'a>,
exponent1: DerEncBigUint<'a>,
exponent2: DerEncBigUint<'a>,
coefficient: DerEncBigUint<'a>,
other_prime_infos: Option<asn1::SequenceOf<'a, OtherPrimeInfo<'a>>>,
}
impl RSAPrivateKey<'_> {
pub fn new_owned<'a>(
modulus: &'a Vec<u8>,
public_exponent: &'a Vec<u8>,
private_exponent: &'a Vec<u8>,
prime1: &'a Vec<u8>,
prime2: &'a Vec<u8>,
exponent1: &'a Vec<u8>,
exponent2: &'a Vec<u8>,
coefficient: &'a Vec<u8>,
) -> Result<RSAPrivateKey<'a>> {
Ok(RSAPrivateKey {
version: 0,
modulus: DerEncBigUint::new(modulus.as_slice())?,
public_exponent: DerEncBigUint::new(public_exponent.as_slice())?,
private_exponent: DerEncBigUint::new(private_exponent.as_slice())?,
prime1: DerEncBigUint::new(prime1.as_slice())?,
prime2: DerEncBigUint::new(prime2.as_slice())?,
exponent1: DerEncBigUint::new(exponent1.as_slice())?,
exponent2: DerEncBigUint::new(exponent2.as_slice())?,
coefficient: DerEncBigUint::new(coefficient.as_slice())?,
other_prime_infos: None,
})
}
}
#[derive(Debug)]
pub struct RSAPrivFactory {
data: ObjectFactoryData,
}
impl RSAPrivFactory {
pub fn new() -> RSAPrivFactory {
let mut factory: RSAPrivFactory = RSAPrivFactory {
data: ObjectFactoryData::new(CKO_PRIVATE_KEY),
};
factory.add_common_private_key_attrs();
let attributes = factory.data.get_attributes_mut();
attributes.push(attr_element!(
CKA_MODULUS; OAFlags::RequiredOnCreate | OAFlags::Unchangeable;
Attribute::from_bytes; val Vec::new()));
attributes.push(attr_element!(
CKA_PUBLIC_EXPONENT; OAFlags::RequiredOnCreate
| OAFlags::Unchangeable; Attribute::from_bytes; val Vec::new()));
attributes.push(attr_element!(
CKA_PRIVATE_EXPONENT; OAFlags::Sensitive
| OAFlags::RequiredOnCreate | OAFlags::SettableOnlyOnCreate
| OAFlags::Unchangeable; Attribute::from_bytes; val Vec::new()));
attributes.push(attr_element!(
CKA_PRIME_1; OAFlags::Sensitive | OAFlags::SettableOnlyOnCreate
| OAFlags::Unchangeable; Attribute::from_bytes; val Vec::new()));
attributes.push(attr_element!(
CKA_PRIME_2; OAFlags::Sensitive | OAFlags::SettableOnlyOnCreate
| OAFlags::Unchangeable; Attribute::from_bytes; val Vec::new()));
attributes.push(attr_element!(
CKA_EXPONENT_1; OAFlags::Sensitive | OAFlags::SettableOnlyOnCreate
| OAFlags::Unchangeable; Attribute::from_bytes; val Vec::new()));
attributes.push(attr_element!(
CKA_EXPONENT_2; OAFlags::Sensitive | OAFlags::SettableOnlyOnCreate
| OAFlags::Unchangeable; Attribute::from_bytes; val Vec::new()));
attributes.push(attr_element!(
CKA_COEFFICIENT; OAFlags::Sensitive | OAFlags::SettableOnlyOnCreate
| OAFlags::Unchangeable; Attribute::from_bytes; val Vec::new()));
factory.data.finalize();
factory
}
}
impl ObjectFactory for RSAPrivFactory {
fn create(&self, template: &[CK_ATTRIBUTE]) -> Result<Object> {
let mut obj = self.key_create(template)?;
rsa_check_import(&mut obj)?;
rsa_check_public_key_info(&mut obj)?;
Ok(obj)
}
fn get_data(&self) -> &ObjectFactoryData {
&self.data
}
fn get_data_mut(&mut self) -> &mut ObjectFactoryData {
&mut self.data
}
fn as_key_factory(&self) -> Result<&dyn KeyFactory> {
Ok(self)
}
}
impl KeyFactory for RSAPrivFactory {
fn export_for_wrapping(&self, key: &Object) -> Result<Vec<u8>> {
key.check_key_ops(CKO_PRIVATE_KEY, CKK_RSA, CKA_EXTRACTABLE)?;
let pkey = match asn1::write_single(&RSAPrivateKey::new_owned(
key.get_attr_as_bytes(CKA_MODULUS)?,
key.get_attr_as_bytes(CKA_PUBLIC_EXPONENT)?,
key.get_attr_as_bytes(CKA_PRIVATE_EXPONENT)?,
key.get_attr_as_bytes(CKA_PRIME_1)?,
key.get_attr_as_bytes(CKA_PRIME_2)?,
key.get_attr_as_bytes(CKA_EXPONENT_1)?,
key.get_attr_as_bytes(CKA_EXPONENT_2)?,
key.get_attr_as_bytes(CKA_COEFFICIENT)?,
)?) {
Ok(p) => p,
_ => return Err(CKR_GENERAL_ERROR)?,
};
let pkeyinfo = PrivateKeyInfo::new(&pkey.as_slice(), pkcs::RSA_ALG)?;
match asn1::write_single(&pkeyinfo) {
Ok(x) => Ok(x),
Err(_) => Err(CKR_GENERAL_ERROR)?,
}
}
fn import_from_wrapped(
&self,
data: Vec<u8>,
template: &[CK_ATTRIBUTE],
) -> Result<Object> {
let mut key = self.key_unwrap(template)?;
key.ensure_ulong(CKA_CLASS, CKO_PRIVATE_KEY)?;
key.ensure_ulong(CKA_KEY_TYPE, CKK_RSA)
.map_err(|_| CKR_TEMPLATE_INCONSISTENT)?;
let (tlv, extra) = match asn1::strip_tlv(&data) {
Ok(x) => x,
Err(_) => return Err(CKR_WRAPPED_KEY_INVALID)?,
};
if !extra.iter().all(|b| *b == 0) {
return Err(CKR_WRAPPED_KEY_INVALID)?;
}
let pkeyinfo = match tlv.parse::<PrivateKeyInfo>() {
Ok(k) => k,
Err(_) => return Err(CKR_WRAPPED_KEY_INVALID)?,
};
if pkeyinfo.get_algorithm() != &pkcs::RSA_ALG {
return Err(CKR_WRAPPED_KEY_INVALID)?;
}
let rsapkey = match asn1::parse_single::<RSAPrivateKey>(
pkeyinfo.get_private_key(),
) {
Ok(k) => k,
Err(_) => return Err(CKR_WRAPPED_KEY_INVALID)?,
};
key.ensure_bytes(
CKA_MODULUS,
rsapkey.modulus.as_nopad_bytes().to_vec(),
)?;
key.ensure_bytes(
CKA_PUBLIC_EXPONENT,
rsapkey.public_exponent.as_nopad_bytes().to_vec(),
)?;
key.ensure_bytes(
CKA_PRIVATE_EXPONENT,
rsapkey.private_exponent.as_nopad_bytes().to_vec(),
)?;
key.ensure_bytes(
CKA_PRIME_1,
rsapkey.prime1.as_nopad_bytes().to_vec(),
)?;
key.ensure_bytes(
CKA_PRIME_2,
rsapkey.prime2.as_nopad_bytes().to_vec(),
)?;
key.ensure_bytes(
CKA_EXPONENT_1,
rsapkey.exponent1.as_nopad_bytes().to_vec(),
)?;
key.ensure_bytes(
CKA_EXPONENT_2,
rsapkey.exponent2.as_nopad_bytes().to_vec(),
)?;
key.ensure_bytes(
CKA_COEFFICIENT,
rsapkey.coefficient.as_nopad_bytes().to_vec(),
)?;
rsa_check_public_key_info(&mut key)?;
Ok(key)
}
}
impl PrivKeyFactory for RSAPrivFactory {}
#[derive(Debug)]
struct RsaPKCSMechanism {
info: CK_MECHANISM_INFO,
}
impl Mechanism for RsaPKCSMechanism {
fn info(&self) -> &CK_MECHANISM_INFO {
&self.info
}
fn encryption_new(
&self,
mech: &CK_MECHANISM,
key: &Object,
) -> Result<Box<dyn Encryption>> {
if self.info.flags & CKF_ENCRYPT != CKF_ENCRYPT {
return Err(CKR_MECHANISM_INVALID)?;
}
match key.check_key_ops(CKO_PUBLIC_KEY, CKK_RSA, CKA_ENCRYPT) {
Ok(_) => (),
Err(e) => return Err(e),
}
Ok(Box::new(RsaPKCSOperation::encrypt_new(
mech, key, &self.info,
)?))
}
fn decryption_new(
&self,
mech: &CK_MECHANISM,
key: &Object,
) -> Result<Box<dyn Decryption>> {
if self.info.flags & CKF_DECRYPT != CKF_DECRYPT {
return Err(CKR_MECHANISM_INVALID)?;
}
match key.check_key_ops(CKO_PRIVATE_KEY, CKK_RSA, CKA_DECRYPT) {
Ok(_) => (),
Err(e) => return Err(e),
}
Ok(Box::new(RsaPKCSOperation::decrypt_new(
mech, key, &self.info,
)?))
}
fn sign_new(
&self,
mech: &CK_MECHANISM,
key: &Object,
) -> Result<Box<dyn Sign>> {
if self.info.flags & CKF_SIGN != CKF_SIGN {
return Err(CKR_MECHANISM_INVALID)?;
}
match key.check_key_ops(CKO_PRIVATE_KEY, CKK_RSA, CKA_SIGN) {
Ok(_) => (),
Err(e) => return Err(e),
}
Ok(Box::new(RsaPKCSOperation::sign_new(mech, key, &self.info)?))
}
fn verify_new(
&self,
mech: &CK_MECHANISM,
key: &Object,
) -> Result<Box<dyn Verify>> {
if self.info.flags & CKF_VERIFY != CKF_VERIFY {
return Err(CKR_MECHANISM_INVALID)?;
}
match key.check_key_ops(CKO_PUBLIC_KEY, CKK_RSA, CKA_VERIFY) {
Ok(_) => (),
Err(e) => return Err(e),
}
Ok(Box::new(RsaPKCSOperation::verify_new(
mech, key, &self.info,
)?))
}
fn verify_signature_new(
&self,
mech: &CK_MECHANISM,
key: &Object,
signature: &[u8],
) -> Result<Box<dyn VerifySignature>> {
if self.info.flags & CKF_VERIFY != CKF_VERIFY {
return Err(CKR_MECHANISM_INVALID)?;
}
match key.check_key_ops(CKO_PUBLIC_KEY, CKK_RSA, CKA_VERIFY) {
Ok(_) => (),
Err(e) => return Err(e),
}
Ok(Box::new(RsaPKCSOperation::verify_signature_new(
mech, key, &self.info, signature,
)?))
}
fn generate_keypair(
&self,
mech: &CK_MECHANISM,
pubkey_template: &[CK_ATTRIBUTE],
prikey_template: &[CK_ATTRIBUTE],
) -> Result<(Object, Object)> {
let mut pubkey = PUBLIC_KEY_FACTORY
.as_key_factory()?
.key_generate(pubkey_template)?;
pubkey
.ensure_ulong(CKA_CLASS, CKO_PUBLIC_KEY)
.map_err(|_| CKR_TEMPLATE_INCONSISTENT)?;
pubkey
.ensure_ulong(CKA_KEY_TYPE, CKK_RSA)
.map_err(|_| CKR_TEMPLATE_INCONSISTENT)?;
let bits =
usize::try_from(pubkey.get_attr_as_ulong(CKA_MODULUS_BITS)?)?;
let exponent: Vec<u8> = match pubkey.get_attr(CKA_PUBLIC_EXPONENT) {
Some(a) => a.get_value().clone(),
None => {
pubkey.set_attr(Attribute::from_bytes(
CKA_PUBLIC_EXPONENT,
vec![0x01, 0x00, 0x01],
))?;
pubkey.get_attr_as_bytes(CKA_PUBLIC_EXPONENT)?.clone()
}
};
let mut privkey = PRIVATE_KEY_FACTORY
.as_key_factory()?
.key_generate(prikey_template)?;
privkey
.ensure_ulong(CKA_CLASS, CKO_PRIVATE_KEY)
.map_err(|_| CKR_TEMPLATE_INCONSISTENT)?;
privkey
.ensure_ulong(CKA_KEY_TYPE, CKK_RSA)
.map_err(|_| CKR_TEMPLATE_INCONSISTENT)?;
RsaPKCSOperation::generate_keypair(
exponent,
bits,
&mut pubkey,
&mut privkey,
)?;
default_key_attributes(&mut privkey, mech.mechanism)?;
default_key_attributes(&mut pubkey, mech.mechanism)?;
rsa_check_public_key_info(&mut pubkey)?;
privkey.ensure_slice(
CKA_PUBLIC_KEY_INFO,
pubkey.get_attr_as_bytes(CKA_PUBLIC_KEY_INFO)?,
)?;
Ok((pubkey, privkey))
}
fn wrap_key(
&self,
mech: &CK_MECHANISM,
wrapping_key: &Object,
key: &Object,
data: &mut [u8],
key_template: &Box<dyn ObjectFactory>,
) -> Result<usize> {
if self.info.flags & CKF_WRAP != CKF_WRAP {
return Err(CKR_MECHANISM_INVALID)?;
}
RsaPKCSOperation::wrap(
mech,
wrapping_key,
key_template.as_key_factory()?.export_for_wrapping(key)?,
data,
&self.info,
)
}
fn unwrap_key(
&self,
mech: &CK_MECHANISM,
wrapping_key: &Object,
data: &[u8],
template: &[CK_ATTRIBUTE],
key_template: &Box<dyn ObjectFactory>,
) -> Result<Object> {
if self.info.flags & CKF_UNWRAP != CKF_UNWRAP {
return Err(CKR_MECHANISM_INVALID)?;
}
let keydata =
RsaPKCSOperation::unwrap(mech, wrapping_key, data, &self.info)?;
key_template
.as_key_factory()?
.import_from_wrapped(keydata, template)
}
}