Coverage Report

Created: 2026-08-14 07:05

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