parsec_interface/operations/
psa_asymmetric_encrypt.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 plaintext: 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_encrypt_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.plaintext.is_empty()
43 {
44 return Err(ResponseStatus::PsaErrorInvalidArgument);
45 }
46 Ok(())
47 }
48}
49
50#[derive(Derivative)]
52#[derivative(Debug)]
53pub struct Result {
54 #[derivative(Debug = "ignore")]
56 pub ciphertext: zeroize::Zeroizing<Vec<u8>>,
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62 use crate::operations::psa_algorithm::{AsymmetricEncryption, Hash};
63 use crate::operations::psa_key_attributes::{Lifetime, Policy, Type, UsageFlags};
64
65 fn get_attrs() -> Attributes {
66 let mut usage_flags = UsageFlags::default();
67 let _ = usage_flags.set_encrypt();
68 Attributes {
69 lifetime: Lifetime::Persistent,
70 key_type: Type::RsaKeyPair,
71 bits: 256,
72 policy: Policy {
73 usage_flags,
74 permitted_algorithms: AsymmetricEncryption::RsaPkcs1v15Crypt.into(),
75 },
76 }
77 }
78
79 #[test]
80 fn validate_success() {
81 (Operation {
82 key_name: String::from("some key"),
83 alg: AsymmetricEncryption::RsaPkcs1v15Crypt,
84 plaintext: vec![0xff, 32].into(),
85 salt: None,
86 })
87 .validate(get_attrs())
88 .unwrap();
89 }
90
91 #[test]
92 fn cannot_encrypt() {
93 let mut attrs = get_attrs();
94 attrs.policy.usage_flags = UsageFlags::default();
95 assert_eq!(
96 (Operation {
97 key_name: String::from("some key"),
98 alg: AsymmetricEncryption::RsaPkcs1v15Crypt,
99 plaintext: vec![0xff, 32].into(),
100 salt: None,
101 })
102 .validate(attrs)
103 .unwrap_err(),
104 ResponseStatus::PsaErrorNotPermitted
105 );
106 }
107
108 #[test]
109 fn wrong_algorithm() {
110 assert_eq!(
111 (Operation {
112 key_name: String::from("some key"),
113 alg: AsymmetricEncryption::RsaOaep {
114 hash_alg: Hash::Sha256,
115 },
116 plaintext: vec![0xff, 32].into(),
117 salt: None,
118 })
119 .validate(get_attrs())
120 .unwrap_err(),
121 ResponseStatus::PsaErrorNotPermitted
122 );
123 }
124
125 #[test]
126 fn invalid_plaintext() {
127 assert_eq!(
128 (Operation {
129 key_name: String::from("some key"),
130 alg: AsymmetricEncryption::RsaPkcs1v15Crypt,
131 plaintext: vec![].into(),
132 salt: None,
133 })
134 .validate(get_attrs())
135 .unwrap_err(),
136 ResponseStatus::PsaErrorInvalidArgument
137 );
138 }
139
140 #[test]
141 fn salt_with_rsapkcs1v15crypt() {
142 assert_eq!(
143 (Operation {
144 key_name: String::from("some key"),
145 alg: AsymmetricEncryption::RsaPkcs1v15Crypt,
146 plaintext: vec![0xff, 32].into(),
147 salt: Some(zeroize::Zeroizing::new(vec![0xff, 32])),
148 })
149 .validate(get_attrs())
150 .unwrap_err(),
151 ResponseStatus::PsaErrorInvalidArgument
152 );
153 }
154}