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}
26
27/// A struct indicating the portion of a buffer written to, and/or not written to, during an
28/// encryption/decryption operation.
29pub struct BufferUpdate<'a> {
30    written: &'a [u8],
31    remainder: &'a mut [u8],
32}
33
34impl<'a> BufferUpdate<'a> {
35    fn new(out_buffer: &'a mut [u8], written_len: usize) -> Self {
36        let (written, remainder) = out_buffer.split_at_mut(written_len);
37        Self { written, remainder }
38    }
39}
40
41impl BufferUpdate<'_> {
42    /// Returns the slice from the buffer that was modified by the operation.
43    #[must_use]
44    pub fn written(&self) -> &[u8] {
45        self.written
46    }
47
48    /// Returns the slice of the buffer that was not modified by the operation.
49    #[must_use]
50    pub fn remainder(&self) -> &[u8] {
51        self.remainder
52    }
53
54    /// Returns a mutable slice of the buffer that was not modified by the operation.
55    #[must_use]
56    pub fn remainder_mut(&mut self) -> &mut [u8] {
57        self.remainder
58    }
59}
60
61fn evp_encrypt_init(
62    cipher_ctx: &mut LcPtr<EVP_CIPHER_CTX>,
63    cipher: &ConstPointer<EVP_CIPHER>,
64    key: &[u8],
65    iv: Option<&[u8]>,
66) -> Result<(), Unspecified> {
67    let iv_ptr: *const u8 = if let Some(iv) = iv {
68        iv.as_ptr()
69    } else {
70        null()
71    };
72
73    // AWS-LC copies the key and iv values into the EVP_CIPHER_CTX, and thus can be dropped after this.
74    if 1 != unsafe {
75        EVP_EncryptInit_ex(
76            *cipher_ctx.as_mut(),
77            **cipher,
78            null_mut(),
79            key.as_ptr(),
80            iv_ptr,
81        )
82    } {
83        return Err(Unspecified);
84    }
85
86    Ok(())
87}
88
89fn evp_decrypt_init(
90    cipher_ctx: &mut LcPtr<EVP_CIPHER_CTX>,
91    cipher: &ConstPointer<EVP_CIPHER>,
92    key: &[u8],
93    iv: Option<&[u8]>,
94) -> Result<(), Unspecified> {
95    let iv_ptr: *const u8 = if let Some(iv) = iv {
96        iv.as_ptr()
97    } else {
98        null()
99    };
100
101    // AWS-LC copies the key and iv values into the EVP_CIPHER_CTX, and thus can be dropped after this.
102    if 1 != unsafe {
103        EVP_DecryptInit_ex(
104            *cipher_ctx.as_mut(),
105            **cipher,
106            null_mut(),
107            key.as_ptr(),
108            iv_ptr,
109        )
110    } {
111        return Err(Unspecified);
112    }
113
114    Ok(())
115}
116
117impl StreamingEncryptingKey {
118    #[allow(clippy::needless_pass_by_value)]
119    fn new(
120        key: UnboundCipherKey,
121        mode: OperatingMode,
122        context: EncryptionContext,
123    ) -> Result<Self, Unspecified> {
124        let algorithm = key.algorithm();
125        let mut cipher_ctx = LcPtr::new(unsafe { EVP_CIPHER_CTX_new() })?;
126        let cipher = mode.evp_cipher(key.algorithm);
127        let key_bytes = key.key_bytes.as_ref();
128        debug_assert_eq!(
129            key_bytes.len(),
130            <usize>::try_from(unsafe { EVP_CIPHER_key_length(*cipher) }).unwrap()
131        );
132
133        match &context {
134            ctx @ EncryptionContext::Iv128(..) => {
135                let iv = <&[u8]>::try_from(ctx)?;
136                debug_assert_eq!(
137                    iv.len(),
138                    <usize>::try_from(unsafe { EVP_CIPHER_iv_length(*cipher) }).unwrap()
139                );
140                evp_encrypt_init(&mut cipher_ctx, &cipher, key_bytes, Some(iv))?;
141            }
142            EncryptionContext::None => {
143                evp_encrypt_init(&mut cipher_ctx, &cipher, key_bytes, None)?;
144            }
145        }
146
147        Ok(Self {
148            algorithm,
149            mode,
150            cipher_ctx,
151            context,
152        })
153    }
154
155    /// Updates the internal state of the key with the provided ciphertext `input`,
156    /// potentially writing bytes of ciphertext to `output`.
157    ///
158    /// The number of bytes written to `output` can be up to `input.len()`
159    /// plus the block length of the algorithm (e.g., [`Algorithm::block_len`]).
160    ///
161    /// # Errors
162    /// * Returns an error if the `output` buffer is smaller than the length of
163    ///   the `input` plus the algorithm's block length (e.g. [`Algorithm::block_len`]) minus one.
164    /// * May return an error if the length of `input` plus the algorithm's block length is larger than `i32::MAX`.
165    pub fn update<'a>(
166        &mut self,
167        input: &[u8],
168        output: &'a mut [u8],
169    ) -> Result<BufferUpdate<'a>, Unspecified> {
170        let min_outsize = input
171            .len()
172            .checked_add(self.algorithm().block_len())
173            .ok_or(Unspecified)?
174            - 1;
175        if output.len() < min_outsize {
176            return Err(Unspecified);
177        }
178        let mut outlen: i32 = 0;
179        let inlen: i32 = input.len().try_into()?;
180
181        if 1 != unsafe {
182            EVP_EncryptUpdate(
183                *self.cipher_ctx.as_mut(),
184                output.as_mut_ptr(),
185                &mut outlen,
186                input.as_ptr(),
187                inlen,
188            )
189        } {
190            return Err(Unspecified);
191        }
192        let outlen: usize = outlen.try_into()?;
193        debug_assert!(outlen <= min_outsize);
194        Ok(BufferUpdate::new(output, outlen))
195    }
196
197    /// Finishes the encryption operation, writing any remaining ciphertext to
198    /// `output`.
199    ///
200    /// The number of bytes written to `output` can be up to the block length of
201    /// [`Algorithm::block_len`].
202    ///
203    /// # Errors
204    /// * Returns an error if the `output` buffer is smaller than the algorithm's
205    ///   block length.
206    pub fn finish(
207        mut self,
208        output: &mut [u8],
209    ) -> Result<(DecryptionContext, BufferUpdate), Unspecified> {
210        if output.len() < self.algorithm().block_len() {
211            return Err(Unspecified);
212        }
213        let mut outlen: i32 = 0;
214
215        if 1 != indicator_check!(unsafe {
216            EVP_EncryptFinal_ex(*self.cipher_ctx.as_mut(), output.as_mut_ptr(), &mut outlen)
217        }) {
218            return Err(Unspecified);
219        }
220        let outlen: usize = outlen.try_into()?;
221        debug_assert!(outlen <= self.algorithm().block_len());
222        Ok((self.context.into(), BufferUpdate::new(output, outlen)))
223    }
224
225    /// Returns the cipher operating mode.
226    #[must_use]
227    pub fn mode(&self) -> OperatingMode {
228        self.mode
229    }
230
231    /// Returns the cipher algorithm.
232    #[must_use]
233    pub fn algorithm(&self) -> &'static Algorithm {
234        self.algorithm
235    }
236
237    /// Constructs a `StreamingEncryptingKey` for encrypting data using the CTR cipher mode.
238    /// The resulting ciphertext will be the same length as the plaintext.
239    ///
240    /// # Errors
241    /// Returns and error on an internal failure.
242    pub fn ctr(key: UnboundCipherKey) -> Result<Self, Unspecified> {
243        let context = key.algorithm().new_encryption_context(OperatingMode::CTR)?;
244        Self::less_safe_ctr(key, context)
245    }
246
247    /// Constructs a `StreamingEncryptingKey` for encrypting data using the CTR cipher mode.
248    /// The resulting ciphertext will be the same length as the plaintext.
249    ///
250    /// This is considered less safe because the caller could potentially construct
251    /// an `EncryptionContext` from a previously used initialization vector (IV).
252    ///
253    /// # Errors
254    /// Returns an error on an internal failure.
255    pub fn less_safe_ctr(
256        key: UnboundCipherKey,
257        context: EncryptionContext,
258    ) -> Result<Self, Unspecified> {
259        Self::new(key, OperatingMode::CTR, context)
260    }
261
262    /// Constructs a `StreamingEncryptingKey` for encrypting data using the CBC cipher mode
263    /// with pkcs7 padding.
264    /// The resulting ciphertext will be longer than the plaintext; padding is added
265    /// to fill the next block of ciphertext.
266    ///
267    /// # Errors
268    /// Returns an error on an internal failure.
269    pub fn cbc_pkcs7(key: UnboundCipherKey) -> Result<Self, Unspecified> {
270        let context = key.algorithm().new_encryption_context(OperatingMode::CBC)?;
271        Self::less_safe_cbc_pkcs7(key, context)
272    }
273
274    /// Constructs a `StreamingEncryptingKey` for encrypting data using the CFB128 cipher mode.
275    /// The resulting ciphertext will be the same length as the plaintext.
276    ///
277    /// # Errors
278    /// Returns and error on an internal failure.
279    pub fn cfb128(key: UnboundCipherKey) -> Result<Self, Unspecified> {
280        let context = key
281            .algorithm()
282            .new_encryption_context(OperatingMode::CFB128)?;
283        Self::less_safe_cfb128(key, context)
284    }
285
286    /// Constructs a `StreamingEncryptingKey` for encrypting using ECB cipher mode with PKCS7 padding.
287    /// The resulting plaintext will be the same length as the ciphertext.
288    ///
289    /// # ☠️ ️️️DANGER ☠️
290    /// Offered for computability purposes only. This is an extremely dangerous mode, and
291    /// very likely not what you want to use.
292    ///
293    /// # Errors
294    /// Returns an error on an internal failure.
295    pub fn ecb_pkcs7(key: UnboundCipherKey) -> Result<Self, Unspecified> {
296        let context = key.algorithm().new_encryption_context(OperatingMode::ECB)?;
297        Self::new(key, OperatingMode::ECB, context)
298    }
299
300    /// Constructs a `StreamingEncryptingKey` for encrypting data using the CFB128 cipher mode.
301    /// The resulting ciphertext will be the same length as the plaintext.
302    ///
303    /// This is considered less safe because the caller could potentially construct
304    /// an `EncryptionContext` from a previously used initialization vector (IV).
305    ///
306    /// # Errors
307    /// Returns an error on an internal failure.
308    pub fn less_safe_cfb128(
309        key: UnboundCipherKey,
310        context: EncryptionContext,
311    ) -> Result<Self, Unspecified> {
312        Self::new(key, OperatingMode::CFB128, context)
313    }
314
315    /// Constructs a `StreamingEncryptingKey` for encrypting data using the CBC cipher mode
316    /// with pkcs7 padding.
317    /// The resulting ciphertext will be longer than the plaintext; padding is added
318    /// to fill the next block of ciphertext.
319    ///
320    /// This is considered less safe because the caller could potentially construct
321    /// an `EncryptionContext` from a previously used initialization vector (IV).
322    ///
323    /// # Errors
324    /// Returns an error on an internal failure.
325    pub fn less_safe_cbc_pkcs7(
326        key: UnboundCipherKey,
327        context: EncryptionContext,
328    ) -> Result<Self, Unspecified> {
329        Self::new(key, OperatingMode::CBC, context)
330    }
331}
332
333/// A key for streaming decryption operations.
334pub struct StreamingDecryptingKey {
335    algorithm: &'static Algorithm,
336    mode: OperatingMode,
337    cipher_ctx: LcPtr<EVP_CIPHER_CTX>,
338}
339impl StreamingDecryptingKey {
340    #[allow(clippy::needless_pass_by_value)]
341    fn new(
342        key: UnboundCipherKey,
343        mode: OperatingMode,
344        context: DecryptionContext,
345    ) -> Result<Self, Unspecified> {
346        let mut cipher_ctx = LcPtr::new(unsafe { EVP_CIPHER_CTX_new() })?;
347        let algorithm = key.algorithm();
348        let cipher = mode.evp_cipher(key.algorithm);
349        let key_bytes = key.key_bytes.as_ref();
350        debug_assert_eq!(
351            key_bytes.len(),
352            <usize>::try_from(unsafe { EVP_CIPHER_key_length(*cipher) }).unwrap()
353        );
354
355        match &context {
356            ctx @ DecryptionContext::Iv128(..) => {
357                let iv = <&[u8]>::try_from(ctx)?;
358                debug_assert_eq!(
359                    iv.len(),
360                    <usize>::try_from(unsafe { EVP_CIPHER_iv_length(*cipher) }).unwrap()
361                );
362                evp_decrypt_init(&mut cipher_ctx, &cipher, key_bytes, Some(iv))?;
363            }
364            DecryptionContext::None => {
365                evp_decrypt_init(&mut cipher_ctx, &cipher, key_bytes, None)?;
366            }
367        }
368
369        Ok(Self {
370            algorithm,
371            mode,
372            cipher_ctx,
373        })
374    }
375
376    /// Updates the internal state of the key with the provided ciphertext `input`,
377    /// potentially also writing bytes of plaintext to `output`.
378    /// The number of bytes written to `output` can be up to `input.len()`
379    /// plus the block length of the cipher algorithm (e.g., [`Algorithm::block_len`]).
380    ///
381    /// # Errors
382    /// * Returns an error if the `output` buffer is smaller than the length of
383    ///   the `input` plus the algorithm's block length.
384    /// * May return an error if the length of `input` plus the algorithm's block length is larger
385    ///   than `i32::MAX`.
386    pub fn update<'a>(
387        &mut self,
388        input: &[u8],
389        output: &'a mut [u8],
390    ) -> Result<BufferUpdate<'a>, Unspecified> {
391        let mut outlen: i32 = 0;
392        let inlen: i32 = input.len().try_into()?;
393
394        let min_outsize = input
395            .len()
396            .checked_add(self.algorithm().block_len())
397            .ok_or(Unspecified)?;
398        if output.len() < min_outsize {
399            return Err(Unspecified);
400        }
401
402        if 1 != unsafe {
403            EVP_DecryptUpdate(
404                *self.cipher_ctx.as_mut(),
405                output.as_mut_ptr(),
406                &mut outlen,
407                input.as_ptr(),
408                inlen,
409            )
410        } {
411            return Err(Unspecified);
412        }
413        let outlen: usize = outlen.try_into()?;
414        debug_assert!(outlen <= min_outsize);
415        Ok(BufferUpdate::new(output, outlen))
416    }
417
418    /// Finishes the decryption operation, writing the remaining plaintext to
419    /// `output`.
420    /// The number of bytes written to `output` can be up to the block length of
421    /// the cipher algorithm (e.g., [`Algorithm::block_len`]).
422    ///
423    /// # Errors
424    /// * Returns an error if the `output` buffer is smaller than the algorithm's
425    ///   block length.
426    pub fn finish(mut self, output: &mut [u8]) -> Result<BufferUpdate, Unspecified> {
427        if output.len() < self.algorithm().block_len() {
428            return Err(Unspecified);
429        }
430        let mut outlen: i32 = 0;
431
432        if 1 != indicator_check!(unsafe {
433            EVP_DecryptFinal_ex(*self.cipher_ctx.as_mut(), output.as_mut_ptr(), &mut outlen)
434        }) {
435            return Err(Unspecified);
436        }
437        let outlen: usize = outlen.try_into()?;
438        debug_assert!(outlen <= self.algorithm().block_len());
439        Ok(BufferUpdate::new(output, outlen))
440    }
441
442    /// Returns the cipher operating mode.
443    #[must_use]
444    pub fn mode(&self) -> OperatingMode {
445        self.mode
446    }
447
448    /// Returns the cipher algorithm
449    #[must_use]
450    pub fn algorithm(&self) -> &'static Algorithm {
451        self.algorithm
452    }
453
454    /// Constructs a `StreamingDecryptingKey` for decrypting using the CTR cipher mode.
455    /// The resulting plaintext will be the same length as the ciphertext.
456    ///
457    /// # Errors
458    /// Returns an error on an internal failure.
459    pub fn ctr(key: UnboundCipherKey, context: DecryptionContext) -> Result<Self, Unspecified> {
460        Self::new(key, OperatingMode::CTR, context)
461    }
462
463    /// Constructs a `StreamingDecryptingKey` for decrypting using the CBC cipher mode.
464    /// The resulting plaintext will be shorter than the ciphertext.
465    ///
466    /// # Errors
467    /// Returns an error on an internal failure.
468    pub fn cbc_pkcs7(
469        key: UnboundCipherKey,
470        context: DecryptionContext,
471    ) -> Result<Self, Unspecified> {
472        Self::new(key, OperatingMode::CBC, context)
473    }
474
475    // Constructs a `StreamingDecryptingKey` for decrypting using the CFB128 cipher mode.
476    /// The resulting plaintext will be the same length as the ciphertext.
477    ///
478    /// # Errors
479    /// Returns an error on an internal failure.
480    pub fn cfb128(key: UnboundCipherKey, context: DecryptionContext) -> Result<Self, Unspecified> {
481        Self::new(key, OperatingMode::CFB128, context)
482    }
483
484    /// Constructs a `StreamingDecryptingKey` for decrypting using the ECB cipher mode.
485    /// The resulting plaintext will be the same length as the ciphertext.
486    ///
487    /// # ☠️ ️️️DANGER ☠️
488    /// Offered for computability purposes only. This is an extremely dangerous mode, and
489    /// very likely not what you want to use.
490    ///
491    /// # Errors
492    /// Returns an error on an internal failure.
493    pub fn ecb_pkcs7(
494        key: UnboundCipherKey,
495        context: DecryptionContext,
496    ) -> Result<Self, Unspecified> {
497        Self::new(key, OperatingMode::ECB, context)
498    }
499}
500
501#[cfg(test)]
502mod tests {
503    use crate::cipher::{
504        DecryptionContext, EncryptionContext, OperatingMode, StreamingDecryptingKey,
505        StreamingEncryptingKey, UnboundCipherKey, AES_128, AES_256, AES_256_KEY_LEN,
506    };
507    use crate::iv::{FixedLength, IV_LEN_128_BIT};
508    use crate::rand::{SecureRandom, SystemRandom};
509    use crate::test::from_hex;
510    use paste::*;
511
512    fn step_encrypt(
513        mut encrypting_key: StreamingEncryptingKey,
514        plaintext: &[u8],
515        step: usize,
516    ) -> (Box<[u8]>, DecryptionContext) {
517        let alg = encrypting_key.algorithm();
518        let mode = encrypting_key.mode();
519        let n = plaintext.len();
520        let mut ciphertext = vec![0u8; n + alg.block_len()];
521
522        let mut in_idx: usize = 0;
523        let mut out_idx: usize = 0;
524        loop {
525            let mut in_end = in_idx + step;
526            if in_end > n {
527                in_end = n;
528            }
529            let out_end = out_idx + (in_end - in_idx) + alg.block_len();
530            let output = encrypting_key
531                .update(
532                    &plaintext[in_idx..in_end],
533                    &mut ciphertext[out_idx..out_end],
534                )
535                .unwrap();
536            in_idx += step;
537            out_idx += output.written().len();
538            if in_idx >= n {
539                break;
540            }
541        }
542        let out_end = out_idx + alg.block_len();
543        let (decrypt_iv, output) = encrypting_key
544            .finish(&mut ciphertext[out_idx..out_end])
545            .unwrap();
546        let outlen = output.written().len();
547        ciphertext.truncate(out_idx + outlen);
548        match mode {
549            OperatingMode::CBC | OperatingMode::ECB => {
550                assert!(ciphertext.len() > plaintext.len());
551                assert!(ciphertext.len() <= plaintext.len() + alg.block_len());
552            }
553            _ => {
554                assert_eq!(ciphertext.len(), plaintext.len());
555            }
556        }
557
558        (ciphertext.into_boxed_slice(), decrypt_iv)
559    }
560
561    fn step_decrypt(
562        mut decrypting_key: StreamingDecryptingKey,
563        ciphertext: &[u8],
564        step: usize,
565    ) -> Box<[u8]> {
566        let alg = decrypting_key.algorithm();
567        let mode = decrypting_key.mode();
568        let n = ciphertext.len();
569        let mut plaintext = vec![0u8; n + alg.block_len()];
570
571        let mut in_idx: usize = 0;
572        let mut out_idx: usize = 0;
573        loop {
574            let mut in_end = in_idx + step;
575            if in_end > n {
576                in_end = n;
577            }
578            let out_end = out_idx + (in_end - in_idx) + alg.block_len();
579            let output = decrypting_key
580                .update(
581                    &ciphertext[in_idx..in_end],
582                    &mut plaintext[out_idx..out_end],
583                )
584                .unwrap();
585            in_idx += step;
586            out_idx += output.written().len();
587            if in_idx >= n {
588                break;
589            }
590        }
591        let out_end = out_idx + alg.block_len();
592        let output = decrypting_key
593            .finish(&mut plaintext[out_idx..out_end])
594            .unwrap();
595        let outlen = output.written().len();
596        plaintext.truncate(out_idx + outlen);
597        match mode {
598            OperatingMode::CBC | OperatingMode::ECB => {
599                assert!(ciphertext.len() > plaintext.len());
600                assert!(ciphertext.len() <= plaintext.len() + alg.block_len());
601            }
602            _ => {
603                assert_eq!(ciphertext.len(), plaintext.len());
604            }
605        }
606        plaintext.into_boxed_slice()
607    }
608
609    macro_rules! helper_stream_step_encrypt_test {
610        ($mode:ident) => {
611            paste! {
612                fn [<helper_test_ $mode _stream_encrypt_step_n_bytes>](
613                    encrypting_key_creator: impl Fn() -> StreamingEncryptingKey,
614                    decrypting_key_creator: impl Fn(DecryptionContext) -> StreamingDecryptingKey,
615                    n: usize,
616                    step: usize,
617                ) {
618                    let mut input = vec![0u8; n];
619                    let random = SystemRandom::new();
620                    random.fill(&mut input).unwrap();
621
622                    let encrypting_key = encrypting_key_creator();
623
624                    let (ciphertext, decrypt_iv) = step_encrypt(encrypting_key, &input, step);
625
626                    let decrypting_key = decrypting_key_creator(decrypt_iv);
627
628                    let plaintext = step_decrypt(decrypting_key, &ciphertext, step);
629
630                    assert_eq!(input.as_slice(), &*plaintext);
631                }
632            }
633        };
634    }
635
636    helper_stream_step_encrypt_test!(cbc_pkcs7);
637    helper_stream_step_encrypt_test!(ctr);
638    helper_stream_step_encrypt_test!(cfb128);
639    helper_stream_step_encrypt_test!(ecb_pkcs7);
640
641    #[test]
642    fn test_step_cbc() {
643        let random = SystemRandom::new();
644        let mut key = [0u8; AES_256_KEY_LEN];
645        random.fill(&mut key).unwrap();
646        let key = key;
647
648        let encrypting_key_creator = || {
649            let key = UnboundCipherKey::new(&AES_256, &key.clone()).unwrap();
650            StreamingEncryptingKey::cbc_pkcs7(key).unwrap()
651        };
652        let decrypting_key_creator = |decryption_ctx: DecryptionContext| {
653            let key = UnboundCipherKey::new(&AES_256, &key.clone()).unwrap();
654            StreamingDecryptingKey::cbc_pkcs7(key, decryption_ctx).unwrap()
655        };
656
657        for i in 13..=21 {
658            for j in 124..=131 {
659                helper_test_cbc_pkcs7_stream_encrypt_step_n_bytes(
660                    encrypting_key_creator,
661                    decrypting_key_creator,
662                    j,
663                    i,
664                );
665            }
666            for j in 124..=131 {
667                helper_test_cbc_pkcs7_stream_encrypt_step_n_bytes(
668                    encrypting_key_creator,
669                    decrypting_key_creator,
670                    j,
671                    j - i,
672                );
673            }
674        }
675        for j in 124..=131 {
676            helper_test_cbc_pkcs7_stream_encrypt_step_n_bytes(
677                encrypting_key_creator,
678                decrypting_key_creator,
679                j,
680                j,
681            );
682            helper_test_cbc_pkcs7_stream_encrypt_step_n_bytes(
683                encrypting_key_creator,
684                decrypting_key_creator,
685                j,
686                256,
687            );
688            helper_test_cbc_pkcs7_stream_encrypt_step_n_bytes(
689                encrypting_key_creator,
690                decrypting_key_creator,
691                j,
692                1,
693            );
694        }
695    }
696
697    #[test]
698    fn test_step_ctr() {
699        let random = SystemRandom::new();
700        let mut key = [0u8; AES_256_KEY_LEN];
701        random.fill(&mut key).unwrap();
702
703        let encrypting_key_creator = || {
704            let key = UnboundCipherKey::new(&AES_256, &key.clone()).unwrap();
705            StreamingEncryptingKey::ctr(key).unwrap()
706        };
707        let decrypting_key_creator = |decryption_ctx: DecryptionContext| {
708            let key = UnboundCipherKey::new(&AES_256, &key.clone()).unwrap();
709            StreamingDecryptingKey::ctr(key, decryption_ctx).unwrap()
710        };
711
712        for i in 13..=21 {
713            for j in 124..=131 {
714                helper_test_ctr_stream_encrypt_step_n_bytes(
715                    encrypting_key_creator,
716                    decrypting_key_creator,
717                    j,
718                    i,
719                );
720            }
721            for j in 124..=131 {
722                helper_test_ctr_stream_encrypt_step_n_bytes(
723                    encrypting_key_creator,
724                    decrypting_key_creator,
725                    j,
726                    j - i,
727                );
728            }
729        }
730        for j in 124..=131 {
731            helper_test_ctr_stream_encrypt_step_n_bytes(
732                encrypting_key_creator,
733                decrypting_key_creator,
734                j,
735                j,
736            );
737            helper_test_ctr_stream_encrypt_step_n_bytes(
738                encrypting_key_creator,
739                decrypting_key_creator,
740                j,
741                256,
742            );
743            helper_test_ctr_stream_encrypt_step_n_bytes(
744                encrypting_key_creator,
745                decrypting_key_creator,
746                j,
747                1,
748            );
749        }
750    }
751
752    #[test]
753    fn test_step_cfb128() {
754        let random = SystemRandom::new();
755        let mut key = [0u8; AES_256_KEY_LEN];
756        random.fill(&mut key).unwrap();
757
758        let encrypting_key_creator = || {
759            let key = UnboundCipherKey::new(&AES_256, &key.clone()).unwrap();
760            StreamingEncryptingKey::cfb128(key).unwrap()
761        };
762        let decrypting_key_creator = |decryption_ctx: DecryptionContext| {
763            let key = UnboundCipherKey::new(&AES_256, &key.clone()).unwrap();
764            StreamingDecryptingKey::cfb128(key, decryption_ctx).unwrap()
765        };
766
767        for i in 13..=21 {
768            for j in 124..=131 {
769                helper_test_cfb128_stream_encrypt_step_n_bytes(
770                    encrypting_key_creator,
771                    decrypting_key_creator,
772                    j,
773                    i,
774                );
775            }
776            for j in 124..=131 {
777                helper_test_cfb128_stream_encrypt_step_n_bytes(
778                    encrypting_key_creator,
779                    decrypting_key_creator,
780                    j,
781                    j - i,
782                );
783            }
784        }
785        for j in 124..=131 {
786            helper_test_cfb128_stream_encrypt_step_n_bytes(
787                encrypting_key_creator,
788                decrypting_key_creator,
789                j,
790                j,
791            );
792            helper_test_cfb128_stream_encrypt_step_n_bytes(
793                encrypting_key_creator,
794                decrypting_key_creator,
795                j,
796                256,
797            );
798            helper_test_cfb128_stream_encrypt_step_n_bytes(
799                encrypting_key_creator,
800                decrypting_key_creator,
801                j,
802                1,
803            );
804        }
805    }
806
807    #[test]
808    fn test_step_ecb_pkcs7() {
809        let random = SystemRandom::new();
810        let mut key = [0u8; AES_256_KEY_LEN];
811        random.fill(&mut key).unwrap();
812
813        let encrypting_key_creator = || {
814            let key = UnboundCipherKey::new(&AES_256, &key.clone()).unwrap();
815            StreamingEncryptingKey::ecb_pkcs7(key).unwrap()
816        };
817        let decrypting_key_creator = |decryption_ctx: DecryptionContext| {
818            let key = UnboundCipherKey::new(&AES_256, &key.clone()).unwrap();
819            StreamingDecryptingKey::ecb_pkcs7(key, decryption_ctx).unwrap()
820        };
821
822        for i in 13..=21 {
823            for j in 124..=131 {
824                helper_test_ecb_pkcs7_stream_encrypt_step_n_bytes(
825                    encrypting_key_creator,
826                    decrypting_key_creator,
827                    j,
828                    i,
829                );
830            }
831            for j in 124..=131 {
832                helper_test_ecb_pkcs7_stream_encrypt_step_n_bytes(
833                    encrypting_key_creator,
834                    decrypting_key_creator,
835                    j,
836                    j - i,
837                );
838            }
839        }
840        for j in 124..=131 {
841            helper_test_ecb_pkcs7_stream_encrypt_step_n_bytes(
842                encrypting_key_creator,
843                decrypting_key_creator,
844                j,
845                j,
846            );
847            helper_test_ecb_pkcs7_stream_encrypt_step_n_bytes(
848                encrypting_key_creator,
849                decrypting_key_creator,
850                j,
851                256,
852            );
853            helper_test_ecb_pkcs7_stream_encrypt_step_n_bytes(
854                encrypting_key_creator,
855                decrypting_key_creator,
856                j,
857                1,
858            );
859        }
860    }
861
862    macro_rules! streaming_cipher_kat {
863        ($name:ident, $alg:expr, $mode:expr, $key:literal, $iv: literal, $plaintext:literal, $ciphertext:literal, $from_step:literal, $to_step:literal) => {
864            #[test]
865            fn $name() {
866                let key = from_hex($key).unwrap();
867                let input = from_hex($plaintext).unwrap();
868                let expected_ciphertext = from_hex($ciphertext).unwrap();
869                let iv = from_hex($iv).unwrap();
870
871                for step in ($from_step..=$to_step) {
872                    let ec = EncryptionContext::Iv128(
873                        FixedLength::<IV_LEN_128_BIT>::try_from(iv.as_slice()).unwrap(),
874                    );
875
876                    let unbound_key = UnboundCipherKey::new($alg, &key).unwrap();
877
878                    let encrypting_key =
879                        StreamingEncryptingKey::new(unbound_key, $mode, ec).unwrap();
880
881                    let (ciphertext, decrypt_ctx) = step_encrypt(encrypting_key, &input, step);
882
883                    assert_eq!(expected_ciphertext.as_slice(), ciphertext.as_ref());
884
885                    let unbound_key2 = UnboundCipherKey::new($alg, &key).unwrap();
886                    let decrypting_key =
887                        StreamingDecryptingKey::new(unbound_key2, $mode, decrypt_ctx).unwrap();
888
889                    let plaintext = step_decrypt(decrypting_key, &ciphertext, step);
890                    assert_eq!(input.as_slice(), plaintext.as_ref());
891                }
892            }
893        };
894        ($name:ident, $alg:expr, $mode:expr, $key:literal, $plaintext:literal, $ciphertext:literal, $from_step:literal, $to_step:literal) => {
895            #[test]
896            fn $name() {
897                let key = from_hex($key).unwrap();
898                let input = from_hex($plaintext).unwrap();
899                let expected_ciphertext = from_hex($ciphertext).unwrap();
900
901                for step in ($from_step..=$to_step) {
902                    let unbound_key = UnboundCipherKey::new($alg, &key).unwrap();
903
904                    let encrypting_key =
905                        StreamingEncryptingKey::new(unbound_key, $mode, EncryptionContext::None)
906                            .unwrap();
907
908                    let (ciphertext, decrypt_ctx) = step_encrypt(encrypting_key, &input, step);
909
910                    assert_eq!(expected_ciphertext.as_slice(), ciphertext.as_ref());
911
912                    let unbound_key2 = UnboundCipherKey::new($alg, &key).unwrap();
913                    let decrypting_key =
914                        StreamingDecryptingKey::new(unbound_key2, $mode, decrypt_ctx).unwrap();
915
916                    let plaintext = step_decrypt(decrypting_key, &ciphertext, step);
917                    assert_eq!(input.as_slice(), plaintext.as_ref());
918                }
919            }
920        };
921    }
922
923    streaming_cipher_kat!(
924        test_iv_aes_128_ctr_16_bytes,
925        &AES_128,
926        OperatingMode::CTR,
927        "000102030405060708090a0b0c0d0e0f",
928        "00000000000000000000000000000000",
929        "00112233445566778899aabbccddeeff",
930        "c6b01904c3da3df5e7d62bd96d153686",
931        2,
932        9
933    );
934    streaming_cipher_kat!(
935        test_iv_aes_256_ctr_15_bytes,
936        &AES_256,
937        OperatingMode::CTR,
938        "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
939        "00000000000000000000000000000000",
940        "00112233445566778899aabbccddee",
941        "f28122856e1cf9a7216a30d111f399",
942        2,
943        9
944    );
945
946    streaming_cipher_kat!(
947        test_openssl_aes_128_ctr_15_bytes,
948        &AES_128,
949        OperatingMode::CTR,
950        "244828580821c1652582c76e34d299f5",
951        "093145d5af233f46072a5eb5adc11aa1",
952        "3ee38cec171e6cf466bf0df98aa0e1",
953        "bd7d928f60e3422d96b3f8cd614eb2",
954        2,
955        9
956    );
957
958    streaming_cipher_kat!(
959        test_openssl_aes_256_ctr_15_bytes,
960        &AES_256,
961        OperatingMode::CTR,
962        "0857db8240ea459bdf660b4cced66d1f2d3734ff2de7b81e92740e65e7cc6a1d",
963        "f028ecb053f801102d11fccc9d303a27",
964        "eca7285d19f3c20e295378460e8729",
965        "b5098e5e788de6ac2f2098eb2fc6f8",
966        2,
967        9
968    );
969
970    streaming_cipher_kat!(
971        test_iv_aes_128_cbc_16_bytes,
972        &AES_128,
973        OperatingMode::CBC,
974        "000102030405060708090a0b0c0d0e0f",
975        "00000000000000000000000000000000",
976        "00112233445566778899aabbccddeeff",
977        "69c4e0d86a7b0430d8cdb78070b4c55a9e978e6d16b086570ef794ef97984232",
978        2,
979        9
980    );
981
982    streaming_cipher_kat!(
983        test_iv_aes_256_cbc_15_bytes,
984        &AES_256,
985        OperatingMode::CBC,
986        "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
987        "00000000000000000000000000000000",
988        "00112233445566778899aabbccddee",
989        "2ddfb635a651a43f582997966840ca0c",
990        2,
991        9
992    );
993
994    streaming_cipher_kat!(
995        test_openssl_aes_128_cbc_15_bytes,
996        &AES_128,
997        OperatingMode::CBC,
998        "053304bb3899e1d99db9d29343ea782d",
999        "b5313560244a4822c46c2a0c9d0cf7fd",
1000        "a3e4c990356c01f320043c3d8d6f43",
1001        "ad96993f248bd6a29760ec7ccda95ee1",
1002        2,
1003        9
1004    );
1005
1006    streaming_cipher_kat!(
1007        test_openssl_aes_128_cbc_16_bytes,
1008        &AES_128,
1009        OperatingMode::CBC,
1010        "95af71f1c63e4a1d0b0b1a27fb978283",
1011        "89e40797dca70197ff87d3dbb0ef2802",
1012        "aece7b5e3c3df1ffc9802d2dfe296dc7",
1013        "301b5dab49fb11e919d0d39970d06739301919743304f23f3cbc67d28564b25b",
1014        2,
1015        9
1016    );
1017
1018    streaming_cipher_kat!(
1019        test_openssl_aes_256_cbc_15_bytes,
1020        &AES_256,
1021        OperatingMode::CBC,
1022        "d369e03e9752784917cc7bac1db7399598d9555e691861d9dd7b3292a693ef57",
1023        "1399bb66b2f6ad99a7f064140eaaa885",
1024        "7385f5784b85bf0a97768ddd896d6d",
1025        "4351082bac9b4593ae8848cc9dfb5a01",
1026        2,
1027        9
1028    );
1029
1030    streaming_cipher_kat!(
1031        test_openssl_aes_256_cbc_16_bytes,
1032        &AES_256,
1033        OperatingMode::CBC,
1034        "d4a8206dcae01242f9db79a4ecfe277d0f7bb8ccbafd8f9809adb39f35aa9b41",
1035        "24f6076548fb9d93c8f7ed9f6e661ef9",
1036        "a39c1fdf77ea3e1f18178c0ec237c70a",
1037        "f1af484830a149ee0387b854d65fe87ca0e62efc1c8e6909d4b9ab8666470453",
1038        2,
1039        9
1040    );
1041
1042    streaming_cipher_kat!(
1043        test_openssl_aes_128_cfb128_16_bytes,
1044        &AES_128,
1045        OperatingMode::CFB128,
1046        "5c353f739429bbd48b7e3f9a76facf4d",
1047        "7b2c7ce17a9b6a59a9e64253b98c8cd1",
1048        "add1bcebeaabe9423d4e916400e877c5",
1049        "8440ec442e4135a613ddb2ce26107e10",
1050        2,
1051        9
1052    );
1053
1054    streaming_cipher_kat!(
1055        test_openssl_aes_128_cfb128_15_bytes,
1056        &AES_128,
1057        OperatingMode::CFB128,
1058        "e1f39d70ad378efc1ac318aa8ac4489f",
1059        "ec78c3d54fff2fe09678c7883024ddce",
1060        "b8c905004b2a92a323769f1b8dc1b2",
1061        "964c3e9bf8bf2a3cca02d8e2e75608",
1062        2,
1063        9
1064    );
1065
1066    streaming_cipher_kat!(
1067        test_openssl_aes_256_cfb128_16_bytes,
1068        &AES_256,
1069        OperatingMode::CFB128,
1070        "0e8117d0984d6acb957a5d6ca526a12fa612ce5de2daadebd42c14d28a0a192e",
1071        "09147a153b230a40cd7bf4197ad0e825",
1072        "13f4540a4e06394148ade31a6f678787",
1073        "250e590e47b7613b7d0a53f684e970d6",
1074        2,
1075        9
1076    );
1077
1078    streaming_cipher_kat!(
1079        test_openssl_aes_256_cfb128_15_bytes,
1080        &AES_256,
1081        OperatingMode::CFB128,
1082        "5cb17d8d5b9dbd81e4f1e0a2c82ebf36cf61156388fb7abf99d4526622858225",
1083        "13c77415ec24f3e2f784f228478a85be",
1084        "3efa583df4405aab61e18155aa7e0d",
1085        "c1f2ffe8aa5064199e8f4f1b388303",
1086        2,
1087        9
1088    );
1089
1090    streaming_cipher_kat!(
1091        test_openssl_aes_128_ecb_pkcs7_16_bytes,
1092        &AES_128,
1093        OperatingMode::ECB,
1094        "a1b7cd124f9824a1532d8440f8136788",
1095        "388118e6848b0cea97401707a754d7a1",
1096        "19b7c7f5d9c2bda3f957e9e7d20847828d5eb5624bcbf221014063a87b38d133",
1097        2,
1098        9
1099    );
1100
1101    streaming_cipher_kat!(
1102        test_openssl_aes_128_ecb_pkcs7_15_bytes,
1103        &AES_128,
1104        OperatingMode::ECB,
1105        "d10e12accb837aaffbb284448e53138c",
1106        "b21cfd1c9e6e7e6e912c82c7dd1aa8",
1107        "3d1168e61df34b51c6ab6745c20ee881",
1108        2,
1109        9
1110    );
1111
1112    streaming_cipher_kat!(
1113        test_openssl_aes_256_ecb_pkcs7_16_bytes,
1114        &AES_256,
1115        OperatingMode::ECB,
1116        "0600f4ad4eda4bc8e3e99592abdfce7eb08fee0ccc801c5ccee26134bcaafbbd",
1117        "516b45cb1342239a549bd8c1d5998f98",
1118        "854c593555a213e4a862c6f66aa4a79631faca131eba6f163e5cd3940e9c0a57",
1119        2,
1120        9
1121    );
1122
1123    streaming_cipher_kat!(
1124        test_openssl_aes_256_ecb_pkcs7_15_bytes,
1125        &AES_256,
1126        OperatingMode::ECB,
1127        "80f235756c8f70094ae1f99a95a599c27c4452a4b8412fd934e2b253f7098508",
1128        "2235590b90190d7a1dc2464a0205ad",
1129        "8547d8ac8dc6d9cebb2dc77a7034bb67",
1130        2,
1131        9
1132    );
1133}