parsec_interface/operations/
psa_asymmetric_decrypt.rs1use super::psa_key_attributes::Attributes;
8use crate::operations::psa_algorithm::AsymmetricEncryption;
9use crate::requests::ResponseStatus;
10use derivative::Derivative;
11
12#[derive(Derivative)]
14#[derivative(Debug)]
15pub struct Operation {
16 pub key_name: String,
18 pub alg: AsymmetricEncryption,
20 #[derivative(Debug = "ignore")]
22 pub ciphertext: zeroize::Zeroizing<Vec<u8>>,
23 #[derivative(Debug = "ignore")]
25 pub salt: Option<zeroize::Zeroizing<Vec<u8>>>,
26}
27
28impl Operation {
29 pub fn validate(&self, key_attributes: Attributes) -> crate::requests::Result<()> {
38 key_attributes.can_decrypt_message()?;
39 key_attributes.permits_alg(self.alg.into())?;
40 key_attributes.compatible_with_alg(self.alg.into())?;
41 if (self.alg == AsymmetricEncryption::RsaPkcs1v15Crypt && self.salt.is_some())
42 || self.ciphertext.is_empty()
43 {
44 return Err(ResponseStatus::PsaErrorInvalidArgument);
45 }
46 Ok(())
47 }
48}
49
50#[derive(Derivative)]
54#[derivative(Debug)]
55pub struct Result {
56 #[derivative(Debug = "ignore")]
58 pub plaintext: zeroize::Zeroizing<Vec<u8>>,
59}
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64 use crate::operations::psa_algorithm::{AsymmetricEncryption, Hash};
65 use crate::operations::psa_key_attributes::{Lifetime, Policy, Type, UsageFlags};
66 use zeroize::Zeroizing;
67
68 fn get_attrs() -> Attributes {
69 let mut usage_flags = UsageFlags::default();
70 let _ = usage_flags.set_decrypt();
71 Attributes {
72 lifetime: Lifetime::Persistent,
73 key_type: Type::RsaKeyPair,
74 bits: 256,
75 policy: Policy {
76 usage_flags,
77 permitted_algorithms: AsymmetricEncryption::RsaPkcs1v15Crypt.into(),
78 },
79 }
80 }
81
82 #[test]
83 fn validate_success() {
84 (Operation {
85 key_name: String::from("some key"),
86 alg: AsymmetricEncryption::RsaPkcs1v15Crypt,
87 ciphertext: Zeroizing::new(vec![0xff, 32]),
88 salt: None,
89 })
90 .validate(get_attrs())
91 .unwrap();
92 }
93
94 #[test]
95 fn cannot_decrypt() {
96 let mut attrs = get_attrs();
97 attrs.policy.usage_flags = UsageFlags::default();
98 assert_eq!(
99 (Operation {
100 key_name: String::from("some key"),
101 alg: AsymmetricEncryption::RsaPkcs1v15Crypt,
102 ciphertext: Zeroizing::new(vec![0xff, 32]),
103 salt: None,
104 })
105 .validate(attrs)
106 .unwrap_err(),
107 ResponseStatus::PsaErrorNotPermitted
108 );
109 }
110
111 #[test]
112 fn wrong_algorithm() {
113 assert_eq!(
114 (Operation {
115 key_name: String::from("some key"),
116 alg: AsymmetricEncryption::RsaOaep {
117 hash_alg: Hash::Sha256,
118 },
119 ciphertext: Zeroizing::new(vec![0xff, 32]),
120 salt: None,
121 })
122 .validate(get_attrs())
123 .unwrap_err(),
124 ResponseStatus::PsaErrorNotPermitted
125 );
126 }
127
128 #[test]
129 fn invalid_ciphertext() {
130 assert_eq!(
131 (Operation {
132 key_name: String::from("some key"),
133 alg: AsymmetricEncryption::RsaPkcs1v15Crypt,
134 ciphertext: Zeroizing::new(vec![]),
135 salt: None,
136 })
137 .validate(get_attrs())
138 .unwrap_err(),
139 ResponseStatus::PsaErrorInvalidArgument
140 );
141 }
142
143 #[test]
144 fn salt_with_rsapkcs1v15crypt() {
145 assert_eq!(
146 (Operation {
147 key_name: String::from("some key"),
148 alg: AsymmetricEncryption::RsaPkcs1v15Crypt,
149 ciphertext: Zeroizing::new(vec![0xff, 32]),
150 salt: Some(zeroize::Zeroizing::new(vec![0xff, 32])),
151 })
152 .validate(get_attrs())
153 .unwrap_err(),
154 ResponseStatus::PsaErrorInvalidArgument
155 );
156 }
157}