use super::constants::*;
use super::psa_crypto_binding::{
self, psa_algorithm_t, psa_core_key_attributes_t, psa_key_attributes_t, psa_key_bits_t,
psa_key_handle_t, psa_key_id_t, psa_key_policy_s, psa_key_type_t, psa_key_usage_t,
psa_status_t,
};
use log::error;
use parsec_interface::operations::key_attributes;
use parsec_interface::operations::key_attributes::{
Algorithm, AlgorithmInner, HashAlgorithm, KeyType, SignAlgorithm,
};
use parsec_interface::requests::{ResponseStatus, Result};
use std::convert::TryFrom;
use std::convert::TryInto;
pub fn convert_key_attributes(
attrs: &key_attributes::KeyAttributes,
key_id: psa_key_id_t,
) -> Result<psa_key_attributes_t> {
Ok(psa_key_attributes_t {
core: psa_core_key_attributes_t {
type_: convert_key_type(attrs.key_type)?,
lifetime: PSA_KEY_LIFETIME_PERSISTENT,
id: key_id,
policy: psa_key_policy_s {
usage: convert_key_usage(&attrs),
alg: convert_algorithm(&attrs.algorithm)?,
alg2: 0,
},
bits: convert_key_bits(attrs.key_size),
flags: 0,
},
domain_parameters: ::std::ptr::null_mut(),
domain_parameters_size: 0,
})
}
pub fn get_empty_key_attributes() -> psa_key_attributes_t {
psa_key_attributes_t {
core: psa_core_key_attributes_t {
type_: 0,
lifetime: 0,
id: 0,
policy: psa_key_policy_s {
usage: 0,
alg: 0,
alg2: 0,
},
bits: 0,
flags: 0,
},
domain_parameters: ::std::ptr::null_mut(),
domain_parameters_size: 0,
}
}
pub fn convert_key_bits(key_size: u32) -> psa_key_bits_t {
psa_key_bits_t::try_from(key_size).unwrap_or(PSA_KEY_BITS_TOO_LARGE)
}
pub fn convert_key_type(key_type: KeyType) -> Result<psa_key_type_t> {
match key_type {
KeyType::RsaKeypair => Ok(PSA_KEY_TYPE_RSA_KEYPAIR),
KeyType::RsaPublicKey => Ok(PSA_KEY_TYPE_RSA_PUBLIC_KEY),
_ => Err(ResponseStatus::PsaErrorNotSupported),
}
}
pub fn convert_key_usage(operation: &key_attributes::KeyAttributes) -> psa_key_usage_t {
let mut usage: psa_key_usage_t = 0;
if operation.permit_decrypt {
usage |= PSA_KEY_USAGE_DECRYPT;
}
if operation.permit_encrypt {
usage |= PSA_KEY_USAGE_ENCRYPT;
}
if operation.permit_export {
usage |= PSA_KEY_USAGE_EXPORT;
}
if operation.permit_sign {
usage |= PSA_KEY_USAGE_SIGN;
}
if operation.permit_verify {
usage |= PSA_KEY_USAGE_VERIFY;
}
if operation.permit_derive {
usage |= PSA_KEY_USAGE_DERIVE;
}
usage
}
pub fn convert_algorithm(alg: &Algorithm) -> Result<psa_algorithm_t> {
let mut algo_val: psa_algorithm_t;
match alg.inner() {
AlgorithmInner::Sign(sign, hash) => {
algo_val = match sign {
SignAlgorithm::RsaPkcs1v15Sign => PSA_ALG_RSA_PKCS1V15_SIGN_BASE,
_ => return Err(ResponseStatus::PsaErrorNotSupported),
};
if let Some(hash_alg) = hash {
algo_val |= convert_hash_algorithm(*hash_alg) & PSA_ALG_HASH_MASK;
}
}
_ => return Err(ResponseStatus::PsaErrorNotSupported),
}
Ok(algo_val)
}
pub fn convert_hash_algorithm(hash: HashAlgorithm) -> psa_algorithm_t {
match hash {
HashAlgorithm::Md2 => PSA_ALG_MD2,
HashAlgorithm::Md4 => PSA_ALG_MD4,
HashAlgorithm::Md5 => PSA_ALG_MD5,
HashAlgorithm::Ripemd160 => PSA_ALG_RIPEMD160,
HashAlgorithm::Sha1 => PSA_ALG_SHA_1,
HashAlgorithm::Sha224 => PSA_ALG_SHA_224,
HashAlgorithm::Sha256 => PSA_ALG_SHA_256,
HashAlgorithm::Sha384 => PSA_ALG_SHA_384,
HashAlgorithm::Sha512 => PSA_ALG_SHA_512,
HashAlgorithm::Sha512224 => PSA_ALG_SHA_512_224,
HashAlgorithm::Sha512256 => PSA_ALG_SHA_512_256,
HashAlgorithm::Sha3224 => PSA_ALG_SHA3_224,
HashAlgorithm::Sha3256 => PSA_ALG_SHA3_256,
HashAlgorithm::Sha3384 => PSA_ALG_SHA3_384,
HashAlgorithm::Sha3512 => PSA_ALG_SHA3_512,
}
}
const PSA_STATUS_TO_RESPONSE_STATUS_OFFSET: psa_status_t = 1000;
pub fn convert_status(psa_status: psa_status_t) -> ResponseStatus {
let psa_status = match psa_status.checked_abs() {
Some(status) => status,
None => return ResponseStatus::InvalidEncoding,
};
let psa_status = match psa_status.checked_add(PSA_STATUS_TO_RESPONSE_STATUS_OFFSET) {
Some(status) => status,
None => return ResponseStatus::InvalidEncoding,
};
let psa_status = match u16::try_from(psa_status) {
Ok(status) => status,
Err(_) => return ResponseStatus::InvalidEncoding,
};
psa_status
.try_into()
.unwrap_or(ResponseStatus::InvalidEncoding)
}
macro_rules! bits_to_bytes {
($size:expr) => {
($size + 7) / 8
};
}
pub fn psa_asymmetric_sign_output_size(key_attrs: &psa_key_attributes_t) -> Result<usize> {
match key_attrs.core.type_ {
PSA_KEY_TYPE_RSA_KEYPAIR => Ok(usize::from(bits_to_bytes!(key_attrs.core.bits))),
PSA_KEY_TYPE_ECC_KEYPAIR_BASE => Ok(usize::from(bits_to_bytes!(key_attrs.core.bits) * 2)),
_ => Err(ResponseStatus::PsaErrorNotSupported),
}
}
pub fn psa_export_public_key_size(key_attrs: &psa_key_attributes_t) -> Result<usize> {
macro_rules! export_asn1_int_max_size {
($size:expr) => {
($size) / 8 + 5
};
};
match key_attrs.core.type_ {
PSA_KEY_TYPE_RSA_PUBLIC_KEY | PSA_KEY_TYPE_RSA_KEYPAIR => Ok(usize::from(
export_asn1_int_max_size!(key_attrs.core.bits) + 11,
)),
_ => Err(ResponseStatus::PsaErrorNotSupported),
}
}
pub struct KeyAttributes(psa_key_attributes_t);
impl KeyAttributes {
pub unsafe fn reset(&mut self) {
psa_crypto_binding::psa_reset_key_attributes(&mut self.0);
}
pub fn raw(&self) -> psa_key_attributes_t {
self.0
}
}
impl AsRef<psa_key_attributes_t> for KeyAttributes {
fn as_ref(&self) -> &psa_key_attributes_t {
&self.0
}
}
impl AsMut<psa_key_attributes_t> for KeyAttributes {
fn as_mut(&mut self) -> &mut psa_key_attributes_t {
&mut self.0
}
}
pub struct KeyHandle(psa_key_handle_t);
impl KeyHandle {
pub unsafe fn open(key_id: psa_key_id_t) -> Result<KeyHandle> {
let mut key_handle: psa_key_handle_t = Default::default();
let open_key_status = psa_crypto_binding::psa_open_key(key_id, &mut key_handle);
if open_key_status != PSA_SUCCESS {
error!("Open key status: {}", open_key_status);
Err(convert_status(open_key_status))
} else {
Ok(KeyHandle(key_handle))
}
}
pub unsafe fn generate(attributes: &psa_key_attributes_t) -> Result<Self> {
let mut key_handle: psa_key_handle_t = Default::default();
let status = psa_crypto_binding::psa_generate_key(attributes, &mut key_handle);
if status != PSA_SUCCESS {
error!("Generate key status: {}", status);
Err(convert_status(status))
} else {
Ok(KeyHandle(key_handle))
}
}
pub unsafe fn import(attributes: &psa_key_attributes_t, key_data: Vec<u8>) -> Result<Self> {
let mut key_handle: psa_key_handle_t = Default::default();
let status = psa_crypto_binding::psa_import_key(
attributes,
key_data.as_ptr(),
key_data.len(),
&mut key_handle,
);
if status != PSA_SUCCESS {
error!("Import key status: {}", status);
Err(convert_status(status))
} else {
Ok(KeyHandle(key_handle))
}
}
pub unsafe fn attributes(&self) -> Result<KeyAttributes> {
let mut key_attrs = get_empty_key_attributes();
let get_attrs_status = psa_crypto_binding::psa_get_key_attributes(self.0, &mut key_attrs);
if get_attrs_status != PSA_SUCCESS {
error!("Get key attributes status: {}", get_attrs_status);
Err(convert_status(get_attrs_status))
} else {
Ok(KeyAttributes(key_attrs))
}
}
pub unsafe fn close(&mut self) -> Result<()> {
let status = psa_crypto_binding::psa_close_key(self.0);
if status != PSA_SUCCESS {
error!("Close key status: {}", status);
Err(convert_status(status))
} else {
Ok(())
}
}
pub fn raw(&self) -> psa_key_handle_t {
self.0
}
}
impl AsRef<psa_key_handle_t> for KeyHandle {
fn as_ref(&self) -> &psa_key_handle_t {
&self.0
}
}
impl AsMut<psa_key_handle_t> for KeyHandle {
fn as_mut(&mut self) -> &mut psa_key_handle_t {
&mut self.0
}
}