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