Skip to main content

cryptography/modes/
mod.rs

1//! Generic block-cipher modes of operation.
2//!
3//! Implemented in this layer:
4//!
5//! - SP 800-38A confidentiality modes: ECB, CBC, CFB (full-block), CFB8, OFB, CTR
6//! - SP 800-38B authentication mode: CMAC
7//! - SP 800-38C authenticated mode: CCM
8//! - SP 800-38D authenticated mode: GCM / GMAC
9//! - SP 800-38E storage mode: XTS (128-bit block ciphers only)
10//! - RFC 3394 / SP 800-38F key wrap mode: AES Key Wrap (no padding)
11//! - EAX authenticated mode
12//! - OCB3 authenticated mode (RFC 7253)
13//! - AES-GCM-SIV misuse-resistant mode (RFC 8452)
14//! - RFC 5297 misuse-resistant mode: SIV
15//! - RFC 8439 AEAD: ChaCha20-Poly1305
16//!
17//! These adapters are generic over any `BlockCipher` in the crate, so the same
18//! wrapper works with AES, DES, Camellia, PRESENT, and the other block
19//! primitives exposed here.
20//!
21//! The point of this layer is to separate primitive choice from mode choice:
22//! one block cipher implementation can be dropped into several standardized
23//! operating modes without duplicating the mode logic in every cipher module.
24
25use crate::BlockCipher;
26
27pub mod chacha20_poly1305;
28pub mod eax;
29pub mod gcm_siv;
30pub mod ocb;
31pub mod poly1305;
32pub mod siv;
33pub use chacha20_poly1305::ChaCha20Poly1305;
34pub use eax::Eax;
35pub use gcm_siv::{Aes128GcmSiv, Aes256GcmSiv};
36pub use ocb::Ocb;
37pub use poly1305::Poly1305;
38pub use siv::Siv;
39
40#[inline]
41fn assert_block_multiple<C: BlockCipher>(buf: &[u8]) {
42    assert_eq!(
43        buf.len() % C::BLOCK_LEN,
44        0,
45        "buffer length must be a multiple of the block length"
46    );
47}
48
49#[inline]
50fn xor_in_place(dst: &mut [u8], src: &[u8]) {
51    for (d, s) in dst.iter_mut().zip(src.iter()) {
52        *d ^= *s;
53    }
54}
55
56#[inline]
57fn increment_be(counter: &mut [u8]) {
58    // CTR-style modes treat the IV/counter block as a single big-endian
59    // integer so incrementing from the tail matches the NIST block-mode
60    // specifications.
61    for b in counter.iter_mut().rev() {
62        let (next, carry) = b.overflowing_add(1);
63        *b = next;
64        if !carry {
65            break;
66        }
67    }
68}
69
70#[inline]
71fn rb_for(block_len: usize) -> u8 {
72    match block_len {
73        8 => 0x1b,
74        16 => 0x87,
75        _ => panic!("CMAC only supports 64-bit or 128-bit block ciphers"),
76    }
77}
78
79fn dbl(block: &[u8]) -> Vec<u8> {
80    // CMAC subkeys are generated by doubling in GF(2^n), so this shifts the
81    // block left by one bit and folds the carry bit back in via the mode's
82    // reduction constant (`Rb`).
83    let mut out = vec![0u8; block.len()];
84    let mut carry = 0u8;
85    for (o, &b) in out.iter_mut().rev().zip(block.iter().rev()) {
86        *o = (b << 1) | carry;
87        carry = b >> 7;
88    }
89    if carry != 0 {
90        let last = out.len() - 1;
91        out[last] ^= rb_for(block.len());
92    }
93    out
94}
95
96#[inline]
97fn assert_block_128<C: BlockCipher>() {
98    assert_eq!(
99        C::BLOCK_LEN,
100        16,
101        "this mode requires a 128-bit block cipher"
102    );
103}
104
105#[inline]
106fn xor_block16_in_place(dst: &mut [u8; 16], src: &[u8; 16]) {
107    for i in 0..16 {
108        dst[i] ^= src[i];
109    }
110}
111
112#[inline]
113fn increment_be32(counter: &mut [u8; 16]) {
114    // GCM's fast path reserves the low 32 bits of the pre-counter block as the
115    // incremented invocation field, so only the final four bytes advance here.
116    for b in counter[12..].iter_mut().rev() {
117        let (next, carry) = b.overflowing_add(1);
118        *b = next;
119        if !carry {
120            break;
121        }
122    }
123}
124
125const GCM_MAX_COUNTER_BLOCKS: u64 = (u32::MAX as u64) - 1;
126const GCM_MAX_PAYLOAD_BYTES: u64 = GCM_MAX_COUNTER_BLOCKS * 16;
127
128#[inline]
129fn gcm_payload_len_allowed_u64(len_bytes: u64) -> bool {
130    // SP 800-38D bounds GCTR to at most 2^32 - 2 block invocations per key/nonce.
131    len_bytes.saturating_add(15) / 16 <= GCM_MAX_COUNTER_BLOCKS
132}
133
134#[inline]
135fn gcm_payload_len_allowed(len_bytes: usize) -> bool {
136    gcm_payload_len_allowed_u64(u64::try_from(len_bytes).unwrap_or(u64::MAX))
137}
138
139#[inline]
140fn assert_gcm_payload_len(len_bytes: usize) {
141    assert!(
142        gcm_payload_len_allowed(len_bytes),
143        "GCM payload too large: max {} bytes per key/nonce",
144        GCM_MAX_PAYLOAD_BYTES
145    );
146}
147
148#[inline]
149fn gf_mul_x_xts(tweak: &mut [u8; 16]) {
150    // SP 800-38E treats tweaks as elements of GF(2^128) encoded little-endian.
151    // Multiplication by x is a one-bit left shift across bytes; when a carry
152    // leaves the top bit, reduce by x^128 + x^7 + x^2 + x + 1, which is `0x87`
153    // in this byte order, so the xor lands in `tweak[0]`.
154    let mut carry = 0u8;
155    for b in tweak.iter_mut() {
156        let next = *b >> 7;
157        *b = (*b << 1) | carry;
158        carry = next;
159    }
160    if carry != 0 {
161        tweak[0] ^= 0x87;
162    }
163}
164
165#[inline]
166fn xex_encrypt_block<C: BlockCipher>(cipher: &C, tweak: &[u8; 16], block: &mut [u8; 16]) {
167    xor_block16_in_place(block, tweak);
168    cipher.encrypt(block);
169    xor_block16_in_place(block, tweak);
170}
171
172#[inline]
173fn xex_decrypt_block<C: BlockCipher>(cipher: &C, tweak: &[u8; 16], block: &mut [u8; 16]) {
174    xor_block16_in_place(block, tweak);
175    cipher.decrypt(block);
176    xor_block16_in_place(block, tweak);
177}
178
179/// Multiply `x` and `y` in GF(2¹²⁸) using the GCM field — variable-time.
180///
181/// **Field definition.**  GCM uses GF(2¹²⁸) with the reduction polynomial
182/// f(α) = α¹²⁸ + α⁷ + α² + α + 1.  Elements are 128-bit polynomials over
183/// GF(2); addition is XOR; multiplication is polynomial multiply mod f.
184///
185/// **Bit convention.**  GCM uses a "reflected" bit order where bit 127 of the
186/// `u128` represents the coefficient of α⁰ (constant term) and bit 0
187/// represents α¹²⁷.  Under this convention, multiplying by α is a right-shift
188/// by 1.  If the low bit (α¹²⁷) was 1, the shift overflows and must be reduced
189/// by XOR-ing with `R`.
190///
191/// **`R` constant.**  `R = 0xe100_..._0000` encodes the remainder
192/// `f(α) mod α¹²⁸ = α⁷ + α² + α + 1` in reflected bit order:
193/// 0xe1 = 1110_0001 → bits 7,6,5,0 → coefficients α⁰,α¹,α²,α⁷ ✓
194///
195/// **Algorithm.**  Standard right-to-left binary scalar multiplication:
196/// for each bit of `x` (MSB first in the reflected convention), conditionally
197/// accumulate `v` into `z`, then advance `v` by one α-multiplication step.
198///
199/// Not constant-time — branches on bits of `x` and `v`.  Use [`ghash_mul_ct`]
200/// when the inputs may be secret.
201#[inline]
202fn ghash_mul_vt(x: u128, y: u128) -> u128 {
203    // SP 800-38D Algorithm 1 reduction constant for p(x)=x^128+x^7+x^2+x+1.
204    // GHASH uses a bit-reflected representation, so the low terms
205    // (x^7+x^2+x+1) encode as 0xe1 in the most-significant byte.
206    const R: u128 = 0xe100_0000_0000_0000_0000_0000_0000_0000;
207
208    let mut z = 0u128;
209    let mut v = y;
210    for i in 0..128 {
211        if ((x >> (127 - i)) & 1) != 0 {
212            z ^= v;
213        }
214        if (v & 1) == 0 {
215            v >>= 1;
216        } else {
217            v = (v >> 1) ^ R;
218        }
219    }
220    z
221}
222
223/// Multiply `x` and `y` in GF(2¹²⁸) — constant-time version of [`ghash_mul_vt`].
224///
225/// Same field and algorithm as `ghash_mul_vt`, but both conditional XORs are
226/// replaced with branchless masking so neither the bit-pattern of `x` nor the
227/// carry bit of `v` leaks through timing.
228#[inline]
229fn ghash_mul_ct(x: u128, y: u128) -> u128 {
230    // Same reflected reduction constant as `ghash_mul_vt`: in GHASH bit order,
231    // x^7 + x^2 + x + 1 maps to 0xe1 in the most-significant byte.
232    const R: u128 = 0xe100_0000_0000_0000_0000_0000_0000_0000;
233
234    let mut z = 0u128;
235    let mut v = y;
236    for i in 0..128 {
237        // Turn one bit into an all-ones/all-zero mask and use it to
238        // conditionally xor without data-dependent branches.
239        let bit = u8::try_from((x >> (127 - i)) & 1).expect("single bit fits in u8");
240        let bit_mask = 0u128.wrapping_sub(u128::from(bit));
241        z ^= v & bit_mask;
242
243        let lsb = u8::try_from(v & 1).expect("single bit fits in u8");
244        let lsb_mask = 0u128.wrapping_sub(u128::from(lsb));
245        v = (v >> 1) ^ (R & lsb_mask);
246    }
247    z
248}
249
250type GhashMulFn = fn(u128, u128) -> u128;
251
252fn ghash_update(y: &mut u128, h: u128, data: &[u8], mul: GhashMulFn) {
253    let mut block = [0u8; 16];
254    for chunk in data.chunks(16) {
255        block.fill(0);
256        block[..chunk.len()].copy_from_slice(chunk);
257        *y ^= u128::from_be_bytes(block);
258        *y = mul(*y, h);
259    }
260}
261
262fn ghash(h: u128, aad: &[u8], ciphertext: &[u8], mul: GhashMulFn) -> u128 {
263    let mut y = 0u128;
264    ghash_update(&mut y, h, aad, mul);
265    ghash_update(&mut y, h, ciphertext, mul);
266
267    let mut len_block = [0u8; 16];
268    // SP 800-38D GHASH appends bit lengths, not byte lengths.
269    len_block[..8].copy_from_slice(&((aad.len() as u64) << 3).to_be_bytes());
270    len_block[8..].copy_from_slice(&((ciphertext.len() as u64) << 3).to_be_bytes());
271    y ^= u128::from_be_bytes(len_block);
272    mul(y, h)
273}
274
275#[inline]
276fn ghash_iv(h: u128, iv: &[u8], mul: GhashMulFn) -> [u8; 16] {
277    // SP 800-38D §7.1 fast path: for 96-bit IVs, J0 = IV || 0^31 || 1.
278    if iv.len() == 12 {
279        let mut j0 = [0u8; 16];
280        j0[..12].copy_from_slice(iv);
281        j0[15] = 1;
282        return j0;
283    }
284    // Non-96-bit IVs are GHASHed with the standard length block.
285    ghash(h, &[], iv, mul).to_be_bytes()
286}
287
288#[inline]
289fn gcm_hash_subkey<C: BlockCipher>(cipher: &C) -> u128 {
290    // GCM hash subkey H = E_K(0^128) per SP 800-38D.
291    let mut h = [0u8; 16];
292    cipher.encrypt(&mut h);
293    u128::from_be_bytes(h)
294}
295
296#[inline]
297fn counter_keystream<C: BlockCipher>(cipher: &C, counter: &[u8; 16]) -> [u8; 16] {
298    let mut out = *counter;
299    cipher.encrypt(&mut out);
300    out
301}
302
303fn gcm_compute_tag<C: BlockCipher>(
304    cipher: &C,
305    nonce: &[u8],
306    aad: &[u8],
307    ciphertext: &[u8],
308    mul: GhashMulFn,
309) -> [u8; 16] {
310    assert_block_128::<C>();
311    assert_gcm_payload_len(ciphertext.len());
312    let h = gcm_hash_subkey(cipher);
313    let j0 = ghash_iv(h, nonce, mul);
314    let s = ghash(h, aad, ciphertext, mul);
315    let tag_mask = u128::from_be_bytes(counter_keystream(cipher, &j0));
316    (s ^ tag_mask).to_be_bytes()
317}
318
319fn gcm_compute_tag_with_h<C: BlockCipher>(
320    cipher: &C,
321    h: u128,
322    nonce: &[u8],
323    aad: &[u8],
324    ciphertext: &[u8],
325    mul: GhashMulFn,
326) -> [u8; 16] {
327    assert_gcm_payload_len(ciphertext.len());
328    let j0 = ghash_iv(h, nonce, mul);
329    let s = ghash(h, aad, ciphertext, mul);
330    let tag_mask = u128::from_be_bytes(counter_keystream(cipher, &j0));
331    (s ^ tag_mask).to_be_bytes()
332}
333
334#[inline]
335fn ccm_l_from_nonce(nonce: &[u8]) -> usize {
336    assert!(
337        (7..=13).contains(&nonce.len()),
338        "CCM nonce length must be in 7..=13 bytes"
339    );
340    15 - nonce.len()
341}
342
343#[inline]
344fn assert_ccm_tag_len(tag_len: usize) {
345    assert!(
346        (4..=16).contains(&tag_len) && tag_len.is_multiple_of(2),
347        "CCM tag length must be one of {{4,6,8,10,12,14,16}}"
348    );
349}
350
351#[inline]
352fn ccm_pack_len(block: &mut [u8; 16], l: usize, value: u64) {
353    let needed_bits = l * 8;
354    assert!(
355        needed_bits >= 64 || value < (1u64 << needed_bits),
356        "CCM length/counter does not fit in L bytes"
357    );
358    for i in 0..l {
359        block[15 - i] = u8::try_from((value >> (8 * i)) & 0xff).expect("single byte");
360    }
361}
362
363#[inline]
364fn ccm_b0(nonce: &[u8], msg_len: usize, aad_len: usize, tag_len: usize) -> [u8; 16] {
365    let l = ccm_l_from_nonce(nonce);
366    assert_ccm_tag_len(tag_len);
367    let msg_len_u64 = u64::try_from(msg_len).expect("message length fits u64");
368
369    let mut b0 = [0u8; 16];
370    let aad_flag = u8::from(aad_len != 0) << 6;
371    let t_field = u8::try_from((tag_len - 2) / 2).expect("CCM tag field fits u8") << 3;
372    let l_field = u8::try_from(l - 1).expect("CCM L field fits u8");
373    b0[0] = aad_flag | t_field | l_field;
374    b0[1..1 + nonce.len()].copy_from_slice(nonce);
375    ccm_pack_len(&mut b0, l, msg_len_u64);
376    b0
377}
378
379#[inline]
380fn ccm_counter_block(nonce: &[u8], counter: u64) -> [u8; 16] {
381    let l = ccm_l_from_nonce(nonce);
382    let mut ctr = [0u8; 16];
383    ctr[0] = u8::try_from(l - 1).expect("CCM L field fits u8");
384    ctr[1..1 + nonce.len()].copy_from_slice(nonce);
385    ccm_pack_len(&mut ctr, l, counter);
386    ctr
387}
388
389fn ccm_encode_aad(aad: &[u8]) -> Vec<u8> {
390    if aad.is_empty() {
391        return Vec::new();
392    }
393
394    let mut out = Vec::with_capacity(aad.len() + 16);
395    let aad_len = aad.len() as u64;
396    if aad_len < ((1u64 << 16) - (1u64 << 8)) {
397        out.extend_from_slice(
398            &u16::try_from(aad_len)
399                .expect("length range checked")
400                .to_be_bytes(),
401        );
402    } else if aad_len < (1u64 << 32) {
403        out.extend_from_slice(&[0xff, 0xfe]);
404        out.extend_from_slice(&(aad_len as u32).to_be_bytes());
405    } else {
406        out.extend_from_slice(&[0xff, 0xff]);
407        out.extend_from_slice(&aad_len.to_be_bytes());
408    }
409    out.extend_from_slice(aad);
410    if !out.len().is_multiple_of(16) {
411        out.resize(out.len().next_multiple_of(16), 0);
412    }
413    out
414}
415
416fn ccm_cbc_mac<C: BlockCipher>(
417    cipher: &C,
418    nonce: &[u8],
419    aad: &[u8],
420    plaintext: &[u8],
421    tag_len: usize,
422) -> [u8; 16] {
423    assert_block_128::<C>();
424    let mut y = [0u8; 16];
425
426    let b0 = ccm_b0(nonce, plaintext.len(), aad.len(), tag_len);
427    xor_block16_in_place(&mut y, &b0);
428    cipher.encrypt(&mut y);
429
430    let aad_encoded = ccm_encode_aad(aad);
431    for chunk in aad_encoded.chunks(16) {
432        let mut block = [0u8; 16];
433        block.copy_from_slice(chunk);
434        xor_block16_in_place(&mut y, &block);
435        cipher.encrypt(&mut y);
436    }
437
438    for chunk in plaintext.chunks(16) {
439        let mut block = [0u8; 16];
440        block[..chunk.len()].copy_from_slice(chunk);
441        xor_block16_in_place(&mut y, &block);
442        cipher.encrypt(&mut y);
443    }
444
445    y
446}
447
448fn ccm_apply_ctr<C: BlockCipher>(cipher: &C, nonce: &[u8], data: &mut [u8]) {
449    for (i, chunk) in data.chunks_mut(16).enumerate() {
450        let ctr = ccm_counter_block(nonce, u64::try_from(i + 1).expect("counter fits u64"));
451        let stream = counter_keystream(cipher, &ctr);
452        xor_in_place(chunk, &stream[..chunk.len()]);
453    }
454}
455
456const AES_KEY_WRAP_DEFAULT_IV: [u8; 8] = [0xA6; 8];
457
458#[inline]
459fn xor_aes_kw_t(a: &mut [u8; 8], t: u64) {
460    let t_be = t.to_be_bytes();
461    for i in 0..8 {
462        a[i] ^= t_be[i];
463    }
464}
465
466/// AES Key Wrap (RFC 3394) over 64-bit semiblocks with the default IV.
467///
468/// This is the no-padding variant standardized in RFC 3394 and SP 800-38F.
469/// Inputs must be a multiple of 8 bytes and at least 16 bytes long.
470pub struct AesKeyWrap<C> {
471    cipher: C,
472}
473
474impl<C> AesKeyWrap<C> {
475    /// Wrap an AES cipher instance for RFC 3394 key wrap operations.
476    pub fn new(cipher: C) -> Self {
477        Self { cipher }
478    }
479
480    /// Borrow the wrapped AES cipher.
481    pub fn cipher(&self) -> &C {
482        &self.cipher
483    }
484}
485
486impl<C: BlockCipher> AesKeyWrap<C> {
487    /// Wrap key material with the RFC 3394 default IV (`A6A6A6A6A6A6A6A6`).
488    ///
489    /// Returns `None` when `key_data` is not a multiple of 8 bytes or is
490    /// shorter than 16 bytes.
491    pub fn wrap_key(&self, key_data: &[u8]) -> Option<Vec<u8>> {
492        self.wrap_key_with_iv(key_data, &AES_KEY_WRAP_DEFAULT_IV)
493    }
494
495    /// Wrap key material with an explicit 64-bit initial register value.
496    ///
497    /// Returns `None` when `key_data` is not a multiple of 8 bytes or is
498    /// shorter than 16 bytes.
499    pub fn wrap_key_with_iv(&self, key_data: &[u8], iv: &[u8; 8]) -> Option<Vec<u8>> {
500        assert_block_128::<C>();
501        if !key_data.len().is_multiple_of(8) || key_data.len() < 16 {
502            return None;
503        }
504
505        let n = key_data.len() / 8;
506        let mut a = *iv;
507        let mut r = Vec::with_capacity(n);
508        for chunk in key_data.chunks_exact(8) {
509            let mut block = [0u8; 8];
510            block.copy_from_slice(chunk);
511            r.push(block);
512        }
513
514        for j in 0..6usize {
515            for (i, ri) in r.iter_mut().enumerate() {
516                let mut b = [0u8; 16];
517                b[..8].copy_from_slice(&a);
518                b[8..].copy_from_slice(ri);
519                self.cipher.encrypt(&mut b);
520
521                a.copy_from_slice(&b[..8]);
522                let t =
523                    u64::try_from(j * n + i + 1).expect("AES-KW step index must fit in 64 bits");
524                xor_aes_kw_t(&mut a, t);
525                ri.copy_from_slice(&b[8..]);
526            }
527        }
528
529        let mut wrapped = Vec::with_capacity((n + 1) * 8);
530        wrapped.extend_from_slice(&a);
531        for ri in r {
532            wrapped.extend_from_slice(&ri);
533        }
534        Some(wrapped)
535    }
536
537    /// Unwrap RFC 3394 key material and verify the default IV integrity check.
538    ///
539    /// Returns `None` when input length is invalid or the integrity check
540    /// fails.
541    pub fn unwrap_key(&self, wrapped: &[u8]) -> Option<Vec<u8>> {
542        self.unwrap_key_with_iv(wrapped, &AES_KEY_WRAP_DEFAULT_IV)
543    }
544
545    /// Unwrap RFC 3394 key material and verify against an explicit IV value.
546    ///
547    /// Returns `None` when input length is invalid or the integrity check
548    /// fails.
549    pub fn unwrap_key_with_iv(&self, wrapped: &[u8], iv: &[u8; 8]) -> Option<Vec<u8>> {
550        assert_block_128::<C>();
551        if !wrapped.len().is_multiple_of(8) || wrapped.len() < 24 {
552            return None;
553        }
554
555        let n = (wrapped.len() / 8) - 1;
556        let mut a = [0u8; 8];
557        a.copy_from_slice(&wrapped[..8]);
558
559        let mut r = Vec::with_capacity(n);
560        for chunk in wrapped[8..].chunks_exact(8) {
561            let mut block = [0u8; 8];
562            block.copy_from_slice(chunk);
563            r.push(block);
564        }
565
566        for j in (0..6usize).rev() {
567            for i in (0..n).rev() {
568                let t =
569                    u64::try_from(j * n + i + 1).expect("AES-KW step index must fit in 64 bits");
570                let mut a_xor_t = a;
571                xor_aes_kw_t(&mut a_xor_t, t);
572
573                let mut b = [0u8; 16];
574                b[..8].copy_from_slice(&a_xor_t);
575                b[8..].copy_from_slice(&r[i]);
576                self.cipher.decrypt(&mut b);
577
578                a.copy_from_slice(&b[..8]);
579                r[i].copy_from_slice(&b[8..]);
580            }
581        }
582
583        if crate::ct::constant_time_eq_mask(&a, iv) != u8::MAX {
584            return None;
585        }
586
587        let mut key_data = Vec::with_capacity(n * 8);
588        for ri in r {
589            key_data.extend_from_slice(&ri);
590        }
591        Some(key_data)
592    }
593}
594
595/// Electronic Codebook (ECB) mode.
596///
597/// This is included because SP 800-38A defines it, but it should only be used
598/// for single-block operations or controlled test vectors. It leaks repeated
599/// plaintext patterns.
600pub struct Ecb<C> {
601    cipher: C,
602}
603
604impl<C> Ecb<C> {
605    /// Wrap a block cipher in SP 800-38A ECB mode.
606    pub fn new(cipher: C) -> Self {
607        Self { cipher }
608    }
609
610    /// Borrow the wrapped block cipher.
611    pub fn cipher(&self) -> &C {
612        &self.cipher
613    }
614}
615
616impl<C: BlockCipher> Ecb<C> {
617    /// Encrypt block-aligned data in place without padding.
618    pub fn encrypt_nopad(&self, data: &mut [u8]) {
619        assert_block_multiple::<C>(data);
620        for block in data.chunks_exact_mut(C::BLOCK_LEN) {
621            self.cipher.encrypt(block);
622        }
623    }
624
625    /// Decrypt block-aligned data in place without padding.
626    pub fn decrypt_nopad(&self, data: &mut [u8]) {
627        assert_block_multiple::<C>(data);
628        for block in data.chunks_exact_mut(C::BLOCK_LEN) {
629            self.cipher.decrypt(block);
630        }
631    }
632}
633
634/// Cipher Block Chaining (CBC) mode.
635pub struct Cbc<C> {
636    cipher: C,
637}
638
639impl<C> Cbc<C> {
640    /// Wrap a block cipher in SP 800-38A CBC mode.
641    pub fn new(cipher: C) -> Self {
642        Self { cipher }
643    }
644
645    /// Borrow the wrapped block cipher.
646    pub fn cipher(&self) -> &C {
647        &self.cipher
648    }
649}
650
651impl<C: BlockCipher> Cbc<C> {
652    /// # Panics
653    ///
654    /// Panics if `iv.len()` does not match the block size, or if `data.len()`
655    /// is not an exact multiple of the block size.
656    pub fn encrypt_nopad(&self, iv: &[u8], data: &mut [u8]) {
657        assert_eq!(iv.len(), C::BLOCK_LEN, "wrong IV length");
658        assert_block_multiple::<C>(data);
659
660        let mut prev = iv.to_vec();
661        for block in data.chunks_exact_mut(C::BLOCK_LEN) {
662            xor_in_place(block, &prev);
663            self.cipher.encrypt(block);
664            prev.copy_from_slice(block);
665        }
666    }
667
668    /// # Panics
669    ///
670    /// Panics if `iv.len()` does not match the block size, or if `data.len()`
671    /// is not an exact multiple of the block size.
672    pub fn decrypt_nopad(&self, iv: &[u8], data: &mut [u8]) {
673        assert_eq!(iv.len(), C::BLOCK_LEN, "wrong IV length");
674        assert_block_multiple::<C>(data);
675
676        let mut prev = iv.to_vec();
677        let mut tmp = vec![0u8; C::BLOCK_LEN];
678
679        for block in data.chunks_exact_mut(C::BLOCK_LEN) {
680            tmp.copy_from_slice(block);
681            self.cipher.decrypt(block);
682            xor_in_place(block, &prev);
683            prev.copy_from_slice(&tmp);
684        }
685    }
686}
687
688/// Cipher Feedback (CFB) mode with a segment size equal to the full block.
689pub struct Cfb<C> {
690    cipher: C,
691}
692
693impl<C> Cfb<C> {
694    /// Wrap a block cipher in SP 800-38A CFB mode.
695    pub fn new(cipher: C) -> Self {
696        Self { cipher }
697    }
698
699    /// Borrow the wrapped block cipher.
700    pub fn cipher(&self) -> &C {
701        &self.cipher
702    }
703}
704
705impl<C: BlockCipher> Cfb<C> {
706    /// # Panics
707    ///
708    /// Panics if `iv.len()` does not match the block size, or if `data.len()`
709    /// is not an exact multiple of the block size.
710    pub fn encrypt_nopad(&self, iv: &[u8], data: &mut [u8]) {
711        assert_eq!(iv.len(), C::BLOCK_LEN, "wrong IV length");
712        assert_block_multiple::<C>(data);
713
714        let mut feedback = iv.to_vec();
715        let mut keystream = feedback.clone();
716
717        for block in data.chunks_exact_mut(C::BLOCK_LEN) {
718            keystream.copy_from_slice(&feedback);
719            self.cipher.encrypt(&mut keystream);
720            xor_in_place(block, &keystream);
721            feedback.copy_from_slice(block);
722        }
723    }
724
725    /// # Panics
726    ///
727    /// Panics if `iv.len()` does not match the block size, or if `data.len()`
728    /// is not an exact multiple of the block size.
729    pub fn decrypt_nopad(&self, iv: &[u8], data: &mut [u8]) {
730        assert_eq!(iv.len(), C::BLOCK_LEN, "wrong IV length");
731        assert_block_multiple::<C>(data);
732
733        let mut feedback = iv.to_vec();
734        let mut keystream = feedback.clone();
735        let mut tmp = vec![0u8; C::BLOCK_LEN];
736
737        for block in data.chunks_exact_mut(C::BLOCK_LEN) {
738            tmp.copy_from_slice(block);
739            keystream.copy_from_slice(&feedback);
740            self.cipher.encrypt(&mut keystream);
741            xor_in_place(block, &keystream);
742            feedback.copy_from_slice(&tmp);
743        }
744    }
745}
746
747/// Cipher Feedback (CFB) mode with an 8-bit segment size (CFB8).
748pub struct Cfb8<C> {
749    cipher: C,
750}
751
752impl<C> Cfb8<C> {
753    /// Wrap a block cipher in CFB8 mode.
754    pub fn new(cipher: C) -> Self {
755        Self { cipher }
756    }
757
758    /// Borrow the wrapped block cipher.
759    pub fn cipher(&self) -> &C {
760        &self.cipher
761    }
762}
763
764impl<C: BlockCipher> Cfb8<C> {
765    /// # Panics
766    ///
767    /// Panics if `iv.len()` does not match the block size.
768    pub fn encrypt(&self, iv: &[u8], data: &mut [u8]) {
769        assert_eq!(iv.len(), C::BLOCK_LEN, "wrong IV length");
770        let mut state = iv.to_vec();
771        let mut stream = vec![0u8; C::BLOCK_LEN];
772
773        for byte in data.iter_mut() {
774            stream.copy_from_slice(&state);
775            self.cipher.encrypt(&mut stream);
776            let ct = *byte ^ stream[0];
777            state.rotate_left(1);
778            state[C::BLOCK_LEN - 1] = ct;
779            *byte = ct;
780        }
781    }
782
783    /// # Panics
784    ///
785    /// Panics if `iv.len()` does not match the block size.
786    pub fn decrypt(&self, iv: &[u8], data: &mut [u8]) {
787        assert_eq!(iv.len(), C::BLOCK_LEN, "wrong IV length");
788        let mut state = iv.to_vec();
789        let mut stream = vec![0u8; C::BLOCK_LEN];
790
791        for byte in data.iter_mut() {
792            let ct = *byte;
793            stream.copy_from_slice(&state);
794            self.cipher.encrypt(&mut stream);
795            *byte = ct ^ stream[0];
796            state.rotate_left(1);
797            state[C::BLOCK_LEN - 1] = ct;
798        }
799    }
800}
801
802/// Output Feedback (OFB) mode.
803pub struct Ofb<C> {
804    cipher: C,
805}
806
807impl<C> Ofb<C> {
808    /// Wrap a block cipher in SP 800-38A OFB mode.
809    pub fn new(cipher: C) -> Self {
810        Self { cipher }
811    }
812
813    /// Borrow the wrapped block cipher.
814    pub fn cipher(&self) -> &C {
815        &self.cipher
816    }
817}
818
819impl<C: BlockCipher> Ofb<C> {
820    /// # Panics
821    ///
822    /// Panics if `iv.len()` does not match the block size.
823    pub fn apply_keystream(&self, iv: &[u8], data: &mut [u8]) {
824        assert_eq!(iv.len(), C::BLOCK_LEN, "wrong IV length");
825
826        let mut feedback = iv.to_vec();
827        for chunk in data.chunks_mut(C::BLOCK_LEN) {
828            self.cipher.encrypt(&mut feedback);
829            xor_in_place(chunk, &feedback[..chunk.len()]);
830        }
831    }
832}
833
834/// Counter (CTR) mode with a big-endian incrementing counter block.
835pub struct Ctr<C> {
836    cipher: C,
837}
838
839impl<C> Ctr<C> {
840    /// Wrap a block cipher in SP 800-38A CTR mode.
841    pub fn new(cipher: C) -> Self {
842        Self { cipher }
843    }
844
845    /// Borrow the wrapped block cipher.
846    pub fn cipher(&self) -> &C {
847        &self.cipher
848    }
849}
850
851impl<C: BlockCipher> Ctr<C> {
852    /// # Panics
853    ///
854    /// Panics if `counter.len()` does not match the block size.
855    pub fn apply_keystream(&self, counter: &[u8], data: &mut [u8]) {
856        assert_eq!(counter.len(), C::BLOCK_LEN, "wrong counter length");
857
858        let mut ctr = counter.to_vec();
859        let mut stream = ctr.clone();
860
861        for chunk in data.chunks_mut(C::BLOCK_LEN) {
862            stream.copy_from_slice(&ctr);
863            self.cipher.encrypt(&mut stream);
864            xor_in_place(chunk, &stream[..chunk.len()]);
865            increment_be(&mut ctr);
866        }
867    }
868}
869
870/// XEX-based Tweaked `CodeBook` mode with ciphertext Stealing (XTS).
871///
872/// This implementation supports 128-bit block ciphers, which is the case
873/// covered by SP 800-38E / XTS-AES.
874pub struct Xts<C> {
875    data_cipher: C,
876    tweak_cipher: C,
877}
878
879impl<C> Xts<C> {
880    /// Wrap a pair of block ciphers in SP 800-38E XTS mode.
881    ///
882    /// `data_cipher` encrypts the sector payload blocks. `tweak_cipher`
883    /// derives the per-sector tweak stream from the caller-supplied tweak.
884    pub fn new(data_cipher: C, tweak_cipher: C) -> Self {
885        Self {
886            data_cipher,
887            tweak_cipher,
888        }
889    }
890
891    /// Borrow the data-encryption cipher.
892    pub fn data_cipher(&self) -> &C {
893        &self.data_cipher
894    }
895
896    /// Borrow the tweak-derivation cipher.
897    pub fn tweak_cipher(&self) -> &C {
898        &self.tweak_cipher
899    }
900}
901
902impl<C: BlockCipher> Xts<C> {
903    /// # Panics
904    ///
905    /// Panics if the wrapped cipher does not have a 128-bit block size, or if
906    /// `data` is shorter than one complete block.
907    pub fn encrypt_sector(&self, tweak_value: &[u8; 16], data: &mut [u8]) {
908        assert_block_128::<C>();
909        assert!(
910            data.len() >= 16,
911            "XTS requires at least one complete block in each data unit"
912        );
913
914        let full_blocks = data.len() / 16;
915        let rem = data.len() % 16;
916
917        let mut tweak = *tweak_value;
918        self.tweak_cipher.encrypt(&mut tweak);
919
920        if rem == 0 {
921            for block in data.chunks_exact_mut(16) {
922                let mut tmp = [0u8; 16];
923                tmp.copy_from_slice(block);
924                xex_encrypt_block(&self.data_cipher, &tweak, &mut tmp);
925                block.copy_from_slice(&tmp);
926                gf_mul_x_xts(&mut tweak);
927            }
928            return;
929        }
930
931        for block in data[..(full_blocks - 1) * 16].chunks_exact_mut(16) {
932            let mut tmp = [0u8; 16];
933            tmp.copy_from_slice(block);
934            xex_encrypt_block(&self.data_cipher, &tweak, &mut tmp);
935            block.copy_from_slice(&tmp);
936            gf_mul_x_xts(&mut tweak);
937        }
938
939        let last_full_start = (full_blocks - 1) * 16;
940        let mut cc = [0u8; 16];
941        cc.copy_from_slice(&data[last_full_start..last_full_start + 16]);
942        xex_encrypt_block(&self.data_cipher, &tweak, &mut cc);
943
944        let mut pp = [0u8; 16];
945        pp[..rem].copy_from_slice(&data[last_full_start + 16..]);
946        pp[rem..].copy_from_slice(&cc[rem..]);
947        data[last_full_start + 16..].copy_from_slice(&cc[..rem]);
948
949        let mut next_tweak = tweak;
950        gf_mul_x_xts(&mut next_tweak);
951        xex_encrypt_block(&self.data_cipher, &next_tweak, &mut pp);
952        data[last_full_start..last_full_start + 16].copy_from_slice(&pp);
953    }
954
955    /// # Panics
956    ///
957    /// Panics if the wrapped cipher does not have a 128-bit block size, or if
958    /// `data` is shorter than one complete block.
959    pub fn decrypt_sector(&self, tweak_value: &[u8; 16], data: &mut [u8]) {
960        assert_block_128::<C>();
961        assert!(
962            data.len() >= 16,
963            "XTS requires at least one complete block in each data unit"
964        );
965
966        let full_blocks = data.len() / 16;
967        let rem = data.len() % 16;
968
969        let mut tweak = *tweak_value;
970        self.tweak_cipher.encrypt(&mut tweak);
971
972        if rem == 0 {
973            for block in data.chunks_exact_mut(16) {
974                let mut tmp = [0u8; 16];
975                tmp.copy_from_slice(block);
976                xex_decrypt_block(&self.data_cipher, &tweak, &mut tmp);
977                block.copy_from_slice(&tmp);
978                gf_mul_x_xts(&mut tweak);
979            }
980            return;
981        }
982
983        for block in data[..(full_blocks - 1) * 16].chunks_exact_mut(16) {
984            let mut tmp = [0u8; 16];
985            tmp.copy_from_slice(block);
986            xex_decrypt_block(&self.data_cipher, &tweak, &mut tmp);
987            block.copy_from_slice(&tmp);
988            gf_mul_x_xts(&mut tweak);
989        }
990
991        let last_full_start = (full_blocks - 1) * 16;
992        let mut next_tweak = tweak;
993        gf_mul_x_xts(&mut next_tweak);
994
995        let mut pp = [0u8; 16];
996        pp.copy_from_slice(&data[last_full_start..last_full_start + 16]);
997        xex_decrypt_block(&self.data_cipher, &next_tweak, &mut pp);
998
999        let mut cc = [0u8; 16];
1000        cc[..rem].copy_from_slice(&data[last_full_start + 16..]);
1001        cc[rem..].copy_from_slice(&pp[rem..]);
1002
1003        let mut last_full = cc;
1004        xex_decrypt_block(&self.data_cipher, &tweak, &mut last_full);
1005
1006        data[last_full_start..last_full_start + 16].copy_from_slice(&last_full);
1007        data[last_full_start + 16..].copy_from_slice(&pp[..rem]);
1008    }
1009}
1010
1011/// Cipher-based Message Authentication Code (CMAC).
1012pub struct Cmac<C> {
1013    cipher: C,
1014}
1015
1016impl<C> Cmac<C> {
1017    /// Wrap a block cipher in SP 800-38B CMAC mode.
1018    pub fn new(cipher: C) -> Self {
1019        Self { cipher }
1020    }
1021
1022    /// Borrow the wrapped block cipher.
1023    pub fn cipher(&self) -> &C {
1024        &self.cipher
1025    }
1026}
1027
1028/// Counter with CBC-MAC (CCM) with compile-time detached tag length.
1029///
1030/// `TAG_LEN` must be one of RFC 3610's valid lengths:
1031/// `{4, 6, 8, 10, 12, 14, 16}`.
1032pub struct Ccm<C, const TAG_LEN: usize = 16> {
1033    cipher: C,
1034}
1035
1036impl<C, const TAG_LEN: usize> Ccm<C, TAG_LEN> {
1037    /// Wrap a 128-bit block cipher in SP 800-38C CCM mode.
1038    pub fn new(cipher: C) -> Self {
1039        assert_ccm_tag_len(TAG_LEN);
1040        Self { cipher }
1041    }
1042
1043    /// Borrow the wrapped block cipher.
1044    pub fn cipher(&self) -> &C {
1045        &self.cipher
1046    }
1047
1048    /// Return the detached authentication tag length in bytes.
1049    pub fn tag_len(&self) -> usize {
1050        TAG_LEN
1051    }
1052}
1053
1054impl<C: BlockCipher, const TAG_LEN: usize> Ccm<C, TAG_LEN> {
1055    /// Compute a detached CCM tag over `plaintext` and associated data.
1056    #[must_use]
1057    pub fn compute_tag(&self, nonce: &[u8], aad: &[u8], plaintext: &[u8]) -> [u8; TAG_LEN] {
1058        let t = ccm_cbc_mac(&self.cipher, nonce, aad, plaintext, TAG_LEN);
1059        let s0 = counter_keystream(&self.cipher, &ccm_counter_block(nonce, 0));
1060        let mut tag = [0u8; TAG_LEN];
1061        for i in 0..TAG_LEN {
1062            tag[i] = t[i] ^ s0[i];
1063        }
1064        tag
1065    }
1066
1067    /// Encrypt `data` in place and return the detached CCM authentication tag.
1068    #[must_use]
1069    pub fn encrypt(&self, nonce: &[u8], aad: &[u8], data: &mut [u8]) -> [u8; TAG_LEN] {
1070        assert_block_128::<C>();
1071        let tag = self.compute_tag(nonce, aad, data);
1072        ccm_apply_ctr(&self.cipher, nonce, data);
1073        tag
1074    }
1075
1076    /// Verify `tag` and decrypt in place on success.
1077    ///
1078    /// Returns `false` and leaves `data` unchanged when verification fails.
1079    pub fn decrypt(&self, nonce: &[u8], aad: &[u8], data: &mut [u8], tag: &[u8; TAG_LEN]) -> bool {
1080        assert_block_128::<C>();
1081
1082        // In CCM, authentication is over plaintext, so decrypt to a temporary
1083        // buffer first and only commit if tag verification succeeds.
1084        let mut plaintext = data.to_vec();
1085        ccm_apply_ctr(&self.cipher, nonce, &mut plaintext);
1086
1087        let expected = self.compute_tag(nonce, aad, &plaintext);
1088        if crate::ct::constant_time_eq_mask(&expected, tag) != u8::MAX {
1089            // Zeroize the decrypted buffer before dropping: CCM must decrypt
1090            // before authenticating (MAC is over plaintext), so on auth failure
1091            // the plaintext briefly exists on the heap and must be wiped.
1092            crate::ct::zeroize_slice(&mut plaintext);
1093            return false;
1094        }
1095
1096        data.copy_from_slice(&plaintext);
1097        true
1098    }
1099}
1100
1101/// Galois/Counter Mode (GCM) with a full 128-bit authentication tag.
1102///
1103/// Per NIST SP 800-38D, this implementation enforces a per-call payload limit
1104/// of `(2^32 - 2)` counter blocks (`68_719_476_704` bytes) so the 32-bit
1105/// counter field cannot wrap.
1106///
1107/// Callers must still ensure nonce uniqueness per key; this API is stateless and
1108/// cannot enforce global `(key, nonce)` uniqueness.
1109///
1110/// # Examples
1111///
1112/// ```rust
1113/// use cryptography::{Aes256, Gcm};
1114///
1115/// let key = [0x11u8; 32];
1116/// let nonce = [0x22u8; 12];
1117/// let aad = b"hdr";
1118/// let mut ciphertext = *b"payload";
1119///
1120/// let aead = Gcm::new(Aes256::new(&key));
1121/// let tag = aead.encrypt(&nonce, aad, &mut ciphertext);
1122///
1123/// let mut recovered = ciphertext;
1124/// assert!(aead.decrypt(&nonce, aad, &mut recovered, &tag));
1125/// assert_eq!(recovered, *b"payload");
1126/// ```
1127pub struct Gcm<C> {
1128    cipher: C,
1129}
1130
1131/// Variable-time Galois/Counter Mode (GCM) reference path.
1132///
1133/// This keeps the historical GHASH implementation for comparison and legacy
1134/// profiling. Use [`Gcm`] for the default constant-time software GHASH path.
1135///
1136/// It enforces the same SP 800-38D payload bound as [`Gcm`]:
1137/// `(2^32 - 2)` counter blocks (`68_719_476_704` bytes) per call.
1138pub struct GcmVt<C> {
1139    cipher: C,
1140}
1141
1142impl<C> Gcm<C> {
1143    /// Wrap a 128-bit block cipher in SP 800-38D GCM mode.
1144    pub fn new(cipher: C) -> Self {
1145        Self { cipher }
1146    }
1147
1148    /// Borrow the wrapped block cipher.
1149    pub fn cipher(&self) -> &C {
1150        &self.cipher
1151    }
1152}
1153
1154impl<C> GcmVt<C> {
1155    /// Wrap a 128-bit block cipher in variable-time SP 800-38D GCM mode.
1156    pub fn new(cipher: C) -> Self {
1157        Self { cipher }
1158    }
1159
1160    /// Borrow the wrapped block cipher.
1161    pub fn cipher(&self) -> &C {
1162        &self.cipher
1163    }
1164}
1165
1166impl<C: BlockCipher> Gcm<C> {
1167    /// Compute the GCM authentication tag over `aad` and `ciphertext`.
1168    ///
1169    /// Panics if `ciphertext.len()` exceeds the SP 800-38D per-call bound of
1170    /// `68_719_476_704` bytes.
1171    #[must_use]
1172    pub fn compute_tag(&self, nonce: &[u8], aad: &[u8], ciphertext: &[u8]) -> [u8; 16] {
1173        gcm_compute_tag(&self.cipher, nonce, aad, ciphertext, ghash_mul_ct)
1174    }
1175
1176    /// Encrypt in place and return the 128-bit authentication tag.
1177    ///
1178    /// Panics if `data.len()` exceeds the SP 800-38D per-call bound of
1179    /// `68_719_476_704` bytes.
1180    #[must_use]
1181    pub fn encrypt(&self, nonce: &[u8], aad: &[u8], data: &mut [u8]) -> [u8; 16] {
1182        assert_block_128::<C>();
1183        assert_gcm_payload_len(data.len());
1184        let mut h = [0u8; 16];
1185        self.cipher.encrypt(&mut h);
1186        let h = u128::from_be_bytes(h);
1187        let j0 = ghash_iv(h, nonce, ghash_mul_ct);
1188        let mut counter = j0;
1189        increment_be32(&mut counter);
1190
1191        for chunk in data.chunks_mut(16) {
1192            let stream = counter_keystream(&self.cipher, &counter);
1193            xor_in_place(chunk, &stream[..chunk.len()]);
1194            increment_be32(&mut counter);
1195        }
1196
1197        let s = ghash(h, aad, data, ghash_mul_ct);
1198        let tag_mask = u128::from_be_bytes(counter_keystream(&self.cipher, &j0));
1199        (s ^ tag_mask).to_be_bytes()
1200    }
1201
1202    /// Verify the tag and, if valid, decrypt in place.
1203    ///
1204    /// Returns `false` and leaves `data` unchanged if tag verification fails.
1205    ///
1206    /// Panics if `data.len()` exceeds the SP 800-38D per-call bound of
1207    /// `68_719_476_704` bytes.
1208    pub fn decrypt(&self, nonce: &[u8], aad: &[u8], data: &mut [u8], tag: &[u8]) -> bool {
1209        assert_block_128::<C>();
1210        assert_gcm_payload_len(data.len());
1211        let h = gcm_hash_subkey(&self.cipher);
1212        let expected = gcm_compute_tag_with_h(&self.cipher, h, nonce, aad, data, ghash_mul_ct);
1213        if crate::ct::constant_time_eq_mask(&expected, tag) != u8::MAX {
1214            return false;
1215        }
1216        let j0 = ghash_iv(h, nonce, ghash_mul_ct);
1217        let mut counter = j0;
1218        increment_be32(&mut counter);
1219
1220        for chunk in data.chunks_mut(16) {
1221            let stream = counter_keystream(&self.cipher, &counter);
1222            xor_in_place(chunk, &stream[..chunk.len()]);
1223            increment_be32(&mut counter);
1224        }
1225
1226        true
1227    }
1228}
1229
1230impl<C: BlockCipher> GcmVt<C> {
1231    /// Compute the GCM authentication tag over `aad` and `ciphertext`.
1232    ///
1233    /// Panics if `ciphertext.len()` exceeds the SP 800-38D per-call bound of
1234    /// `68_719_476_704` bytes.
1235    #[must_use]
1236    pub fn compute_tag(&self, nonce: &[u8], aad: &[u8], ciphertext: &[u8]) -> [u8; 16] {
1237        gcm_compute_tag(&self.cipher, nonce, aad, ciphertext, ghash_mul_vt)
1238    }
1239
1240    /// Encrypt in place and return the 128-bit authentication tag.
1241    ///
1242    /// Panics if `data.len()` exceeds the SP 800-38D per-call bound of
1243    /// `68_719_476_704` bytes.
1244    #[must_use]
1245    pub fn encrypt(&self, nonce: &[u8], aad: &[u8], data: &mut [u8]) -> [u8; 16] {
1246        assert_block_128::<C>();
1247        assert_gcm_payload_len(data.len());
1248        let mut h = [0u8; 16];
1249        self.cipher.encrypt(&mut h);
1250        let h = u128::from_be_bytes(h);
1251        let j0 = ghash_iv(h, nonce, ghash_mul_vt);
1252        let mut counter = j0;
1253        increment_be32(&mut counter);
1254
1255        for chunk in data.chunks_mut(16) {
1256            let stream = counter_keystream(&self.cipher, &counter);
1257            xor_in_place(chunk, &stream[..chunk.len()]);
1258            increment_be32(&mut counter);
1259        }
1260
1261        let s = ghash(h, aad, data, ghash_mul_vt);
1262        let tag_mask = u128::from_be_bytes(counter_keystream(&self.cipher, &j0));
1263        (s ^ tag_mask).to_be_bytes()
1264    }
1265
1266    /// Verify the tag and, if valid, decrypt in place.
1267    ///
1268    /// Returns `false` and leaves `data` unchanged if tag verification fails.
1269    ///
1270    /// Panics if `data.len()` exceeds the SP 800-38D per-call bound of
1271    /// `68_719_476_704` bytes.
1272    pub fn decrypt(&self, nonce: &[u8], aad: &[u8], data: &mut [u8], tag: &[u8]) -> bool {
1273        assert_block_128::<C>();
1274        assert_gcm_payload_len(data.len());
1275        let h = gcm_hash_subkey(&self.cipher);
1276        let expected = gcm_compute_tag_with_h(&self.cipher, h, nonce, aad, data, ghash_mul_vt);
1277        if crate::ct::constant_time_eq_mask(&expected, tag) != u8::MAX {
1278            return false;
1279        }
1280        let j0 = ghash_iv(h, nonce, ghash_mul_vt);
1281        let mut counter = j0;
1282        increment_be32(&mut counter);
1283
1284        for chunk in data.chunks_mut(16) {
1285            let stream = counter_keystream(&self.cipher, &counter);
1286            xor_in_place(chunk, &stream[..chunk.len()]);
1287            increment_be32(&mut counter);
1288        }
1289
1290        true
1291    }
1292}
1293
1294/// Galois Message Authentication Code (GMAC).
1295pub struct Gmac<C> {
1296    cipher: C,
1297}
1298
1299/// Variable-time Galois Message Authentication Code (GMAC) reference path.
1300///
1301/// This keeps the historical variable-time GHASH backend for comparison.
1302/// Use [`Gmac`] for the constant-time default.
1303pub struct GmacVt<C> {
1304    cipher: C,
1305}
1306
1307impl<C> Gmac<C> {
1308    /// Wrap a 128-bit block cipher in SP 800-38D GMAC mode.
1309    pub fn new(cipher: C) -> Self {
1310        Self { cipher }
1311    }
1312
1313    /// Borrow the wrapped block cipher.
1314    pub fn cipher(&self) -> &C {
1315        &self.cipher
1316    }
1317}
1318
1319impl<C> GmacVt<C> {
1320    /// Wrap a 128-bit block cipher in variable-time SP 800-38D GMAC mode.
1321    pub fn new(cipher: C) -> Self {
1322        Self { cipher }
1323    }
1324
1325    /// Borrow the wrapped block cipher.
1326    pub fn cipher(&self) -> &C {
1327        &self.cipher
1328    }
1329}
1330
1331impl<C: BlockCipher> Gmac<C> {
1332    /// Compute a GMAC tag over associated data only.
1333    #[must_use]
1334    pub fn compute(&self, nonce: &[u8], aad: &[u8]) -> [u8; 16] {
1335        gcm_compute_tag(&self.cipher, nonce, aad, &[], ghash_mul_ct)
1336    }
1337
1338    /// Verify a GMAC tag in constant time.
1339    pub fn verify(&self, nonce: &[u8], aad: &[u8], tag: &[u8]) -> bool {
1340        crate::ct::constant_time_eq_mask(&self.compute(nonce, aad), tag) == u8::MAX
1341    }
1342}
1343
1344impl<C: BlockCipher> GmacVt<C> {
1345    /// Compute a GMAC tag over associated data only.
1346    #[must_use]
1347    pub fn compute(&self, nonce: &[u8], aad: &[u8]) -> [u8; 16] {
1348        gcm_compute_tag(&self.cipher, nonce, aad, &[], ghash_mul_vt)
1349    }
1350
1351    /// Verify a GMAC tag in constant time.
1352    pub fn verify(&self, nonce: &[u8], aad: &[u8], tag: &[u8]) -> bool {
1353        crate::ct::constant_time_eq_mask(&self.compute(nonce, aad), tag) == u8::MAX
1354    }
1355}
1356
1357impl<C: BlockCipher> Cmac<C> {
1358    /// Compute a CMAC tag over arbitrary-length input.
1359    pub fn compute(&self, data: &[u8]) -> Vec<u8> {
1360        let blk = C::BLOCK_LEN;
1361        let mut l = vec![0u8; blk];
1362        self.cipher.encrypt(&mut l);
1363        let k1 = dbl(&l);
1364        let k2 = dbl(&k1);
1365
1366        let n = if data.is_empty() {
1367            1
1368        } else {
1369            data.len().div_ceil(blk)
1370        };
1371        let last_complete = !data.is_empty() && data.len().is_multiple_of(blk);
1372
1373        let mut x = vec![0u8; blk];
1374        let mut y = vec![0u8; blk];
1375
1376        for block in data.chunks(blk).take(n.saturating_sub(1)) {
1377            y.copy_from_slice(&x);
1378            xor_in_place(&mut y, block);
1379            self.cipher.encrypt(&mut y);
1380            x.copy_from_slice(&y);
1381        }
1382
1383        let mut m_last = vec![0u8; blk];
1384        if last_complete {
1385            let start = (n - 1) * blk;
1386            m_last.copy_from_slice(&data[start..start + blk]);
1387            xor_in_place(&mut m_last, &k1);
1388        } else {
1389            let start = (n - 1) * blk;
1390            let rem = data.len().saturating_sub(start);
1391            if rem != 0 {
1392                m_last[..rem].copy_from_slice(&data[start..]);
1393            }
1394            m_last[rem] = 0x80;
1395            xor_in_place(&mut m_last, &k2);
1396        }
1397
1398        xor_in_place(&mut m_last, &x);
1399        self.cipher.encrypt(&mut m_last);
1400        m_last
1401    }
1402
1403    /// Verify a CMAC tag in constant time.
1404    pub fn verify(&self, data: &[u8], tag: &[u8]) -> bool {
1405        crate::ct::constant_time_eq_mask(&self.compute(data), tag) == u8::MAX
1406    }
1407}
1408
1409#[cfg(test)]
1410mod tests {
1411    use super::*;
1412    use crate::{Aes128, Aes192, Aes256};
1413
1414    fn parse<const N: usize>(s: &str) -> [u8; N] {
1415        let mut out = [0u8; N];
1416        assert_eq!(s.len(), 2 * N);
1417        for i in 0..N {
1418            out[i] = u8::from_str_radix(&s[2 * i..2 * i + 2], 16).unwrap();
1419        }
1420        out
1421    }
1422
1423    fn parse_vec(s: &str) -> Vec<u8> {
1424        assert_eq!(s.len() % 2, 0);
1425        let mut out = Vec::with_capacity(s.len() / 2);
1426        let bytes = s.as_bytes();
1427        let mut i = 0usize;
1428        while i + 1 < bytes.len() {
1429            let hi =
1430                u8::from_str_radix(std::str::from_utf8(&bytes[i..i + 1]).unwrap(), 16).unwrap();
1431            let lo =
1432                u8::from_str_radix(std::str::from_utf8(&bytes[i + 1..i + 2]).unwrap(), 16).unwrap();
1433            out.push((hi << 4) | lo);
1434            i += 2;
1435        }
1436        out
1437    }
1438
1439    #[test]
1440    fn ecb_aes128_sp800_38a() {
1441        let key = parse::<16>("2b7e151628aed2a6abf7158809cf4f3c");
1442        let mut data = [
1443            parse::<16>("6bc1bee22e409f96e93d7e117393172a"),
1444            parse::<16>("ae2d8a571e03ac9c9eb76fac45af8e51"),
1445            parse::<16>("30c81c46a35ce411e5fbc1191a0a52ef"),
1446            parse::<16>("f69f2445df4f9b17ad2b417be66c3710"),
1447        ]
1448        .concat();
1449        let expected = [
1450            parse::<16>("3ad77bb40d7a3660a89ecaf32466ef97"),
1451            parse::<16>("f5d3d58503b9699de785895a96fdbaaf"),
1452            parse::<16>("43b1cd7f598ece23881b00e3ed030688"),
1453            parse::<16>("7b0c785e27e8ad3f8223207104725dd4"),
1454        ]
1455        .concat();
1456
1457        Ecb::new(Aes128::new(&key)).encrypt_nopad(&mut data);
1458        assert_eq!(data, expected);
1459        Ecb::new(Aes128::new(&key)).decrypt_nopad(&mut data);
1460        assert_eq!(
1461            data,
1462            [
1463                parse::<16>("6bc1bee22e409f96e93d7e117393172a"),
1464                parse::<16>("ae2d8a571e03ac9c9eb76fac45af8e51"),
1465                parse::<16>("30c81c46a35ce411e5fbc1191a0a52ef"),
1466                parse::<16>("f69f2445df4f9b17ad2b417be66c3710"),
1467            ]
1468            .concat()
1469        );
1470    }
1471
1472    #[test]
1473    fn ecb_aes256_sp800_38a() {
1474        // NIST SP 800-38A, F.1.5 ECB-AES256.
1475        let key = parse::<32>("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4");
1476        let mut data = [
1477            parse::<16>("6bc1bee22e409f96e93d7e117393172a"),
1478            parse::<16>("ae2d8a571e03ac9c9eb76fac45af8e51"),
1479            parse::<16>("30c81c46a35ce411e5fbc1191a0a52ef"),
1480            parse::<16>("f69f2445df4f9b17ad2b417be66c3710"),
1481        ]
1482        .concat();
1483        let expected = [
1484            parse::<16>("f3eed1bdb5d2a03c064b5a7e3db181f8"),
1485            parse::<16>("591ccb10d410ed26dc5ba74a31362870"),
1486            parse::<16>("b6ed21b99ca6f4f9f153e7b1beafed1d"),
1487            parse::<16>("23304b7a39f9f3ff067d8d8f9e24ecc7"),
1488        ]
1489        .concat();
1490
1491        Ecb::new(Aes256::new(&key)).encrypt_nopad(&mut data);
1492        assert_eq!(data, expected);
1493        Ecb::new(Aes256::new(&key)).decrypt_nopad(&mut data);
1494        assert_eq!(
1495            data,
1496            [
1497                parse::<16>("6bc1bee22e409f96e93d7e117393172a"),
1498                parse::<16>("ae2d8a571e03ac9c9eb76fac45af8e51"),
1499                parse::<16>("30c81c46a35ce411e5fbc1191a0a52ef"),
1500                parse::<16>("f69f2445df4f9b17ad2b417be66c3710"),
1501            ]
1502            .concat()
1503        );
1504    }
1505
1506    #[test]
1507    fn cbc_aes128_sp800_38a() {
1508        let key = parse::<16>("2b7e151628aed2a6abf7158809cf4f3c");
1509        let iv = parse::<16>("000102030405060708090a0b0c0d0e0f");
1510        let mut data = [
1511            parse::<16>("6bc1bee22e409f96e93d7e117393172a"),
1512            parse::<16>("ae2d8a571e03ac9c9eb76fac45af8e51"),
1513            parse::<16>("30c81c46a35ce411e5fbc1191a0a52ef"),
1514            parse::<16>("f69f2445df4f9b17ad2b417be66c3710"),
1515        ]
1516        .concat();
1517        let expected = [
1518            parse::<16>("7649abac8119b246cee98e9b12e9197d"),
1519            parse::<16>("5086cb9b507219ee95db113a917678b2"),
1520            parse::<16>("73bed6b8e3c1743b7116e69e22229516"),
1521            parse::<16>("3ff1caa1681fac09120eca307586e1a7"),
1522        ]
1523        .concat();
1524
1525        let mode = Cbc::new(Aes128::new(&key));
1526        mode.encrypt_nopad(&iv, &mut data);
1527        assert_eq!(data, expected);
1528        mode.decrypt_nopad(&iv, &mut data);
1529        assert_eq!(
1530            data,
1531            [
1532                parse::<16>("6bc1bee22e409f96e93d7e117393172a"),
1533                parse::<16>("ae2d8a571e03ac9c9eb76fac45af8e51"),
1534                parse::<16>("30c81c46a35ce411e5fbc1191a0a52ef"),
1535                parse::<16>("f69f2445df4f9b17ad2b417be66c3710"),
1536            ]
1537            .concat()
1538        );
1539    }
1540
1541    #[test]
1542    fn cbc_aes256_sp800_38a() {
1543        // NIST SP 800-38A, F.2.5 CBC-AES256.
1544        let key = parse::<32>("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4");
1545        let iv = parse::<16>("000102030405060708090a0b0c0d0e0f");
1546        let mut data = [
1547            parse::<16>("6bc1bee22e409f96e93d7e117393172a"),
1548            parse::<16>("ae2d8a571e03ac9c9eb76fac45af8e51"),
1549            parse::<16>("30c81c46a35ce411e5fbc1191a0a52ef"),
1550            parse::<16>("f69f2445df4f9b17ad2b417be66c3710"),
1551        ]
1552        .concat();
1553        let expected = [
1554            parse::<16>("f58c4c04d6e5f1ba779eabfb5f7bfbd6"),
1555            parse::<16>("9cfc4e967edb808d679f777bc6702c7d"),
1556            parse::<16>("39f23369a9d9bacfa530e26304231461"),
1557            parse::<16>("b2eb05e2c39be9fcda6c19078c6a9d1b"),
1558        ]
1559        .concat();
1560
1561        let mode = Cbc::new(Aes256::new(&key));
1562        mode.encrypt_nopad(&iv, &mut data);
1563        assert_eq!(data, expected);
1564        mode.decrypt_nopad(&iv, &mut data);
1565        assert_eq!(
1566            data,
1567            [
1568                parse::<16>("6bc1bee22e409f96e93d7e117393172a"),
1569                parse::<16>("ae2d8a571e03ac9c9eb76fac45af8e51"),
1570                parse::<16>("30c81c46a35ce411e5fbc1191a0a52ef"),
1571                parse::<16>("f69f2445df4f9b17ad2b417be66c3710"),
1572            ]
1573            .concat()
1574        );
1575    }
1576
1577    #[test]
1578    fn cfb_aes128_sp800_38a() {
1579        let key = parse::<16>("2b7e151628aed2a6abf7158809cf4f3c");
1580        let iv = parse::<16>("000102030405060708090a0b0c0d0e0f");
1581        let mut data = [
1582            parse::<16>("6bc1bee22e409f96e93d7e117393172a"),
1583            parse::<16>("ae2d8a571e03ac9c9eb76fac45af8e51"),
1584            parse::<16>("30c81c46a35ce411e5fbc1191a0a52ef"),
1585            parse::<16>("f69f2445df4f9b17ad2b417be66c3710"),
1586        ]
1587        .concat();
1588        let expected = [
1589            parse::<16>("3b3fd92eb72dad20333449f8e83cfb4a"),
1590            parse::<16>("c8a64537a0b3a93fcde3cdad9f1ce58b"),
1591            parse::<16>("26751f67a3cbb140b1808cf187a4f4df"),
1592            parse::<16>("c04b05357c5d1c0eeac4c66f9ff7f2e6"),
1593        ]
1594        .concat();
1595
1596        let mode = Cfb::new(Aes128::new(&key));
1597        mode.encrypt_nopad(&iv, &mut data);
1598        assert_eq!(data, expected);
1599        mode.decrypt_nopad(&iv, &mut data);
1600        assert_eq!(
1601            data,
1602            [
1603                parse::<16>("6bc1bee22e409f96e93d7e117393172a"),
1604                parse::<16>("ae2d8a571e03ac9c9eb76fac45af8e51"),
1605                parse::<16>("30c81c46a35ce411e5fbc1191a0a52ef"),
1606                parse::<16>("f69f2445df4f9b17ad2b417be66c3710"),
1607            ]
1608            .concat()
1609        );
1610    }
1611
1612    #[test]
1613    fn cfb_aes256_sp800_38a() {
1614        // NIST SP 800-38A, F.3.15 CFB128-AES256.
1615        let key = parse::<32>("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4");
1616        let iv = parse::<16>("000102030405060708090a0b0c0d0e0f");
1617        let mut data = [
1618            parse::<16>("6bc1bee22e409f96e93d7e117393172a"),
1619            parse::<16>("ae2d8a571e03ac9c9eb76fac45af8e51"),
1620            parse::<16>("30c81c46a35ce411e5fbc1191a0a52ef"),
1621            parse::<16>("f69f2445df4f9b17ad2b417be66c3710"),
1622        ]
1623        .concat();
1624        let expected = [
1625            parse::<16>("dc7e84bfda79164b7ecd8486985d3860"),
1626            parse::<16>("39ffed143b28b1c832113c6331e5407b"),
1627            parse::<16>("df10132415e54b92a13ed0a8267ae2f9"),
1628            parse::<16>("75a385741ab9cef82031623d55b1e471"),
1629        ]
1630        .concat();
1631
1632        let mode = Cfb::new(Aes256::new(&key));
1633        mode.encrypt_nopad(&iv, &mut data);
1634        assert_eq!(data, expected);
1635        mode.decrypt_nopad(&iv, &mut data);
1636        assert_eq!(
1637            data,
1638            [
1639                parse::<16>("6bc1bee22e409f96e93d7e117393172a"),
1640                parse::<16>("ae2d8a571e03ac9c9eb76fac45af8e51"),
1641                parse::<16>("30c81c46a35ce411e5fbc1191a0a52ef"),
1642                parse::<16>("f69f2445df4f9b17ad2b417be66c3710"),
1643            ]
1644            .concat()
1645        );
1646    }
1647
1648    #[test]
1649    fn cfb8_aes128_roundtrip() {
1650        let key = parse::<16>("2b7e151628aed2a6abf7158809cf4f3c");
1651        let iv = parse::<16>("000102030405060708090a0b0c0d0e0f");
1652        let plaintext = *b"cfb8 mode roundtrip check";
1653        let mut data = plaintext;
1654
1655        let mode = Cfb8::new(Aes128::new(&key));
1656        mode.encrypt(&iv, &mut data);
1657        assert_ne!(data, plaintext);
1658        mode.decrypt(&iv, &mut data);
1659        assert_eq!(data, plaintext);
1660    }
1661
1662    #[test]
1663    fn cfb8_aes128_sp800_38a_prefix_vector() {
1664        // NIST SP 800-38A, F.3.7 (first 18 CFB8 segments).
1665        let key = parse::<16>("2b7e151628aed2a6abf7158809cf4f3c");
1666        let iv = parse::<16>("000102030405060708090a0b0c0d0e0f");
1667        let mut data = parse_vec("6bc1bee22e409f96e93d7e117393172aae2d");
1668        let expected = parse_vec("3b79424c9c0dd436bace9e0ed4586a4f32b9");
1669
1670        let mode = Cfb8::new(Aes128::new(&key));
1671        mode.encrypt(&iv, &mut data);
1672        assert_eq!(data, expected);
1673        mode.decrypt(&iv, &mut data);
1674        assert_eq!(data, parse_vec("6bc1bee22e409f96e93d7e117393172aae2d"));
1675    }
1676
1677    #[test]
1678    fn ofb_aes128_sp800_38a() {
1679        let key = parse::<16>("2b7e151628aed2a6abf7158809cf4f3c");
1680        let iv = parse::<16>("000102030405060708090a0b0c0d0e0f");
1681        let mut data = [
1682            parse::<16>("6bc1bee22e409f96e93d7e117393172a"),
1683            parse::<16>("ae2d8a571e03ac9c9eb76fac45af8e51"),
1684            parse::<16>("30c81c46a35ce411e5fbc1191a0a52ef"),
1685            parse::<16>("f69f2445df4f9b17ad2b417be66c3710"),
1686        ]
1687        .concat();
1688        let expected = [
1689            parse::<16>("3b3fd92eb72dad20333449f8e83cfb4a"),
1690            parse::<16>("7789508d16918f03f53c52dac54ed825"),
1691            parse::<16>("9740051e9c5fecf64344f7a82260edcc"),
1692            parse::<16>("304c6528f659c77866a510d9c1d6ae5e"),
1693        ]
1694        .concat();
1695
1696        let mode = Ofb::new(Aes128::new(&key));
1697        mode.apply_keystream(&iv, &mut data);
1698        assert_eq!(data, expected);
1699        mode.apply_keystream(&iv, &mut data);
1700        assert_eq!(
1701            data,
1702            [
1703                parse::<16>("6bc1bee22e409f96e93d7e117393172a"),
1704                parse::<16>("ae2d8a571e03ac9c9eb76fac45af8e51"),
1705                parse::<16>("30c81c46a35ce411e5fbc1191a0a52ef"),
1706                parse::<16>("f69f2445df4f9b17ad2b417be66c3710"),
1707            ]
1708            .concat()
1709        );
1710    }
1711
1712    #[test]
1713    fn ofb_aes256_sp800_38a() {
1714        // NIST SP 800-38A, F.4.5 OFB-AES256.
1715        let key = parse::<32>("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4");
1716        let iv = parse::<16>("000102030405060708090a0b0c0d0e0f");
1717        let mut data = [
1718            parse::<16>("6bc1bee22e409f96e93d7e117393172a"),
1719            parse::<16>("ae2d8a571e03ac9c9eb76fac45af8e51"),
1720            parse::<16>("30c81c46a35ce411e5fbc1191a0a52ef"),
1721            parse::<16>("f69f2445df4f9b17ad2b417be66c3710"),
1722        ]
1723        .concat();
1724        let expected = [
1725            parse::<16>("dc7e84bfda79164b7ecd8486985d3860"),
1726            parse::<16>("4febdc6740d20b3ac88f6ad82a4fb08d"),
1727            parse::<16>("71ab47a086e86eedf39d1c5bba97c408"),
1728            parse::<16>("0126141d67f37be8538f5a8be740e484"),
1729        ]
1730        .concat();
1731
1732        let mode = Ofb::new(Aes256::new(&key));
1733        mode.apply_keystream(&iv, &mut data);
1734        assert_eq!(data, expected);
1735        mode.apply_keystream(&iv, &mut data);
1736        assert_eq!(
1737            data,
1738            [
1739                parse::<16>("6bc1bee22e409f96e93d7e117393172a"),
1740                parse::<16>("ae2d8a571e03ac9c9eb76fac45af8e51"),
1741                parse::<16>("30c81c46a35ce411e5fbc1191a0a52ef"),
1742                parse::<16>("f69f2445df4f9b17ad2b417be66c3710"),
1743            ]
1744            .concat()
1745        );
1746    }
1747
1748    #[test]
1749    fn ctr_aes128_sp800_38a() {
1750        let key = parse::<16>("2b7e151628aed2a6abf7158809cf4f3c");
1751        let ctr = parse::<16>("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
1752        let mut data = [
1753            parse::<16>("6bc1bee22e409f96e93d7e117393172a"),
1754            parse::<16>("ae2d8a571e03ac9c9eb76fac45af8e51"),
1755            parse::<16>("30c81c46a35ce411e5fbc1191a0a52ef"),
1756            parse::<16>("f69f2445df4f9b17ad2b417be66c3710"),
1757        ]
1758        .concat();
1759        let expected = [
1760            parse::<16>("874d6191b620e3261bef6864990db6ce"),
1761            parse::<16>("9806f66b7970fdff8617187bb9fffdff"),
1762            parse::<16>("5ae4df3edbd5d35e5b4f09020db03eab"),
1763            parse::<16>("1e031dda2fbe03d1792170a0f3009cee"),
1764        ]
1765        .concat();
1766
1767        let mode = Ctr::new(Aes128::new(&key));
1768        mode.apply_keystream(&ctr, &mut data);
1769        assert_eq!(data, expected);
1770        mode.apply_keystream(&ctr, &mut data);
1771        assert_eq!(
1772            data,
1773            [
1774                parse::<16>("6bc1bee22e409f96e93d7e117393172a"),
1775                parse::<16>("ae2d8a571e03ac9c9eb76fac45af8e51"),
1776                parse::<16>("30c81c46a35ce411e5fbc1191a0a52ef"),
1777                parse::<16>("f69f2445df4f9b17ad2b417be66c3710"),
1778            ]
1779            .concat()
1780        );
1781    }
1782
1783    #[test]
1784    fn ctr_aes256_sp800_38a() {
1785        // NIST SP 800-38A, F.5.5 CTR-AES256.
1786        let key = parse::<32>("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4");
1787        let ctr = parse::<16>("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
1788        let mut data = [
1789            parse::<16>("6bc1bee22e409f96e93d7e117393172a"),
1790            parse::<16>("ae2d8a571e03ac9c9eb76fac45af8e51"),
1791            parse::<16>("30c81c46a35ce411e5fbc1191a0a52ef"),
1792            parse::<16>("f69f2445df4f9b17ad2b417be66c3710"),
1793        ]
1794        .concat();
1795        let expected = [
1796            parse::<16>("601ec313775789a5b7a7f504bbf3d228"),
1797            parse::<16>("f443e3ca4d62b59aca84e990cacaf5c5"),
1798            parse::<16>("2b0930daa23de94ce87017ba2d84988d"),
1799            parse::<16>("dfc9c58db67aada613c2dd08457941a6"),
1800        ]
1801        .concat();
1802
1803        let mode = Ctr::new(Aes256::new(&key));
1804        mode.apply_keystream(&ctr, &mut data);
1805        assert_eq!(data, expected);
1806        mode.apply_keystream(&ctr, &mut data);
1807        assert_eq!(
1808            data,
1809            [
1810                parse::<16>("6bc1bee22e409f96e93d7e117393172a"),
1811                parse::<16>("ae2d8a571e03ac9c9eb76fac45af8e51"),
1812                parse::<16>("30c81c46a35ce411e5fbc1191a0a52ef"),
1813                parse::<16>("f69f2445df4f9b17ad2b417be66c3710"),
1814            ]
1815            .concat()
1816        );
1817    }
1818
1819    #[test]
1820    fn cmac_aes128_sp800_38b() {
1821        let key = parse::<16>("2b7e151628aed2a6abf7158809cf4f3c");
1822        let mode = Cmac::new(Aes128::new(&key));
1823
1824        assert_eq!(
1825            mode.compute(&[]),
1826            parse::<16>("bb1d6929e95937287fa37d129b756746").to_vec()
1827        );
1828        assert_eq!(
1829            mode.compute(&parse::<16>("6bc1bee22e409f96e93d7e117393172a")),
1830            parse::<16>("070a16b46b4d4144f79bdd9dd04a287c").to_vec()
1831        );
1832        let mut msg = Vec::with_capacity(40);
1833        msg.extend_from_slice(&parse::<16>("6bc1bee22e409f96e93d7e117393172a"));
1834        msg.extend_from_slice(&parse::<16>("ae2d8a571e03ac9c9eb76fac45af8e51"));
1835        msg.extend_from_slice(&parse::<8>("30c81c46a35ce411"));
1836        assert_eq!(
1837            mode.compute(&msg),
1838            parse::<16>("dfa66747de9ae63030ca32611497c827").to_vec()
1839        );
1840        assert!(mode.verify(&msg, &parse::<16>("dfa66747de9ae63030ca32611497c827")));
1841    }
1842
1843    #[test]
1844    fn xts_aes128_two_block_matches_openssl() {
1845        let key1 = parse::<16>("000102030405060708090a0b0c0d0e0f");
1846        let key2 = parse::<16>("101112131415161718191a1b1c1d1e1f");
1847        let tweak = [0u8; 16];
1848        let mut data =
1849            parse::<32>("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
1850        let expected =
1851            parse::<32>("74a109aabf1937c022d19da4b96cbc40b8ddc9c0653a7fb0dc8425c7ef276dea");
1852
1853        let mode = Xts::new(Aes128::new(&key1), Aes128::new(&key2));
1854        mode.encrypt_sector(&tweak, &mut data);
1855        assert_eq!(data, expected);
1856        mode.decrypt_sector(&tweak, &mut data);
1857        assert_eq!(
1858            data,
1859            parse::<32>("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f")
1860        );
1861    }
1862
1863    #[test]
1864    fn xts_aes128_ciphertext_stealing_matches_openssl() {
1865        let key1 = parse::<16>("000102030405060708090a0b0c0d0e0f");
1866        let key2 = parse::<16>("101112131415161718191a1b1c1d1e1f");
1867        let tweak = [0u8; 16];
1868        let mut data =
1869            parse::<31>("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e");
1870        let expected =
1871            parse::<31>("03ab02ee0037b6327b1110429d562a8674a109aabf1937c022d19da4b96cbc");
1872
1873        let mode = Xts::new(Aes128::new(&key1), Aes128::new(&key2));
1874        mode.encrypt_sector(&tweak, &mut data);
1875        assert_eq!(data, expected);
1876        mode.decrypt_sector(&tweak, &mut data);
1877        assert_eq!(
1878            data,
1879            parse::<31>("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e")
1880        );
1881    }
1882
1883    #[test]
1884    fn xts_aes128_runtime_cross_check_with_openssl() {
1885        let key1 = parse::<16>("000102030405060708090a0b0c0d0e0f");
1886        let key2 = parse::<16>("101112131415161718191a1b1c1d1e1f");
1887        let tweak = [0u8; 16];
1888        let plaintext =
1889            parse::<31>("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e");
1890
1891        let Some(expected) = crate::test_utils::run_openssl(
1892            &[
1893                "enc",
1894                "-aes-128-xts",
1895                "-e",
1896                "-nopad",
1897                "-K",
1898                "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
1899                "-iv",
1900                "00000000000000000000000000000000",
1901            ],
1902            &plaintext,
1903        ) else {
1904            return;
1905        };
1906
1907        let mut data = plaintext;
1908        let mode = Xts::new(Aes128::new(&key1), Aes128::new(&key2));
1909        mode.encrypt_sector(&tweak, &mut data);
1910        assert_eq!(data.as_slice(), expected.as_slice());
1911    }
1912
1913    #[test]
1914    fn xts_aes128_nist_cavp_vector() {
1915        // NIST CAVP XTSGenAES128.rsp, "format tweak value input - 128 hex str",
1916        // ENCRYPT, COUNT = 1.
1917        let key1 = parse::<16>("a1b90cba3f06ac353b2c343876081762");
1918        let key2 = parse::<16>("090923026e91771815f29dab01932f2f");
1919        let tweak = parse::<16>("4faef7117cda59c66e4b92013e768ad5");
1920        let mut data = parse::<16>("ebabce95b14d3c8d6fb350390790311c");
1921        let expected = parse::<16>("778ae8b43cb98d5a825081d5be471c63");
1922
1923        let mode = Xts::new(Aes128::new(&key1), Aes128::new(&key2));
1924        mode.encrypt_sector(&tweak, &mut data);
1925        assert_eq!(data, expected);
1926        mode.decrypt_sector(&tweak, &mut data);
1927        assert_eq!(data, parse::<16>("ebabce95b14d3c8d6fb350390790311c"));
1928    }
1929
1930    #[test]
1931    fn ctr_des_roundtrip_generic() {
1932        let key = parse::<8>("133457799bbcdff1");
1933        let counter = parse::<8>("0123456789abcdef");
1934        let original = *b"generic DES mode path!";
1935        let mut data = original;
1936
1937        let mode = Ctr::new(crate::Des::new(&key).expect("non-weak DES test key"));
1938        mode.apply_keystream(&counter, &mut data);
1939        assert_ne!(data, original);
1940        mode.apply_keystream(&counter, &mut data);
1941        assert_eq!(data, original);
1942    }
1943
1944    #[test]
1945    fn gcm_aes128_empty_plaintext_nist() {
1946        let key = [0u8; 16];
1947        let iv = [0u8; 12];
1948        let mut data = Vec::new();
1949        let mode = Gcm::new(Aes128::new(&key));
1950
1951        let tag = mode.encrypt(&iv, &[], &mut data);
1952        assert_eq!(data, Vec::<u8>::new());
1953        assert_eq!(tag, parse::<16>("58e2fccefa7e3061367f1d57a4e7455a"));
1954        assert!(mode.decrypt(&iv, &[], &mut data, &tag));
1955    }
1956
1957    #[test]
1958    fn gcm_aes128_single_block_nist() {
1959        let key = [0u8; 16];
1960        let iv = [0u8; 12];
1961        let mut data = [0u8; 16];
1962        let expected_ct = parse::<16>("0388dace60b6a392f328c2b971b2fe78");
1963        let expected_tag = parse::<16>("ab6e47d42cec13bdf53a67b21257bddf");
1964        let mode = Gcm::new(Aes128::new(&key));
1965
1966        let tag = mode.encrypt(&iv, &[], &mut data);
1967        assert_eq!(data, expected_ct);
1968        assert_eq!(tag, expected_tag);
1969        assert!(mode.decrypt(&iv, &[], &mut data, &tag));
1970        assert_eq!(data, [0u8; 16]);
1971    }
1972
1973    #[test]
1974    fn gcm_aes128_with_aad_nist() {
1975        let key = parse::<16>("feffe9928665731c6d6a8f9467308308");
1976        let iv = parse::<12>("cafebabefacedbaddecaf888");
1977        let aad = parse::<20>("feedfacedeadbeeffeedfacedeadbeefabaddad2");
1978        let mut data = parse::<64>(
1979            "d9313225f88406e5a55909c5aff5269a\
1980             86a7a9531534f7da2e4c303d8a318a72\
1981             1c3c0c95956809532fcf0e2449a6b525\
1982             b16aedf5aa0de657ba637b391aafd255",
1983        );
1984        let expected_ct = parse::<64>(
1985            "42831ec2217774244b7221b784d0d49c\
1986             e3aa212f2c02a4e035c17e2329aca12e\
1987             21d514b25466931c7d8f6a5aac84aa05\
1988             1ba30b396a0aac973d58e091473f5985",
1989        );
1990        let expected_tag = parse::<16>("da80ce830cfda02da2a218a1744f4c76");
1991        let mode = Gcm::new(Aes128::new(&key));
1992
1993        let tag = mode.encrypt(&iv, &aad, &mut data);
1994        assert_eq!(data, expected_ct);
1995        assert_eq!(tag, expected_tag);
1996        assert!(mode.decrypt(&iv, &aad, &mut data, &tag));
1997        assert_eq!(
1998            data,
1999            parse::<64>(
2000                "d9313225f88406e5a55909c5aff5269a\
2001                 86a7a9531534f7da2e4c303d8a318a72\
2002                 1c3c0c95956809532fcf0e2449a6b525\
2003                 b16aedf5aa0de657ba637b391aafd255",
2004            )
2005        );
2006    }
2007
2008    #[test]
2009    fn gcm_aes256_single_block_cavp() {
2010        // NIST CAVP gcmEncryptExtIV256.rsp
2011        // [Keylen=256, IVlen=96, PTlen=128, AADlen=0, Taglen=128], Count=0.
2012        let key = parse::<32>("31bdadd96698c204aa9ce1448ea94ae1fb4a9a0b3c9d773b51bb1822666b8f22");
2013        let iv = parse::<12>("0d18e06c7c725ac9e362e1ce");
2014        let mut data = parse::<16>("2db5168e932556f8089a0622981d017d");
2015        let expected_ct = parse::<16>("fa4362189661d163fcd6a56d8bf0405a");
2016        let expected_tag = parse::<16>("d636ac1bbedd5cc3ee727dc2ab4a9489");
2017
2018        let mode = Gcm::new(Aes256::new(&key));
2019        let tag = mode.encrypt(&iv, &[], &mut data);
2020        assert_eq!(data, expected_ct);
2021        assert_eq!(tag, expected_tag);
2022        assert!(mode.decrypt(&iv, &[], &mut data, &tag));
2023        assert_eq!(data, parse::<16>("2db5168e932556f8089a0622981d017d"));
2024    }
2025
2026    #[test]
2027    fn gcm_aes256_non_96bit_iv_auth_only_cavp() {
2028        // NIST CAVP gcmEncryptExtIV256.rsp
2029        // [Keylen=256, IVlen=8, PTlen=0, AADlen=128, Taglen=128], Count=0.
2030        let key = parse::<32>("c639f716597a86afd12319199e21a62b1fc0277a70e3ca120bd3ff745be88604");
2031        let iv = parse::<1>("29");
2032        let aad = parse::<16>("20fda1db6911d160121dc3c48e5f19b2");
2033        let mut data: [u8; 0] = [];
2034        let expected_tag = parse::<16>("221a3398f20d0d9fe913f33a6cd413d3");
2035
2036        let mode = Gcm::new(Aes256::new(&key));
2037        let tag = mode.encrypt(&iv, &aad, &mut data);
2038        assert_eq!(tag, expected_tag);
2039        assert!(mode.decrypt(&iv, &aad, &mut data, &tag));
2040    }
2041
2042    #[test]
2043    fn gcm_rejects_wrong_tag_without_decrypting() {
2044        let key = [0u8; 16];
2045        let iv = [0u8; 12];
2046        let mut data = [0u8; 16];
2047        let mode = Gcm::new(Aes128::new(&key));
2048        let tag = mode.encrypt(&iv, &[], &mut data);
2049        let mut bad_tag = tag;
2050        bad_tag[0] ^= 1;
2051        let ciphertext = data;
2052
2053        assert!(!mode.decrypt(&iv, &[], &mut data, &bad_tag));
2054        assert_eq!(data, ciphertext);
2055    }
2056
2057    #[test]
2058    fn gcm_ct_and_vt_backends_match() {
2059        let key = parse::<16>("feffe9928665731c6d6a8f9467308308");
2060        let iv = parse::<12>("cafebabefacedbaddecaf888");
2061        let aad = parse::<20>("feedfacedeadbeeffeedfacedeadbeefabaddad2");
2062        let plaintext = parse::<64>(
2063            "d9313225f88406e5a55909c5aff5269a\
2064             86a7a9531534f7da2e4c303d8a318a72\
2065             1c3c0c95956809532fcf0e2449a6b525\
2066             b16aedf5aa0de657ba637b391aafd255",
2067        );
2068
2069        let gcm_ct = Gcm::new(Aes128::new(&key));
2070        let gcm_vt = GcmVt::new(Aes128::new(&key));
2071
2072        let mut ct_data = plaintext;
2073        let mut vt_data = plaintext;
2074        let ct_tag = gcm_ct.encrypt(&iv, &aad, &mut ct_data);
2075        let vt_tag = gcm_vt.encrypt(&iv, &aad, &mut vt_data);
2076
2077        assert_eq!(ct_data, vt_data);
2078        assert_eq!(ct_tag, vt_tag);
2079        assert!(gcm_ct.decrypt(&iv, &aad, &mut ct_data, &ct_tag));
2080        assert!(gcm_vt.decrypt(&iv, &aad, &mut vt_data, &vt_tag));
2081        assert_eq!(ct_data, plaintext);
2082        assert_eq!(vt_data, plaintext);
2083    }
2084
2085    #[test]
2086    fn gcm_payload_limit_matches_sp800_38d_bound() {
2087        assert!(gcm_payload_len_allowed_u64(0));
2088        assert!(gcm_payload_len_allowed_u64(1));
2089        assert!(gcm_payload_len_allowed_u64(16));
2090        assert!(gcm_payload_len_allowed_u64(GCM_MAX_PAYLOAD_BYTES));
2091        assert!(!gcm_payload_len_allowed_u64(GCM_MAX_PAYLOAD_BYTES + 1));
2092    }
2093
2094    #[test]
2095    fn gmac_matches_gcm_on_empty_plaintext() {
2096        let key = parse::<16>("feffe9928665731c6d6a8f9467308308");
2097        let iv = parse::<12>("cafebabefacedbaddecaf888");
2098        let aad = parse::<20>("feedfacedeadbeeffeedfacedeadbeefabaddad2");
2099
2100        let gcm = Gcm::new(Aes128::new(&key));
2101        let gmac = Gmac::new(Aes128::new(&key));
2102        let tag = gmac.compute(&iv, &aad);
2103
2104        assert_eq!(tag, gcm.compute_tag(&iv, &aad, &[]));
2105        assert!(gmac.verify(&iv, &aad, &tag));
2106    }
2107
2108    #[test]
2109    fn gmac_ct_and_vt_backends_match() {
2110        let key = parse::<16>("feffe9928665731c6d6a8f9467308308");
2111        let iv = parse::<12>("cafebabefacedbaddecaf888");
2112        let aad = parse::<20>("feedfacedeadbeeffeedfacedeadbeefabaddad2");
2113
2114        let gmac_ct = Gmac::new(Aes128::new(&key));
2115        let gmac_vt = GmacVt::new(Aes128::new(&key));
2116
2117        let tag_ct = gmac_ct.compute(&iv, &aad);
2118        let tag_vt = gmac_vt.compute(&iv, &aad);
2119
2120        assert_eq!(tag_ct, tag_vt);
2121        assert!(gmac_ct.verify(&iv, &aad, &tag_ct));
2122        assert!(gmac_vt.verify(&iv, &aad, &tag_vt));
2123    }
2124
2125    #[test]
2126    fn ccm_aes128_rfc3610_packet_vector_1() {
2127        // RFC 3610, section 8, Packet Vector #1.
2128        let key = parse::<16>("c0c1c2c3c4c5c6c7c8c9cacbcccdcecf");
2129        let nonce = parse::<13>("00000003020100a0a1a2a3a4a5");
2130        let aad = parse::<8>("0001020304050607");
2131        let mut msg = parse::<23>("08090a0b0c0d0e0f101112131415161718191a1b1c1d1e");
2132        let expected_ct = parse::<23>("588c979a61c663d2f066d0c2c0f989806d5f6b61dac384");
2133        let expected_tag = parse::<8>("17e8d12cfdf926e0");
2134
2135        let mode = Ccm::<_, 8>::new(Aes128::new(&key));
2136        let tag = mode.encrypt(&nonce, &aad, &mut msg);
2137        assert_eq!(msg, expected_ct);
2138        assert_eq!(tag, expected_tag);
2139
2140        assert!(mode.decrypt(&nonce, &aad, &mut msg, &tag));
2141        assert_eq!(
2142            msg,
2143            parse::<23>("08090a0b0c0d0e0f101112131415161718191a1b1c1d1e")
2144        );
2145    }
2146
2147    #[test]
2148    fn ccm_aes128_rfc3610_packet_vector_2() {
2149        // RFC 3610, section 8, Packet Vector #2.
2150        let key = parse::<16>("c0c1c2c3c4c5c6c7c8c9cacbcccdcecf");
2151        let nonce = parse::<13>("00000004030201a0a1a2a3a4a5");
2152        let aad = parse::<8>("0001020304050607");
2153        let mut msg = parse::<24>("08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
2154        let expected_ct = parse::<24>("72c91a36e135f8cf291ca894085c87e3cc15c439c9e43a3b");
2155        let expected_tag = parse::<8>("a091d56e10400916");
2156
2157        let mode = Ccm::<_, 8>::new(Aes128::new(&key));
2158        let tag = mode.encrypt(&nonce, &aad, &mut msg);
2159        assert_eq!(msg, expected_ct);
2160        assert_eq!(tag, expected_tag);
2161
2162        assert!(mode.decrypt(&nonce, &aad, &mut msg, &tag));
2163        assert_eq!(
2164            msg,
2165            parse::<24>("08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f")
2166        );
2167    }
2168
2169    #[test]
2170    fn ccm_tag_mismatch_rejected() {
2171        let key = [0x11u8; 16];
2172        let nonce = [0x22u8; 13];
2173        let aad = b"header";
2174        let mode = Ccm::<_, 12>::new(Aes128::new(&key));
2175        let mut data = *b"ccm plaintext data";
2176        let tag = mode.encrypt(&nonce, aad, &mut data);
2177        let ciphertext = data;
2178
2179        let mut bad_tag = tag;
2180        bad_tag[0] ^= 0x80;
2181        assert!(!mode.decrypt(&nonce, aad, &mut data, &bad_tag));
2182        assert_eq!(data, ciphertext);
2183
2184        assert!(mode.decrypt(&nonce, aad, &mut data, &tag));
2185        assert_eq!(data, *b"ccm plaintext data");
2186    }
2187
2188    #[test]
2189    fn ccm_aes128_cavp_tlen_4_vector() {
2190        // NIST CAVP VTT128.rsp, [Tlen = 4], Count = 0.
2191        let key = parse::<16>("43b1a6bc8d0d22d6d1ca95c18593cca5");
2192        let nonce = parse::<13>("9882578e750b9682c6ca7f8f86");
2193        let aad = parse::<32>("2084f3861c9ad0ccee7c63a7e05aece5db8b34bd8724cc06b4ca99a7f9c4914f");
2194        let mut msg = parse::<24>("a2b381c7d1545c408fe29817a21dc435a154c87256346b05");
2195        let expected_ct = parse::<24>("cc69ed76985e0ed4c8365a72775e5a19bfccc71aeb116c85");
2196        let expected_tag = parse::<4>("a8c74677");
2197
2198        let mode = Ccm::<_, 4>::new(Aes128::new(&key));
2199        let tag = mode.encrypt(&nonce, &aad, &mut msg);
2200        assert_eq!(msg, expected_ct);
2201        assert_eq!(tag, expected_tag);
2202        assert!(mode.decrypt(&nonce, &aad, &mut msg, &tag));
2203        assert_eq!(
2204            msg,
2205            parse::<24>("a2b381c7d1545c408fe29817a21dc435a154c87256346b05")
2206        );
2207    }
2208
2209    #[test]
2210    fn ccm_aes128_cavp_tlen_16_vector() {
2211        // NIST CAVP VTT128.rsp, [Tlen = 16], Count = 0.
2212        let key = parse::<16>("4189351b5caea375a0299e81c621bf43");
2213        let nonce = parse::<13>("48c0906930561e0ab0ef4cd972");
2214        let aad = parse::<32>("40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951");
2215        let mut msg = parse::<24>("4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef");
2216        let expected_ct = parse::<24>("26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6");
2217        let expected_tag = parse::<16>("d80e8bf80f4a46cab06d4313f0db9be9");
2218
2219        let mode = Ccm::<_, 16>::new(Aes128::new(&key));
2220        let tag = mode.encrypt(&nonce, &aad, &mut msg);
2221        assert_eq!(msg, expected_ct);
2222        assert_eq!(tag, expected_tag);
2223        assert!(mode.decrypt(&nonce, &aad, &mut msg, &tag));
2224        assert_eq!(
2225            msg,
2226            parse::<24>("4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef")
2227        );
2228    }
2229
2230    #[test]
2231    fn aes_key_wrap_rfc3394_4_1() {
2232        let kek = parse::<16>("000102030405060708090A0B0C0D0E0F");
2233        let key_data = parse::<16>("00112233445566778899AABBCCDDEEFF");
2234        let expected = parse::<24>("1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5");
2235        let kw = AesKeyWrap::new(Aes128::new(&kek));
2236
2237        assert_eq!(kw.wrap_key(&key_data), Some(expected.to_vec()));
2238        assert_eq!(kw.unwrap_key(&expected), Some(key_data.to_vec()));
2239    }
2240
2241    #[test]
2242    fn aes_key_wrap_rfc3394_4_2() {
2243        let kek = parse::<24>("000102030405060708090A0B0C0D0E0F1011121314151617");
2244        let key_data = parse::<16>("00112233445566778899AABBCCDDEEFF");
2245        let expected = parse::<24>("96778B25AE6CA435F92B5B97C050AED2468AB8A17AD84E5D");
2246        let kw = AesKeyWrap::new(Aes192::new(&kek));
2247
2248        assert_eq!(kw.wrap_key(&key_data), Some(expected.to_vec()));
2249        assert_eq!(kw.unwrap_key(&expected), Some(key_data.to_vec()));
2250    }
2251
2252    #[test]
2253    fn aes_key_wrap_rfc3394_4_3() {
2254        let kek = parse::<32>("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F");
2255        let key_data = parse::<16>("00112233445566778899AABBCCDDEEFF");
2256        let expected = parse::<24>("64E8C3F9CE0F5BA263E9777905818A2A93C8191E7D6E8AE7");
2257        let kw = AesKeyWrap::new(Aes256::new(&kek));
2258
2259        assert_eq!(kw.wrap_key(&key_data), Some(expected.to_vec()));
2260        assert_eq!(kw.unwrap_key(&expected), Some(key_data.to_vec()));
2261    }
2262
2263    #[test]
2264    fn aes_key_wrap_rfc3394_4_4() {
2265        let kek = parse::<24>("000102030405060708090A0B0C0D0E0F1011121314151617");
2266        let key_data = parse::<24>("00112233445566778899AABBCCDDEEFF0001020304050607");
2267        let expected =
2268            parse::<32>("031D33264E15D33268F24EC260743EDCE1C6C7DDEE725A936BA814915C6762D2");
2269        let kw = AesKeyWrap::new(Aes192::new(&kek));
2270
2271        assert_eq!(kw.wrap_key(&key_data), Some(expected.to_vec()));
2272        assert_eq!(kw.unwrap_key(&expected), Some(key_data.to_vec()));
2273    }
2274
2275    #[test]
2276    fn aes_key_wrap_rfc3394_4_5() {
2277        let kek = parse::<32>("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F");
2278        let key_data = parse::<24>("00112233445566778899AABBCCDDEEFF0001020304050607");
2279        let expected =
2280            parse::<32>("A8F9BC1612C68B3FF6E6F4FBE30E71E4769C8B80A32CB8958CD5D17D6B254DA1");
2281        let kw = AesKeyWrap::new(Aes256::new(&kek));
2282
2283        assert_eq!(kw.wrap_key(&key_data), Some(expected.to_vec()));
2284        assert_eq!(kw.unwrap_key(&expected), Some(key_data.to_vec()));
2285    }
2286
2287    #[test]
2288    fn aes_key_wrap_rfc3394_4_6() {
2289        let kek = parse::<32>("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F");
2290        let key_data =
2291            parse::<32>("00112233445566778899AABBCCDDEEFF000102030405060708090A0B0C0D0E0F");
2292        let expected = parse::<40>(
2293            "28C9F404C4B810F4CBCCB35CFB87F8263F5786E2D80ED326CBC7F0E71A99F43BFB988B9B7A02DD21",
2294        );
2295        let kw = AesKeyWrap::new(Aes256::new(&kek));
2296
2297        assert_eq!(kw.wrap_key(&key_data), Some(expected.to_vec()));
2298        assert_eq!(kw.unwrap_key(&expected), Some(key_data.to_vec()));
2299    }
2300
2301    #[test]
2302    fn aes_key_wrap_rejects_bad_lengths_and_tampering() {
2303        let kw = AesKeyWrap::new(Aes128::new(&[0u8; 16]));
2304
2305        assert!(kw.wrap_key(&[]).is_none());
2306        assert!(kw.wrap_key(&[0u8; 8]).is_none());
2307        assert!(kw.wrap_key(&[0u8; 15]).is_none());
2308        assert!(kw.unwrap_key(&[]).is_none());
2309        assert!(kw.unwrap_key(&[0u8; 16]).is_none());
2310
2311        let mut wrapped = kw.wrap_key(&[0u8; 16]).expect("wrap");
2312        wrapped[0] ^= 1;
2313        assert!(kw.unwrap_key(&wrapped).is_none());
2314    }
2315}