parsec_interface/operations/
psa_aead_decrypt.rs1use super::psa_key_attributes::Attributes;
8use crate::operations::psa_algorithm::Aead;
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: Aead,
20 #[derivative(Debug = "ignore")]
22 pub nonce: zeroize::Zeroizing<Vec<u8>>,
23 #[derivative(Debug = "ignore")]
25 pub additional_data: zeroize::Zeroizing<Vec<u8>>,
26 #[derivative(Debug = "ignore")]
30 pub ciphertext: zeroize::Zeroizing<Vec<u8>>,
31}
32
33impl Operation {
34 pub fn validate(&self, key_attributes: Attributes) -> crate::requests::Result<()> {
43 key_attributes.can_decrypt_message()?;
44 key_attributes.permits_alg(self.alg.into())?;
45 key_attributes.compatible_with_alg(self.alg.into())?;
46 if self.ciphertext.is_empty() || self.nonce.is_empty() {
47 return Err(ResponseStatus::PsaErrorInvalidArgument);
48 }
49 Ok(())
50 }
51}
52
53#[derive(Derivative)]
55#[derivative(Debug)]
56pub struct Result {
57 #[derivative(Debug = "ignore")]
59 pub plaintext: zeroize::Zeroizing<Vec<u8>>,
60}
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65 use crate::operations::psa_algorithm::AeadWithDefaultLengthTag;
66 use crate::operations::psa_key_attributes::{Lifetime, Policy, Type, UsageFlags};
67 use psa_crypto::types::algorithm::Aead;
68
69 fn get_attrs() -> Attributes {
70 let mut usage_flags = UsageFlags::default();
71 let _ = usage_flags.set_decrypt();
72
73 Attributes {
74 lifetime: Lifetime::Persistent,
75 key_type: Type::Aes,
76 bits: 0,
77 policy: Policy {
78 usage_flags,
79 permitted_algorithms: Aead::AeadWithDefaultLengthTag(AeadWithDefaultLengthTag::Ccm)
80 .into(),
81 },
82 }
83 }
84
85 #[test]
86 fn validate_success() {
87 (Operation {
88 key_name: String::from("some key"),
89 alg: AeadWithDefaultLengthTag::Ccm.into(),
90 ciphertext: vec![0xff, 32].into(),
91 nonce: vec![0xaa, 12].into(),
92 additional_data: vec![0xff, 16].into(),
93 })
94 .validate(get_attrs())
95 .unwrap();
96 }
97
98 #[test]
99 fn cannot_decrypt() {
100 let mut attrs = get_attrs();
101 attrs.policy.usage_flags = UsageFlags::default();
102 assert_eq!(
103 (Operation {
104 key_name: String::from("some key"),
105 alg: AeadWithDefaultLengthTag::Ccm.into(),
106 ciphertext: vec![0xff, 32].into(),
107 nonce: vec![0xaa, 12].into(),
108 additional_data: vec![0xff, 16].into()
109 })
110 .validate(attrs)
111 .unwrap_err(),
112 ResponseStatus::PsaErrorNotPermitted
113 );
114 }
115
116 #[test]
117 fn wrong_algorithm() {
118 assert_eq!(
119 (Operation {
120 key_name: String::from("some key"),
121 alg: AeadWithDefaultLengthTag::Gcm.into(),
122 ciphertext: vec![0xff, 32].into(),
123 nonce: vec![0xaa, 12].into(),
124 additional_data: vec![0xff, 16].into()
125 })
126 .validate(get_attrs())
127 .unwrap_err(),
128 ResponseStatus::PsaErrorNotPermitted
129 );
130 }
131
132 #[test]
133 fn invalid_plaintext() {
134 assert_eq!(
135 (Operation {
136 key_name: String::from("some key"),
137 alg: AeadWithDefaultLengthTag::Ccm.into(),
138 ciphertext: vec![].into(),
139 nonce: vec![0xaa, 12].into(),
140 additional_data: vec![0xff, 16].into()
141 })
142 .validate(get_attrs())
143 .unwrap_err(),
144 ResponseStatus::PsaErrorInvalidArgument
145 );
146 }
147
148 #[test]
149 fn invalid_nonce() {
150 assert_eq!(
151 (Operation {
152 key_name: String::from("some key"),
153 alg: AeadWithDefaultLengthTag::Ccm.into(),
154 ciphertext: vec![0xff, 32].into(),
155 nonce: vec![].into(),
156 additional_data: vec![0xff, 16].into()
157 })
158 .validate(get_attrs())
159 .unwrap_err(),
160 ResponseStatus::PsaErrorInvalidArgument
161 );
162 }
163}