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        let mut cipher_ctx = LcPtr::new(unsafe { EVP_CIPHER_CTX_new() })?;
129        let cipher = mode.evp_cipher(key.algorithm);
130        let key_bytes = key.key_bytes.as_ref();
131        if key_bytes.len()
132            != <usize>::try_from(unsafe { EVP_CIPHER_key_length(cipher.as_const_ptr()) }).unwrap()
133        {
134            return Err(Unspecified);
135        }
136
137        match &context {
138            ctx @ EncryptionContext::Iv128(..) => {
139                let iv = <&[u8]>::try_from(ctx)?;
140                debug_assert_eq!(
141                    iv.len(),
142                    <usize>::try_from(unsafe { EVP_CIPHER_iv_length(cipher.as_const_ptr()) })
143                        .unwrap()
144                );
145                evp_encrypt_init(&mut cipher_ctx, &cipher, key_bytes, Some(iv))?;
146            }
147            EncryptionContext::None => {
148                evp_encrypt_init(&mut cipher_ctx, &cipher, key_bytes, None)?;
149            }
150        }
151
152        Ok(Self {
153            algorithm,
154            mode,
155            cipher_ctx,
156            context,
157            output_generated: 0,
158        })
159    }
160
161    fn update_internal<'a>(
162        &mut self,
163        input: &[u8],
164        output: &'a mut [u8],
165        min_outsize: usize,
166    ) -> Result<BufferUpdate<'a>, Unspecified> {
167        if output.len() < min_outsize {
168            return Err(Unspecified);
169        }
170        let mut outlen: i32 = 0;
171        let inlen: i32 = input.len().try_into()?;
172
173        if 1 != unsafe {
174            EVP_EncryptUpdate(
175                self.cipher_ctx.as_mut_ptr(),
176                output.as_mut_ptr(),
177                &mut outlen,
178                input.as_ptr(),
179                inlen,
180            )
181        } {
182            return Err(Unspecified);
183        }
184        let outlen: usize = outlen.try_into()?;
185        debug_assert!(outlen <= min_outsize);
186        self.output_generated += outlen;
187        assert!(outlen <= output.len());
188
189        Ok(BufferUpdate::new(output, outlen))
190    }
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    pub fn update<'a>(
203        &mut self,
204        input: &[u8],
205        output: &'a mut [u8],
206    ) -> Result<BufferUpdate<'a>, Unspecified> {
207        let min_outsize = input
208            .len()
209            .checked_add(self.algorithm().block_len())
210            .ok_or(Unspecified)?
211            .checked_sub(1)
212            .ok_or(Unspecified)?;
213        self.update_internal(input, output, min_outsize)
214    }
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    pub fn less_safe_update<'a>(
238        &mut self,
239        input: &[u8],
240        output: &'a mut [u8],
241    ) -> Result<BufferUpdate<'a>, Unspecified> {
242        let next_total = self
243            .output_generated
244            .checked_add(input.len())
245            .ok_or(Unspecified)?;
246        let extra_buffer_size = (self.algorithm().block_len
247            - next_total.rem_euclid(self.algorithm().block_len))
248        .rem_euclid(self.algorithm().block_len);
249        let min_outsize = input
250            .len()
251            .checked_add(extra_buffer_size)
252            .ok_or(Unspecified)?;
253        self.update_internal(input, output, min_outsize)
254    }
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    pub fn finish(
266        mut self,
267        output: &mut [u8],
268    ) -> Result<(DecryptionContext, BufferUpdate<'_>), Unspecified> {
269        if output.len() < self.algorithm().block_len() {
270            return Err(Unspecified);
271        }
272        let mut outlen: i32 = 0;
273
274        if 1 != indicator_check!(unsafe {
275            EVP_EncryptFinal_ex(
276                self.cipher_ctx.as_mut_ptr(),
277                output.as_mut_ptr(),
278                &mut outlen,
279            )
280        }) {
281            return Err(Unspecified);
282        }
283        let outlen: usize = outlen.try_into()?;
284        debug_assert!(outlen <= self.algorithm().block_len());
285        Ok((self.context.into(), BufferUpdate::new(output, outlen)))
286    }
287
288    /// Returns the cipher operating mode.
289    #[must_use]
290    pub fn mode(&self) -> OperatingMode {
291        self.mode
292    }
293
294    /// Returns the cipher algorithm.
295    #[must_use]
296    pub fn algorithm(&self) -> &'static Algorithm {
297        self.algorithm
298    }
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    pub fn ctr(key: UnboundCipherKey) -> Result<Self, Unspecified> {
306        let context = key.algorithm().new_encryption_context(OperatingMode::CTR)?;
307        Self::less_safe_ctr(key, context)
308    }
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    pub fn less_safe_ctr(
319        key: UnboundCipherKey,
320        context: EncryptionContext,
321    ) -> Result<Self, Unspecified> {
322        Self::new(key, OperatingMode::CTR, context)
323    }
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    pub fn cbc_pkcs7(key: UnboundCipherKey) -> Result<Self, Unspecified> {
333        let context = key.algorithm().new_encryption_context(OperatingMode::CBC)?;
334        Self::less_safe_cbc_pkcs7(key, context)
335    }
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    pub fn cfb128(key: UnboundCipherKey) -> Result<Self, Unspecified> {
343        let context = key
344            .algorithm()
345            .new_encryption_context(OperatingMode::CFB128)?;
346        Self::less_safe_cfb128(key, context)
347    }
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    pub fn ecb_pkcs7(key: UnboundCipherKey) -> Result<Self, Unspecified> {
359        let context = key.algorithm().new_encryption_context(OperatingMode::ECB)?;
360        Self::new(key, OperatingMode::ECB, context)
361    }
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    pub fn less_safe_cfb128(
372        key: UnboundCipherKey,
373        context: EncryptionContext,
374    ) -> Result<Self, Unspecified> {
375        Self::new(key, OperatingMode::CFB128, context)
376    }
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    pub fn less_safe_cbc_pkcs7(
389        key: UnboundCipherKey,
390        context: EncryptionContext,
391    ) -> Result<Self, Unspecified> {
392        Self::new(key, OperatingMode::CBC, context)
393    }
394}
395
396/// A key for streaming decryption operations.
397pub struct StreamingDecryptingKey {
398    algorithm: &'static Algorithm,
399    mode: OperatingMode,
400    cipher_ctx: LcPtr<EVP_CIPHER_CTX>,
401    output_generated: usize,
402}
403
404unsafe impl Send for StreamingDecryptingKey {}
405
406impl StreamingDecryptingKey {
407    #[allow(clippy::needless_pass_by_value)]
408    fn new(
409        key: UnboundCipherKey,
410        mode: OperatingMode,
411        context: DecryptionContext,
412    ) -> Result<Self, Unspecified> {
413        let mut cipher_ctx = LcPtr::new(unsafe { EVP_CIPHER_CTX_new() })?;
414        let algorithm = key.algorithm();
415        let cipher = mode.evp_cipher(key.algorithm);
416        let key_bytes = key.key_bytes.as_ref();
417        if key_bytes.len()
418            != <usize>::try_from(unsafe { EVP_CIPHER_key_length(cipher.as_const_ptr()) }).unwrap()
419        {
420            return Err(Unspecified);
421        }
422
423        match &context {
424            ctx @ DecryptionContext::Iv128(..) => {
425                let iv = <&[u8]>::try_from(ctx)?;
426                debug_assert_eq!(
427                    iv.len(),
428                    <usize>::try_from(unsafe { EVP_CIPHER_iv_length(cipher.as_const_ptr()) })
429                        .unwrap()
430                );
431                evp_decrypt_init(&mut cipher_ctx, &cipher, key_bytes, Some(iv))?;
432            }
433            DecryptionContext::None => {
434                evp_decrypt_init(&mut cipher_ctx, &cipher, key_bytes, None)?;
435            }
436        }
437
438        Ok(Self {
439            algorithm,
440            mode,
441            cipher_ctx,
442            output_generated: 0,
443        })
444    }
445
446    fn update_internal<'a>(
447        &mut self,
448        input: &[u8],
449        output: &'a mut [u8],
450        min_outsize: usize,
451    ) -> Result<BufferUpdate<'a>, Unspecified> {
452        if output.len() < min_outsize {
453            return Err(Unspecified);
454        }
455        let mut outlen: i32 = 0;
456        let inlen: i32 = input.len().try_into()?;
457
458        if 1 != unsafe {
459            EVP_DecryptUpdate(
460                self.cipher_ctx.as_mut_ptr(),
461                output.as_mut_ptr(),
462                &mut outlen,
463                input.as_ptr(),
464                inlen,
465            )
466        } {
467            return Err(Unspecified);
468        }
469        let outlen: usize = outlen.try_into()?;
470        debug_assert!(outlen <= min_outsize);
471        self.output_generated += outlen;
472        assert!(outlen <= output.len());
473
474        Ok(BufferUpdate::new(output, outlen))
475    }
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    pub fn update<'a>(
488        &mut self,
489        input: &[u8],
490        output: &'a mut [u8],
491    ) -> Result<BufferUpdate<'a>, Unspecified> {
492        let min_outsize = input
493            .len()
494            .checked_add(self.algorithm().block_len())
495            .ok_or(Unspecified)?
496            .checked_sub(1)
497            .ok_or(Unspecified)?;
498        self.update_internal(input, output, min_outsize)
499    }
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    pub fn less_safe_update<'a>(
523        &mut self,
524        input: &[u8],
525        output: &'a mut [u8],
526    ) -> Result<BufferUpdate<'a>, Unspecified> {
527        let next_total = self
528            .output_generated
529            .checked_add(input.len())
530            .ok_or(Unspecified)?;
531        let extra_buffer_size = (self.algorithm().block_len
532            - next_total.rem_euclid(self.algorithm().block_len))
533        .rem_euclid(self.algorithm().block_len);
534        let min_outsize = input
535            .len()
536            .checked_add(extra_buffer_size)
537            .ok_or(Unspecified)?;
538        self.update_internal(input, output, min_outsize)
539    }
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    pub fn finish(mut self, output: &mut [u8]) -> Result<BufferUpdate<'_>, Unspecified> {
550        if output.len() < self.algorithm().block_len() {
551            return Err(Unspecified);
552        }
553        let mut outlen: i32 = 0;
554
555        if 1 != indicator_check!(unsafe {
556            EVP_DecryptFinal_ex(
557                self.cipher_ctx.as_mut_ptr(),
558                output.as_mut_ptr(),
559                &mut outlen,
560            )
561        }) {
562            return Err(Unspecified);
563        }
564        let outlen: usize = outlen.try_into()?;
565        debug_assert!(outlen <= self.algorithm().block_len());
566        Ok(BufferUpdate::new(output, outlen))
567    }
568
569    /// Returns the cipher operating mode.
570    #[must_use]
571    pub fn mode(&self) -> OperatingMode {
572        self.mode
573    }
574
575    /// Returns the cipher algorithm
576    #[must_use]
577    pub fn algorithm(&self) -> &'static Algorithm {
578        self.algorithm
579    }
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    pub fn ctr(key: UnboundCipherKey, context: DecryptionContext) -> Result<Self, Unspecified> {
587        Self::new(key, OperatingMode::CTR, context)
588    }
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    pub fn cbc_pkcs7(
596        key: UnboundCipherKey,
597        context: DecryptionContext,
598    ) -> Result<Self, Unspecified> {
599        Self::new(key, OperatingMode::CBC, context)
600    }
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    pub fn cfb128(key: UnboundCipherKey, context: DecryptionContext) -> Result<Self, Unspecified> {
608        Self::new(key, OperatingMode::CFB128, context)
609    }
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    pub fn ecb_pkcs7(
621        key: UnboundCipherKey,
622        context: DecryptionContext,
623    ) -> Result<Self, Unspecified> {
624        Self::new(key, OperatingMode::ECB, context)
625    }
626}
627
628#[cfg(test)]
629mod 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}