aws_lc_rs/rsa/encryption/
oaep.rs1#![allow(clippy::module_name_repetitions)]
5
6use super::{EncryptionAlgorithmId, PrivateDecryptingKey, PublicEncryptingKey};
7use crate::aws_lc::{
8 EVP_PKEY_CTX_set0_rsa_oaep_label, EVP_PKEY_CTX_set_rsa_mgf1_md, EVP_PKEY_CTX_set_rsa_oaep_md,
9 EVP_PKEY_CTX_set_rsa_padding, EVP_PKEY_decrypt, EVP_PKEY_decrypt_init, EVP_PKEY_encrypt,
10 EVP_PKEY_encrypt_init, EVP_sha1, EVP_sha256, EVP_sha384, EVP_sha512, OPENSSL_malloc, EVP_MD,
11 EVP_PKEY_CTX, RSA_PKCS1_OAEP_PADDING,
12};
13use crate::error::Unspecified;
14use crate::fips::indicator_check;
15use crate::ptr::{DetachableLcPtr, LcPtr};
16use core::fmt::Debug;
17use core::mem::size_of_val;
18use core::ptr::null_mut;
19
20pub const OAEP_SHA1_MGF1SHA1: OaepAlgorithm = OaepAlgorithm {
22 id: EncryptionAlgorithmId::OaepSha1Mgf1sha1,
23 oaep_hash_fn: EVP_sha1,
24 mgf1_hash_fn: EVP_sha1,
25};
26
27pub const OAEP_SHA256_MGF1SHA256: OaepAlgorithm = OaepAlgorithm {
29 id: EncryptionAlgorithmId::OaepSha256Mgf1sha256,
30 oaep_hash_fn: EVP_sha256,
31 mgf1_hash_fn: EVP_sha256,
32};
33
34pub const OAEP_SHA384_MGF1SHA384: OaepAlgorithm = OaepAlgorithm {
36 id: EncryptionAlgorithmId::OaepSha384Mgf1sha384,
37 oaep_hash_fn: EVP_sha384,
38 mgf1_hash_fn: EVP_sha384,
39};
40
41pub const OAEP_SHA512_MGF1SHA512: OaepAlgorithm = OaepAlgorithm {
43 id: EncryptionAlgorithmId::OaepSha512Mgf1sha512,
44 oaep_hash_fn: EVP_sha512,
45 mgf1_hash_fn: EVP_sha512,
46};
47
48type OaepHashFn = unsafe extern "C" fn() -> *const EVP_MD;
49type Mgf1HashFn = unsafe extern "C" fn() -> *const EVP_MD;
50
51pub struct OaepAlgorithm {
53 id: EncryptionAlgorithmId,
54 oaep_hash_fn: OaepHashFn,
55 mgf1_hash_fn: Mgf1HashFn,
56}
57
58impl OaepAlgorithm {
59 #[must_use]
61 pub fn id(&self) -> EncryptionAlgorithmId {
62 self.id
63 }
64
65 #[inline]
66 fn oaep_hash_fn(&self) -> OaepHashFn {
67 self.oaep_hash_fn
68 }
69
70 #[inline]
71 fn mgf1_hash_fn(&self) -> Mgf1HashFn {
72 self.mgf1_hash_fn
73 }
74}
75
76impl Debug for OaepAlgorithm {
77 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
78 Debug::fmt(&self.id, f)
79 }
80}
81
82pub struct OaepPublicEncryptingKey {
84 public_key: PublicEncryptingKey,
85}
86
87impl OaepPublicEncryptingKey {
88 pub fn new(public_key: PublicEncryptingKey) -> Result<Self, Unspecified> {
92 Ok(Self { public_key })
93 }
94
95 pub fn encrypt<'ciphertext>(
108 &self,
109 algorithm: &'static OaepAlgorithm,
110 plaintext: &[u8],
111 ciphertext: &'ciphertext mut [u8],
112 label: Option<&[u8]>,
113 ) -> Result<&'ciphertext mut [u8], Unspecified> {
114 let mut pkey_ctx = self.public_key.0.create_EVP_PKEY_CTX()?;
115
116 if 1 != unsafe { EVP_PKEY_encrypt_init(*pkey_ctx.as_mut()) } {
117 return Err(Unspecified);
118 }
119
120 configure_oaep_crypto_operation(
121 &mut pkey_ctx,
122 algorithm.oaep_hash_fn(),
123 algorithm.mgf1_hash_fn(),
124 label,
125 )?;
126
127 let mut out_len = ciphertext.len();
128
129 if 1 != indicator_check!(unsafe {
130 EVP_PKEY_encrypt(
131 *pkey_ctx.as_mut(),
132 ciphertext.as_mut_ptr(),
133 &mut out_len,
134 plaintext.as_ptr(),
135 plaintext.len(),
136 )
137 }) {
138 return Err(Unspecified);
139 }
140
141 Ok(&mut ciphertext[..out_len])
142 }
143
144 #[must_use]
146 pub fn key_size_bytes(&self) -> usize {
147 self.public_key.key_size_bytes()
148 }
149
150 #[must_use]
152 pub fn key_size_bits(&self) -> usize {
153 self.public_key.key_size_bits()
154 }
155
156 #[must_use]
158 pub fn max_plaintext_size(&self, algorithm: &'static OaepAlgorithm) -> usize {
159 #[allow(unreachable_patterns)]
160 let hash_len: usize = match algorithm.id() {
161 EncryptionAlgorithmId::OaepSha1Mgf1sha1 => 20,
162 EncryptionAlgorithmId::OaepSha256Mgf1sha256 => 32,
163 EncryptionAlgorithmId::OaepSha384Mgf1sha384 => 48,
164 EncryptionAlgorithmId::OaepSha512Mgf1sha512 => 64,
165 _ => unreachable!(),
166 };
167
168 self.key_size_bytes() - 2 * hash_len - 2
170 }
171
172 #[must_use]
174 pub fn ciphertext_size(&self) -> usize {
175 self.key_size_bytes()
176 }
177}
178
179impl Debug for OaepPublicEncryptingKey {
180 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
181 f.debug_struct("OaepPublicEncryptingKey")
182 .finish_non_exhaustive()
183 }
184}
185
186pub struct OaepPrivateDecryptingKey {
188 private_key: PrivateDecryptingKey,
189}
190
191impl OaepPrivateDecryptingKey {
192 pub fn new(private_key: PrivateDecryptingKey) -> Result<Self, Unspecified> {
196 Ok(Self { private_key })
197 }
198
199 pub fn decrypt<'plaintext>(
212 &self,
213 algorithm: &'static OaepAlgorithm,
214 ciphertext: &[u8],
215 plaintext: &'plaintext mut [u8],
216 label: Option<&[u8]>,
217 ) -> Result<&'plaintext mut [u8], Unspecified> {
218 let mut pkey_ctx = self.private_key.0.create_EVP_PKEY_CTX()?;
219
220 if 1 != unsafe { EVP_PKEY_decrypt_init(*pkey_ctx.as_mut()) } {
221 return Err(Unspecified);
222 }
223
224 configure_oaep_crypto_operation(
225 &mut pkey_ctx,
226 algorithm.oaep_hash_fn(),
227 algorithm.mgf1_hash_fn(),
228 label,
229 )?;
230
231 let mut out_len = plaintext.len();
232
233 if 1 != indicator_check!(unsafe {
234 EVP_PKEY_decrypt(
235 *pkey_ctx.as_mut(),
236 plaintext.as_mut_ptr(),
237 &mut out_len,
238 ciphertext.as_ptr(),
239 ciphertext.len(),
240 )
241 }) {
242 return Err(Unspecified);
243 }
244
245 Ok(&mut plaintext[..out_len])
246 }
247
248 #[must_use]
250 pub fn key_size_bytes(&self) -> usize {
251 self.private_key.key_size_bytes()
252 }
253
254 #[must_use]
256 pub fn key_size_bits(&self) -> usize {
257 self.private_key.key_size_bits()
258 }
259
260 #[must_use]
262 pub fn min_output_size(&self) -> usize {
263 self.key_size_bytes()
264 }
265}
266
267impl Debug for OaepPrivateDecryptingKey {
268 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
269 f.debug_struct("OaepPrivateDecryptingKey")
270 .finish_non_exhaustive()
271 }
272}
273
274fn configure_oaep_crypto_operation(
275 evp_pkey_ctx: &mut LcPtr<EVP_PKEY_CTX>,
276 oaep_hash_fn: OaepHashFn,
277 mgf1_hash_fn: Mgf1HashFn,
278 label: Option<&[u8]>,
279) -> Result<(), Unspecified> {
280 if 1 != unsafe { EVP_PKEY_CTX_set_rsa_padding(*evp_pkey_ctx.as_mut(), RSA_PKCS1_OAEP_PADDING) }
281 {
282 return Err(Unspecified);
283 }
284
285 if 1 != unsafe { EVP_PKEY_CTX_set_rsa_oaep_md(*evp_pkey_ctx.as_mut(), oaep_hash_fn()) } {
286 return Err(Unspecified);
287 }
288
289 if 1 != unsafe { EVP_PKEY_CTX_set_rsa_mgf1_md(*evp_pkey_ctx.as_mut(), mgf1_hash_fn()) } {
290 return Err(Unspecified);
291 }
292
293 let label = label.unwrap_or(&[0u8; 0]);
294
295 if label.is_empty() {
296 if 1 != unsafe { EVP_PKEY_CTX_set0_rsa_oaep_label(*evp_pkey_ctx.as_mut(), null_mut(), 0) } {
298 return Err(Unspecified);
299 }
300 return Ok(());
301 }
302
303 let mut label_ptr =
305 DetachableLcPtr::<u8>::new(unsafe { OPENSSL_malloc(size_of_val(label)) }.cast())?;
306
307 {
308 let label_ptr =
310 unsafe { core::slice::from_raw_parts_mut(*label_ptr.as_mut(), label.len()) };
311 label_ptr.copy_from_slice(label);
312 }
313
314 if 1 != unsafe {
315 EVP_PKEY_CTX_set0_rsa_oaep_label(*evp_pkey_ctx.as_mut(), *label_ptr, label.len())
316 } {
317 return Err(Unspecified);
318 }
319
320 label_ptr.detach();
322
323 Ok(())
324}