/rust/registry/src/index.crates.io-1949cf8c6b5b557f/aws-lc-rs-1.16.3/src/cipher/streaming.rs
Line | Count | Source |
1 | | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. |
2 | | // SPDX-License-Identifier: Apache-2.0 OR ISC |
3 | | |
4 | | use crate::aws_lc::{ |
5 | | EVP_CIPHER_CTX_new, EVP_CIPHER_iv_length, EVP_CIPHER_key_length, EVP_DecryptFinal_ex, |
6 | | EVP_DecryptInit_ex, EVP_DecryptUpdate, EVP_EncryptFinal_ex, EVP_EncryptInit_ex, |
7 | | EVP_EncryptUpdate, EVP_CIPHER, EVP_CIPHER_CTX, |
8 | | }; |
9 | | use crate::cipher::{ |
10 | | Algorithm, DecryptionContext, EncryptionContext, OperatingMode, UnboundCipherKey, |
11 | | }; |
12 | | use crate::error::Unspecified; |
13 | | use crate::fips::indicator_check; |
14 | | use crate::ptr::LcPtr; |
15 | | use std::ptr::{null, null_mut}; |
16 | | |
17 | | use super::ConstPointer; |
18 | | |
19 | | /// A key for streaming encryption operations. |
20 | | pub struct StreamingEncryptingKey { |
21 | | algorithm: &'static Algorithm, |
22 | | mode: OperatingMode, |
23 | | cipher_ctx: LcPtr<EVP_CIPHER_CTX>, |
24 | | context: EncryptionContext, |
25 | | output_generated: usize, |
26 | | } |
27 | | |
28 | | unsafe impl Send for StreamingEncryptingKey {} |
29 | | |
30 | | /// A struct indicating the portion of a buffer written to, and/or not written to, during an |
31 | | /// encryption/decryption operation. |
32 | | pub struct BufferUpdate<'a> { |
33 | | written: &'a [u8], |
34 | | remainder: &'a mut [u8], |
35 | | } |
36 | | |
37 | | impl<'a> BufferUpdate<'a> { |
38 | 0 | fn new(out_buffer: &'a mut [u8], written_len: usize) -> Self { |
39 | 0 | let (written, remainder) = out_buffer.split_at_mut(written_len); |
40 | 0 | Self { written, remainder } |
41 | 0 | } |
42 | | } |
43 | | |
44 | | impl BufferUpdate<'_> { |
45 | | /// Returns the slice from the buffer that was modified by the operation. |
46 | | #[must_use] |
47 | 0 | pub fn written(&self) -> &[u8] { |
48 | 0 | self.written |
49 | 0 | } |
50 | | |
51 | | /// Returns the slice of the buffer that was not modified by the operation. |
52 | | #[must_use] |
53 | 0 | pub fn remainder(&self) -> &[u8] { |
54 | 0 | self.remainder |
55 | 0 | } |
56 | | |
57 | | /// Returns a mutable slice of the buffer that was not modified by the operation. |
58 | | #[must_use] |
59 | 0 | pub fn remainder_mut(&mut self) -> &mut [u8] { |
60 | 0 | self.remainder |
61 | 0 | } |
62 | | } |
63 | | |
64 | 0 | fn evp_encrypt_init( |
65 | 0 | cipher_ctx: &mut LcPtr<EVP_CIPHER_CTX>, |
66 | 0 | cipher: &ConstPointer<EVP_CIPHER>, |
67 | 0 | key: &[u8], |
68 | 0 | iv: Option<&[u8]>, |
69 | 0 | ) -> Result<(), Unspecified> { |
70 | 0 | let iv_ptr: *const u8 = if let Some(iv) = iv { |
71 | 0 | iv.as_ptr() |
72 | | } else { |
73 | 0 | null() |
74 | | }; |
75 | | |
76 | | // AWS-LC copies the key and iv values into the EVP_CIPHER_CTX, and thus can be dropped after this. |
77 | 0 | if 1 != unsafe { |
78 | 0 | EVP_EncryptInit_ex( |
79 | 0 | cipher_ctx.as_mut_ptr(), |
80 | 0 | cipher.as_const_ptr(), |
81 | 0 | null_mut(), |
82 | 0 | key.as_ptr(), |
83 | 0 | iv_ptr, |
84 | 0 | ) |
85 | 0 | } { |
86 | 0 | return Err(Unspecified); |
87 | 0 | } |
88 | | |
89 | 0 | Ok(()) |
90 | 0 | } |
91 | | |
92 | 0 | fn evp_decrypt_init( |
93 | 0 | cipher_ctx: &mut LcPtr<EVP_CIPHER_CTX>, |
94 | 0 | cipher: &ConstPointer<EVP_CIPHER>, |
95 | 0 | key: &[u8], |
96 | 0 | iv: Option<&[u8]>, |
97 | 0 | ) -> Result<(), Unspecified> { |
98 | 0 | let iv_ptr: *const u8 = if let Some(iv) = iv { |
99 | 0 | iv.as_ptr() |
100 | | } else { |
101 | 0 | null() |
102 | | }; |
103 | | |
104 | | // AWS-LC copies the key and iv values into the EVP_CIPHER_CTX, and thus can be dropped after this. |
105 | 0 | if 1 != unsafe { |
106 | 0 | EVP_DecryptInit_ex( |
107 | 0 | cipher_ctx.as_mut_ptr(), |
108 | 0 | cipher.as_const_ptr(), |
109 | 0 | null_mut(), |
110 | 0 | key.as_ptr(), |
111 | 0 | iv_ptr, |
112 | 0 | ) |
113 | 0 | } { |
114 | 0 | return Err(Unspecified); |
115 | 0 | } |
116 | | |
117 | 0 | Ok(()) |
118 | 0 | } |
119 | | |
120 | | impl StreamingEncryptingKey { |
121 | | #[allow(clippy::needless_pass_by_value)] |
122 | 0 | fn new( |
123 | 0 | key: UnboundCipherKey, |
124 | 0 | mode: OperatingMode, |
125 | 0 | context: EncryptionContext, |
126 | 0 | ) -> Result<Self, Unspecified> { |
127 | 0 | let algorithm = key.algorithm(); |
128 | 0 | let mut cipher_ctx = LcPtr::new(unsafe { EVP_CIPHER_CTX_new() })?; |
129 | 0 | let cipher = mode.evp_cipher(key.algorithm); |
130 | 0 | let key_bytes = key.key_bytes.as_ref(); |
131 | 0 | if key_bytes.len() |
132 | 0 | != <usize>::try_from(unsafe { EVP_CIPHER_key_length(cipher.as_const_ptr()) }).unwrap() |
133 | | { |
134 | 0 | return Err(Unspecified); |
135 | 0 | } |
136 | | |
137 | 0 | match &context { |
138 | 0 | ctx @ EncryptionContext::Iv128(..) => { |
139 | 0 | let iv = <&[u8]>::try_from(ctx)?; |
140 | 0 | debug_assert_eq!( |
141 | 0 | iv.len(), |
142 | 0 | <usize>::try_from(unsafe { EVP_CIPHER_iv_length(cipher.as_const_ptr()) }) |
143 | 0 | .unwrap() |
144 | | ); |
145 | 0 | evp_encrypt_init(&mut cipher_ctx, &cipher, key_bytes, Some(iv))?; |
146 | | } |
147 | | EncryptionContext::None => { |
148 | 0 | evp_encrypt_init(&mut cipher_ctx, &cipher, key_bytes, None)?; |
149 | | } |
150 | | } |
151 | | |
152 | 0 | Ok(Self { |
153 | 0 | algorithm, |
154 | 0 | mode, |
155 | 0 | cipher_ctx, |
156 | 0 | context, |
157 | 0 | output_generated: 0, |
158 | 0 | }) |
159 | 0 | } |
160 | | |
161 | 0 | fn update_internal<'a>( |
162 | 0 | &mut self, |
163 | 0 | input: &[u8], |
164 | 0 | output: &'a mut [u8], |
165 | 0 | min_outsize: usize, |
166 | 0 | ) -> Result<BufferUpdate<'a>, Unspecified> { |
167 | 0 | if output.len() < min_outsize { |
168 | 0 | return Err(Unspecified); |
169 | 0 | } |
170 | 0 | let mut outlen: i32 = 0; |
171 | 0 | let inlen: i32 = input.len().try_into()?; |
172 | | |
173 | 0 | if 1 != unsafe { |
174 | 0 | EVP_EncryptUpdate( |
175 | 0 | self.cipher_ctx.as_mut_ptr(), |
176 | 0 | output.as_mut_ptr(), |
177 | 0 | &mut outlen, |
178 | 0 | input.as_ptr(), |
179 | 0 | inlen, |
180 | 0 | ) |
181 | 0 | } { |
182 | 0 | return Err(Unspecified); |
183 | 0 | } |
184 | 0 | let outlen: usize = outlen.try_into()?; |
185 | 0 | debug_assert!(outlen <= min_outsize); |
186 | 0 | self.output_generated += outlen; |
187 | 0 | assert!(outlen <= output.len()); |
188 | | |
189 | 0 | Ok(BufferUpdate::new(output, outlen)) |
190 | 0 | } |
191 | | |
192 | | /// Updates the internal state of the key with the provided plaintext `input`, |
193 | | /// potentially writing bytes of ciphertext to `output`. |
194 | | /// |
195 | | /// The number of bytes written to `output` can be up to `input.len()` |
196 | | /// plus the block length of the algorithm (e.g., [`Algorithm::block_len`]) minus one. |
197 | | /// |
198 | | /// # Errors |
199 | | /// * Returns an error if the `output` buffer is smaller than the length of |
200 | | /// the `input` plus the algorithm's block length (e.g. [`Algorithm::block_len`]) minus one. |
201 | | /// * May return an error if the length of `input` plus the algorithm's block length is larger than `i32::MAX`. |
202 | 0 | pub fn update<'a>( |
203 | 0 | &mut self, |
204 | 0 | input: &[u8], |
205 | 0 | output: &'a mut [u8], |
206 | 0 | ) -> Result<BufferUpdate<'a>, Unspecified> { |
207 | 0 | let min_outsize = input |
208 | 0 | .len() |
209 | 0 | .checked_add(self.algorithm().block_len()) |
210 | 0 | .ok_or(Unspecified)? |
211 | 0 | .checked_sub(1) |
212 | 0 | .ok_or(Unspecified)?; |
213 | 0 | self.update_internal(input, output, min_outsize) |
214 | 0 | } |
215 | | |
216 | | /// Updates the internal state of the key with the provided plaintext `input`, |
217 | | /// potentially writing bytes of ciphertext to `output`. |
218 | | /// |
219 | | /// This function has looser output buffer size requirements than [`Self::update`], |
220 | | /// calculating the minimum required size based on the total bytes of output generated |
221 | | /// and the cipher's block length. This is considered "less safe" because it's |
222 | | /// based on assumptions about the state of the underlying operations. |
223 | | /// |
224 | | /// The minimum output buffer size is calculated based on how many bytes are needed to |
225 | | /// reach the next block boundary after processing the input. If `next_total` is the sum |
226 | | /// of bytes already generated plus `input.len()`, then the minimum size is: |
227 | | /// `input.len() + ((block_len - (next_total % block_len)) % block_len)` |
228 | | /// |
229 | | /// # Errors |
230 | | /// Returns an error if the `output` buffer is smaller than the calculated minimum size, |
231 | | /// if the total output length overflows, or if the length of `input` is larger than |
232 | | /// `i32::MAX`. |
233 | | /// |
234 | | /// # Panics |
235 | | /// Panics if the number of bytes written by the cipher operation exceeds the output |
236 | | /// buffer length. |
237 | 0 | pub fn less_safe_update<'a>( |
238 | 0 | &mut self, |
239 | 0 | input: &[u8], |
240 | 0 | output: &'a mut [u8], |
241 | 0 | ) -> Result<BufferUpdate<'a>, Unspecified> { |
242 | 0 | let next_total = self |
243 | 0 | .output_generated |
244 | 0 | .checked_add(input.len()) |
245 | 0 | .ok_or(Unspecified)?; |
246 | 0 | let extra_buffer_size = (self.algorithm().block_len |
247 | 0 | - next_total.rem_euclid(self.algorithm().block_len)) |
248 | 0 | .rem_euclid(self.algorithm().block_len); |
249 | 0 | let min_outsize = input |
250 | 0 | .len() |
251 | 0 | .checked_add(extra_buffer_size) |
252 | 0 | .ok_or(Unspecified)?; |
253 | 0 | self.update_internal(input, output, min_outsize) |
254 | 0 | } |
255 | | |
256 | | /// Finishes the encryption operation, writing any remaining ciphertext to |
257 | | /// `output`. |
258 | | /// |
259 | | /// The number of bytes written to `output` can be up to the block length of |
260 | | /// [`Algorithm::block_len`]. |
261 | | /// |
262 | | /// # Errors |
263 | | /// * Returns an error if the `output` buffer is smaller than the algorithm's |
264 | | /// block length. |
265 | 0 | pub fn finish( |
266 | 0 | mut self, |
267 | 0 | output: &mut [u8], |
268 | 0 | ) -> Result<(DecryptionContext, BufferUpdate<'_>), Unspecified> { |
269 | 0 | if output.len() < self.algorithm().block_len() { |
270 | 0 | return Err(Unspecified); |
271 | 0 | } |
272 | 0 | let mut outlen: i32 = 0; |
273 | | |
274 | 0 | if 1 != indicator_check!(unsafe { |
275 | 0 | EVP_EncryptFinal_ex( |
276 | 0 | self.cipher_ctx.as_mut_ptr(), |
277 | 0 | output.as_mut_ptr(), |
278 | 0 | &mut outlen, |
279 | 0 | ) |
280 | 0 | }) { |
281 | 0 | return Err(Unspecified); |
282 | 0 | } |
283 | 0 | let outlen: usize = outlen.try_into()?; |
284 | 0 | debug_assert!(outlen <= self.algorithm().block_len()); |
285 | 0 | Ok((self.context.into(), BufferUpdate::new(output, outlen))) |
286 | 0 | } |
287 | | |
288 | | /// Returns the cipher operating mode. |
289 | | #[must_use] |
290 | 0 | pub fn mode(&self) -> OperatingMode { |
291 | 0 | self.mode |
292 | 0 | } |
293 | | |
294 | | /// Returns the cipher algorithm. |
295 | | #[must_use] |
296 | 0 | pub fn algorithm(&self) -> &'static Algorithm { |
297 | 0 | self.algorithm |
298 | 0 | } |
299 | | |
300 | | /// Constructs a `StreamingEncryptingKey` for encrypting data using the CTR cipher mode. |
301 | | /// The resulting ciphertext will be the same length as the plaintext. |
302 | | /// |
303 | | /// # Errors |
304 | | /// Returns and error on an internal failure. |
305 | 0 | pub fn ctr(key: UnboundCipherKey) -> Result<Self, Unspecified> { |
306 | 0 | let context = key.algorithm().new_encryption_context(OperatingMode::CTR)?; |
307 | 0 | Self::less_safe_ctr(key, context) |
308 | 0 | } |
309 | | |
310 | | /// Constructs a `StreamingEncryptingKey` for encrypting data using the CTR cipher mode. |
311 | | /// The resulting ciphertext will be the same length as the plaintext. |
312 | | /// |
313 | | /// This is considered less safe because the caller could potentially construct |
314 | | /// an `EncryptionContext` from a previously used initialization vector (IV). |
315 | | /// |
316 | | /// # Errors |
317 | | /// Returns an error on an internal failure. |
318 | 0 | pub fn less_safe_ctr( |
319 | 0 | key: UnboundCipherKey, |
320 | 0 | context: EncryptionContext, |
321 | 0 | ) -> Result<Self, Unspecified> { |
322 | 0 | Self::new(key, OperatingMode::CTR, context) |
323 | 0 | } |
324 | | |
325 | | /// Constructs a `StreamingEncryptingKey` for encrypting data using the CBC cipher mode |
326 | | /// with pkcs7 padding. |
327 | | /// The resulting ciphertext will be longer than the plaintext; padding is added |
328 | | /// to fill the next block of ciphertext. |
329 | | /// |
330 | | /// # Errors |
331 | | /// Returns an error on an internal failure. |
332 | 0 | pub fn cbc_pkcs7(key: UnboundCipherKey) -> Result<Self, Unspecified> { |
333 | 0 | let context = key.algorithm().new_encryption_context(OperatingMode::CBC)?; |
334 | 0 | Self::less_safe_cbc_pkcs7(key, context) |
335 | 0 | } |
336 | | |
337 | | /// Constructs a `StreamingEncryptingKey` for encrypting data using the CFB128 cipher mode. |
338 | | /// The resulting ciphertext will be the same length as the plaintext. |
339 | | /// |
340 | | /// # Errors |
341 | | /// Returns and error on an internal failure. |
342 | 0 | pub fn cfb128(key: UnboundCipherKey) -> Result<Self, Unspecified> { |
343 | 0 | let context = key |
344 | 0 | .algorithm() |
345 | 0 | .new_encryption_context(OperatingMode::CFB128)?; |
346 | 0 | Self::less_safe_cfb128(key, context) |
347 | 0 | } |
348 | | |
349 | | /// Constructs a `StreamingEncryptingKey` for encrypting using ECB cipher mode with PKCS7 padding. |
350 | | /// The resulting plaintext will be the same length as the ciphertext. |
351 | | /// |
352 | | /// # ☠️ ️️️DANGER ☠️ |
353 | | /// Offered for computability purposes only. This is an extremely dangerous mode, and |
354 | | /// very likely not what you want to use. |
355 | | /// |
356 | | /// # Errors |
357 | | /// Returns an error on an internal failure. |
358 | 0 | pub fn ecb_pkcs7(key: UnboundCipherKey) -> Result<Self, Unspecified> { |
359 | 0 | let context = key.algorithm().new_encryption_context(OperatingMode::ECB)?; |
360 | 0 | Self::new(key, OperatingMode::ECB, context) |
361 | 0 | } |
362 | | |
363 | | /// Constructs a `StreamingEncryptingKey` for encrypting data using the CFB128 cipher mode. |
364 | | /// The resulting ciphertext will be the same length as the plaintext. |
365 | | /// |
366 | | /// This is considered less safe because the caller could potentially construct |
367 | | /// an `EncryptionContext` from a previously used initialization vector (IV). |
368 | | /// |
369 | | /// # Errors |
370 | | /// Returns an error on an internal failure. |
371 | 0 | pub fn less_safe_cfb128( |
372 | 0 | key: UnboundCipherKey, |
373 | 0 | context: EncryptionContext, |
374 | 0 | ) -> Result<Self, Unspecified> { |
375 | 0 | Self::new(key, OperatingMode::CFB128, context) |
376 | 0 | } |
377 | | |
378 | | /// Constructs a `StreamingEncryptingKey` for encrypting data using the CBC cipher mode |
379 | | /// with pkcs7 padding. |
380 | | /// The resulting ciphertext will be longer than the plaintext; padding is added |
381 | | /// to fill the next block of ciphertext. |
382 | | /// |
383 | | /// This is considered less safe because the caller could potentially construct |
384 | | /// an `EncryptionContext` from a previously used initialization vector (IV). |
385 | | /// |
386 | | /// # Errors |
387 | | /// Returns an error on an internal failure. |
388 | 0 | pub fn less_safe_cbc_pkcs7( |
389 | 0 | key: UnboundCipherKey, |
390 | 0 | context: EncryptionContext, |
391 | 0 | ) -> Result<Self, Unspecified> { |
392 | 0 | Self::new(key, OperatingMode::CBC, context) |
393 | 0 | } |
394 | | } |
395 | | |
396 | | /// A key for streaming decryption operations. |
397 | | pub struct StreamingDecryptingKey { |
398 | | algorithm: &'static Algorithm, |
399 | | mode: OperatingMode, |
400 | | cipher_ctx: LcPtr<EVP_CIPHER_CTX>, |
401 | | output_generated: usize, |
402 | | } |
403 | | |
404 | | unsafe impl Send for StreamingDecryptingKey {} |
405 | | |
406 | | impl StreamingDecryptingKey { |
407 | | #[allow(clippy::needless_pass_by_value)] |
408 | 0 | fn new( |
409 | 0 | key: UnboundCipherKey, |
410 | 0 | mode: OperatingMode, |
411 | 0 | context: DecryptionContext, |
412 | 0 | ) -> Result<Self, Unspecified> { |
413 | 0 | let mut cipher_ctx = LcPtr::new(unsafe { EVP_CIPHER_CTX_new() })?; |
414 | 0 | let algorithm = key.algorithm(); |
415 | 0 | let cipher = mode.evp_cipher(key.algorithm); |
416 | 0 | let key_bytes = key.key_bytes.as_ref(); |
417 | 0 | if key_bytes.len() |
418 | 0 | != <usize>::try_from(unsafe { EVP_CIPHER_key_length(cipher.as_const_ptr()) }).unwrap() |
419 | | { |
420 | 0 | return Err(Unspecified); |
421 | 0 | } |
422 | | |
423 | 0 | match &context { |
424 | 0 | ctx @ DecryptionContext::Iv128(..) => { |
425 | 0 | let iv = <&[u8]>::try_from(ctx)?; |
426 | 0 | debug_assert_eq!( |
427 | 0 | iv.len(), |
428 | 0 | <usize>::try_from(unsafe { EVP_CIPHER_iv_length(cipher.as_const_ptr()) }) |
429 | 0 | .unwrap() |
430 | | ); |
431 | 0 | evp_decrypt_init(&mut cipher_ctx, &cipher, key_bytes, Some(iv))?; |
432 | | } |
433 | | DecryptionContext::None => { |
434 | 0 | evp_decrypt_init(&mut cipher_ctx, &cipher, key_bytes, None)?; |
435 | | } |
436 | | } |
437 | | |
438 | 0 | Ok(Self { |
439 | 0 | algorithm, |
440 | 0 | mode, |
441 | 0 | cipher_ctx, |
442 | 0 | output_generated: 0, |
443 | 0 | }) |
444 | 0 | } |
445 | | |
446 | 0 | fn update_internal<'a>( |
447 | 0 | &mut self, |
448 | 0 | input: &[u8], |
449 | 0 | output: &'a mut [u8], |
450 | 0 | min_outsize: usize, |
451 | 0 | ) -> Result<BufferUpdate<'a>, Unspecified> { |
452 | 0 | if output.len() < min_outsize { |
453 | 0 | return Err(Unspecified); |
454 | 0 | } |
455 | 0 | let mut outlen: i32 = 0; |
456 | 0 | let inlen: i32 = input.len().try_into()?; |
457 | | |
458 | 0 | if 1 != unsafe { |
459 | 0 | EVP_DecryptUpdate( |
460 | 0 | self.cipher_ctx.as_mut_ptr(), |
461 | 0 | output.as_mut_ptr(), |
462 | 0 | &mut outlen, |
463 | 0 | input.as_ptr(), |
464 | 0 | inlen, |
465 | 0 | ) |
466 | 0 | } { |
467 | 0 | return Err(Unspecified); |
468 | 0 | } |
469 | 0 | let outlen: usize = outlen.try_into()?; |
470 | 0 | debug_assert!(outlen <= min_outsize); |
471 | 0 | self.output_generated += outlen; |
472 | 0 | assert!(outlen <= output.len()); |
473 | | |
474 | 0 | Ok(BufferUpdate::new(output, outlen)) |
475 | 0 | } |
476 | | |
477 | | /// Updates the internal state of the key with the provided ciphertext `input`, |
478 | | /// potentially also writing bytes of plaintext to `output`. |
479 | | /// The number of bytes written to `output` can be up to `input.len()` |
480 | | /// plus the block length of the cipher algorithm (e.g., [`Algorithm::block_len`]) minus one. |
481 | | /// |
482 | | /// # Errors |
483 | | /// * Returns an error if the `output` buffer is smaller than the length of |
484 | | /// the `input` plus the algorithm's block length minus one. |
485 | | /// * May return an error if the length of `input` plus the algorithm's block length is larger |
486 | | /// than `i32::MAX`. |
487 | 0 | pub fn update<'a>( |
488 | 0 | &mut self, |
489 | 0 | input: &[u8], |
490 | 0 | output: &'a mut [u8], |
491 | 0 | ) -> Result<BufferUpdate<'a>, Unspecified> { |
492 | 0 | let min_outsize = input |
493 | 0 | .len() |
494 | 0 | .checked_add(self.algorithm().block_len()) |
495 | 0 | .ok_or(Unspecified)? |
496 | 0 | .checked_sub(1) |
497 | 0 | .ok_or(Unspecified)?; |
498 | 0 | self.update_internal(input, output, min_outsize) |
499 | 0 | } |
500 | | |
501 | | /// Updates the internal state of the key with the provided ciphertext `input`, |
502 | | /// potentially writing bytes of plaintext to `output`. |
503 | | /// |
504 | | /// This function has looser output buffer size requirements than [`Self::update`], |
505 | | /// calculating the minimum required size based on the total bytes of output generated |
506 | | /// and the cipher's block length. This is considered "less safe" because it's |
507 | | /// based on assumptions about the state of the underlying operations. |
508 | | /// |
509 | | /// The minimum output buffer size is calculated based on how many bytes are needed to |
510 | | /// reach the next block boundary after processing the input. If `next_total` is the sum |
511 | | /// of bytes already generated plus `input.len()`, then the minimum size is: |
512 | | /// `input.len() + ((block_len - (next_total % block_len)) % block_len)` |
513 | | /// |
514 | | /// # Errors |
515 | | /// Returns an error if the `output` buffer is smaller than the calculated minimum size, |
516 | | /// if the total output length overflows, or if the length of `input` is larger than |
517 | | /// `i32::MAX`. |
518 | | /// |
519 | | /// # Panics |
520 | | /// Panics if the number of bytes written by the cipher operation exceeds the output |
521 | | /// buffer length. |
522 | 0 | pub fn less_safe_update<'a>( |
523 | 0 | &mut self, |
524 | 0 | input: &[u8], |
525 | 0 | output: &'a mut [u8], |
526 | 0 | ) -> Result<BufferUpdate<'a>, Unspecified> { |
527 | 0 | let next_total = self |
528 | 0 | .output_generated |
529 | 0 | .checked_add(input.len()) |
530 | 0 | .ok_or(Unspecified)?; |
531 | 0 | let extra_buffer_size = (self.algorithm().block_len |
532 | 0 | - next_total.rem_euclid(self.algorithm().block_len)) |
533 | 0 | .rem_euclid(self.algorithm().block_len); |
534 | 0 | let min_outsize = input |
535 | 0 | .len() |
536 | 0 | .checked_add(extra_buffer_size) |
537 | 0 | .ok_or(Unspecified)?; |
538 | 0 | self.update_internal(input, output, min_outsize) |
539 | 0 | } |
540 | | |
541 | | /// Finishes the decryption operation, writing the remaining plaintext to |
542 | | /// `output`. |
543 | | /// The number of bytes written to `output` can be up to the block length of |
544 | | /// the cipher algorithm (e.g., [`Algorithm::block_len`]). |
545 | | /// |
546 | | /// # Errors |
547 | | /// * Returns an error if the `output` buffer is smaller than the algorithm's |
548 | | /// block length. |
549 | 0 | pub fn finish(mut self, output: &mut [u8]) -> Result<BufferUpdate<'_>, Unspecified> { |
550 | 0 | if output.len() < self.algorithm().block_len() { |
551 | 0 | return Err(Unspecified); |
552 | 0 | } |
553 | 0 | let mut outlen: i32 = 0; |
554 | | |
555 | 0 | if 1 != indicator_check!(unsafe { |
556 | 0 | EVP_DecryptFinal_ex( |
557 | 0 | self.cipher_ctx.as_mut_ptr(), |
558 | 0 | output.as_mut_ptr(), |
559 | 0 | &mut outlen, |
560 | 0 | ) |
561 | 0 | }) { |
562 | 0 | return Err(Unspecified); |
563 | 0 | } |
564 | 0 | let outlen: usize = outlen.try_into()?; |
565 | 0 | debug_assert!(outlen <= self.algorithm().block_len()); |
566 | 0 | Ok(BufferUpdate::new(output, outlen)) |
567 | 0 | } |
568 | | |
569 | | /// Returns the cipher operating mode. |
570 | | #[must_use] |
571 | 0 | pub fn mode(&self) -> OperatingMode { |
572 | 0 | self.mode |
573 | 0 | } |
574 | | |
575 | | /// Returns the cipher algorithm |
576 | | #[must_use] |
577 | 0 | pub fn algorithm(&self) -> &'static Algorithm { |
578 | 0 | self.algorithm |
579 | 0 | } |
580 | | |
581 | | /// Constructs a `StreamingDecryptingKey` for decrypting using the CTR cipher mode. |
582 | | /// The resulting plaintext will be the same length as the ciphertext. |
583 | | /// |
584 | | /// # Errors |
585 | | /// Returns an error on an internal failure. |
586 | 0 | pub fn ctr(key: UnboundCipherKey, context: DecryptionContext) -> Result<Self, Unspecified> { |
587 | 0 | Self::new(key, OperatingMode::CTR, context) |
588 | 0 | } |
589 | | |
590 | | /// Constructs a `StreamingDecryptingKey` for decrypting using the CBC cipher mode. |
591 | | /// The resulting plaintext will be shorter than the ciphertext. |
592 | | /// |
593 | | /// # Errors |
594 | | /// Returns an error on an internal failure. |
595 | 0 | pub fn cbc_pkcs7( |
596 | 0 | key: UnboundCipherKey, |
597 | 0 | context: DecryptionContext, |
598 | 0 | ) -> Result<Self, Unspecified> { |
599 | 0 | Self::new(key, OperatingMode::CBC, context) |
600 | 0 | } |
601 | | |
602 | | // Constructs a `StreamingDecryptingKey` for decrypting using the CFB128 cipher mode. |
603 | | /// The resulting plaintext will be the same length as the ciphertext. |
604 | | /// |
605 | | /// # Errors |
606 | | /// Returns an error on an internal failure. |
607 | 0 | pub fn cfb128(key: UnboundCipherKey, context: DecryptionContext) -> Result<Self, Unspecified> { |
608 | 0 | Self::new(key, OperatingMode::CFB128, context) |
609 | 0 | } |
610 | | |
611 | | /// Constructs a `StreamingDecryptingKey` for decrypting using the ECB cipher mode. |
612 | | /// The resulting plaintext will be the same length as the ciphertext. |
613 | | /// |
614 | | /// # ☠️ ️️️DANGER ☠️ |
615 | | /// Offered for computability purposes only. This is an extremely dangerous mode, and |
616 | | /// very likely not what you want to use. |
617 | | /// |
618 | | /// # Errors |
619 | | /// Returns an error on an internal failure. |
620 | 0 | pub fn ecb_pkcs7( |
621 | 0 | key: UnboundCipherKey, |
622 | 0 | context: DecryptionContext, |
623 | 0 | ) -> Result<Self, Unspecified> { |
624 | 0 | Self::new(key, OperatingMode::ECB, context) |
625 | 0 | } |
626 | | } |
627 | | |
628 | | #[cfg(test)] |
629 | | mod tests { |
630 | | use crate::cipher::{ |
631 | | DecryptionContext, EncryptionContext, OperatingMode, StreamingDecryptingKey, |
632 | | StreamingEncryptingKey, UnboundCipherKey, AES_128, AES_256, AES_256_KEY_LEN, |
633 | | }; |
634 | | use crate::iv::{FixedLength, IV_LEN_128_BIT}; |
635 | | use crate::rand::{SecureRandom, SystemRandom}; |
636 | | use crate::test::from_hex; |
637 | | use paste::*; |
638 | | |
639 | | /// Generic helper for step encryption that accepts a closure for the update operation. |
640 | | /// The closure receives: (key, input, output_buffer, out_idx, block_len, step) |
641 | | /// and returns the number of bytes written. |
642 | | fn step_encrypt_with_updater<F>( |
643 | | mut encrypting_key: StreamingEncryptingKey, |
644 | | plaintext: &[u8], |
645 | | step: usize, |
646 | | mut updater: F, |
647 | | ) -> (Box<[u8]>, DecryptionContext) |
648 | | where |
649 | | F: FnMut(&mut StreamingEncryptingKey, &[u8], &mut [u8], usize, usize, usize) -> usize, |
650 | | { |
651 | | let alg = encrypting_key.algorithm(); |
652 | | let mode = encrypting_key.mode(); |
653 | | let block_len = alg.block_len(); |
654 | | let n = plaintext.len(); |
655 | | let mut ciphertext = vec![0u8; n + block_len]; |
656 | | |
657 | | let mut in_idx: usize = 0; |
658 | | let mut out_idx: usize = 0; |
659 | | loop { |
660 | | let mut in_end = in_idx + step; |
661 | | if in_end > n { |
662 | | in_end = n; |
663 | | } |
664 | | let written = updater( |
665 | | &mut encrypting_key, |
666 | | &plaintext[in_idx..in_end], |
667 | | &mut ciphertext, |
668 | | out_idx, |
669 | | block_len, |
670 | | step, |
671 | | ); |
672 | | in_idx += step; |
673 | | out_idx += written; |
674 | | if in_idx >= n { |
675 | | break; |
676 | | } |
677 | | } |
678 | | let out_end = out_idx + block_len; |
679 | | let (decrypt_iv, output) = encrypting_key |
680 | | .finish(&mut ciphertext[out_idx..out_end]) |
681 | | .unwrap(); |
682 | | let outlen = output.written().len(); |
683 | | ciphertext.truncate(out_idx + outlen); |
684 | | match mode { |
685 | | OperatingMode::CBC | OperatingMode::ECB => { |
686 | | assert!(ciphertext.len() > plaintext.len()); |
687 | | assert!(ciphertext.len() <= plaintext.len() + block_len); |
688 | | } |
689 | | _ => { |
690 | | assert_eq!(ciphertext.len(), plaintext.len()); |
691 | | } |
692 | | } |
693 | | |
694 | | (ciphertext.into_boxed_slice(), decrypt_iv) |
695 | | } |
696 | | |
697 | | /// Generic helper for step decryption that accepts a closure for the update operation. |
698 | | /// The closure receives: (key, input, output_buffer, out_idx, block_len, step) |
699 | | /// and returns the number of bytes written. |
700 | | fn step_decrypt_with_updater<F>( |
701 | | mut decrypting_key: StreamingDecryptingKey, |
702 | | ciphertext: &[u8], |
703 | | step: usize, |
704 | | mut updater: F, |
705 | | ) -> Box<[u8]> |
706 | | where |
707 | | F: FnMut(&mut StreamingDecryptingKey, &[u8], &mut [u8], usize, usize, usize) -> usize, |
708 | | { |
709 | | let alg = decrypting_key.algorithm(); |
710 | | let mode = decrypting_key.mode(); |
711 | | let block_len = alg.block_len(); |
712 | | let n = ciphertext.len(); |
713 | | let mut plaintext = vec![0u8; n + block_len]; |
714 | | |
715 | | let mut in_idx: usize = 0; |
716 | | let mut out_idx: usize = 0; |
717 | | loop { |
718 | | let mut in_end = in_idx + step; |
719 | | if in_end > n { |
720 | | in_end = n; |
721 | | } |
722 | | let written = updater( |
723 | | &mut decrypting_key, |
724 | | &ciphertext[in_idx..in_end], |
725 | | &mut plaintext, |
726 | | out_idx, |
727 | | block_len, |
728 | | step, |
729 | | ); |
730 | | in_idx += step; |
731 | | out_idx += written; |
732 | | if in_idx >= n { |
733 | | break; |
734 | | } |
735 | | } |
736 | | let out_end = out_idx + block_len; |
737 | | let output = decrypting_key |
738 | | .finish(&mut plaintext[out_idx..out_end]) |
739 | | .unwrap(); |
740 | | let outlen = output.written().len(); |
741 | | plaintext.truncate(out_idx + outlen); |
742 | | match mode { |
743 | | OperatingMode::CBC | OperatingMode::ECB => { |
744 | | assert!(ciphertext.len() > plaintext.len()); |
745 | | assert!(ciphertext.len() <= plaintext.len() + block_len); |
746 | | } |
747 | | _ => { |
748 | | assert_eq!(ciphertext.len(), plaintext.len()); |
749 | | } |
750 | | } |
751 | | plaintext.into_boxed_slice() |
752 | | } |
753 | | |
754 | | fn step_encrypt( |
755 | | encrypting_key: StreamingEncryptingKey, |
756 | | plaintext: &[u8], |
757 | | step: usize, |
758 | | ) -> (Box<[u8]>, DecryptionContext) { |
759 | | step_encrypt_with_updater( |
760 | | encrypting_key, |
761 | | plaintext, |
762 | | step, |
763 | | |key, input, output, out_idx, block_len, _step| { |
764 | | let out_end = out_idx + input.len() + block_len - 1; |
765 | | let result = key.update(input, &mut output[out_idx..out_end]).unwrap(); |
766 | | result.written().len() |
767 | | }, |
768 | | ) |
769 | | } |
770 | | |
771 | | fn step_decrypt( |
772 | | decrypting_key: StreamingDecryptingKey, |
773 | | ciphertext: &[u8], |
774 | | step: usize, |
775 | | ) -> Box<[u8]> { |
776 | | step_decrypt_with_updater( |
777 | | decrypting_key, |
778 | | ciphertext, |
779 | | step, |
780 | | |key, input, output, out_idx, block_len, _step| { |
781 | | let out_end = out_idx + input.len() + block_len - 1; |
782 | | let result = key.update(input, &mut output[out_idx..out_end]).unwrap(); |
783 | | result.written().len() |
784 | | }, |
785 | | ) |
786 | | } |
787 | | |
788 | | fn step_encrypt_less_safe( |
789 | | encrypting_key: StreamingEncryptingKey, |
790 | | plaintext: &[u8], |
791 | | step: usize, |
792 | | ) -> (Box<[u8]>, DecryptionContext) { |
793 | | step_encrypt_with_updater( |
794 | | encrypting_key, |
795 | | plaintext, |
796 | | step, |
797 | | |key, input, output, out_idx, block_len, step| { |
798 | | let input_len = input.len(); |
799 | | let next_total = out_idx + input_len; |
800 | | // Calculate the tighter minimum output buffer size |
801 | | let min_out_len = input_len + ((block_len - (next_total % block_len)) % block_len); |
802 | | if input_len % block_len == 0 && step % block_len == 0 { |
803 | | // When input is provided one block at a time, no additional space should be needed. |
804 | | assert!(input_len == min_out_len); |
805 | | } |
806 | | let out_end = out_idx + min_out_len; |
807 | | let result = key |
808 | | .less_safe_update(input, &mut output[out_idx..out_end]) |
809 | | .unwrap(); |
810 | | result.written().len() |
811 | | }, |
812 | | ) |
813 | | } |
814 | | |
815 | | fn step_decrypt_less_safe( |
816 | | decrypting_key: StreamingDecryptingKey, |
817 | | ciphertext: &[u8], |
818 | | step: usize, |
819 | | ) -> Box<[u8]> { |
820 | | step_decrypt_with_updater( |
821 | | decrypting_key, |
822 | | ciphertext, |
823 | | step, |
824 | | |key, input, output, out_idx, block_len, step| { |
825 | | let input_len = input.len(); |
826 | | let next_total = out_idx + input_len; |
827 | | // Calculate the tighter minimum output buffer size |
828 | | let min_out_len = input_len + ((block_len - (next_total % block_len)) % block_len); |
829 | | if input_len % block_len == 0 && step % block_len == 0 { |
830 | | // When input is provided one block at a time, no additional space should be needed. |
831 | | assert!(input_len == min_out_len); |
832 | | } |
833 | | let out_end = out_idx + min_out_len; |
834 | | let result = key |
835 | | .less_safe_update(input, &mut output[out_idx..out_end]) |
836 | | .unwrap(); |
837 | | result.written().len() |
838 | | }, |
839 | | ) |
840 | | } |
841 | | |
842 | | macro_rules! helper_stream_step_encrypt_test { |
843 | | ($mode:ident) => { |
844 | | paste! { |
845 | | fn [<helper_test_ $mode _stream_encrypt_step_n_bytes>]( |
846 | | encrypting_key_creator: impl Fn() -> StreamingEncryptingKey, |
847 | | decrypting_key_creator: impl Fn(DecryptionContext) -> StreamingDecryptingKey, |
848 | | n: usize, |
849 | | step: usize, |
850 | | ) { |
851 | | let mut input = vec![0u8; n]; |
852 | | let random = SystemRandom::new(); |
853 | | random.fill(&mut input).unwrap(); |
854 | | |
855 | | let encrypting_key = encrypting_key_creator(); |
856 | | |
857 | | let (ciphertext, decrypt_iv) = step_encrypt(encrypting_key, &input, step); |
858 | | |
859 | | let decrypting_key = decrypting_key_creator(decrypt_iv); |
860 | | |
861 | | let plaintext = step_decrypt(decrypting_key, &ciphertext, step); |
862 | | |
863 | | assert_eq!(input.as_slice(), &*plaintext); |
864 | | } |
865 | | } |
866 | | }; |
867 | | ($mode:ident, less_safe) => { |
868 | | paste! { |
869 | | fn [<helper_test_ $mode _stream_encrypt_step_n_bytes_less_safe>]( |
870 | | encrypting_key_creator: impl Fn() -> StreamingEncryptingKey, |
871 | | decrypting_key_creator: impl Fn(DecryptionContext) -> StreamingDecryptingKey, |
872 | | n: usize, |
873 | | step: usize, |
874 | | ) { |
875 | | let mut input = vec![0u8; n]; |
876 | | let random = SystemRandom::new(); |
877 | | random.fill(&mut input).unwrap(); |
878 | | |
879 | | let encrypting_key = encrypting_key_creator(); |
880 | | |
881 | | let (ciphertext, decrypt_iv) = step_encrypt_less_safe(encrypting_key, &input, step); |
882 | | |
883 | | let decrypting_key = decrypting_key_creator(decrypt_iv); |
884 | | |
885 | | let plaintext = step_decrypt_less_safe(decrypting_key, &ciphertext, step); |
886 | | |
887 | | assert_eq!(input.as_slice(), &*plaintext); |
888 | | } |
889 | | } |
890 | | }; |
891 | | } |
892 | | |
893 | | helper_stream_step_encrypt_test!(cbc_pkcs7); |
894 | | helper_stream_step_encrypt_test!(ctr); |
895 | | helper_stream_step_encrypt_test!(cfb128); |
896 | | helper_stream_step_encrypt_test!(ecb_pkcs7); |
897 | | |
898 | | helper_stream_step_encrypt_test!(cbc_pkcs7, less_safe); |
899 | | helper_stream_step_encrypt_test!(ctr, less_safe); |
900 | | helper_stream_step_encrypt_test!(cfb128, less_safe); |
901 | | helper_stream_step_encrypt_test!(ecb_pkcs7, less_safe); |
902 | | |
903 | | #[test] |
904 | | fn test_step_cbc() { |
905 | | let random = SystemRandom::new(); |
906 | | let mut key = [0u8; AES_256_KEY_LEN]; |
907 | | random.fill(&mut key).unwrap(); |
908 | | let key = key; |
909 | | |
910 | | let encrypting_key_creator = || { |
911 | | let key = UnboundCipherKey::new(&AES_256, &key.clone()).unwrap(); |
912 | | StreamingEncryptingKey::cbc_pkcs7(key).unwrap() |
913 | | }; |
914 | | let decrypting_key_creator = |decryption_ctx: DecryptionContext| { |
915 | | let key = UnboundCipherKey::new(&AES_256, &key.clone()).unwrap(); |
916 | | StreamingDecryptingKey::cbc_pkcs7(key, decryption_ctx).unwrap() |
917 | | }; |
918 | | |
919 | | for i in 13..=21 { |
920 | | for j in 124..=131 { |
921 | | helper_test_cbc_pkcs7_stream_encrypt_step_n_bytes( |
922 | | encrypting_key_creator, |
923 | | decrypting_key_creator, |
924 | | j, |
925 | | i, |
926 | | ); |
927 | | } |
928 | | for j in 124..=131 { |
929 | | helper_test_cbc_pkcs7_stream_encrypt_step_n_bytes( |
930 | | encrypting_key_creator, |
931 | | decrypting_key_creator, |
932 | | j, |
933 | | j - i, |
934 | | ); |
935 | | } |
936 | | } |
937 | | for j in 124..=131 { |
938 | | helper_test_cbc_pkcs7_stream_encrypt_step_n_bytes( |
939 | | encrypting_key_creator, |
940 | | decrypting_key_creator, |
941 | | j, |
942 | | j, |
943 | | ); |
944 | | helper_test_cbc_pkcs7_stream_encrypt_step_n_bytes( |
945 | | encrypting_key_creator, |
946 | | decrypting_key_creator, |
947 | | j, |
948 | | 256, |
949 | | ); |
950 | | helper_test_cbc_pkcs7_stream_encrypt_step_n_bytes( |
951 | | encrypting_key_creator, |
952 | | decrypting_key_creator, |
953 | | j, |
954 | | 1, |
955 | | ); |
956 | | } |
957 | | } |
958 | | |
959 | | #[test] |
960 | | fn test_step_ctr() { |
961 | | let random = SystemRandom::new(); |
962 | | let mut key = [0u8; AES_256_KEY_LEN]; |
963 | | random.fill(&mut key).unwrap(); |
964 | | |
965 | | let encrypting_key_creator = || { |
966 | | let key = UnboundCipherKey::new(&AES_256, &key.clone()).unwrap(); |
967 | | StreamingEncryptingKey::ctr(key).unwrap() |
968 | | }; |
969 | | let decrypting_key_creator = |decryption_ctx: DecryptionContext| { |
970 | | let key = UnboundCipherKey::new(&AES_256, &key.clone()).unwrap(); |
971 | | StreamingDecryptingKey::ctr(key, decryption_ctx).unwrap() |
972 | | }; |
973 | | |
974 | | for i in 13..=21 { |
975 | | for j in 124..=131 { |
976 | | helper_test_ctr_stream_encrypt_step_n_bytes( |
977 | | encrypting_key_creator, |
978 | | decrypting_key_creator, |
979 | | j, |
980 | | i, |
981 | | ); |
982 | | } |
983 | | for j in 124..=131 { |
984 | | helper_test_ctr_stream_encrypt_step_n_bytes( |
985 | | encrypting_key_creator, |
986 | | decrypting_key_creator, |
987 | | j, |
988 | | j - i, |
989 | | ); |
990 | | } |
991 | | } |
992 | | for j in 124..=131 { |
993 | | helper_test_ctr_stream_encrypt_step_n_bytes( |
994 | | encrypting_key_creator, |
995 | | decrypting_key_creator, |
996 | | j, |
997 | | j, |
998 | | ); |
999 | | helper_test_ctr_stream_encrypt_step_n_bytes( |
1000 | | encrypting_key_creator, |
1001 | | decrypting_key_creator, |
1002 | | j, |
1003 | | 256, |
1004 | | ); |
1005 | | helper_test_ctr_stream_encrypt_step_n_bytes( |
1006 | | encrypting_key_creator, |
1007 | | decrypting_key_creator, |
1008 | | j, |
1009 | | 1, |
1010 | | ); |
1011 | | } |
1012 | | } |
1013 | | |
1014 | | #[test] |
1015 | | fn test_step_cfb128() { |
1016 | | let random = SystemRandom::new(); |
1017 | | let mut key = [0u8; AES_256_KEY_LEN]; |
1018 | | random.fill(&mut key).unwrap(); |
1019 | | |
1020 | | let encrypting_key_creator = || { |
1021 | | let key = UnboundCipherKey::new(&AES_256, &key.clone()).unwrap(); |
1022 | | StreamingEncryptingKey::cfb128(key).unwrap() |
1023 | | }; |
1024 | | let decrypting_key_creator = |decryption_ctx: DecryptionContext| { |
1025 | | let key = UnboundCipherKey::new(&AES_256, &key.clone()).unwrap(); |
1026 | | StreamingDecryptingKey::cfb128(key, decryption_ctx).unwrap() |
1027 | | }; |
1028 | | |
1029 | | for i in 13..=21 { |
1030 | | for j in 124..=131 { |
1031 | | helper_test_cfb128_stream_encrypt_step_n_bytes( |
1032 | | encrypting_key_creator, |
1033 | | decrypting_key_creator, |
1034 | | j, |
1035 | | i, |
1036 | | ); |
1037 | | } |
1038 | | for j in 124..=131 { |
1039 | | helper_test_cfb128_stream_encrypt_step_n_bytes( |
1040 | | encrypting_key_creator, |
1041 | | decrypting_key_creator, |
1042 | | j, |
1043 | | j - i, |
1044 | | ); |
1045 | | } |
1046 | | } |
1047 | | for j in 124..=131 { |
1048 | | helper_test_cfb128_stream_encrypt_step_n_bytes( |
1049 | | encrypting_key_creator, |
1050 | | decrypting_key_creator, |
1051 | | j, |
1052 | | j, |
1053 | | ); |
1054 | | helper_test_cfb128_stream_encrypt_step_n_bytes( |
1055 | | encrypting_key_creator, |
1056 | | decrypting_key_creator, |
1057 | | j, |
1058 | | 256, |
1059 | | ); |
1060 | | helper_test_cfb128_stream_encrypt_step_n_bytes( |
1061 | | encrypting_key_creator, |
1062 | | decrypting_key_creator, |
1063 | | j, |
1064 | | 1, |
1065 | | ); |
1066 | | } |
1067 | | } |
1068 | | |
1069 | | #[test] |
1070 | | fn test_step_ecb_pkcs7() { |
1071 | | let random = SystemRandom::new(); |
1072 | | let mut key = [0u8; AES_256_KEY_LEN]; |
1073 | | random.fill(&mut key).unwrap(); |
1074 | | |
1075 | | let encrypting_key_creator = || { |
1076 | | let key = UnboundCipherKey::new(&AES_256, &key.clone()).unwrap(); |
1077 | | StreamingEncryptingKey::ecb_pkcs7(key).unwrap() |
1078 | | }; |
1079 | | let decrypting_key_creator = |decryption_ctx: DecryptionContext| { |
1080 | | let key = UnboundCipherKey::new(&AES_256, &key.clone()).unwrap(); |
1081 | | StreamingDecryptingKey::ecb_pkcs7(key, decryption_ctx).unwrap() |
1082 | | }; |
1083 | | |
1084 | | for i in 13..=21 { |
1085 | | for j in 124..=131 { |
1086 | | helper_test_ecb_pkcs7_stream_encrypt_step_n_bytes( |
1087 | | encrypting_key_creator, |
1088 | | decrypting_key_creator, |
1089 | | j, |
1090 | | i, |
1091 | | ); |
1092 | | } |
1093 | | for j in 124..=131 { |
1094 | | helper_test_ecb_pkcs7_stream_encrypt_step_n_bytes( |
1095 | | encrypting_key_creator, |
1096 | | decrypting_key_creator, |
1097 | | j, |
1098 | | j - i, |
1099 | | ); |
1100 | | } |
1101 | | } |
1102 | | for j in 124..=131 { |
1103 | | helper_test_ecb_pkcs7_stream_encrypt_step_n_bytes( |
1104 | | encrypting_key_creator, |
1105 | | decrypting_key_creator, |
1106 | | j, |
1107 | | j, |
1108 | | ); |
1109 | | helper_test_ecb_pkcs7_stream_encrypt_step_n_bytes( |
1110 | | encrypting_key_creator, |
1111 | | decrypting_key_creator, |
1112 | | j, |
1113 | | 256, |
1114 | | ); |
1115 | | helper_test_ecb_pkcs7_stream_encrypt_step_n_bytes( |
1116 | | encrypting_key_creator, |
1117 | | decrypting_key_creator, |
1118 | | j, |
1119 | | 1, |
1120 | | ); |
1121 | | } |
1122 | | } |
1123 | | |
1124 | | #[test] |
1125 | | fn test_step_cbc_less_safe() { |
1126 | | let random = SystemRandom::new(); |
1127 | | let mut key = [0u8; AES_256_KEY_LEN]; |
1128 | | random.fill(&mut key).unwrap(); |
1129 | | let key = key; |
1130 | | |
1131 | | let encrypting_key_creator = || { |
1132 | | let key = UnboundCipherKey::new(&AES_256, &key.clone()).unwrap(); |
1133 | | StreamingEncryptingKey::cbc_pkcs7(key).unwrap() |
1134 | | }; |
1135 | | let decrypting_key_creator = |decryption_ctx: DecryptionContext| { |
1136 | | let key = UnboundCipherKey::new(&AES_256, &key.clone()).unwrap(); |
1137 | | StreamingDecryptingKey::cbc_pkcs7(key, decryption_ctx).unwrap() |
1138 | | }; |
1139 | | |
1140 | | for i in 13..=21 { |
1141 | | for j in 124..=131 { |
1142 | | helper_test_cbc_pkcs7_stream_encrypt_step_n_bytes_less_safe( |
1143 | | encrypting_key_creator, |
1144 | | decrypting_key_creator, |
1145 | | j, |
1146 | | i, |
1147 | | ); |
1148 | | } |
1149 | | for j in 124..=131 { |
1150 | | helper_test_cbc_pkcs7_stream_encrypt_step_n_bytes_less_safe( |
1151 | | encrypting_key_creator, |
1152 | | decrypting_key_creator, |
1153 | | j, |
1154 | | j - i, |
1155 | | ); |
1156 | | } |
1157 | | } |
1158 | | for j in 124..=131 { |
1159 | | helper_test_cbc_pkcs7_stream_encrypt_step_n_bytes_less_safe( |
1160 | | encrypting_key_creator, |
1161 | | decrypting_key_creator, |
1162 | | j, |
1163 | | j, |
1164 | | ); |
1165 | | helper_test_cbc_pkcs7_stream_encrypt_step_n_bytes_less_safe( |
1166 | | encrypting_key_creator, |
1167 | | decrypting_key_creator, |
1168 | | j, |
1169 | | 256, |
1170 | | ); |
1171 | | helper_test_cbc_pkcs7_stream_encrypt_step_n_bytes_less_safe( |
1172 | | encrypting_key_creator, |
1173 | | decrypting_key_creator, |
1174 | | j, |
1175 | | 1, |
1176 | | ); |
1177 | | } |
1178 | | } |
1179 | | |
1180 | | #[test] |
1181 | | fn test_step_ctr_less_safe() { |
1182 | | let random = SystemRandom::new(); |
1183 | | let mut key = [0u8; AES_256_KEY_LEN]; |
1184 | | random.fill(&mut key).unwrap(); |
1185 | | |
1186 | | let encrypting_key_creator = || { |
1187 | | let key = UnboundCipherKey::new(&AES_256, &key.clone()).unwrap(); |
1188 | | StreamingEncryptingKey::ctr(key).unwrap() |
1189 | | }; |
1190 | | let decrypting_key_creator = |decryption_ctx: DecryptionContext| { |
1191 | | let key = UnboundCipherKey::new(&AES_256, &key.clone()).unwrap(); |
1192 | | StreamingDecryptingKey::ctr(key, decryption_ctx).unwrap() |
1193 | | }; |
1194 | | |
1195 | | for i in 13..=21 { |
1196 | | for j in 124..=131 { |
1197 | | helper_test_ctr_stream_encrypt_step_n_bytes_less_safe( |
1198 | | encrypting_key_creator, |
1199 | | decrypting_key_creator, |
1200 | | j, |
1201 | | i, |
1202 | | ); |
1203 | | } |
1204 | | for j in 124..=131 { |
1205 | | helper_test_ctr_stream_encrypt_step_n_bytes_less_safe( |
1206 | | encrypting_key_creator, |
1207 | | decrypting_key_creator, |
1208 | | j, |
1209 | | j - i, |
1210 | | ); |
1211 | | } |
1212 | | } |
1213 | | for j in 124..=131 { |
1214 | | helper_test_ctr_stream_encrypt_step_n_bytes_less_safe( |
1215 | | encrypting_key_creator, |
1216 | | decrypting_key_creator, |
1217 | | j, |
1218 | | j, |
1219 | | ); |
1220 | | helper_test_ctr_stream_encrypt_step_n_bytes_less_safe( |
1221 | | encrypting_key_creator, |
1222 | | decrypting_key_creator, |
1223 | | j, |
1224 | | 256, |
1225 | | ); |
1226 | | helper_test_ctr_stream_encrypt_step_n_bytes_less_safe( |
1227 | | encrypting_key_creator, |
1228 | | decrypting_key_creator, |
1229 | | j, |
1230 | | 1, |
1231 | | ); |
1232 | | } |
1233 | | } |
1234 | | |
1235 | | #[test] |
1236 | | fn test_step_cfb128_less_safe() { |
1237 | | let random = SystemRandom::new(); |
1238 | | let mut key = [0u8; AES_256_KEY_LEN]; |
1239 | | random.fill(&mut key).unwrap(); |
1240 | | |
1241 | | let encrypting_key_creator = || { |
1242 | | let key = UnboundCipherKey::new(&AES_256, &key.clone()).unwrap(); |
1243 | | StreamingEncryptingKey::cfb128(key).unwrap() |
1244 | | }; |
1245 | | let decrypting_key_creator = |decryption_ctx: DecryptionContext| { |
1246 | | let key = UnboundCipherKey::new(&AES_256, &key.clone()).unwrap(); |
1247 | | StreamingDecryptingKey::cfb128(key, decryption_ctx).unwrap() |
1248 | | }; |
1249 | | |
1250 | | for i in 13..=21 { |
1251 | | for j in 124..=131 { |
1252 | | helper_test_cfb128_stream_encrypt_step_n_bytes_less_safe( |
1253 | | encrypting_key_creator, |
1254 | | decrypting_key_creator, |
1255 | | j, |
1256 | | i, |
1257 | | ); |
1258 | | } |
1259 | | for j in 124..=131 { |
1260 | | helper_test_cfb128_stream_encrypt_step_n_bytes_less_safe( |
1261 | | encrypting_key_creator, |
1262 | | decrypting_key_creator, |
1263 | | j, |
1264 | | j - i, |
1265 | | ); |
1266 | | } |
1267 | | } |
1268 | | for j in 124..=131 { |
1269 | | helper_test_cfb128_stream_encrypt_step_n_bytes_less_safe( |
1270 | | encrypting_key_creator, |
1271 | | decrypting_key_creator, |
1272 | | j, |
1273 | | j, |
1274 | | ); |
1275 | | helper_test_cfb128_stream_encrypt_step_n_bytes_less_safe( |
1276 | | encrypting_key_creator, |
1277 | | decrypting_key_creator, |
1278 | | j, |
1279 | | 256, |
1280 | | ); |
1281 | | helper_test_cfb128_stream_encrypt_step_n_bytes_less_safe( |
1282 | | encrypting_key_creator, |
1283 | | decrypting_key_creator, |
1284 | | j, |
1285 | | 1, |
1286 | | ); |
1287 | | } |
1288 | | } |
1289 | | |
1290 | | #[test] |
1291 | | fn test_step_ecb_pkcs7_less_safe() { |
1292 | | let random = SystemRandom::new(); |
1293 | | let mut key = [0u8; AES_256_KEY_LEN]; |
1294 | | random.fill(&mut key).unwrap(); |
1295 | | |
1296 | | let encrypting_key_creator = || { |
1297 | | let key = UnboundCipherKey::new(&AES_256, &key.clone()).unwrap(); |
1298 | | StreamingEncryptingKey::ecb_pkcs7(key).unwrap() |
1299 | | }; |
1300 | | let decrypting_key_creator = |decryption_ctx: DecryptionContext| { |
1301 | | let key = UnboundCipherKey::new(&AES_256, &key.clone()).unwrap(); |
1302 | | StreamingDecryptingKey::ecb_pkcs7(key, decryption_ctx).unwrap() |
1303 | | }; |
1304 | | |
1305 | | for i in 13..=21 { |
1306 | | for j in 124..=131 { |
1307 | | helper_test_ecb_pkcs7_stream_encrypt_step_n_bytes_less_safe( |
1308 | | encrypting_key_creator, |
1309 | | decrypting_key_creator, |
1310 | | j, |
1311 | | i, |
1312 | | ); |
1313 | | } |
1314 | | for j in 124..=131 { |
1315 | | helper_test_ecb_pkcs7_stream_encrypt_step_n_bytes_less_safe( |
1316 | | encrypting_key_creator, |
1317 | | decrypting_key_creator, |
1318 | | j, |
1319 | | j - i, |
1320 | | ); |
1321 | | } |
1322 | | } |
1323 | | for j in 124..=131 { |
1324 | | helper_test_ecb_pkcs7_stream_encrypt_step_n_bytes_less_safe( |
1325 | | encrypting_key_creator, |
1326 | | decrypting_key_creator, |
1327 | | j, |
1328 | | j, |
1329 | | ); |
1330 | | helper_test_ecb_pkcs7_stream_encrypt_step_n_bytes_less_safe( |
1331 | | encrypting_key_creator, |
1332 | | decrypting_key_creator, |
1333 | | j, |
1334 | | 256, |
1335 | | ); |
1336 | | helper_test_ecb_pkcs7_stream_encrypt_step_n_bytes_less_safe( |
1337 | | encrypting_key_creator, |
1338 | | decrypting_key_creator, |
1339 | | j, |
1340 | | 1, |
1341 | | ); |
1342 | | } |
1343 | | } |
1344 | | |
1345 | | macro_rules! streaming_cipher_kat { |
1346 | | ($name:ident, $alg:expr, $mode:expr, $key:literal, $iv: literal, $plaintext:literal, $ciphertext:literal, $from_step:literal, $to_step:literal) => { |
1347 | | #[test] |
1348 | | fn $name() { |
1349 | | let key = from_hex($key).unwrap(); |
1350 | | let input = from_hex($plaintext).unwrap(); |
1351 | | let expected_ciphertext = from_hex($ciphertext).unwrap(); |
1352 | | let iv = from_hex($iv).unwrap(); |
1353 | | |
1354 | | for step in ($from_step..=$to_step) { |
1355 | | let ec = EncryptionContext::Iv128( |
1356 | | FixedLength::<IV_LEN_128_BIT>::try_from(iv.as_slice()).unwrap(), |
1357 | | ); |
1358 | | |
1359 | | let unbound_key = UnboundCipherKey::new($alg, &key).unwrap(); |
1360 | | |
1361 | | let encrypting_key = |
1362 | | StreamingEncryptingKey::new(unbound_key, $mode, ec).unwrap(); |
1363 | | |
1364 | | let (ciphertext, decrypt_ctx) = step_encrypt(encrypting_key, &input, step); |
1365 | | |
1366 | | assert_eq!(expected_ciphertext.as_slice(), ciphertext.as_ref()); |
1367 | | |
1368 | | let unbound_key2 = UnboundCipherKey::new($alg, &key).unwrap(); |
1369 | | let decrypting_key = |
1370 | | StreamingDecryptingKey::new(unbound_key2, $mode, decrypt_ctx).unwrap(); |
1371 | | |
1372 | | let plaintext = step_decrypt(decrypting_key, &ciphertext, step); |
1373 | | assert_eq!(input.as_slice(), plaintext.as_ref()); |
1374 | | } |
1375 | | } |
1376 | | }; |
1377 | | ($name:ident, $alg:expr, $mode:expr, $key:literal, $plaintext:literal, $ciphertext:literal, $from_step:literal, $to_step:literal) => { |
1378 | | #[test] |
1379 | | fn $name() { |
1380 | | let key = from_hex($key).unwrap(); |
1381 | | let input = from_hex($plaintext).unwrap(); |
1382 | | let expected_ciphertext = from_hex($ciphertext).unwrap(); |
1383 | | |
1384 | | for step in ($from_step..=$to_step) { |
1385 | | let unbound_key = UnboundCipherKey::new($alg, &key).unwrap(); |
1386 | | |
1387 | | let encrypting_key = |
1388 | | StreamingEncryptingKey::new(unbound_key, $mode, EncryptionContext::None) |
1389 | | .unwrap(); |
1390 | | |
1391 | | let (ciphertext, decrypt_ctx) = step_encrypt(encrypting_key, &input, step); |
1392 | | |
1393 | | assert_eq!(expected_ciphertext.as_slice(), ciphertext.as_ref()); |
1394 | | |
1395 | | let unbound_key2 = UnboundCipherKey::new($alg, &key).unwrap(); |
1396 | | let decrypting_key = |
1397 | | StreamingDecryptingKey::new(unbound_key2, $mode, decrypt_ctx).unwrap(); |
1398 | | |
1399 | | let plaintext = step_decrypt(decrypting_key, &ciphertext, step); |
1400 | | assert_eq!(input.as_slice(), plaintext.as_ref()); |
1401 | | } |
1402 | | } |
1403 | | }; |
1404 | | } |
1405 | | |
1406 | | streaming_cipher_kat!( |
1407 | | test_iv_aes_128_ctr_16_bytes, |
1408 | | &AES_128, |
1409 | | OperatingMode::CTR, |
1410 | | "000102030405060708090a0b0c0d0e0f", |
1411 | | "00000000000000000000000000000000", |
1412 | | "00112233445566778899aabbccddeeff", |
1413 | | "c6b01904c3da3df5e7d62bd96d153686", |
1414 | | 2, |
1415 | | 9 |
1416 | | ); |
1417 | | streaming_cipher_kat!( |
1418 | | test_iv_aes_256_ctr_15_bytes, |
1419 | | &AES_256, |
1420 | | OperatingMode::CTR, |
1421 | | "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", |
1422 | | "00000000000000000000000000000000", |
1423 | | "00112233445566778899aabbccddee", |
1424 | | "f28122856e1cf9a7216a30d111f399", |
1425 | | 2, |
1426 | | 9 |
1427 | | ); |
1428 | | |
1429 | | streaming_cipher_kat!( |
1430 | | test_openssl_aes_128_ctr_15_bytes, |
1431 | | &AES_128, |
1432 | | OperatingMode::CTR, |
1433 | | "244828580821c1652582c76e34d299f5", |
1434 | | "093145d5af233f46072a5eb5adc11aa1", |
1435 | | "3ee38cec171e6cf466bf0df98aa0e1", |
1436 | | "bd7d928f60e3422d96b3f8cd614eb2", |
1437 | | 2, |
1438 | | 9 |
1439 | | ); |
1440 | | |
1441 | | streaming_cipher_kat!( |
1442 | | test_openssl_aes_256_ctr_15_bytes, |
1443 | | &AES_256, |
1444 | | OperatingMode::CTR, |
1445 | | "0857db8240ea459bdf660b4cced66d1f2d3734ff2de7b81e92740e65e7cc6a1d", |
1446 | | "f028ecb053f801102d11fccc9d303a27", |
1447 | | "eca7285d19f3c20e295378460e8729", |
1448 | | "b5098e5e788de6ac2f2098eb2fc6f8", |
1449 | | 2, |
1450 | | 9 |
1451 | | ); |
1452 | | |
1453 | | streaming_cipher_kat!( |
1454 | | test_iv_aes_128_cbc_16_bytes, |
1455 | | &AES_128, |
1456 | | OperatingMode::CBC, |
1457 | | "000102030405060708090a0b0c0d0e0f", |
1458 | | "00000000000000000000000000000000", |
1459 | | "00112233445566778899aabbccddeeff", |
1460 | | "69c4e0d86a7b0430d8cdb78070b4c55a9e978e6d16b086570ef794ef97984232", |
1461 | | 2, |
1462 | | 9 |
1463 | | ); |
1464 | | |
1465 | | streaming_cipher_kat!( |
1466 | | test_iv_aes_256_cbc_15_bytes, |
1467 | | &AES_256, |
1468 | | OperatingMode::CBC, |
1469 | | "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", |
1470 | | "00000000000000000000000000000000", |
1471 | | "00112233445566778899aabbccddee", |
1472 | | "2ddfb635a651a43f582997966840ca0c", |
1473 | | 2, |
1474 | | 9 |
1475 | | ); |
1476 | | |
1477 | | streaming_cipher_kat!( |
1478 | | test_openssl_aes_128_cbc_15_bytes, |
1479 | | &AES_128, |
1480 | | OperatingMode::CBC, |
1481 | | "053304bb3899e1d99db9d29343ea782d", |
1482 | | "b5313560244a4822c46c2a0c9d0cf7fd", |
1483 | | "a3e4c990356c01f320043c3d8d6f43", |
1484 | | "ad96993f248bd6a29760ec7ccda95ee1", |
1485 | | 2, |
1486 | | 9 |
1487 | | ); |
1488 | | |
1489 | | streaming_cipher_kat!( |
1490 | | test_openssl_aes_128_cbc_16_bytes, |
1491 | | &AES_128, |
1492 | | OperatingMode::CBC, |
1493 | | "95af71f1c63e4a1d0b0b1a27fb978283", |
1494 | | "89e40797dca70197ff87d3dbb0ef2802", |
1495 | | "aece7b5e3c3df1ffc9802d2dfe296dc7", |
1496 | | "301b5dab49fb11e919d0d39970d06739301919743304f23f3cbc67d28564b25b", |
1497 | | 2, |
1498 | | 9 |
1499 | | ); |
1500 | | |
1501 | | streaming_cipher_kat!( |
1502 | | test_openssl_aes_256_cbc_15_bytes, |
1503 | | &AES_256, |
1504 | | OperatingMode::CBC, |
1505 | | "d369e03e9752784917cc7bac1db7399598d9555e691861d9dd7b3292a693ef57", |
1506 | | "1399bb66b2f6ad99a7f064140eaaa885", |
1507 | | "7385f5784b85bf0a97768ddd896d6d", |
1508 | | "4351082bac9b4593ae8848cc9dfb5a01", |
1509 | | 2, |
1510 | | 9 |
1511 | | ); |
1512 | | |
1513 | | streaming_cipher_kat!( |
1514 | | test_openssl_aes_256_cbc_16_bytes, |
1515 | | &AES_256, |
1516 | | OperatingMode::CBC, |
1517 | | "d4a8206dcae01242f9db79a4ecfe277d0f7bb8ccbafd8f9809adb39f35aa9b41", |
1518 | | "24f6076548fb9d93c8f7ed9f6e661ef9", |
1519 | | "a39c1fdf77ea3e1f18178c0ec237c70a", |
1520 | | "f1af484830a149ee0387b854d65fe87ca0e62efc1c8e6909d4b9ab8666470453", |
1521 | | 2, |
1522 | | 9 |
1523 | | ); |
1524 | | |
1525 | | streaming_cipher_kat!( |
1526 | | test_openssl_aes_128_cfb128_16_bytes, |
1527 | | &AES_128, |
1528 | | OperatingMode::CFB128, |
1529 | | "5c353f739429bbd48b7e3f9a76facf4d", |
1530 | | "7b2c7ce17a9b6a59a9e64253b98c8cd1", |
1531 | | "add1bcebeaabe9423d4e916400e877c5", |
1532 | | "8440ec442e4135a613ddb2ce26107e10", |
1533 | | 2, |
1534 | | 9 |
1535 | | ); |
1536 | | |
1537 | | streaming_cipher_kat!( |
1538 | | test_openssl_aes_128_cfb128_15_bytes, |
1539 | | &AES_128, |
1540 | | OperatingMode::CFB128, |
1541 | | "e1f39d70ad378efc1ac318aa8ac4489f", |
1542 | | "ec78c3d54fff2fe09678c7883024ddce", |
1543 | | "b8c905004b2a92a323769f1b8dc1b2", |
1544 | | "964c3e9bf8bf2a3cca02d8e2e75608", |
1545 | | 2, |
1546 | | 9 |
1547 | | ); |
1548 | | |
1549 | | streaming_cipher_kat!( |
1550 | | test_openssl_aes_256_cfb128_16_bytes, |
1551 | | &AES_256, |
1552 | | OperatingMode::CFB128, |
1553 | | "0e8117d0984d6acb957a5d6ca526a12fa612ce5de2daadebd42c14d28a0a192e", |
1554 | | "09147a153b230a40cd7bf4197ad0e825", |
1555 | | "13f4540a4e06394148ade31a6f678787", |
1556 | | "250e590e47b7613b7d0a53f684e970d6", |
1557 | | 2, |
1558 | | 9 |
1559 | | ); |
1560 | | |
1561 | | streaming_cipher_kat!( |
1562 | | test_openssl_aes_256_cfb128_15_bytes, |
1563 | | &AES_256, |
1564 | | OperatingMode::CFB128, |
1565 | | "5cb17d8d5b9dbd81e4f1e0a2c82ebf36cf61156388fb7abf99d4526622858225", |
1566 | | "13c77415ec24f3e2f784f228478a85be", |
1567 | | "3efa583df4405aab61e18155aa7e0d", |
1568 | | "c1f2ffe8aa5064199e8f4f1b388303", |
1569 | | 2, |
1570 | | 9 |
1571 | | ); |
1572 | | |
1573 | | streaming_cipher_kat!( |
1574 | | test_openssl_aes_128_ecb_pkcs7_16_bytes, |
1575 | | &AES_128, |
1576 | | OperatingMode::ECB, |
1577 | | "a1b7cd124f9824a1532d8440f8136788", |
1578 | | "388118e6848b0cea97401707a754d7a1", |
1579 | | "19b7c7f5d9c2bda3f957e9e7d20847828d5eb5624bcbf221014063a87b38d133", |
1580 | | 2, |
1581 | | 9 |
1582 | | ); |
1583 | | |
1584 | | streaming_cipher_kat!( |
1585 | | test_openssl_aes_128_ecb_pkcs7_15_bytes, |
1586 | | &AES_128, |
1587 | | OperatingMode::ECB, |
1588 | | "d10e12accb837aaffbb284448e53138c", |
1589 | | "b21cfd1c9e6e7e6e912c82c7dd1aa8", |
1590 | | "3d1168e61df34b51c6ab6745c20ee881", |
1591 | | 2, |
1592 | | 9 |
1593 | | ); |
1594 | | |
1595 | | streaming_cipher_kat!( |
1596 | | test_openssl_aes_256_ecb_pkcs7_16_bytes, |
1597 | | &AES_256, |
1598 | | OperatingMode::ECB, |
1599 | | "0600f4ad4eda4bc8e3e99592abdfce7eb08fee0ccc801c5ccee26134bcaafbbd", |
1600 | | "516b45cb1342239a549bd8c1d5998f98", |
1601 | | "854c593555a213e4a862c6f66aa4a79631faca131eba6f163e5cd3940e9c0a57", |
1602 | | 2, |
1603 | | 9 |
1604 | | ); |
1605 | | |
1606 | | streaming_cipher_kat!( |
1607 | | test_openssl_aes_256_ecb_pkcs7_15_bytes, |
1608 | | &AES_256, |
1609 | | OperatingMode::ECB, |
1610 | | "80f235756c8f70094ae1f99a95a599c27c4452a4b8412fd934e2b253f7098508", |
1611 | | "2235590b90190d7a1dc2464a0205ad", |
1612 | | "8547d8ac8dc6d9cebb2dc77a7034bb67", |
1613 | | 2, |
1614 | | 9 |
1615 | | ); |
1616 | | } |