use crate::attribute::Attribute;
use crate::ec::get_ec_point_from_obj;
use crate::error::Result;
use crate::object::Object;
use crate::ossl::common::{get_evp_pkey_type_from_obj, osslctx};
use crate::pkcs11::*;
use ossl::pkey::{EccData, EvpPkey, PkeyData};
use ossl::OsslSecret;
pub fn ecm_object_to_pkey(
key: &Object,
class: CK_OBJECT_CLASS,
) -> Result<EvpPkey> {
let kclass = key.get_attr_as_ulong(CKA_CLASS)?;
if kclass != class {
return Err(CKR_KEY_TYPE_INCONSISTENT)?;
}
match kclass {
CKO_PUBLIC_KEY => Ok(EvpPkey::import(
osslctx(),
get_evp_pkey_type_from_obj(key)?,
PkeyData::Ecc(EccData {
pubkey: Some(get_ec_point_from_obj(key)?),
prikey: None,
}),
)?),
CKO_PRIVATE_KEY => Ok(EvpPkey::import(
osslctx(),
get_evp_pkey_type_from_obj(key)?,
PkeyData::Ecc(EccData {
pubkey: None,
prikey: Some(OsslSecret::from_vec(
key.get_attr_as_bytes(CKA_VALUE)?.clone(),
)),
}),
)?),
_ => Err(CKR_KEY_TYPE_INCONSISTENT)?,
}
}
#[derive(Debug)]
pub struct ECMontgomeryOperation {}
impl ECMontgomeryOperation {
pub fn generate_keypair(
pubkey: &mut Object,
privkey: &mut Object,
) -> Result<()> {
let pkey =
EvpPkey::generate(osslctx(), get_evp_pkey_type_from_obj(pubkey)?)?;
let mut ecc = match pkey.export()? {
PkeyData::Ecc(e) => e,
_ => return Err(CKR_GENERAL_ERROR)?,
};
if let Some(key) = ecc.pubkey.take() {
pubkey.set_attr(Attribute::from_bytes(
CKA_EC_POINT,
(&key).to_vec(),
))?;
} else {
return Err(CKR_DEVICE_ERROR)?;
}
if let Some(key) = ecc.prikey.take() {
privkey
.set_attr(Attribute::from_bytes(CKA_VALUE, (&key).to_vec()))?;
} else {
return Err(CKR_DEVICE_ERROR)?;
}
Ok(())
}
}