1#![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#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Zeroize)]
26pub struct Attributes {
27 pub lifetime: Lifetime,
29 pub key_type: Type,
31 pub bits: usize,
33 pub policy: Policy,
35}
36
37impl Attributes {
38 pub fn is_exportable(self) -> bool {
40 self.policy.usage_flags.export
41 }
42
43 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 pub fn is_hash_signable(self) -> bool {
78 self.policy.usage_flags.sign_hash
79 }
80
81 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 pub fn is_hash_verifiable(self) -> bool {
93 self.policy.usage_flags.verify_hash
94 }
95
96 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 pub fn is_message_signable(self) -> bool {
108 self.policy.usage_flags.sign_hash | self.policy.usage_flags.sign_message
109 }
110
111 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 pub fn is_message_verifiable(self) -> bool {
123 self.policy.usage_flags.verify_hash | self.policy.usage_flags.verify_message
124 }
125
126 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 pub fn is_encrypt_permitted(self) -> bool {
138 self.policy.usage_flags.encrypt
139 }
140
141 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 pub fn is_decrypt_permitted(self) -> bool {
153 self.policy.usage_flags.decrypt
154 }
155
156 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 pub fn is_derivable(self) -> bool {
168 self.policy.usage_flags.derive
169 }
170
171 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 #[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 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 permitted_alg => permitted_alg == alg,
202 }
203 }
204
205 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 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 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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 if size > 0 {
441 Ok(size)
442 } else {
443 Err(Error::DataInvalid)
444 }
445 }
446
447 #[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 #[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 #[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 #[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#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Zeroize)]
503pub enum Lifetime {
504 Volatile,
506 Persistent,
509 Custom(u32),
512}
513
514#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Zeroize)]
516pub enum Type {
517 RawData,
520 Hmac,
522 Derive,
524 Aes,
526 Des,
528 Camellia,
530 Arc4,
532 Chacha20,
534 RsaPublicKey,
536 RsaKeyPair,
538 EccKeyPair {
540 curve_family: EccFamily,
542 },
543 EccPublicKey {
545 curve_family: EccFamily,
547 },
548 DhKeyPair {
550 group_family: DhFamily,
552 },
553 DhPublicKey {
555 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 pub fn is_ecc_key_pair(self) -> bool {
590 matches!(self, Type::EccKeyPair { .. })
591 }
592
593 pub fn is_ecc_public_key(self) -> bool {
603 matches!(self, Type::EccPublicKey { .. })
604 }
605
606 pub fn is_rsa_public_key(self) -> bool {
608 matches!(self, Type::RsaPublicKey)
609 }
610
611 pub fn is_dh_public_key(self) -> bool {
613 matches!(self, Type::DhPublicKey { .. })
614 }
615
616 pub fn is_dh_key_pair(self) -> bool {
618 matches!(self, Type::DhKeyPair { .. })
619 }
620
621 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 #[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#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Zeroize)]
652pub enum EccFamily {
653 SecpK1,
659 SecpR1,
667 #[deprecated = "This family of curve is weak and deprecated."]
671 SecpR2,
672 SectK1,
681 SectR1,
689 #[deprecated = "This family of curve is weak and deprecated."]
693 SectR2,
694 BrainpoolPR1,
704 Frp,
708 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#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Zeroize)]
733pub enum DhFamily {
734 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#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Zeroize)]
750pub struct Policy {
751 pub usage_flags: UsageFlags,
753 pub permitted_algorithms: Algorithm,
755}
756
757#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, Zeroize)]
759pub struct UsageFlags {
760 export: bool,
762 copy: bool,
764 cache: bool,
766 encrypt: bool,
768 decrypt: bool,
770 sign_message: bool,
772 verify_message: bool,
774 sign_hash: bool,
776 verify_hash: bool,
778 derive: bool,
780}
781
782impl UsageFlags {
783 pub fn set_export(&mut self) -> &mut Self {
785 self.export = true;
786 self
787 }
788 pub fn export(&self) -> bool {
790 self.export
791 }
792 pub fn set_copy(&mut self) -> &mut Self {
794 self.copy = true;
795 self
796 }
797 pub fn copy(&self) -> bool {
799 self.copy
800 }
801 pub fn set_cache(&mut self) -> &mut Self {
803 self.cache = true;
804 self
805 }
806 pub fn cache(&self) -> bool {
808 self.cache
809 }
810 pub fn set_encrypt(&mut self) -> &mut Self {
812 self.encrypt = true;
813 self
814 }
815 pub fn encrypt(&self) -> bool {
817 self.encrypt
818 }
819 pub fn set_decrypt(&mut self) -> &mut Self {
821 self.decrypt = true;
822 self
823 }
824 pub fn decrypt(&self) -> bool {
826 self.decrypt
827 }
828 pub fn set_sign_hash(&mut self) -> &mut Self {
830 self.sign_hash = true;
831 self.sign_message = true;
832 self
833 }
834 pub fn sign_hash(&self) -> bool {
836 self.sign_hash
837 }
838 pub fn set_sign_message(&mut self) -> &mut Self {
840 self.sign_message = true;
841 self
842 }
843 pub fn sign_message(&self) -> bool {
845 self.sign_message
846 }
847 pub fn set_verify_hash(&mut self) -> &mut Self {
849 self.verify_hash = true;
850 self.verify_message = true;
851 self
852 }
853 pub fn verify_hash(&self) -> bool {
855 self.verify_hash
856 }
857 pub fn set_verify_message(&mut self) -> &mut Self {
859 self.verify_message = true;
860 self
861 }
862 pub fn verify_message(&self) -> bool {
864 self.verify_message
865 }
866 pub fn set_derive(&mut self) -> &mut Self {
868 self.derive = true;
869 self
870 }
871 pub fn derive(&self) -> bool {
873 self.derive
874 }
875}
876
877#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Zeroize)]
879pub struct Id(pub(crate) psa_key_id_t);
880
881impl Id {
882 #[cfg(feature = "operations")]
884 pub fn from_persistent_key_id(id: u32) -> Result<Self> {
885 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 fn try_from(attributes: Attributes) -> Result<Self> {
922 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 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 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 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 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 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 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 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 Ok(attributes.bits)
988 }
989 }
990 }
991 _ => {
992 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 if flags.sign_hash {
1057 usage_flags |= psa_crypto_sys::PSA_KEY_USAGE_SIGN_HASH;
1058 }
1059 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_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}