#![allow(deprecated)]
#[cfg(feature = "interface")]
use crate::types::status::{Error, Result};
#[cfg(feature = "interface")]
use core::convert::{TryFrom, TryInto};
#[cfg(feature = "interface")]
use log::error;
use serde::{Deserialize, Serialize};
use zeroize::Zeroize;
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Zeroize)]
pub enum Algorithm {
None,
Hash(Hash),
Mac(Mac),
Cipher(Cipher),
Aead(Aead),
AsymmetricSignature(AsymmetricSignature),
AsymmetricEncryption(AsymmetricEncryption),
KeyAgreement(KeyAgreement),
KeyDerivation(KeyDerivation),
}
impl Algorithm {
pub fn is_hmac(self) -> bool {
match self {
Algorithm::Mac(mac_alg) => mac_alg.is_hmac(),
_ => false,
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Zeroize)]
#[allow(deprecated)]
pub enum Hash {
#[deprecated = "The MD2 hash is weak and deprecated and is only recommended for use in legacy protocols."]
Md2,
#[deprecated = "The MD4 hash is weak and deprecated and is only recommended for use in legacy protocols."]
Md4,
#[deprecated = "The MD5 hash is weak and deprecated and is only recommended for use in legacy protocols."]
Md5,
Ripemd160,
#[deprecated = "The SHA-1 hash is weak and deprecated and is only recommended for use in legacy protocols."]
Sha1,
Sha224,
Sha256,
Sha384,
Sha512,
Sha512_224,
Sha512_256,
Sha3_224,
Sha3_256,
Sha3_384,
Sha3_512,
}
impl Hash {
pub fn hash_length(self) -> usize {
match self {
Hash::Md2 | Hash::Md4 | Hash::Md5 => 16,
Hash::Ripemd160 | Hash::Sha1 => 20,
Hash::Sha224 | Hash::Sha512_224 | Hash::Sha3_224 => 28,
Hash::Sha256 | Hash::Sha512_256 | Hash::Sha3_256 => 32,
Hash::Sha384 | Hash::Sha3_384 => 48,
Hash::Sha3_512 | Hash::Sha512 => 64,
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Zeroize)]
pub enum FullLengthMac {
Hmac {
hash_alg: Hash,
},
CbcMac,
Cmac,
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Zeroize)]
pub enum Mac {
FullLength(FullLengthMac),
Truncated {
mac_alg: FullLengthMac,
mac_length: usize,
},
}
impl Mac {
pub fn is_hmac(self) -> bool {
matches!(
self,
Mac::FullLength(FullLengthMac::Hmac { .. })
| Mac::Truncated {
mac_alg: FullLengthMac::Hmac { .. },
..
}
)
}
pub fn is_block_cipher_needed(self) -> bool {
matches!(
self,
Mac::FullLength(FullLengthMac::CbcMac)
| Mac::FullLength(FullLengthMac::Cmac)
| Mac::Truncated {
mac_alg: FullLengthMac::CbcMac,
..
}
| Mac::Truncated {
mac_alg: FullLengthMac::Cmac,
..
}
)
}
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Zeroize)]
#[allow(clippy::pub_enum_variant_names)]
pub enum Cipher {
StreamCipher,
Ctr,
Cfb,
Ofb,
Xts,
EcbNoPadding,
CbcNoPadding,
CbcPkcs7,
}
impl Cipher {
pub fn is_block_cipher_mode(self) -> bool {
matches!(
self,
Cipher::Ctr
| Cipher::Cfb
| Cipher::Ofb
| Cipher::Xts
| Cipher::EcbNoPadding
| Cipher::CbcNoPadding
| Cipher::CbcPkcs7
)
}
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Zeroize)]
pub enum AeadWithDefaultLengthTag {
Ccm,
Gcm,
Chacha20Poly1305,
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Zeroize)]
pub enum Aead {
AeadWithDefaultLengthTag(AeadWithDefaultLengthTag),
AeadWithShortenedTag {
aead_alg: AeadWithDefaultLengthTag,
tag_length: usize,
},
}
impl Aead {
pub fn is_aead_on_block_cipher(self) -> bool {
matches!(
self,
Aead::AeadWithDefaultLengthTag(AeadWithDefaultLengthTag::Ccm)
| Aead::AeadWithDefaultLengthTag(AeadWithDefaultLengthTag::Gcm)
| Aead::AeadWithShortenedTag {
aead_alg: AeadWithDefaultLengthTag::Ccm,
..
}
| Aead::AeadWithShortenedTag {
aead_alg: AeadWithDefaultLengthTag::Gcm,
..
}
)
}
pub fn is_chacha20_poly1305_alg(self) -> bool {
matches!(
self,
Aead::AeadWithDefaultLengthTag(AeadWithDefaultLengthTag::Chacha20Poly1305)
| Aead::AeadWithShortenedTag {
aead_alg: AeadWithDefaultLengthTag::Chacha20Poly1305,
..
}
)
}
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Zeroize)]
pub enum SignHash {
Specific(Hash),
Any,
}
impl SignHash {
pub fn is_alg_permitted(self, alg: SignHash) -> bool {
if let SignHash::Specific(_) = alg {
if self == SignHash::Any {
true
} else {
self == alg
}
} else {
false
}
}
}
impl From<Hash> for SignHash {
fn from(hash: Hash) -> Self {
SignHash::Specific(hash)
}
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Zeroize)]
pub enum AsymmetricSignature {
RsaPkcs1v15Sign {
hash_alg: SignHash,
},
RsaPkcs1v15SignRaw,
RsaPss {
hash_alg: SignHash,
},
Ecdsa {
hash_alg: SignHash,
},
EcdsaAny,
DeterministicEcdsa {
hash_alg: SignHash,
},
}
impl AsymmetricSignature {
pub fn is_alg_permitted(self, alg: AsymmetricSignature) -> bool {
match self {
AsymmetricSignature::RsaPkcs1v15Sign {
hash_alg: hash_policy,
} => {
if let AsymmetricSignature::RsaPkcs1v15Sign { hash_alg } = alg {
hash_policy.is_alg_permitted(hash_alg)
} else {
false
}
}
AsymmetricSignature::RsaPss {
hash_alg: hash_policy,
} => {
if let AsymmetricSignature::RsaPss { hash_alg } = alg {
hash_policy.is_alg_permitted(hash_alg)
} else {
false
}
}
AsymmetricSignature::Ecdsa {
hash_alg: hash_policy,
} => {
if let AsymmetricSignature::Ecdsa { hash_alg } = alg {
hash_policy.is_alg_permitted(hash_alg)
} else {
false
}
}
AsymmetricSignature::DeterministicEcdsa {
hash_alg: hash_policy,
} => {
if let AsymmetricSignature::DeterministicEcdsa { hash_alg } = alg {
hash_policy.is_alg_permitted(hash_alg)
} else {
false
}
}
asymmetric_signature_alg => asymmetric_signature_alg == alg,
}
}
pub fn is_rsa_alg(self) -> bool {
matches!(
self,
AsymmetricSignature::RsaPkcs1v15Sign { .. }
| AsymmetricSignature::RsaPkcs1v15SignRaw
| AsymmetricSignature::RsaPss { .. }
)
}
pub fn is_ecc_alg(self) -> bool {
matches!(
self,
AsymmetricSignature::Ecdsa { .. }
| AsymmetricSignature::EcdsaAny
| AsymmetricSignature::DeterministicEcdsa { .. }
)
}
pub fn is_hash_len_permitted(self, hash_len: usize) -> bool {
match self {
AsymmetricSignature::EcdsaAny | AsymmetricSignature::RsaPkcs1v15SignRaw => true,
AsymmetricSignature::DeterministicEcdsa { hash_alg }
| AsymmetricSignature::RsaPkcs1v15Sign { hash_alg }
| AsymmetricSignature::Ecdsa { hash_alg }
| AsymmetricSignature::RsaPss { hash_alg } => {
if let SignHash::Specific(hash_alg) = hash_alg {
hash_alg.hash_length() == hash_len
} else {
false
}
}
}
}
pub fn hash(self) -> Option<SignHash> {
match self {
AsymmetricSignature::EcdsaAny | AsymmetricSignature::RsaPkcs1v15SignRaw => None,
AsymmetricSignature::DeterministicEcdsa { hash_alg }
| AsymmetricSignature::RsaPkcs1v15Sign { hash_alg }
| AsymmetricSignature::Ecdsa { hash_alg }
| AsymmetricSignature::RsaPss { hash_alg } => Some(hash_alg),
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Zeroize)]
pub enum AsymmetricEncryption {
RsaPkcs1v15Crypt,
RsaOaep {
hash_alg: Hash,
},
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Zeroize)]
pub enum RawKeyAgreement {
Ffdh,
Ecdh,
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Zeroize)]
pub enum KeyAgreement {
Raw(RawKeyAgreement),
WithKeyDerivation {
ka_alg: RawKeyAgreement,
kdf_alg: KeyDerivation,
},
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Zeroize)]
pub enum KeyDerivation {
Hkdf {
hash_alg: Hash,
},
Tls12Prf {
hash_alg: Hash,
},
Tls12PskToMs {
hash_alg: Hash,
},
}
impl From<Hash> for Algorithm {
fn from(alg: Hash) -> Self {
Algorithm::Hash(alg)
}
}
impl From<Mac> for Algorithm {
fn from(alg: Mac) -> Self {
Algorithm::Mac(alg)
}
}
impl From<Cipher> for Algorithm {
fn from(alg: Cipher) -> Self {
Algorithm::Cipher(alg)
}
}
impl From<Aead> for Algorithm {
fn from(alg: Aead) -> Self {
Algorithm::Aead(alg)
}
}
impl From<AsymmetricSignature> for Algorithm {
fn from(alg: AsymmetricSignature) -> Self {
Algorithm::AsymmetricSignature(alg)
}
}
impl From<AsymmetricEncryption> for Algorithm {
fn from(alg: AsymmetricEncryption) -> Self {
Algorithm::AsymmetricEncryption(alg)
}
}
impl From<KeyAgreement> for Algorithm {
fn from(alg: KeyAgreement) -> Self {
Algorithm::KeyAgreement(alg)
}
}
impl From<KeyDerivation> for Algorithm {
fn from(alg: KeyDerivation) -> Self {
Algorithm::KeyDerivation(alg)
}
}
#[cfg(feature = "interface")]
impl TryFrom<psa_crypto_sys::psa_algorithm_t> for Algorithm {
type Error = Error;
fn try_from(alg: psa_crypto_sys::psa_algorithm_t) -> Result<Self> {
if alg == 0 {
Ok(Algorithm::None)
} else if psa_crypto_sys::PSA_ALG_IS_HASH(alg) {
let hash: Hash = alg.try_into()?;
Ok(hash.into())
} else if psa_crypto_sys::PSA_ALG_IS_MAC(alg) {
let mac: Mac = alg.try_into()?;
Ok(mac.into())
} else if psa_crypto_sys::PSA_ALG_IS_CIPHER(alg) {
error!("Cipher algorithms are not supported.");
Err(Error::NotSupported)
} else if psa_crypto_sys::PSA_ALG_IS_AEAD(alg) {
let aead: Aead = alg.try_into()?;
Ok(aead.into())
} else if psa_crypto_sys::PSA_ALG_IS_SIGN(alg) {
let asym_sign: AsymmetricSignature = alg.try_into()?;
Ok(asym_sign.into())
} else if psa_crypto_sys::PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg) {
let asym_encryption: AsymmetricEncryption = alg.try_into()?;
Ok(asym_encryption.into())
} else if psa_crypto_sys::PSA_ALG_IS_KEY_AGREEMENT(alg) {
let key_agreement: KeyAgreement = alg.try_into()?;
Ok(key_agreement.into())
} else if psa_crypto_sys::PSA_ALG_IS_KEY_DERIVATION(alg) {
let key_derivation: KeyDerivation = alg.try_into()?;
Ok(key_derivation.into())
} else {
error!("Can not find a valid Algorithm for {}.", alg);
Err(Error::NotSupported)
}
}
}
#[cfg(feature = "interface")]
impl TryFrom<Algorithm> for psa_crypto_sys::psa_algorithm_t {
type Error = Error;
fn try_from(alg: Algorithm) -> Result<Self> {
match alg {
Algorithm::None => Ok(0),
Algorithm::Hash(hash) => Ok(hash.into()),
Algorithm::AsymmetricSignature(asym_sign) => Ok(asym_sign.into()),
Algorithm::AsymmetricEncryption(asym_encrypt) => Ok(asym_encrypt.into()),
Algorithm::Mac(mac) => Ok(mac.into()),
Algorithm::KeyAgreement(key_agreement) => Ok(key_agreement.into()),
Algorithm::KeyDerivation(key_derivation) => Ok(key_derivation.into()),
Algorithm::Aead(aead) => Ok(aead.into()),
_ => {
error!("Algorithm not supported: {:?}.", alg);
Err(Error::NotSupported)
}
}
}
}
#[cfg(feature = "interface")]
impl TryFrom<psa_crypto_sys::psa_algorithm_t> for Hash {
type Error = Error;
fn try_from(alg: psa_crypto_sys::psa_algorithm_t) -> Result<Self> {
match alg {
psa_crypto_sys::PSA_ALG_MD2 => Ok(Hash::Md2),
psa_crypto_sys::PSA_ALG_MD4 => Ok(Hash::Md4),
psa_crypto_sys::PSA_ALG_MD5 => Ok(Hash::Md5),
psa_crypto_sys::PSA_ALG_RIPEMD160 => Ok(Hash::Ripemd160),
psa_crypto_sys::PSA_ALG_SHA_1 => Ok(Hash::Sha1),
psa_crypto_sys::PSA_ALG_SHA_224 => Ok(Hash::Sha224),
psa_crypto_sys::PSA_ALG_SHA_256 => Ok(Hash::Sha256),
psa_crypto_sys::PSA_ALG_SHA_384 => Ok(Hash::Sha384),
psa_crypto_sys::PSA_ALG_SHA_512 => Ok(Hash::Sha512),
psa_crypto_sys::PSA_ALG_SHA_512_224 => Ok(Hash::Sha512_224),
psa_crypto_sys::PSA_ALG_SHA_512_256 => Ok(Hash::Sha512_256),
psa_crypto_sys::PSA_ALG_SHA3_224 => Ok(Hash::Sha3_224),
psa_crypto_sys::PSA_ALG_SHA3_256 => Ok(Hash::Sha3_256),
psa_crypto_sys::PSA_ALG_SHA3_384 => Ok(Hash::Sha3_384),
psa_crypto_sys::PSA_ALG_SHA3_512 => Ok(Hash::Sha3_512),
a => {
error!("Can not find a valid Hash algorithm for {}.", a);
Err(Error::InvalidArgument)
}
}
}
}
#[cfg(feature = "interface")]
impl From<Hash> for psa_crypto_sys::psa_algorithm_t {
fn from(hash: Hash) -> Self {
match hash {
Hash::Md2 => psa_crypto_sys::PSA_ALG_MD2,
Hash::Md4 => psa_crypto_sys::PSA_ALG_MD4,
Hash::Md5 => psa_crypto_sys::PSA_ALG_MD5,
Hash::Ripemd160 => psa_crypto_sys::PSA_ALG_RIPEMD160,
Hash::Sha1 => psa_crypto_sys::PSA_ALG_SHA_1,
Hash::Sha224 => psa_crypto_sys::PSA_ALG_SHA_224,
Hash::Sha256 => psa_crypto_sys::PSA_ALG_SHA_256,
Hash::Sha384 => psa_crypto_sys::PSA_ALG_SHA_384,
Hash::Sha512 => psa_crypto_sys::PSA_ALG_SHA_512,
Hash::Sha512_224 => psa_crypto_sys::PSA_ALG_SHA_512_224,
Hash::Sha512_256 => psa_crypto_sys::PSA_ALG_SHA_512_256,
Hash::Sha3_224 => psa_crypto_sys::PSA_ALG_SHA3_224,
Hash::Sha3_256 => psa_crypto_sys::PSA_ALG_SHA3_256,
Hash::Sha3_384 => psa_crypto_sys::PSA_ALG_SHA3_384,
Hash::Sha3_512 => psa_crypto_sys::PSA_ALG_SHA3_512,
}
}
}
#[cfg(feature = "interface")]
impl TryFrom<psa_crypto_sys::psa_algorithm_t> for SignHash {
type Error = Error;
fn try_from(alg: psa_crypto_sys::psa_algorithm_t) -> Result<Self> {
if alg == psa_crypto_sys::PSA_ALG_ANY_HASH {
Ok(SignHash::Any)
} else {
Ok(SignHash::Specific(alg.try_into()?))
}
}
}
#[cfg(feature = "interface")]
impl From<SignHash> for psa_crypto_sys::psa_algorithm_t {
fn from(sign_hash: SignHash) -> Self {
match sign_hash {
SignHash::Specific(hash) => hash.into(),
SignHash::Any => psa_crypto_sys::PSA_ALG_ANY_HASH,
}
}
}
#[cfg(feature = "interface")]
impl TryFrom<psa_crypto_sys::psa_algorithm_t> for AsymmetricSignature {
type Error = Error;
fn try_from(alg: psa_crypto_sys::psa_algorithm_t) -> Result<Self> {
if alg == psa_crypto_sys::PSA_ALG_RSA_PKCS1V15_SIGN_RAW {
Ok(AsymmetricSignature::RsaPkcs1v15SignRaw)
} else if alg == psa_crypto_sys::PSA_ALG_ECDSA_ANY {
Ok(AsymmetricSignature::EcdsaAny)
} else if psa_crypto_sys::PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) {
Ok(AsymmetricSignature::RsaPkcs1v15Sign {
hash_alg: psa_crypto_sys::PSA_ALG_SIGN_GET_HASH(alg).try_into()?,
})
} else if psa_crypto_sys::PSA_ALG_IS_RSA_PSS(alg) {
Ok(AsymmetricSignature::RsaPss {
hash_alg: psa_crypto_sys::PSA_ALG_SIGN_GET_HASH(alg).try_into()?,
})
} else if psa_crypto_sys::PSA_ALG_IS_ECDSA(alg) {
Ok(AsymmetricSignature::Ecdsa {
hash_alg: psa_crypto_sys::PSA_ALG_SIGN_GET_HASH(alg).try_into()?,
})
} else if psa_crypto_sys::PSA_ALG_IS_DETERMINISTIC_ECDSA(alg) {
Ok(AsymmetricSignature::DeterministicEcdsa {
hash_alg: psa_crypto_sys::PSA_ALG_SIGN_GET_HASH(alg).try_into()?,
})
} else {
error!(
"Can not find a valid AsymmetricSignature algorithm for {}.",
alg
);
Err(Error::InvalidArgument)
}
}
}
#[cfg(feature = "interface")]
impl From<AsymmetricSignature> for psa_crypto_sys::psa_algorithm_t {
fn from(asym_sign: AsymmetricSignature) -> Self {
match asym_sign {
AsymmetricSignature::RsaPkcs1v15Sign { hash_alg } => {
psa_crypto_sys::PSA_ALG_RSA_PKCS1V15_SIGN(hash_alg.into())
}
AsymmetricSignature::RsaPkcs1v15SignRaw => {
psa_crypto_sys::PSA_ALG_RSA_PKCS1V15_SIGN_RAW
}
AsymmetricSignature::RsaPss { hash_alg } => {
psa_crypto_sys::PSA_ALG_RSA_PSS(hash_alg.into())
}
AsymmetricSignature::Ecdsa { hash_alg } => {
psa_crypto_sys::PSA_ALG_ECDSA(hash_alg.into())
}
AsymmetricSignature::EcdsaAny => psa_crypto_sys::PSA_ALG_ECDSA_ANY,
AsymmetricSignature::DeterministicEcdsa { hash_alg } => {
psa_crypto_sys::PSA_ALG_DETERMINISTIC_ECDSA(hash_alg.into())
}
}
}
}
#[cfg(feature = "interface")]
impl TryFrom<psa_crypto_sys::psa_algorithm_t> for AsymmetricEncryption {
type Error = Error;
fn try_from(alg: psa_crypto_sys::psa_algorithm_t) -> Result<Self> {
if alg == psa_crypto_sys::PSA_ALG_RSA_PKCS1V15_CRYPT {
Ok(AsymmetricEncryption::RsaPkcs1v15Crypt)
} else if unsafe { psa_crypto_sys::PSA_ALG_IS_RSA_OAEP(alg) } {
Ok(AsymmetricEncryption::RsaOaep {
hash_alg: psa_crypto_sys::PSA_ALG_RSA_OAEP_GET_HASH(alg).try_into()?,
})
} else {
error!(
"Can not find a valid AsymmetricEncryption algorithm for {}.",
alg
);
Err(Error::InvalidArgument)
}
}
}
#[cfg(feature = "interface")]
impl From<AsymmetricEncryption> for psa_crypto_sys::psa_algorithm_t {
fn from(asym_encrypt: AsymmetricEncryption) -> Self {
match asym_encrypt {
AsymmetricEncryption::RsaPkcs1v15Crypt => psa_crypto_sys::PSA_ALG_RSA_PKCS1V15_CRYPT,
AsymmetricEncryption::RsaOaep { hash_alg } => unsafe {
psa_crypto_sys::PSA_ALG_RSA_OAEP(hash_alg.into())
},
}
}
}
#[cfg(feature = "interface")]
impl TryFrom<psa_crypto_sys::psa_algorithm_t> for Mac {
type Error = Error;
fn try_from(alg: psa_crypto_sys::psa_algorithm_t) -> Result<Self> {
if psa_crypto_sys::PSA_ALG_IS_MAC(alg) {
if unsafe { psa_crypto_sys::PSA_ALG_FULL_LENGTH_MAC(alg) } == alg {
Ok(Mac::FullLength(alg.try_into()?))
} else {
let mac_length = unsafe { psa_crypto_sys::PSA_MAC_TRUNCATED_LENGTH(alg) };
let mac_alg: FullLengthMac =
unsafe { psa_crypto_sys::PSA_ALG_FULL_LENGTH_MAC(alg) }.try_into()?;
Ok(Mac::Truncated {
mac_alg,
mac_length,
})
}
} else {
error!("Can not find a valid MAC algorithm for {}.", alg);
Err(Error::InvalidArgument)
}
}
}
#[cfg(feature = "interface")]
impl TryFrom<psa_crypto_sys::psa_algorithm_t> for FullLengthMac {
type Error = Error;
fn try_from(alg: psa_crypto_sys::psa_algorithm_t) -> Result<Self> {
if psa_crypto_sys::PSA_ALG_IS_HMAC(alg) {
Ok(FullLengthMac::Hmac {
hash_alg: psa_crypto_sys::PSA_ALG_HMAC_GET_HASH(alg).try_into()?,
})
} else if alg == psa_crypto_sys::PSA_ALG_CBC_MAC {
Ok(FullLengthMac::CbcMac)
} else if alg == psa_crypto_sys::PSA_ALG_CMAC {
Ok(FullLengthMac::Cmac)
} else {
error!("Can not find a valid MAC algorithm for {}.", alg);
Err(Error::InvalidArgument)
}
}
}
#[cfg(feature = "interface")]
impl From<Mac> for psa_crypto_sys::psa_algorithm_t {
fn from(mac: Mac) -> Self {
match mac {
Mac::FullLength(full_length_mac) => full_length_mac.into(),
Mac::Truncated {
mac_alg: alg,
mac_length: length,
} => unsafe { psa_crypto_sys::PSA_ALG_TRUNCATED_MAC(alg.into(), length) },
}
}
}
impl From<FullLengthMac> for Mac {
fn from(full_length_mac: FullLengthMac) -> Self {
Mac::FullLength(full_length_mac)
}
}
#[cfg(feature = "interface")]
impl From<FullLengthMac> for psa_crypto_sys::psa_algorithm_t {
fn from(full_length_mac: FullLengthMac) -> Self {
match full_length_mac {
FullLengthMac::CbcMac => psa_crypto_sys::PSA_ALG_CBC_MAC,
FullLengthMac::Cmac => psa_crypto_sys::PSA_ALG_CMAC,
FullLengthMac::Hmac { hash_alg } => unsafe {
psa_crypto_sys::PSA_ALG_HMAC(hash_alg.into())
},
}
}
}
#[cfg(feature = "interface")]
impl TryFrom<psa_crypto_sys::psa_algorithm_t> for Aead {
type Error = Error;
fn try_from(alg: psa_crypto_sys::psa_algorithm_t) -> Result<Self> {
if let Ok(aead_with_default_length_tag) = AeadWithDefaultLengthTag::try_from(alg) {
Ok(Aead::AeadWithDefaultLengthTag(aead_with_default_length_tag))
} else {
let aead_alg = AeadWithDefaultLengthTag::try_from(unsafe {
psa_crypto_sys::PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(alg)
})?;
let tag_length = psa_crypto_sys::PSA_ALG_AEAD_TAG_TRUNCATED_LENGTH(alg);
Ok(Aead::AeadWithShortenedTag {
aead_alg,
tag_length,
})
}
}
}
#[cfg(feature = "interface")]
impl TryFrom<psa_crypto_sys::psa_algorithm_t> for AeadWithDefaultLengthTag {
type Error = Error;
fn try_from(alg: psa_crypto_sys::psa_algorithm_t) -> Result<Self> {
if alg
== unsafe {
psa_crypto_sys::PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(psa_crypto_sys::PSA_ALG_CCM)
}
{
Ok(AeadWithDefaultLengthTag::Ccm)
} else if alg
== unsafe {
psa_crypto_sys::PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(psa_crypto_sys::PSA_ALG_GCM)
}
{
Ok(AeadWithDefaultLengthTag::Gcm)
} else if alg
== unsafe {
psa_crypto_sys::PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(
psa_crypto_sys::PSA_ALG_CHACHA20_POLY1305,
)
}
{
Ok(AeadWithDefaultLengthTag::Chacha20Poly1305)
} else {
error!("Can not find a valid Aead algorithm for {}.", alg);
Err(Error::InvalidArgument)
}
}
}
#[cfg(feature = "interface")]
impl From<Aead> for psa_crypto_sys::psa_algorithm_t {
fn from(aead: Aead) -> Self {
match aead {
Aead::AeadWithDefaultLengthTag(aead_with_default_length_mac) => {
aead_with_default_length_mac.into()
}
Aead::AeadWithShortenedTag {
aead_alg,
tag_length,
} => unsafe {
psa_crypto_sys::PSA_ALG_AEAD_WITH_SHORTENED_TAG(aead_alg.into(), tag_length)
},
}
}
}
#[cfg(feature = "interface")]
impl From<AeadWithDefaultLengthTag> for psa_crypto_sys::psa_algorithm_t {
fn from(aead_with_default_length_tag: AeadWithDefaultLengthTag) -> Self {
match aead_with_default_length_tag {
AeadWithDefaultLengthTag::Ccm => unsafe {
psa_crypto_sys::PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(psa_crypto_sys::PSA_ALG_CCM)
},
AeadWithDefaultLengthTag::Gcm => unsafe {
psa_crypto_sys::PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(psa_crypto_sys::PSA_ALG_GCM)
},
AeadWithDefaultLengthTag::Chacha20Poly1305 => unsafe {
psa_crypto_sys::PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(
psa_crypto_sys::PSA_ALG_CHACHA20_POLY1305,
)
},
}
}
}
impl From<AeadWithDefaultLengthTag> for Aead {
fn from(aead_with_default_tag_length: AeadWithDefaultLengthTag) -> Self {
Aead::AeadWithDefaultLengthTag(aead_with_default_tag_length)
}
}
#[cfg(feature = "interface")]
impl From<KeyAgreement> for psa_crypto_sys::psa_algorithm_t {
fn from(key_agreement: KeyAgreement) -> Self {
match key_agreement {
KeyAgreement::Raw(raw_key_agreement) => raw_key_agreement.into(),
KeyAgreement::WithKeyDerivation { ka_alg, kdf_alg } => unsafe {
psa_crypto_sys::PSA_ALG_KEY_AGREEMENT(ka_alg.into(), kdf_alg.into())
},
}
}
}
#[cfg(feature = "interface")]
impl TryFrom<psa_crypto_sys::psa_algorithm_t> for KeyAgreement {
type Error = Error;
fn try_from(alg: psa_crypto_sys::psa_algorithm_t) -> Result<Self> {
if psa_crypto_sys::PSA_ALG_IS_KEY_AGREEMENT(alg) {
if psa_crypto_sys::PSA_ALG_IS_RAW_KEY_AGREEMENT(alg) {
Ok(KeyAgreement::Raw(alg.try_into()?))
} else {
Ok(KeyAgreement::WithKeyDerivation {
ka_alg: unsafe { psa_crypto_sys::PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) }
.try_into()?,
kdf_alg: unsafe { psa_crypto_sys::PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) }
.try_into()?,
})
}
} else {
error!("Can not find a valid KeyAgreement algorithm for {}.", alg);
Err(Error::InvalidArgument)
}
}
}
#[cfg(feature = "interface")]
impl TryFrom<psa_crypto_sys::psa_algorithm_t> for RawKeyAgreement {
type Error = Error;
fn try_from(alg: psa_crypto_sys::psa_algorithm_t) -> Result<Self> {
if psa_crypto_sys::PSA_ALG_IS_FFDH(alg) {
Ok(RawKeyAgreement::Ffdh)
} else if psa_crypto_sys::PSA_ALG_IS_ECDH(alg) {
Ok(RawKeyAgreement::Ecdh)
} else {
error!(
"Can not find a valid RawKeyAgreement algorithm for {}.",
alg
);
Err(Error::InvalidArgument)
}
}
}
#[cfg(feature = "interface")]
impl From<RawKeyAgreement> for psa_crypto_sys::psa_algorithm_t {
fn from(raw_key_agreement: RawKeyAgreement) -> Self {
match raw_key_agreement {
RawKeyAgreement::Ecdh => psa_crypto_sys::PSA_ALG_ECDH,
RawKeyAgreement::Ffdh => psa_crypto_sys::PSA_ALG_FFDH,
}
}
}
impl From<RawKeyAgreement> for KeyAgreement {
fn from(raw_key_agreement: RawKeyAgreement) -> Self {
KeyAgreement::Raw(raw_key_agreement)
}
}
#[cfg(feature = "interface")]
impl From<KeyDerivation> for psa_crypto_sys::psa_algorithm_t {
fn from(key_derivation: KeyDerivation) -> Self {
match key_derivation {
KeyDerivation::Hkdf { hash_alg, .. } => unsafe {
psa_crypto_sys::PSA_ALG_HKDF(hash_alg.into())
},
KeyDerivation::Tls12Prf { hash_alg, .. } => unsafe {
psa_crypto_sys::PSA_ALG_TLS12_PRF(hash_alg.into())
},
KeyDerivation::Tls12PskToMs { hash_alg, .. } => unsafe {
psa_crypto_sys::PSA_ALG_TLS12_PSK_TO_MS(hash_alg.into())
},
}
}
}
#[cfg(feature = "interface")]
impl TryFrom<psa_crypto_sys::psa_algorithm_t> for KeyDerivation {
type Error = Error;
fn try_from(alg: psa_crypto_sys::psa_algorithm_t) -> Result<Self> {
if psa_crypto_sys::PSA_ALG_IS_HKDF(alg) {
Ok(KeyDerivation::Hkdf {
hash_alg: psa_crypto_sys::PSA_ALG_HKDF_GET_HASH(alg).try_into()?,
})
} else if psa_crypto_sys::PSA_ALG_IS_TLS12_PRF(alg) {
Ok(KeyDerivation::Tls12Prf {
hash_alg: psa_crypto_sys::PSA_ALG_TLS12_PRF_GET_HASH(alg).try_into()?,
})
} else if psa_crypto_sys::PSA_ALG_IS_TLS12_PSK_TO_MS(alg) {
Ok(KeyDerivation::Tls12PskToMs {
hash_alg: psa_crypto_sys::PSA_ALG_TLS12_PSK_TO_MS_GET_HASH(alg).try_into()?,
})
} else {
error!("Can not find a valid KeyDerivation algorithm for {}.", alg);
Err(Error::InvalidArgument)
}
}
}
#[cfg(test)]
mod test {
use crate::types::algorithm::{Algorithm, AsymmetricSignature, Hash, SignHash};
use core::convert::{TryFrom, TryInto};
#[test]
fn conversion() {
assert_eq!(
Hash::Sha256,
psa_crypto_sys::PSA_ALG_SHA_256.try_into().unwrap()
);
assert_eq!(psa_crypto_sys::PSA_ALG_SHA_256, Hash::Sha256.into());
assert_eq!(
SignHash::Any,
psa_crypto_sys::PSA_ALG_ANY_HASH.try_into().unwrap()
);
assert_eq!(
SignHash::Specific(Hash::Sha256),
psa_crypto_sys::PSA_ALG_SHA_256.try_into().unwrap()
);
assert_eq!(
Algorithm::AsymmetricSignature(AsymmetricSignature::Ecdsa {
hash_alg: SignHash::Specific(Hash::Sha3_512),
}),
psa_crypto_sys::PSA_ALG_ECDSA(psa_crypto_sys::PSA_ALG_SHA3_512)
.try_into()
.unwrap()
);
assert_eq!(
psa_crypto_sys::PSA_ALG_ECDSA(psa_crypto_sys::PSA_ALG_SHA3_512),
Algorithm::AsymmetricSignature(AsymmetricSignature::Ecdsa {
hash_alg: SignHash::Specific(Hash::Sha3_512),
})
.try_into()
.unwrap()
);
}
#[test]
fn convert_fail() {
let _ = AsymmetricSignature::try_from(0xDEAD_BEEF).unwrap_err();
let _ = AsymmetricSignature::try_from(psa_crypto_sys::PSA_ALG_ANY_HASH).unwrap_err();
let _ = Hash::try_from(psa_crypto_sys::PSA_ALG_ANY_HASH).unwrap_err();
let _ = Hash::try_from(psa_crypto_sys::PSA_ALG_RSA_PKCS1V15_SIGN_RAW).unwrap_err();
}
}