Skip to main content

aws_lc_rs/cipher/
streaming.rs

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