Skip to main content

psa_crypto/types/
key.rs

1// Copyright 2020 Contributors to the Parsec project.
2// SPDX-License-Identifier: Apache-2.0
3
4//! # PSA Key types
5
6#![allow(deprecated)]
7#[cfg(feature = "operations")]
8use crate::initialized;
9#[cfg(feature = "interface")]
10use crate::types::algorithm::{Aead, AsymmetricEncryption, AsymmetricSignature, Mac};
11use crate::types::algorithm::{Algorithm, Cipher, KeyAgreement, RawKeyAgreement};
12#[cfg(feature = "operations")]
13use crate::types::status::Status;
14use crate::types::status::{Error, Result};
15#[cfg(feature = "interface")]
16use core::convert::{TryFrom, TryInto};
17use core::fmt;
18use log::error;
19pub use psa_crypto_sys::{self, psa_key_id_t, PSA_KEY_ID_USER_MAX, PSA_KEY_ID_USER_MIN};
20use serde::{Deserialize, Serialize};
21use zeroize::Zeroize;
22
23/// Native definition of the attributes needed to fully describe
24/// a cryptographic key.
25#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Zeroize)]
26pub struct Attributes {
27    /// Lifetime of the key
28    pub lifetime: Lifetime,
29    /// Intrinsic category and type of the key
30    pub key_type: Type,
31    /// Size of the key in bits
32    pub bits: usize,
33    /// Policy restricting the permitted usage of the key
34    pub policy: Policy,
35}
36
37impl Attributes {
38    /// Check if a key has permission to be exported
39    pub fn is_exportable(self) -> bool {
40        self.policy.usage_flags.export
41    }
42
43    /// Check export in a fallible way
44    ///
45    /// # Example
46    ///
47    /// ```
48    /// use psa_crypto::types::key::{Attributes, Type, Lifetime, Policy, UsageFlags};
49    /// use psa_crypto::types::algorithm::{Algorithm, AsymmetricSignature, Hash};
50    ///
51    /// let mut usage_flags: UsageFlags = Default::default();
52    /// let mut attributes = Attributes {
53    ///     key_type: Type::RsaKeyPair,
54    ///     bits: 1024,
55    ///     lifetime: Lifetime::Volatile,
56    ///     policy: Policy {
57    ///         usage_flags,
58    ///         permitted_algorithms: Algorithm::AsymmetricSignature(AsymmetricSignature::RsaPkcs1v15Sign {
59    ///             hash_alg: Hash::Sha256.into(),
60    ///         }),
61    ///     },
62    /// };
63    ///
64    /// // Can not export because the export flag is set to false.
65    /// attributes.can_export().unwrap_err();
66    /// ```
67    pub fn can_export(self) -> Result<()> {
68        if self.is_exportable() {
69            Ok(())
70        } else {
71            error!("Key attributes do not permit exporting key.");
72            Err(Error::NotPermitted)
73        }
74    }
75
76    /// Check if a key has permission to sign a message hash
77    pub fn is_hash_signable(self) -> bool {
78        self.policy.usage_flags.sign_hash
79    }
80
81    /// Check hash signing permission in a fallible way
82    pub fn can_sign_hash(self) -> Result<()> {
83        if self.is_hash_signable() {
84            Ok(())
85        } else {
86            error!("Key attributes do not permit signing hashes.");
87            Err(Error::NotPermitted)
88        }
89    }
90
91    /// Check if a key has permission to verify a message hash
92    pub fn is_hash_verifiable(self) -> bool {
93        self.policy.usage_flags.verify_hash
94    }
95
96    /// Check hash verifying permission in a fallible way
97    pub fn can_verify_hash(self) -> Result<()> {
98        if self.is_hash_verifiable() {
99            Ok(())
100        } else {
101            error!("Key attributes do not permit verifying hashes.");
102            Err(Error::NotPermitted)
103        }
104    }
105
106    /// Check if a key has permission to sign a message
107    pub fn is_message_signable(self) -> bool {
108        self.policy.usage_flags.sign_hash | self.policy.usage_flags.sign_message
109    }
110
111    /// Check message signing permission in a fallible way
112    pub fn can_sign_message(self) -> Result<()> {
113        if self.is_message_signable() {
114            Ok(())
115        } else {
116            error!("Key attributes do not permit signing messages.");
117            Err(Error::NotPermitted)
118        }
119    }
120
121    /// Check if a key has permission to verify a message
122    pub fn is_message_verifiable(self) -> bool {
123        self.policy.usage_flags.verify_hash | self.policy.usage_flags.verify_message
124    }
125
126    /// Check message verifying permission in a fallible way
127    pub fn can_verify_message(self) -> Result<()> {
128        if self.is_message_verifiable() {
129            Ok(())
130        } else {
131            error!("Key attributes do not permit verifying messages.");
132            Err(Error::NotPermitted)
133        }
134    }
135
136    /// Check if a key has permissions to encrypt a message
137    pub fn is_encrypt_permitted(self) -> bool {
138        self.policy.usage_flags.encrypt
139    }
140
141    /// Check encrypt permission in a fallible way
142    pub fn can_encrypt_message(self) -> Result<()> {
143        if self.is_encrypt_permitted() {
144            Ok(())
145        } else {
146            error!("Key attributes do not permit encrypting messages.");
147            Err(Error::NotPermitted)
148        }
149    }
150
151    /// Check if a key has permissions to decrypt a message
152    pub fn is_decrypt_permitted(self) -> bool {
153        self.policy.usage_flags.decrypt
154    }
155
156    /// Check decrypt permission in a fallible way
157    pub fn can_decrypt_message(self) -> Result<()> {
158        if self.is_decrypt_permitted() {
159            Ok(())
160        } else {
161            error!("Key attributes do not permit decrypting messages.");
162            Err(Error::NotPermitted)
163        }
164    }
165
166    /// Check if a key has permissions to be derived from
167    pub fn is_derivable(self) -> bool {
168        self.policy.usage_flags.derive
169    }
170
171    /// Check derive permission of a fallible way
172    pub fn can_derive_from(self) -> Result<()> {
173        if self.is_derivable() {
174            Ok(())
175        } else {
176            error!("Key attributes do not permit derivation.");
177            Err(Error::NotPermitted)
178        }
179    }
180
181    /// Check if can be converted into psa_key_attributes_t
182    #[cfg(feature = "interface")]
183    pub fn can_convert_into_psa(self) -> Result<()> {
184        let _ = psa_crypto_sys::psa_key_attributes_t::try_from(self)?;
185        Ok(())
186    }
187
188    /// Check if the alg given for a cryptographic operation is permitted to be used with the key
189    pub fn is_alg_permitted(self, alg: Algorithm) -> bool {
190        match self.policy.permitted_algorithms {
191            Algorithm::None => false,
192            Algorithm::AsymmetricSignature(asymmetric_signature_alg_policy) => {
193                if let Algorithm::AsymmetricSignature(asymmetric_signature_alg) = alg {
194                    asymmetric_signature_alg_policy.is_alg_permitted(asymmetric_signature_alg)
195                } else {
196                    false
197                }
198            }
199            // These ones can not be wildcard algorithms: it is sufficient to just check for
200            // equality.
201            permitted_alg => permitted_alg == alg,
202        }
203    }
204
205    /// Check if alg is permitted in a fallible way
206    pub fn permits_alg(self, alg: Algorithm) -> Result<()> {
207        if self.is_alg_permitted(alg) {
208            Ok(())
209        } else {
210            error!("Key attributes do not permit specified algorithm.");
211            Err(Error::NotPermitted)
212        }
213    }
214
215    /// Check if the alg given for a cryptographic operation is compatible with the type of the
216    /// key
217    ///
218    /// # Example
219    ///
220    /// ```
221    /// use psa_crypto::types::key::{Attributes, Type, Lifetime, Policy, UsageFlags};
222    /// use psa_crypto::types::algorithm::{Algorithm, AsymmetricSignature, Hash};
223    ///
224    /// let permitted_alg = Algorithm::AsymmetricSignature(AsymmetricSignature::RsaPkcs1v15Sign {
225    ///     hash_alg: Hash::Sha256.into(),
226    /// });
227    /// let alg = Algorithm::AsymmetricSignature(AsymmetricSignature::RsaPkcs1v15Sign {
228    ///     hash_alg: Hash::Sha256.into(),
229    /// });
230    /// let mut usage_flags: UsageFlags = Default::default();
231    /// let mut attributes = Attributes {
232    ///     key_type: Type::RsaKeyPair,
233    ///     bits: 1024,
234    ///     lifetime: Lifetime::Volatile,
235    ///     policy: Policy {
236    ///         usage_flags,
237    ///         permitted_algorithms: permitted_alg,
238    ///     },
239    /// };
240    ///
241    /// assert!(attributes.is_compatible_with_alg(alg));
242    /// attributes.key_type = Type::RsaPublicKey;
243    /// assert!(attributes.is_compatible_with_alg(alg));
244    /// ```
245    pub fn is_compatible_with_alg(self, alg: Algorithm) -> bool {
246        match self.key_type {
247            Type::RawData => false,
248            Type::Hmac => alg.is_hmac(),
249            Type::Derive => matches!(alg, Algorithm::KeyDerivation(_)),
250            Type::Aes | Type::Camellia => {
251                if let Algorithm::Mac(mac_alg) = alg {
252                    mac_alg.is_block_cipher_needed()
253                } else if let Algorithm::Cipher(cipher_alg) = alg {
254                    cipher_alg.is_block_cipher_mode()
255                } else if let Algorithm::Aead(aead_alg) = alg {
256                    aead_alg.is_aead_on_block_cipher()
257                } else {
258                    false
259                }
260            }
261            Type::Des => {
262                if let Algorithm::Mac(mac_alg) = alg {
263                    mac_alg.is_block_cipher_needed()
264                } else if let Algorithm::Cipher(cipher_alg) = alg {
265                    cipher_alg.is_block_cipher_mode()
266                } else {
267                    false
268                }
269            }
270            Type::Arc4 => alg == Algorithm::Cipher(Cipher::StreamCipher),
271            Type::Chacha20 => {
272                if alg == Algorithm::Cipher(Cipher::StreamCipher) {
273                    true
274                } else if let Algorithm::Aead(aead_alg) = alg {
275                    aead_alg.is_chacha20_poly1305_alg()
276                } else {
277                    false
278                }
279            }
280            Type::RsaPublicKey | Type::RsaKeyPair => {
281                if let Algorithm::AsymmetricSignature(sign_alg) = alg {
282                    sign_alg.is_rsa_alg()
283                } else {
284                    matches!(alg, Algorithm::AsymmetricEncryption(_))
285                }
286            }
287            Type::EccKeyPair { .. } | Type::EccPublicKey { .. } => match alg {
288                Algorithm::KeyAgreement(KeyAgreement::Raw(RawKeyAgreement::Ecdh))
289                | Algorithm::KeyAgreement(KeyAgreement::WithKeyDerivation {
290                    ka_alg: RawKeyAgreement::Ecdh,
291                    ..
292                }) => true,
293                Algorithm::AsymmetricSignature(sign_alg) => sign_alg.is_ecc_alg(),
294                _ => false,
295            },
296            Type::DhKeyPair { .. } | Type::DhPublicKey { .. } => matches!(
297                alg,
298                Algorithm::KeyAgreement(KeyAgreement::Raw(RawKeyAgreement::Ffdh))
299                    | Algorithm::KeyAgreement(KeyAgreement::WithKeyDerivation {
300                        ka_alg: RawKeyAgreement::Ffdh,
301                        ..
302                    })
303            ),
304        }
305    }
306
307    /// Check if alg is compatible in a fallible way
308    pub fn compatible_with_alg(self, alg: Algorithm) -> Result<()> {
309        if self.is_compatible_with_alg(alg) {
310            Ok(())
311        } else {
312            error!("Key attributes are not compatible with specified algorithm.");
313            Err(Error::NotPermitted)
314        }
315    }
316
317    #[cfg(feature = "operations")]
318    pub(crate) fn reset(attributes: &mut psa_crypto_sys::psa_key_attributes_t) {
319        unsafe { psa_crypto_sys::psa_reset_key_attributes(attributes) };
320    }
321
322    /// Gets the attributes for a given key ID
323    ///
324    /// The `Id` structure can be created with the `from_persistent_key_id` constructor on `Id`.
325    ///
326    /// # Example
327    ///
328    /// ```
329    /// # use psa_crypto::operations::key_management;
330    /// # use psa_crypto::types::key::{Attributes, Type, Lifetime, Policy, UsageFlags};
331    /// # use psa_crypto::types::algorithm::{AsymmetricSignature, Hash};
332    /// # let mut usage_flags: UsageFlags = Default::default();
333    /// # usage_flags.set_sign_hash().set_verify_hash();
334    /// # let mut attributes = Attributes {
335    /// #     key_type: Type::RsaKeyPair,
336    /// #     bits: 1024,
337    /// #     lifetime: Lifetime::Volatile,
338    /// #     policy: Policy {
339    /// #         usage_flags,
340    /// #         permitted_algorithms: AsymmetricSignature::RsaPkcs1v15Sign {
341    /// #             hash_alg: Hash::Sha256.into(),
342    /// #         }.into(),
343    /// #     },
344    /// # };
345    /// psa_crypto::init().unwrap();
346    /// let my_key_id = key_management::generate(attributes, None).unwrap();
347    /// //...
348    /// let key_attributes = Attributes::from_key_id(my_key_id);
349    /// ```
350    #[cfg(feature = "operations")]
351    pub fn from_key_id(key_id: Id) -> Result<Self> {
352        initialized()?;
353        let mut key_attributes = unsafe { psa_crypto_sys::psa_key_attributes_init() };
354        Status::from(unsafe {
355            psa_crypto_sys::psa_get_key_attributes(key_id.0, &mut key_attributes)
356        })
357        .to_result()?;
358        let attributes = Attributes::try_from(key_attributes);
359        Attributes::reset(&mut key_attributes);
360        attributes
361    }
362
363    /// Sufficient size for a buffer to export the key, if supported
364    #[cfg(feature = "interface")]
365    pub fn export_key_output_size(self) -> Result<usize> {
366        Attributes::export_key_output_size_base(self.key_type, self.bits)
367    }
368
369    /// Sufficient size for a buffer to export the public key, if supported
370    #[cfg(feature = "interface")]
371    pub fn export_public_key_output_size(self) -> Result<usize> {
372        match self.key_type {
373            Type::RsaKeyPair
374            | Type::RsaPublicKey
375            | Type::EccKeyPair { .. }
376            | Type::EccPublicKey { .. }
377            | Type::DhKeyPair { .. }
378            | Type::DhPublicKey { .. } => {
379                let pub_type = self.key_type.key_type_public_key_of_key_pair()?;
380                Attributes::export_key_output_size_base(pub_type, self.bits)
381            }
382            _ => Err(Error::InvalidArgument),
383        }
384    }
385
386    /// Sufficient size for a buffer to export the given key type, if supported
387    #[cfg(feature = "interface")]
388    fn export_key_output_size_base(key_type: Type, bits: usize) -> Result<usize> {
389        match unsafe { psa_crypto_sys::PSA_EXPORT_KEY_OUTPUT_SIZE(key_type.try_into()?, bits) } {
390            0 => Err(Error::NotSupported),
391            size => Ok(size),
392        }
393    }
394
395    /// Sufficient buffer size for a signature using the given key, if the key is supported
396    #[cfg(feature = "interface")]
397    pub fn sign_output_size(self, alg: AsymmetricSignature) -> Result<usize> {
398        self.compatible_with_alg(alg.into())?;
399        Ok(unsafe {
400            psa_crypto_sys::PSA_SIGN_OUTPUT_SIZE(self.key_type.try_into()?, self.bits, alg.into())
401        })
402    }
403
404    /// Sufficient buffer size for an encrypted message using the given asymmetric encryption algorithm
405    #[cfg(feature = "interface")]
406    pub fn asymmetric_encrypt_output_size(self, alg: AsymmetricEncryption) -> Result<usize> {
407        self.compatible_with_alg(alg.into())?;
408        Ok(unsafe {
409            psa_crypto_sys::PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(
410                self.key_type.try_into()?,
411                self.bits,
412                alg.into(),
413            )
414        })
415    }
416
417    /// Sufficient buffer size for a decrypted message using the given asymmetric encryption algorithm
418    #[cfg(feature = "interface")]
419    pub fn asymmetric_decrypt_output_size(self, alg: AsymmetricEncryption) -> Result<usize> {
420        self.compatible_with_alg(alg.into())?;
421        Ok(unsafe {
422            psa_crypto_sys::PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(
423                self.key_type.try_into()?,
424                self.bits,
425                alg.into(),
426            )
427        })
428    }
429
430    /// Sufficient buffer size for the MAC of the specified algorithm, if compatible
431    #[cfg(feature = "interface")]
432    pub fn mac_length(self, mac_alg: Mac) -> Result<usize> {
433        self.compatible_with_alg(mac_alg.into())?;
434        let size = unsafe {
435            psa_crypto_sys::PSA_MAC_LENGTH(self.key_type.try_into()?, self.bits, mac_alg.into())
436        };
437        // PSA_MAC_LENGTH will return 0 for incompatible algorithms
438        // and other errors. Since we need > 0 mac_length to allocate
439        // space for the mac itself, treat 0 as an error.
440        if size > 0 {
441            Ok(size)
442        } else {
443            Err(Error::DataInvalid)
444        }
445    }
446
447    /// Sufficient buffer size for an encrypted message using the given aead algorithm
448    #[cfg(feature = "interface")]
449    pub fn aead_encrypt_output_size(self, alg: Aead, plaintext_len: usize) -> Result<usize> {
450        self.compatible_with_alg(alg.into())?;
451        Ok(unsafe {
452            psa_crypto_sys::PSA_AEAD_ENCRYPT_OUTPUT_SIZE(
453                self.key_type.try_into()?,
454                alg.into(),
455                plaintext_len,
456            )
457        })
458    }
459
460    /// Sufficient buffer size for an encrypted message using the given aead algorithm
461    #[cfg(feature = "interface")]
462    pub fn aead_decrypt_output_size(self, alg: Aead, ciphertext_len: usize) -> Result<usize> {
463        self.compatible_with_alg(alg.into())?;
464        Ok(unsafe {
465            psa_crypto_sys::PSA_AEAD_DECRYPT_OUTPUT_SIZE(
466                self.key_type.try_into()?,
467                alg.into(),
468                ciphertext_len,
469            )
470        })
471    }
472
473    /// The length of a tag for an AEAD algorithm
474    #[cfg(feature = "interface")]
475    pub fn aead_tag_length(self, alg: Aead) -> Result<usize> {
476        self.compatible_with_alg(alg.into())?;
477        Ok(psa_crypto_sys::PSA_AEAD_TAG_LENGTH(
478            self.key_type.try_into()?,
479            self.bits,
480            alg.into(),
481        ))
482    }
483
484    /// Sufficient buffer size for the resulting shared secret from a raw key agreement
485    #[cfg(feature = "interface")]
486    pub fn raw_key_agreement_output_size(self, alg: RawKeyAgreement) -> Result<usize> {
487        if alg == RawKeyAgreement::Ffdh {
488            return Err(Error::NotSupported);
489        }
490        self.compatible_with_alg(KeyAgreement::Raw(alg).into())?;
491        Ok(unsafe {
492            psa_crypto_sys::PSA_RAW_ECDH_KEY_AGREEMENT_OUTPUT_SIZE(
493                self.key_type.try_into()?,
494                self.bits,
495            )
496        })
497    }
498}
499
500/// The lifetime of a key indicates where it is stored and which application and system actions
501/// will create and destroy it.
502#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Zeroize)]
503pub enum Lifetime {
504    /// A volatile key only exists as long as the identifier to it is not destroyed.
505    Volatile,
506    /// A persistent key remains in storage until it is explicitly destroyed or until the
507    /// corresponding storage area is wiped.
508    Persistent,
509    /// Implementations can offer other storage areas designated by other lifetime values as
510    /// implementation-specific extensions.
511    Custom(u32),
512}
513
514/// Enumeration of key types supported.
515#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Zeroize)]
516pub enum Type {
517    /// Not a valid key type for any cryptographic operation but can be used to store arbitrary
518    /// data in the key store.
519    RawData,
520    /// HMAC key.
521    Hmac,
522    /// A secret key for derivation.
523    Derive,
524    /// Key for a cipher, AEAD or MAC algorithm based on the AES block cipher.
525    Aes,
526    /// Key for a cipher or MAC algorithm based on DES or 3DES (Triple-DES).
527    Des,
528    /// Key for a cipher, AEAD or MAC algorithm based on the Camellia block cipher.
529    Camellia,
530    /// Key for the RC4 stream cipher.
531    Arc4,
532    /// Key for the ChaCha20 stream cipher or the Chacha20-Poly1305 AEAD algorithm.
533    Chacha20,
534    /// RSA public key.
535    RsaPublicKey,
536    /// RSA key pair: both the private and public key.
537    RsaKeyPair,
538    /// Elliptic curve key pair: both the private and public key.
539    EccKeyPair {
540        /// ECC curve family to use.
541        curve_family: EccFamily,
542    },
543    /// Elliptic curve public key.
544    EccPublicKey {
545        /// ECC curve family to use.
546        curve_family: EccFamily,
547    },
548    /// Diffie-Hellman key pair: both the private key and public key.
549    DhKeyPair {
550        /// Diffie-Hellman group family to use.
551        group_family: DhFamily,
552    },
553    /// Diffie-Hellman public key.
554    DhPublicKey {
555        /// Diffie-Hellman group family to use.
556        group_family: DhFamily,
557    },
558}
559
560impl fmt::Display for Type {
561    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
562        match self {
563            Type::RawData => write!(f, "Raw data"),
564            Type::Hmac => write!(f, "HMAC key"),
565            Type::Derive => write!(f, "Derivation key"),
566            Type::Aes => write!(f, "Key for an algorithm based on AES"),
567            Type::Des => write!(f, "Key for an algorithm based on DES or 3DES"),
568            Type::Camellia => write!(f, "Key for an algorithm based on Camellia"),
569            Type::Arc4 => write!(f, "Key for the RC4 stream cipher"),
570            Type::Chacha20 => write!(f, "Key for an algorithm based on ChaCha20"),
571            Type::RsaPublicKey => write!(f, "RSA public key"),
572            Type::RsaKeyPair => write!(f, "RSA key pair"),
573            Type::EccKeyPair { curve_family } => write!(f, "ECC key pair (using {curve_family})"),
574            Type::EccPublicKey { curve_family } => {
575                write!(f, "ECC public key (using {curve_family})")
576            }
577            Type::DhKeyPair { group_family } => {
578                write!(f, "Diffie-Hellman key pair (using {group_family})")
579            }
580            Type::DhPublicKey { group_family } => {
581                write!(f, "Diffie-Hellman public key (using {group_family})")
582            }
583        }
584    }
585}
586
587impl Type {
588    /// Checks if a key type is ECC key pair with any curve family inside.
589    pub fn is_ecc_key_pair(self) -> bool {
590        matches!(self, Type::EccKeyPair { .. })
591    }
592
593    /// Checks if a key type is ECC public key with any curve family inside.
594    ///
595    /// # Example
596    ///
597    /// ```
598    /// use psa_crypto::types::key::{Type, EccFamily};
599    ///
600    /// assert!(Type::EccPublicKey { curve_family: EccFamily::SecpK1}.is_ecc_public_key());
601    /// ```
602    pub fn is_ecc_public_key(self) -> bool {
603        matches!(self, Type::EccPublicKey { .. })
604    }
605
606    /// Checks if a key type is RSA public key.
607    pub fn is_rsa_public_key(self) -> bool {
608        matches!(self, Type::RsaPublicKey)
609    }
610
611    /// Checks if a key type is DH public key with any group family inside.
612    pub fn is_dh_public_key(self) -> bool {
613        matches!(self, Type::DhPublicKey { .. })
614    }
615
616    /// Checks if a key type is DH key pair with any group family inside.
617    pub fn is_dh_key_pair(self) -> bool {
618        matches!(self, Type::DhKeyPair { .. })
619    }
620
621    /// Checks if a key type is an asymmetric public key type.
622    pub fn is_public_key(self) -> bool {
623        self.is_rsa_public_key() || self.is_ecc_public_key() || self.is_dh_public_key()
624    }
625
626    /// If key is public or key pair, returns the corresponding public key type.
627    #[cfg(feature = "interface")]
628    pub fn key_type_public_key_of_key_pair(self) -> Result<Type> {
629        match self {
630            Type::RsaKeyPair
631            | Type::RsaPublicKey
632            | Type::EccKeyPair { .. }
633            | Type::EccPublicKey { .. }
634            | Type::DhKeyPair { .. }
635            | Type::DhPublicKey { .. } => {
636                Ok(
637                    unsafe {
638                        psa_crypto_sys::PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(self.try_into()?)
639                    }
640                    .try_into()?,
641                )
642            }
643            _ => Err(Error::InvalidArgument),
644        }
645    }
646}
647
648/// Enumeration of elliptic curve families supported. They are needed to create an ECC key.
649/// The specific curve used for each family is given by the `bits` field of the key attributes.
650/// See the book for more details.
651#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Zeroize)]
652pub enum EccFamily {
653    /// SEC Koblitz curves over prime fields.
654    /// This family comprises the following curves:
655    ///   * secp192k1: `bits` = 192
656    ///   * secp224k1: `bits` = 225
657    ///   * secp256k1: `bits` = 256
658    SecpK1,
659    /// SEC random curves over prime fields.
660    /// This family comprises the following curves:
661    ///   * secp192r1: `bits` = 192
662    ///   * secp224r1: `bits` = 224
663    ///   * secp256r1: `bits` = 256
664    ///   * secp384r1: `bits` = 384
665    ///   * secp521r1: `bits` = 512
666    SecpR1,
667    /// SEC additional random curves over prime fields.
668    /// This family comprises the following curves:
669    ///   * secp160r2: `bits` = 160 (Deprecated)
670    #[deprecated = "This family of curve is weak and deprecated."]
671    SecpR2,
672    /// SEC Koblitz curves over binary fields.
673    /// This family comprises the following curves:
674    ///   * sect163k1: `bits` = 163 (DEPRECATED)
675    ///   * sect233k1: `bits` = 233
676    ///   * sect239k1: `bits` = 239
677    ///   * sect283k1: `bits` = 283
678    ///   * sect409k1: `bits` = 409
679    ///   * sect571k1: `bits` = 571
680    SectK1,
681    /// SEC random curves over binary fields.
682    /// This family comprises the following curves:
683    ///   * sect163r1: `bits` = 163 (DEPRECATED)
684    ///   * sect233r1: `bits` = 233
685    ///   * sect283r1: `bits` = 283
686    ///   * sect409r1: `bits` = 409
687    ///   * sect571r1: `bits` = 571
688    SectR1,
689    /// SEC additional random curves over binary fields.
690    /// This family comprises the following curves:
691    ///   * sect163r2 : bits = 163 (DEPRECATED)
692    #[deprecated = "This family of curve is weak and deprecated."]
693    SectR2,
694    /// Brainpool P random curves.
695    /// This family comprises the following curves:
696    ///   * brainpoolP160r1: `bits` = 160 (DEPRECATED)
697    ///   * brainpoolP192r1: `bits` = 192
698    ///   * brainpoolP224r1: `bits` = 224
699    ///   * brainpoolP256r1: `bits` = 256
700    ///   * brainpoolP320r1: `bits` = 320
701    ///   * brainpoolP384r1: `bits` = 384
702    ///   * brainpoolP512r1: `bits` = 512
703    BrainpoolPR1,
704    /// Curve used primarily in France and elsewhere in Europe.
705    /// This family comprises one 256-bit curve:
706    ///   * FRP256v1: `bits` = 256
707    Frp,
708    /// Montgomery curves.
709    /// This family comprises the following Montgomery curves:
710    ///   * Curve25519: `bits` = 255
711    ///   * Curve448: `bits` = 448
712    Montgomery,
713}
714
715impl fmt::Display for EccFamily {
716    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
717        match self {
718            EccFamily::SecpK1 => write!(f, "SEC Koblitz curves over prime fields"),
719            EccFamily::SecpR1 => write!(f, "SEC random curves over prime fields"),
720            EccFamily::SecpR2 => write!(f, "SEC additional random curves over prime fields"),
721            EccFamily::SectK1 => write!(f, "SEC Koblitz curves over binary fields"),
722            EccFamily::SectR1 => write!(f, "SEC random curves over binary fields"),
723            EccFamily::SectR2 => write!(f, "SEC additional random curves over binary fields"),
724            EccFamily::BrainpoolPR1 => write!(f, "Brainpool P random curves"),
725            EccFamily::Frp => write!(f, "FRP curve"),
726            EccFamily::Montgomery => write!(f, "Montgomery curve"),
727        }
728    }
729}
730
731/// Enumeration of Diffie Hellman group families supported.
732#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Zeroize)]
733pub enum DhFamily {
734    /// Diffie-Hellman groups defined in RFC 7919 Appendix A.
735    /// This family includes groups with the following `bits`: 2048, 3072, 4096, 6144, 8192.
736    /// An implementation can support all of these sizes or only a subset.
737    Rfc7919,
738}
739
740impl fmt::Display for DhFamily {
741    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
742        match self {
743            DhFamily::Rfc7919 => write!(f, "Diffie-Hellman groups defined in RFC 7919 Appendix A"),
744        }
745    }
746}
747
748/// Definition of the key policy, what is permitted to do with the key.
749#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Zeroize)]
750pub struct Policy {
751    /// Usage flags for the key.
752    pub usage_flags: UsageFlags,
753    /// Permitted algorithms to be used with the key.
754    pub permitted_algorithms: Algorithm,
755}
756
757/// Definition of the usage flags. They encode what kind of operations are permitted on the key.
758#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, Zeroize)]
759pub struct UsageFlags {
760    /// Permission to export the key.
761    export: bool,
762    /// Permission to copy the key.
763    copy: bool,
764    /// Permission for the implementation to cache the key.
765    cache: bool,
766    /// Permission to encrypt a message with the key.
767    encrypt: bool,
768    /// Permission to decrypt a message with the key.
769    decrypt: bool,
770    /// Permission to sign a message with the key.
771    sign_message: bool,
772    /// Permission to verify a message signature with the key.
773    verify_message: bool,
774    /// Permission to sign a message hash with the key.
775    sign_hash: bool,
776    /// Permission to verify a message hash with the key.
777    verify_hash: bool,
778    /// Permission to derive other keys from this key.
779    derive: bool,
780}
781
782impl UsageFlags {
783    ///Setter for the export flag
784    pub fn set_export(&mut self) -> &mut Self {
785        self.export = true;
786        self
787    }
788    ///Getter for the export flag
789    pub fn export(&self) -> bool {
790        self.export
791    }
792    ///Setter for the copy flag
793    pub fn set_copy(&mut self) -> &mut Self {
794        self.copy = true;
795        self
796    }
797    ///Getter for the copy flag
798    pub fn copy(&self) -> bool {
799        self.copy
800    }
801    ///Setter for the cache flag
802    pub fn set_cache(&mut self) -> &mut Self {
803        self.cache = true;
804        self
805    }
806    ///Getter for the cache flag
807    pub fn cache(&self) -> bool {
808        self.cache
809    }
810    ///Setter for the encrypt flag
811    pub fn set_encrypt(&mut self) -> &mut Self {
812        self.encrypt = true;
813        self
814    }
815    ///Getter for the encrypt flag
816    pub fn encrypt(&self) -> bool {
817        self.encrypt
818    }
819    ///Setter for the decrypt flag
820    pub fn set_decrypt(&mut self) -> &mut Self {
821        self.decrypt = true;
822        self
823    }
824    ///Getter for the decrypt flag
825    pub fn decrypt(&self) -> bool {
826        self.decrypt
827    }
828    ///Setter for the sign_hash flag (also sets the sign_message flag)
829    pub fn set_sign_hash(&mut self) -> &mut Self {
830        self.sign_hash = true;
831        self.sign_message = true;
832        self
833    }
834    ///Getter for the sign_hash flag
835    pub fn sign_hash(&self) -> bool {
836        self.sign_hash
837    }
838    ///Setter for the sign_message flag
839    pub fn set_sign_message(&mut self) -> &mut Self {
840        self.sign_message = true;
841        self
842    }
843    ///Getter for the sign_message flag
844    pub fn sign_message(&self) -> bool {
845        self.sign_message
846    }
847    ///Setter for the verify_hash flag (also sets the varify_message flag)
848    pub fn set_verify_hash(&mut self) -> &mut Self {
849        self.verify_hash = true;
850        self.verify_message = true;
851        self
852    }
853    ///Getter for the verify_hash flag
854    pub fn verify_hash(&self) -> bool {
855        self.verify_hash
856    }
857    ///Setter for the verify_message flag
858    pub fn set_verify_message(&mut self) -> &mut Self {
859        self.verify_message = true;
860        self
861    }
862    ///Getter for the verify_message flag
863    pub fn verify_message(&self) -> bool {
864        self.verify_message
865    }
866    ///Setter for the derive flag
867    pub fn set_derive(&mut self) -> &mut Self {
868        self.derive = true;
869        self
870    }
871    ///Getter for the derive flag
872    pub fn derive(&self) -> bool {
873        self.derive
874    }
875}
876
877/// Definition of the key ID.
878#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Zeroize)]
879pub struct Id(pub(crate) psa_key_id_t);
880
881impl Id {
882    /// Create a new Id from a persistent key ID
883    #[cfg(feature = "operations")]
884    pub fn from_persistent_key_id(id: u32) -> Result<Self> {
885        // Checking if the id is one of a persistent key that exists by fetching its attributes.
886        let _ = Attributes::from_key_id(Id(id))?;
887
888        Ok(Id(id))
889    }
890}
891
892#[cfg(feature = "interface")]
893impl TryFrom<Attributes> for psa_crypto_sys::psa_key_attributes_t {
894    type Error = Error;
895    fn try_from(attributes: Attributes) -> Result<Self> {
896        let mut attrs = unsafe { psa_crypto_sys::psa_key_attributes_init() };
897        unsafe { psa_crypto_sys::psa_set_key_lifetime(&mut attrs, attributes.lifetime.into()) };
898        unsafe {
899            psa_crypto_sys::psa_set_key_usage_flags(
900                &mut attrs,
901                attributes.policy.usage_flags.into(),
902            )
903        };
904        unsafe {
905            psa_crypto_sys::psa_set_key_algorithm(
906                &mut attrs,
907                attributes.policy.permitted_algorithms.try_into()?,
908            )
909        };
910        unsafe { psa_crypto_sys::psa_set_key_type(&mut attrs, attributes.key_type.try_into()?) };
911        unsafe { psa_crypto_sys::psa_set_key_bits(&mut attrs, attributes.try_into()?) };
912
913        Ok(attrs)
914    }
915}
916
917#[cfg(feature = "interface")]
918impl TryFrom<Attributes> for usize {
919    type Error = Error;
920    // Check if key size is correct for the key type
921    fn try_from(attributes: Attributes) -> Result<Self> {
922        // For some operations like import 0 size is permitted
923        if attributes.bits == 0 {
924            return Ok(attributes.bits);
925        }
926        match attributes.key_type {
927            Type::EccKeyPair { curve_family } | Type::EccPublicKey { curve_family } => {
928                match curve_family {
929                    // SEC random curves over prime fields.
930                    EccFamily::SecpR1 => match attributes.bits {
931                        192 | 224 | 256 | 284 | 521 => Ok(attributes.bits),
932                        _ => {
933                            error!("Requested key size is not supported ({})", attributes.bits);
934                            Err(Error::InvalidArgument)
935                        }
936                    },
937                    // SEC Koblitz curves over prime fields.
938                    EccFamily::SecpK1 => match attributes.bits {
939                        192 | 224 | 256 => Ok(attributes.bits),
940                        _ => {
941                            error!("Requested key size is not supported ({})", attributes.bits);
942                            Err(Error::InvalidArgument)
943                        }
944                    },
945                    // SEC Koblitz curves over binary fields
946                    EccFamily::SectK1 => match attributes.bits {
947                        233 | 239 | 283 | 409 | 571 => Ok(attributes.bits),
948                        _ => {
949                            error!("Requested key size is not supported ({})", attributes.bits);
950                            Err(Error::InvalidArgument)
951                        }
952                    },
953                    // SEC random curves over binary fields
954                    EccFamily::SectR1 => match attributes.bits {
955                        233 | 283 | 409 | 571 => Ok(attributes.bits),
956                        _ => {
957                            error!("Requested key size is not supported ({})", attributes.bits);
958                            Err(Error::InvalidArgument)
959                        }
960                    },
961                    // Brainpool P random curves
962                    EccFamily::BrainpoolPR1 => match attributes.bits {
963                        192 | 224 | 256 | 320 | 384 | 512 => Ok(attributes.bits),
964                        _ => {
965                            error!("Requested key size is not supported ({})", attributes.bits);
966                            Err(Error::InvalidArgument)
967                        }
968                    },
969                    // Curve used primarily in France and elsewhere in Europe.
970                    EccFamily::Frp => match attributes.bits {
971                        256 => Ok(attributes.bits),
972                        _ => {
973                            error!("Requested key size is not supported ({})", attributes.bits);
974                            Err(Error::InvalidArgument)
975                        }
976                    },
977                    // Montgomery curves
978                    EccFamily::Montgomery => match attributes.bits {
979                        255 | 448 => Ok(attributes.bits),
980                        _ => {
981                            error!("Requested key size is not supported ({})", attributes.bits);
982                            Err(Error::InvalidArgument)
983                        }
984                    },
985                    _ => {
986                        // We don't (yet?) implement checks for other curve families
987                        Ok(attributes.bits)
988                    }
989                }
990            }
991            _ => {
992                // TO-DO We don't (yet?) implement checks for other types
993                Ok(attributes.bits)
994            }
995        }
996    }
997}
998
999#[cfg(feature = "interface")]
1000impl TryFrom<psa_crypto_sys::psa_key_attributes_t> for Attributes {
1001    type Error = Error;
1002    fn try_from(attributes: psa_crypto_sys::psa_key_attributes_t) -> Result<Self> {
1003        Ok(Attributes {
1004            lifetime: unsafe { psa_crypto_sys::psa_get_key_lifetime(&attributes).into() },
1005            key_type: unsafe { psa_crypto_sys::psa_get_key_type(&attributes).try_into()? },
1006            bits: unsafe { psa_crypto_sys::psa_get_key_bits(&attributes) },
1007            policy: Policy {
1008                usage_flags: unsafe { psa_crypto_sys::psa_get_key_usage_flags(&attributes).into() },
1009                permitted_algorithms: unsafe {
1010                    psa_crypto_sys::psa_get_key_algorithm(&attributes).try_into()?
1011                },
1012            },
1013        })
1014    }
1015}
1016
1017#[cfg(feature = "interface")]
1018impl From<Lifetime> for psa_crypto_sys::psa_key_lifetime_t {
1019    fn from(lifetime: Lifetime) -> Self {
1020        match lifetime {
1021            Lifetime::Volatile => psa_crypto_sys::PSA_KEY_LIFETIME_VOLATILE,
1022            Lifetime::Persistent => psa_crypto_sys::PSA_KEY_LIFETIME_PERSISTENT,
1023            Lifetime::Custom(value) => value,
1024        }
1025    }
1026}
1027
1028#[cfg(feature = "interface")]
1029impl From<psa_crypto_sys::psa_key_lifetime_t> for Lifetime {
1030    fn from(lifetime: psa_crypto_sys::psa_key_lifetime_t) -> Self {
1031        match lifetime {
1032            psa_crypto_sys::PSA_KEY_LIFETIME_VOLATILE => Lifetime::Volatile,
1033            psa_crypto_sys::PSA_KEY_LIFETIME_PERSISTENT => Lifetime::Persistent,
1034            value => Lifetime::Custom(value),
1035        }
1036    }
1037}
1038
1039#[cfg(feature = "interface")]
1040impl From<UsageFlags> for psa_crypto_sys::psa_key_usage_t {
1041    fn from(flags: UsageFlags) -> Self {
1042        let mut usage_flags = 0;
1043        if flags.export {
1044            usage_flags |= psa_crypto_sys::PSA_KEY_USAGE_EXPORT;
1045        }
1046        if flags.encrypt {
1047            usage_flags |= psa_crypto_sys::PSA_KEY_USAGE_ENCRYPT;
1048        }
1049        if flags.decrypt {
1050            usage_flags |= psa_crypto_sys::PSA_KEY_USAGE_DECRYPT;
1051        }
1052        //TODO: not yet implemented in Mbed Crypto, uncomment when added
1053        //if flags.sign_message {
1054        //  usage_flags |= psa_crypto_sys::PSA_KEY_USAGE_SIGN_MESSAGE;
1055        //}
1056        if flags.sign_hash {
1057            usage_flags |= psa_crypto_sys::PSA_KEY_USAGE_SIGN_HASH;
1058        }
1059        //if flags.verify_message {
1060        //  usage_flags |= psa_crypto_sys::PSA_KEY_USAGE_VERIFY_MESSAGE;
1061        //}
1062        if flags.verify_hash {
1063            usage_flags |= psa_crypto_sys::PSA_KEY_USAGE_VERIFY_HASH;
1064        }
1065        if flags.derive {
1066            usage_flags |= psa_crypto_sys::PSA_KEY_USAGE_DERIVE;
1067        }
1068        if flags.copy {
1069            usage_flags |= psa_crypto_sys::PSA_KEY_USAGE_COPY;
1070        }
1071        usage_flags
1072    }
1073}
1074
1075#[cfg(feature = "interface")]
1076impl From<psa_crypto_sys::psa_key_usage_t> for UsageFlags {
1077    fn from(flags: psa_crypto_sys::psa_key_usage_t) -> Self {
1078        UsageFlags {
1079            export: flags & psa_crypto_sys::PSA_KEY_USAGE_EXPORT > 0,
1080            copy: false,
1081            cache: false,
1082            encrypt: flags & psa_crypto_sys::PSA_KEY_USAGE_ENCRYPT > 0,
1083            decrypt: flags & psa_crypto_sys::PSA_KEY_USAGE_DECRYPT > 0,
1084            sign_message: flags & psa_crypto_sys::PSA_KEY_USAGE_SIGN_MESSAGE > 0,
1085            verify_message: flags & psa_crypto_sys::PSA_KEY_USAGE_VERIFY_MESSAGE > 0,
1086            sign_hash: flags & psa_crypto_sys::PSA_KEY_USAGE_SIGN_HASH > 0,
1087            verify_hash: flags & psa_crypto_sys::PSA_KEY_USAGE_VERIFY_HASH > 0,
1088            derive: flags & psa_crypto_sys::PSA_KEY_USAGE_DERIVE > 0,
1089        }
1090    }
1091}
1092
1093#[cfg(feature = "interface")]
1094impl TryFrom<EccFamily> for psa_crypto_sys::psa_ecc_family_t {
1095    type Error = Error;
1096    fn try_from(family: EccFamily) -> Result<Self> {
1097        match family {
1098            EccFamily::SecpK1 => Ok(psa_crypto_sys::PSA_ECC_FAMILY_SECP_K1),
1099            EccFamily::SecpR1 => Ok(psa_crypto_sys::PSA_ECC_FAMILY_SECP_R1),
1100            EccFamily::SecpR2 => Ok(psa_crypto_sys::PSA_ECC_FAMILY_SECP_R2),
1101            EccFamily::SectK1 => Ok(psa_crypto_sys::PSA_ECC_FAMILY_SECT_K1),
1102            EccFamily::SectR1 => Ok(psa_crypto_sys::PSA_ECC_FAMILY_SECT_R1),
1103            EccFamily::SectR2 => Ok(psa_crypto_sys::PSA_ECC_FAMILY_SECT_R2),
1104            EccFamily::BrainpoolPR1 => Ok(psa_crypto_sys::PSA_ECC_FAMILY_BRAINPOOL_P_R1),
1105            EccFamily::Frp => Err(Error::NotSupported),
1106            EccFamily::Montgomery => Ok(psa_crypto_sys::PSA_ECC_FAMILY_MONTGOMERY),
1107        }
1108    }
1109}
1110
1111#[cfg(feature = "interface")]
1112impl TryFrom<psa_crypto_sys::psa_ecc_family_t> for EccFamily {
1113    type Error = Error;
1114    fn try_from(family: psa_crypto_sys::psa_ecc_family_t) -> Result<Self> {
1115        match family {
1116            psa_crypto_sys::PSA_ECC_FAMILY_SECP_K1 => Ok(EccFamily::SecpK1),
1117            psa_crypto_sys::PSA_ECC_FAMILY_SECP_R1 => Ok(EccFamily::SecpR1),
1118            psa_crypto_sys::PSA_ECC_FAMILY_SECP_R2 => Ok(EccFamily::SecpR2),
1119            psa_crypto_sys::PSA_ECC_FAMILY_SECT_R1 => Ok(EccFamily::SectR1),
1120            psa_crypto_sys::PSA_ECC_FAMILY_SECT_R2 => Ok(EccFamily::SectR2),
1121            psa_crypto_sys::PSA_ECC_FAMILY_BRAINPOOL_P_R1 => Ok(EccFamily::BrainpoolPR1),
1122            //psa_crypto_sys::PSA_ECC_FAMILY_FRP => Ok(EccFamily::Frp),
1123            psa_crypto_sys::PSA_ECC_FAMILY_MONTGOMERY => Ok(EccFamily::Montgomery),
1124            f => {
1125                error!("Can not recognize the ECC family: {:?}.", f);
1126                Err(Error::GenericError)
1127            }
1128        }
1129    }
1130}
1131
1132#[cfg(feature = "interface")]
1133impl From<DhFamily> for psa_crypto_sys::psa_dh_family_t {
1134    fn from(group: DhFamily) -> Self {
1135        match group {
1136            DhFamily::Rfc7919 => psa_crypto_sys::PSA_DH_FAMILY_RFC7919,
1137        }
1138    }
1139}
1140
1141#[cfg(feature = "interface")]
1142impl TryFrom<psa_crypto_sys::psa_dh_family_t> for DhFamily {
1143    type Error = Error;
1144    fn try_from(group: psa_crypto_sys::psa_dh_family_t) -> Result<Self> {
1145        match group {
1146            psa_crypto_sys::PSA_DH_FAMILY_RFC7919 => Ok(DhFamily::Rfc7919),
1147            f => {
1148                error!("Can not recognize the DH family: {:?}.", f);
1149                Err(Error::GenericError)
1150            }
1151        }
1152    }
1153}
1154
1155#[cfg(feature = "interface")]
1156impl TryFrom<Type> for psa_crypto_sys::psa_key_type_t {
1157    type Error = Error;
1158    fn try_from(key_type: Type) -> Result<Self> {
1159        match key_type {
1160            Type::RawData => Ok(psa_crypto_sys::PSA_KEY_TYPE_RAW_DATA),
1161            Type::Hmac => Ok(psa_crypto_sys::PSA_KEY_TYPE_HMAC),
1162            Type::Derive => Ok(psa_crypto_sys::PSA_KEY_TYPE_DERIVE),
1163            Type::Aes => Ok(psa_crypto_sys::PSA_KEY_TYPE_AES),
1164            Type::Des => Ok(psa_crypto_sys::PSA_KEY_TYPE_DES),
1165            Type::Camellia => Ok(psa_crypto_sys::PSA_KEY_TYPE_CAMELLIA),
1166            Type::Arc4 => Ok(psa_crypto_sys::PSA_KEY_TYPE_ARC4),
1167            Type::Chacha20 => Ok(psa_crypto_sys::PSA_KEY_TYPE_CHACHA20),
1168            Type::RsaPublicKey => Ok(psa_crypto_sys::PSA_KEY_TYPE_RSA_PUBLIC_KEY),
1169            Type::RsaKeyPair => Ok(psa_crypto_sys::PSA_KEY_TYPE_RSA_KEY_PAIR),
1170            Type::EccKeyPair { curve_family } => Ok(psa_crypto_sys::PSA_KEY_TYPE_ECC_KEY_PAIR(
1171                curve_family.try_into()?,
1172            )),
1173            Type::EccPublicKey { curve_family } => Ok(psa_crypto_sys::PSA_KEY_TYPE_ECC_PUBLIC_KEY(
1174                curve_family.try_into()?,
1175            )),
1176            Type::DhKeyPair { group_family } => Ok(psa_crypto_sys::PSA_KEY_TYPE_DH_KEY_PAIR(
1177                group_family.into(),
1178            )),
1179            Type::DhPublicKey { group_family } => Ok(psa_crypto_sys::PSA_KEY_TYPE_DH_PUBLIC_KEY(
1180                group_family.into(),
1181            )),
1182        }
1183    }
1184}
1185
1186#[cfg(feature = "interface")]
1187impl TryFrom<psa_crypto_sys::psa_key_type_t> for Type {
1188    type Error = Error;
1189    fn try_from(key_type: psa_crypto_sys::psa_key_type_t) -> Result<Self> {
1190        match key_type {
1191            psa_crypto_sys::PSA_KEY_TYPE_RAW_DATA => Ok(Type::RawData),
1192            psa_crypto_sys::PSA_KEY_TYPE_HMAC => Ok(Type::Hmac),
1193            psa_crypto_sys::PSA_KEY_TYPE_DERIVE => Ok(Type::Derive),
1194            psa_crypto_sys::PSA_KEY_TYPE_AES => Ok(Type::Aes),
1195            psa_crypto_sys::PSA_KEY_TYPE_DES => Ok(Type::Des),
1196            psa_crypto_sys::PSA_KEY_TYPE_CAMELLIA => Ok(Type::Camellia),
1197            psa_crypto_sys::PSA_KEY_TYPE_ARC4 => Ok(Type::Arc4),
1198            psa_crypto_sys::PSA_KEY_TYPE_CHACHA20 => Ok(Type::Chacha20),
1199            psa_crypto_sys::PSA_KEY_TYPE_RSA_PUBLIC_KEY => Ok(Type::RsaPublicKey),
1200            psa_crypto_sys::PSA_KEY_TYPE_RSA_KEY_PAIR => Ok(Type::RsaKeyPair),
1201            key_type if psa_crypto_sys::PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) => {
1202                Ok(Type::EccKeyPair {
1203                    curve_family: psa_crypto_sys::PSA_KEY_TYPE_ECC_GET_FAMILY(key_type)
1204                        .try_into()?,
1205                })
1206            }
1207            key_type if psa_crypto_sys::PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(key_type) => {
1208                Ok(Type::EccPublicKey {
1209                    curve_family: psa_crypto_sys::PSA_KEY_TYPE_ECC_GET_FAMILY(key_type)
1210                        .try_into()?,
1211                })
1212            }
1213            key_type if psa_crypto_sys::PSA_KEY_TYPE_IS_DH_PUBLIC_KEY(key_type) => {
1214                Ok(Type::DhPublicKey {
1215                    group_family: psa_crypto_sys::PSA_KEY_TYPE_DH_GET_FAMILY(key_type)
1216                        .try_into()?,
1217                })
1218            }
1219            key_type if psa_crypto_sys::PSA_KEY_TYPE_IS_DH_KEY_PAIR(key_type) => {
1220                Ok(Type::DhKeyPair {
1221                    group_family: psa_crypto_sys::PSA_KEY_TYPE_DH_GET_FAMILY(key_type)
1222                        .try_into()?,
1223                })
1224            }
1225            key_type => {
1226                error!("Can not recognize the key type: {:?}.", key_type);
1227                Err(Error::GenericError)
1228            }
1229        }
1230    }
1231}
1232
1233#[cfg(test)]
1234mod tests {
1235    use super::{Attributes, EccFamily, Lifetime, Policy, Type, UsageFlags};
1236    use crate::types::algorithm::{
1237        Aead, AeadWithDefaultLengthTag, Algorithm, AsymmetricSignature, Cipher, FullLengthMac,
1238        Hash, Mac, SignHash,
1239    };
1240    use core::convert::TryInto;
1241
1242    #[test]
1243    fn usage_flags() {
1244        let permitted_alg = Algorithm::AsymmetricSignature(AsymmetricSignature::RsaPkcs1v15Sign {
1245            hash_alg: Hash::Sha256.into(),
1246        });
1247        let mut attributes = Attributes {
1248            key_type: Type::RsaKeyPair,
1249            bits: 1024,
1250            lifetime: Lifetime::Volatile,
1251            policy: Policy {
1252                usage_flags: UsageFlags {
1253                    export: false,
1254                    copy: false,
1255                    cache: false,
1256                    encrypt: false,
1257                    decrypt: false,
1258                    sign_message: false,
1259                    verify_message: false,
1260                    sign_hash: false,
1261                    verify_hash: false,
1262                    derive: false,
1263                },
1264                permitted_algorithms: permitted_alg,
1265            },
1266        };
1267
1268        assert!(!attributes.is_exportable());
1269        assert!(!attributes.is_hash_signable());
1270        assert!(!attributes.is_hash_verifiable());
1271        attributes.policy.usage_flags.export = true;
1272        assert!(attributes.is_exportable());
1273        assert!(!attributes.is_hash_signable());
1274        assert!(!attributes.is_hash_verifiable());
1275        attributes.policy.usage_flags.sign_hash = true;
1276        assert!(attributes.is_exportable());
1277        assert!(attributes.is_hash_signable());
1278        assert!(!attributes.is_hash_verifiable());
1279        attributes.policy.usage_flags.verify_hash = true;
1280        assert!(attributes.is_exportable());
1281        assert!(attributes.is_hash_signable());
1282        assert!(attributes.is_hash_verifiable());
1283
1284        assert!(!attributes.is_derivable());
1285        attributes.policy.usage_flags.derive = true;
1286        assert!(attributes.is_derivable())
1287    }
1288
1289    #[test]
1290    fn permits_good_alg() {
1291        let permitted_alg = Algorithm::AsymmetricSignature(AsymmetricSignature::RsaPkcs1v15Sign {
1292            hash_alg: Hash::Sha256.into(),
1293        });
1294        let alg = Algorithm::AsymmetricSignature(AsymmetricSignature::RsaPkcs1v15Sign {
1295            hash_alg: Hash::Sha256.into(),
1296        });
1297        let attributes = Attributes {
1298            key_type: Type::Hmac,
1299            bits: 1024,
1300            lifetime: Lifetime::Volatile,
1301            policy: Policy {
1302                usage_flags: UsageFlags {
1303                    export: false,
1304                    copy: false,
1305                    cache: false,
1306                    encrypt: false,
1307                    decrypt: false,
1308                    sign_message: false,
1309                    verify_message: false,
1310                    sign_hash: true,
1311                    verify_hash: false,
1312                    derive: false,
1313                },
1314                permitted_algorithms: permitted_alg,
1315            },
1316        };
1317        assert!(attributes.is_alg_permitted(alg));
1318    }
1319
1320    #[test]
1321    fn permits_bad_alg() {
1322        let permitted_alg = Algorithm::Mac(Mac::FullLength(FullLengthMac::Hmac {
1323            hash_alg: Hash::Sha1,
1324        }));
1325        let alg = Algorithm::AsymmetricSignature(AsymmetricSignature::RsaPkcs1v15Sign {
1326            hash_alg: Hash::Sha1.into(),
1327        });
1328        let attributes = Attributes {
1329            key_type: Type::Hmac,
1330            bits: 1024,
1331            lifetime: Lifetime::Volatile,
1332            policy: Policy {
1333                usage_flags: UsageFlags {
1334                    export: false,
1335                    copy: false,
1336                    cache: false,
1337                    encrypt: false,
1338                    decrypt: false,
1339                    sign_message: false,
1340                    verify_message: false,
1341                    sign_hash: true,
1342                    verify_hash: false,
1343                    derive: false,
1344                },
1345                permitted_algorithms: permitted_alg,
1346            },
1347        };
1348        assert!(!attributes.is_alg_permitted(alg));
1349    }
1350
1351    #[test]
1352    fn permits_wildcard_alg() {
1353        let permitted_alg = Algorithm::AsymmetricSignature(AsymmetricSignature::RsaPkcs1v15Sign {
1354            hash_alg: SignHash::Any,
1355        });
1356        let alg = Algorithm::AsymmetricSignature(AsymmetricSignature::RsaPkcs1v15Sign {
1357            hash_alg: Hash::Sha1.into(),
1358        });
1359        let attributes = Attributes {
1360            key_type: Type::Hmac,
1361            bits: 1024,
1362            lifetime: Lifetime::Volatile,
1363            policy: Policy {
1364                usage_flags: UsageFlags {
1365                    export: false,
1366                    copy: false,
1367                    cache: false,
1368                    encrypt: false,
1369                    decrypt: false,
1370                    sign_message: false,
1371                    verify_message: false,
1372                    sign_hash: true,
1373                    verify_hash: false,
1374                    derive: false,
1375                },
1376                permitted_algorithms: permitted_alg,
1377            },
1378        };
1379        assert!(attributes.is_alg_permitted(alg));
1380    }
1381
1382    #[test]
1383    fn permits_bad_wildcard_alg() {
1384        let permitted_alg = Algorithm::AsymmetricSignature(AsymmetricSignature::RsaPkcs1v15Sign {
1385            hash_alg: Hash::Sha256.into(),
1386        });
1387        let alg = Algorithm::AsymmetricSignature(AsymmetricSignature::RsaPkcs1v15Sign {
1388            hash_alg: SignHash::Any,
1389        });
1390        let attributes = Attributes {
1391            key_type: Type::Hmac,
1392            bits: 1024,
1393            lifetime: Lifetime::Volatile,
1394            policy: Policy {
1395                usage_flags: UsageFlags {
1396                    export: false,
1397                    copy: false,
1398                    cache: false,
1399                    encrypt: false,
1400                    decrypt: false,
1401                    sign_message: false,
1402                    verify_message: false,
1403                    sign_hash: true,
1404                    verify_hash: false,
1405                    derive: false,
1406                },
1407                permitted_algorithms: permitted_alg,
1408            },
1409        };
1410        assert!(!attributes.is_alg_permitted(alg));
1411    }
1412
1413    #[test]
1414    fn compat_rsa() {
1415        let permitted_alg = Algorithm::AsymmetricSignature(AsymmetricSignature::RsaPkcs1v15Sign {
1416            hash_alg: Hash::Sha256.into(),
1417        });
1418        let alg = Algorithm::AsymmetricSignature(AsymmetricSignature::RsaPkcs1v15Sign {
1419            hash_alg: Hash::Sha256.into(),
1420        });
1421        let mut attributes = Attributes {
1422            key_type: Type::RsaKeyPair,
1423            bits: 1024,
1424            lifetime: Lifetime::Volatile,
1425            policy: Policy {
1426                usage_flags: UsageFlags {
1427                    export: false,
1428                    copy: false,
1429                    cache: false,
1430                    encrypt: false,
1431                    decrypt: false,
1432                    sign_message: false,
1433                    verify_message: false,
1434                    sign_hash: false,
1435                    verify_hash: false,
1436                    derive: false,
1437                },
1438                permitted_algorithms: permitted_alg,
1439            },
1440        };
1441
1442        assert!(attributes.is_compatible_with_alg(alg));
1443        attributes.key_type = Type::RsaPublicKey;
1444        assert!(attributes.is_compatible_with_alg(alg));
1445    }
1446
1447    #[test]
1448    fn compat_raw_data() {
1449        let permitted_alg = Algorithm::None;
1450        let alg = Algorithm::AsymmetricSignature(AsymmetricSignature::RsaPkcs1v15Sign {
1451            hash_alg: Hash::Sha256.into(),
1452        });
1453        let attributes = Attributes {
1454            key_type: Type::RawData,
1455            bits: 1024,
1456            lifetime: Lifetime::Volatile,
1457            policy: Policy {
1458                usage_flags: UsageFlags {
1459                    export: false,
1460                    copy: false,
1461                    cache: false,
1462                    encrypt: false,
1463                    decrypt: false,
1464                    sign_message: false,
1465                    verify_message: false,
1466                    sign_hash: false,
1467                    verify_hash: false,
1468                    derive: false,
1469                },
1470                permitted_algorithms: permitted_alg,
1471            },
1472        };
1473
1474        assert!(!attributes.is_compatible_with_alg(alg));
1475    }
1476
1477    #[test]
1478    fn compat_block_cipher() {
1479        let permitted_alg = Algorithm::AsymmetricSignature(AsymmetricSignature::RsaPkcs1v15Sign {
1480            hash_alg: Hash::Sha256.into(),
1481        });
1482        let mut alg = Algorithm::Cipher(Cipher::Ofb);
1483        let mut attributes = Attributes {
1484            key_type: Type::Aes,
1485            bits: 1024,
1486            lifetime: Lifetime::Volatile,
1487            policy: Policy {
1488                usage_flags: UsageFlags {
1489                    export: false,
1490                    copy: false,
1491                    cache: false,
1492                    encrypt: false,
1493                    decrypt: false,
1494                    sign_message: false,
1495                    verify_message: false,
1496                    sign_hash: false,
1497                    verify_hash: false,
1498                    derive: false,
1499                },
1500                permitted_algorithms: permitted_alg,
1501            },
1502        };
1503
1504        assert!(attributes.is_compatible_with_alg(alg));
1505        attributes.key_type = Type::Des;
1506        assert!(attributes.is_compatible_with_alg(alg));
1507        attributes.key_type = Type::Camellia;
1508        assert!(attributes.is_compatible_with_alg(alg));
1509        alg = Algorithm::Aead(Aead::AeadWithDefaultLengthTag(
1510            AeadWithDefaultLengthTag::Ccm,
1511        ));
1512        assert!(attributes.is_compatible_with_alg(alg));
1513        attributes.key_type = Type::Des;
1514        assert!(!attributes.is_compatible_with_alg(alg));
1515    }
1516
1517    #[test]
1518    fn compat_chacha() {
1519        let permitted_alg = Algorithm::AsymmetricSignature(AsymmetricSignature::RsaPkcs1v15Sign {
1520            hash_alg: Hash::Sha256.into(),
1521        });
1522        let alg = Algorithm::Aead(Aead::AeadWithDefaultLengthTag(
1523            AeadWithDefaultLengthTag::Chacha20Poly1305,
1524        ));
1525        let attributes = Attributes {
1526            key_type: Type::Chacha20,
1527            bits: 1024,
1528            lifetime: Lifetime::Volatile,
1529            policy: Policy {
1530                usage_flags: UsageFlags {
1531                    export: false,
1532                    copy: false,
1533                    cache: false,
1534                    encrypt: false,
1535                    decrypt: false,
1536                    sign_message: false,
1537                    verify_message: false,
1538                    sign_hash: false,
1539                    verify_hash: false,
1540                    derive: false,
1541                },
1542                permitted_algorithms: permitted_alg,
1543            },
1544        };
1545
1546        assert!(attributes.is_compatible_with_alg(alg));
1547    }
1548
1549    #[test]
1550    fn bad_compat() {
1551        let permitted_alg = Algorithm::AsymmetricSignature(AsymmetricSignature::RsaPkcs1v15Sign {
1552            hash_alg: Hash::Sha256.into(),
1553        });
1554        let alg = Algorithm::AsymmetricSignature(AsymmetricSignature::RsaPkcs1v15Sign {
1555            hash_alg: Hash::Sha256.into(),
1556        });
1557        let attributes = Attributes {
1558            key_type: Type::Hmac,
1559            bits: 1024,
1560            lifetime: Lifetime::Volatile,
1561            policy: Policy {
1562                usage_flags: UsageFlags {
1563                    export: false,
1564                    copy: false,
1565                    cache: false,
1566                    encrypt: false,
1567                    decrypt: false,
1568                    sign_message: false,
1569                    verify_message: false,
1570                    sign_hash: false,
1571                    verify_hash: false,
1572                    derive: false,
1573                },
1574                permitted_algorithms: permitted_alg,
1575            },
1576        };
1577
1578        assert!(!attributes.is_compatible_with_alg(alg));
1579    }
1580
1581    #[test]
1582    fn convert() {
1583        let mut attrs = unsafe { psa_crypto_sys::psa_key_attributes_init() };
1584        unsafe {
1585            psa_crypto_sys::psa_set_key_lifetime(
1586                &mut attrs,
1587                psa_crypto_sys::PSA_KEY_LIFETIME_VOLATILE,
1588            )
1589        };
1590        unsafe {
1591            psa_crypto_sys::psa_set_key_usage_flags(
1592                &mut attrs,
1593                psa_crypto_sys::PSA_KEY_USAGE_SIGN_MESSAGE
1594                    | psa_crypto_sys::PSA_KEY_USAGE_VERIFY_MESSAGE,
1595            )
1596        };
1597        unsafe {
1598            psa_crypto_sys::psa_set_key_algorithm(
1599                &mut attrs,
1600                psa_crypto_sys::PSA_ALG_ECDSA(psa_crypto_sys::PSA_ALG_SHA_256),
1601            )
1602        };
1603        unsafe {
1604            psa_crypto_sys::psa_set_key_type(
1605                &mut attrs,
1606                psa_crypto_sys::PSA_KEY_TYPE_ECC_KEY_PAIR(psa_crypto_sys::PSA_ECC_FAMILY_SECP_K1),
1607            )
1608        };
1609        unsafe { psa_crypto_sys::psa_set_key_bits(&mut attrs, 2048) };
1610
1611        assert_eq!(
1612            Attributes {
1613                key_type: Type::EccKeyPair {
1614                    curve_family: EccFamily::SecpK1,
1615                },
1616                bits: 2048,
1617                lifetime: Lifetime::Volatile,
1618                policy: Policy {
1619                    usage_flags: UsageFlags {
1620                        export: false,
1621                        copy: false,
1622                        cache: false,
1623                        encrypt: false,
1624                        decrypt: false,
1625                        sign_message: true,
1626                        verify_message: true,
1627                        sign_hash: false,
1628                        verify_hash: false,
1629                        derive: false,
1630                    },
1631                    permitted_algorithms: AsymmetricSignature::Ecdsa {
1632                        hash_alg: Hash::Sha256.into(),
1633                    }
1634                    .into(),
1635                },
1636            },
1637            attrs.try_into().unwrap()
1638        );
1639    }
1640}