dcrypt_algorithms/block/aes/
mod.rs

1//! AES block cipher implementations
2//!
3//! This module implements the Advanced Encryption Standard (AES) block cipher
4//! as specified in FIPS 197.
5//!
6//! ## Constant-Time Guarantees
7//!
8//! This implementation mitigates timing side-channel attacks by:
9//! - Using branchless arithmetic for GF(2^8) operations
10//! - Using bitsliced S-box implementations instead of table lookups
11//! - Ensuring consistent memory access patterns
12//! - Validating keys before use to prevent silent failure
13//!
14//! Note: On platforms where AES hardware acceleration is available, consider using
15//! hardware instructions for better side-channel resistance.
16
17use super::BlockCipher;
18use super::CipherAlgorithm;
19use crate::error::{validate, Result};
20use crate::types::SecretBytes;
21use dcrypt_common::security::SecretBuffer;
22use dcrypt_params::utils::symmetric::{
23    AES128_KEY_SIZE, AES192_KEY_SIZE, AES256_KEY_SIZE, AES_BLOCK_SIZE,
24};
25#[cfg(not(feature = "std"))]
26use portable_atomic::{compiler_fence, Ordering};
27use rand::{CryptoRng, RngCore};
28#[cfg(feature = "std")]
29use std::sync::atomic::{compiler_fence, Ordering};
30use zeroize::{Zeroize, ZeroizeOnDrop};
31
32/// Round constants for AES key expansion
33const RCON: [u32; 11] = [
34    0x00000000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000,
35    0x80000000, 0x1b000000, 0x36000000,
36];
37
38/// Multiply two bytes in GF(2⁸) with AES's reduction poly x⁸ + x⁴ + x³ + x + 1
39#[inline(always)]
40fn gf_mul(a: u8, b: u8) -> u8 {
41    let mut p = 0u8;
42    let mut a = a;
43    let mut b = b;
44    for _ in 0..8 {
45        // mask = 0xFF if b&1==1 else 0x00
46        let mask = (b & 1).wrapping_neg();
47        p ^= a & mask;
48        let hi = a & 0x80;
49        a <<= 1;
50        // if hi was set, reduce by 0x1B
51        a ^= ((hi != 0) as u8) * 0x1B;
52        b >>= 1;
53    }
54    p
55}
56
57/// Raise to the 254th power (b⁻¹ in GF(2⁸)) in constant time
58#[inline(always)]
59fn gf_inv(x: u8) -> u8 {
60    // always do the full exponentiation, even for x==0
61    let x2 = gf_mul(x, x);
62    let x4 = gf_mul(x2, x2);
63    let x8 = gf_mul(x4, x4);
64    let x16 = gf_mul(x8, x8);
65    let x32 = gf_mul(x16, x16);
66    let x64 = gf_mul(x32, x32);
67    let x128 = gf_mul(x64, x64);
68    // now multiply together x128·x64·x32·x16·x8·x4·x2
69    let mut y = gf_mul(x128, x64);
70    y = gf_mul(y, x32);
71    y = gf_mul(y, x16);
72    y = gf_mul(y, x8);
73    y = gf_mul(y, x4);
74    y = gf_mul(y, x2);
75
76    // now mask to zero if original x was zero
77    // mask = 0xFF if x!=0, else 0x00
78    let mask = ((x != 0) as u8).wrapping_neg();
79    y & mask
80}
81
82/// AES forward S-box: inv(x) ⊕ ROTL(inv(x),1–4) ⊕ 0x63
83#[inline(always)]
84fn bitsliced_sbox(x: u8) -> u8 {
85    let i = gf_inv(x);
86    i ^ i.rotate_left(1) ^ i.rotate_left(2) ^ i.rotate_left(3) ^ i.rotate_left(4) ^ 0x63
87}
88
89/// AES inverse S-box: undo affine then invert
90#[inline(always)]
91fn bitsliced_inv_sbox(x: u8) -> u8 {
92    // undo affine: y = A(i)⊕0x63  ⇒  i = A⁻¹(y)
93    let y = x ^ 0x63;
94    // A⁻¹ is convolution by t¹ + t³ + t⁶ mod (t⁸+1)
95    let u = y.rotate_left(1) ^ y.rotate_left(3) ^ y.rotate_left(6);
96    gf_inv(u)
97}
98
99/// Converts 4 bytes to a u32 in big-endian order
100#[inline(always)]
101fn bytes_to_u32(bytes: &[u8]) -> u32 {
102    ((bytes[0] as u32) << 24)
103        | ((bytes[1] as u32) << 16)
104        | ((bytes[2] as u32) << 8)
105        | (bytes[3] as u32)
106}
107
108/// Converts a u32 to 4 bytes in big-endian order
109#[inline(always)]
110fn u32_to_bytes(word: u32) -> [u8; 4] {
111    [
112        (word >> 24) as u8,
113        (word >> 16) as u8,
114        (word >> 8) as u8,
115        word as u8,
116    ]
117}
118
119/// Rotates a word left by 8 bits (1 byte)
120#[inline(always)]
121fn rotate_word(word: u32) -> u32 {
122    word.rotate_left(8)
123}
124
125/// Substitutes each byte in a word using the AES S-box, with bitsliced implementation
126#[inline(always)]
127fn sub_word(word: u32) -> u32 {
128    let bytes = u32_to_bytes(word);
129    let sub_bytes = [
130        bitsliced_sbox(bytes[0]),
131        bitsliced_sbox(bytes[1]),
132        bitsliced_sbox(bytes[2]),
133        bitsliced_sbox(bytes[3]),
134    ];
135    bytes_to_u32(&sub_bytes)
136}
137
138/// Type-level constants for AES-128
139pub enum Aes128Algorithm {}
140
141impl CipherAlgorithm for Aes128Algorithm {
142    const KEY_SIZE: usize = AES128_KEY_SIZE;
143    const BLOCK_SIZE: usize = AES_BLOCK_SIZE;
144
145    fn name() -> &'static str {
146        "AES-128"
147    }
148}
149
150/// Type-level constants for AES-192
151pub enum Aes192Algorithm {}
152
153impl CipherAlgorithm for Aes192Algorithm {
154    const KEY_SIZE: usize = AES192_KEY_SIZE;
155    const BLOCK_SIZE: usize = AES_BLOCK_SIZE;
156
157    fn name() -> &'static str {
158        "AES-192"
159    }
160}
161
162/// Type-level constants for AES-256
163pub enum Aes256Algorithm {}
164
165impl CipherAlgorithm for Aes256Algorithm {
166    const KEY_SIZE: usize = AES256_KEY_SIZE;
167    const BLOCK_SIZE: usize = AES_BLOCK_SIZE;
168
169    fn name() -> &'static str {
170        "AES-256"
171    }
172}
173
174/// AES-128 block cipher
175#[derive(Clone, Zeroize, ZeroizeOnDrop)]
176pub struct Aes128 {
177    round_keys: SecretBuffer<176>, // 11 rounds × 16 bytes
178}
179
180/// AES-192 block cipher
181#[derive(Clone, Zeroize, ZeroizeOnDrop)]
182pub struct Aes192 {
183    round_keys: SecretBuffer<208>, // 13 rounds × 16 bytes
184}
185
186/// AES-256 block cipher
187#[derive(Clone, Zeroize, ZeroizeOnDrop)]
188pub struct Aes256 {
189    round_keys: SecretBuffer<240>, // 15 rounds × 16 bytes
190}
191
192// Add CipherAlgorithm implementations for AES structs
193impl CipherAlgorithm for Aes128 {
194    const KEY_SIZE: usize = AES128_KEY_SIZE;
195    const BLOCK_SIZE: usize = AES_BLOCK_SIZE;
196
197    fn name() -> &'static str {
198        "AES-128"
199    }
200}
201
202impl CipherAlgorithm for Aes192 {
203    const KEY_SIZE: usize = AES192_KEY_SIZE;
204    const BLOCK_SIZE: usize = AES_BLOCK_SIZE;
205
206    fn name() -> &'static str {
207        "AES-192"
208    }
209}
210
211impl CipherAlgorithm for Aes256 {
212    const KEY_SIZE: usize = AES256_KEY_SIZE;
213    const BLOCK_SIZE: usize = AES_BLOCK_SIZE;
214
215    fn name() -> &'static str {
216        "AES-256"
217    }
218}
219
220impl Aes128 {
221    /// Performs AES-128 key expansion
222    fn expand_key(key: &[u8]) -> Result<SecretBuffer<176>> {
223        validate::length("AES-128 key", key.len(), AES128_KEY_SIZE)?;
224
225        let mut round_keys_u32 = [0u32; 44];
226
227        // Initial key schedule
228        for i in 0..4 {
229            round_keys_u32[i] = bytes_to_u32(&key[i * 4..(i + 1) * 4]);
230        }
231
232        // Key expansion
233        for i in 4..44 {
234            let mut temp = round_keys_u32[i - 1];
235            if i % 4 == 0 {
236                temp = sub_word(rotate_word(temp)) ^ RCON[i / 4];
237            }
238            round_keys_u32[i] = round_keys_u32[i - 4] ^ temp;
239        }
240
241        // Convert to bytes
242        let mut round_key_bytes = [0u8; 176];
243        for i in 0..44 {
244            let bytes = u32_to_bytes(round_keys_u32[i]);
245            round_key_bytes[i * 4..(i + 1) * 4].copy_from_slice(&bytes);
246        }
247
248        Ok(SecretBuffer::new(round_key_bytes))
249    }
250
251    /// SubBytes step with bitsliced implementation
252    fn sub_bytes(state: &mut [u8; 16]) {
253        for byte in state.iter_mut() {
254            *byte = bitsliced_sbox(*byte);
255        }
256        // ensure no reordering around our bit-ops
257        compiler_fence(Ordering::SeqCst);
258    }
259
260    /// ShiftRows step
261    fn shift_rows(state: &mut [u8; 16]) {
262        let mut temp = [0u8; 16];
263        temp.copy_from_slice(state);
264        state[0] = temp[0];
265        state[4] = temp[4];
266        state[8] = temp[8];
267        state[12] = temp[12];
268        state[1] = temp[5];
269        state[5] = temp[9];
270        state[9] = temp[13];
271        state[13] = temp[1];
272        state[2] = temp[10];
273        state[6] = temp[14];
274        state[10] = temp[2];
275        state[14] = temp[6];
276        state[3] = temp[15];
277        state[7] = temp[3];
278        state[11] = temp[7];
279        state[15] = temp[11];
280    }
281
282    /// Multiply by 2 in GF(2^8)
283    #[inline(always)]
284    fn mul2(byte: u8) -> u8 {
285        let high = byte >> 7;
286        (byte << 1) ^ (high * 0x1B)
287    }
288
289    /// MixColumns step
290    fn mix_columns(state: &mut [u8; 16]) {
291        for c in 0..4 {
292            let i = c * 4;
293            let s0 = state[i];
294            let s1 = state[i + 1];
295            let s2 = state[i + 2];
296            let s3 = state[i + 3];
297            state[i] = Self::mul2(s0) ^ Self::mul2(s1) ^ s1 ^ s2 ^ s3;
298            state[i + 1] = s0 ^ Self::mul2(s1) ^ Self::mul2(s2) ^ s2 ^ s3;
299            state[i + 2] = s0 ^ s1 ^ Self::mul2(s2) ^ Self::mul2(s3) ^ s3;
300            state[i + 3] = Self::mul2(s0) ^ s0 ^ s1 ^ s2 ^ Self::mul2(s3);
301        }
302    }
303
304    /// AddRoundKey step using precomputed bytes for constant-time behavior
305    fn add_round_key(state: &mut [u8; 16], round_key_bytes: &[u8]) -> Result<()> {
306        // Use validation utility for length check
307        validate::min_length("AES round key", round_key_bytes.len(), 16)?;
308
309        for i in 0..16 {
310            state[i] ^= round_key_bytes[i];
311        }
312        Ok(())
313    }
314
315    /// Inverse SubBytes with bitsliced implementation
316    fn inv_sub_bytes(state: &mut [u8; 16]) {
317        for byte in state.iter_mut() {
318            *byte = bitsliced_inv_sbox(*byte);
319        }
320        compiler_fence(Ordering::SeqCst);
321    }
322
323    /// Inverse ShiftRows
324    fn inv_shift_rows(state: &mut [u8; 16]) {
325        let mut temp = [0u8; 16];
326        temp.copy_from_slice(state);
327        state[0] = temp[0];
328        state[4] = temp[4];
329        state[8] = temp[8];
330        state[12] = temp[12];
331        state[1] = temp[13];
332        state[5] = temp[1];
333        state[9] = temp[5];
334        state[13] = temp[9];
335        state[2] = temp[10];
336        state[6] = temp[14];
337        state[10] = temp[2];
338        state[14] = temp[6];
339        state[3] = temp[7];
340        state[7] = temp[11];
341        state[11] = temp[15];
342        state[15] = temp[3];
343    }
344
345    /// GF(2^8) multiplies for InvMixColumns
346    #[inline(always)]
347    fn mul14(byte: u8) -> u8 {
348        Self::mul2(Self::mul2(Self::mul2(byte))) ^ Self::mul2(Self::mul2(byte)) ^ Self::mul2(byte)
349    }
350    #[inline(always)]
351    fn mul13(byte: u8) -> u8 {
352        Self::mul2(Self::mul2(Self::mul2(byte))) ^ Self::mul2(Self::mul2(byte)) ^ byte
353    }
354    #[inline(always)]
355    fn mul11(byte: u8) -> u8 {
356        Self::mul2(Self::mul2(Self::mul2(byte))) ^ Self::mul2(byte) ^ byte
357    }
358    #[inline(always)]
359    fn mul9(byte: u8) -> u8 {
360        Self::mul2(Self::mul2(Self::mul2(byte))) ^ byte
361    }
362
363    /// Inverse MixColumns
364    fn inv_mix_columns(state: &mut [u8; 16]) {
365        for c in 0..4 {
366            let i = c * 4;
367            let s0 = state[i];
368            let s1 = state[i + 1];
369            let s2 = state[i + 2];
370            let s3 = state[i + 3];
371            state[i] = Self::mul14(s0) ^ Self::mul11(s1) ^ Self::mul13(s2) ^ Self::mul9(s3);
372            state[i + 1] = Self::mul9(s0) ^ Self::mul14(s1) ^ Self::mul11(s2) ^ Self::mul13(s3);
373            state[i + 2] = Self::mul13(s0) ^ Self::mul9(s1) ^ Self::mul14(s2) ^ Self::mul11(s3);
374            state[i + 3] = Self::mul11(s0) ^ Self::mul13(s1) ^ Self::mul9(s2) ^ Self::mul14(s3);
375        }
376    }
377}
378
379impl BlockCipher for Aes128 {
380    type Algorithm = Aes128Algorithm;
381    type Key = SecretBytes<16>;
382
383    fn new(key: &Self::Key) -> Self {
384        let round_keys =
385            Self::expand_key(key.as_ref()).expect("AES-128 key expansion should not fail");
386
387        Aes128 { round_keys }
388    }
389
390    fn encrypt_block(&self, block: &mut [u8]) -> Result<()> {
391        // Use validation utility for length check
392        validate::length("AES block", block.len(), AES_BLOCK_SIZE)?;
393
394        // Access round keys through SecretBuffer
395        let round_key_bytes = self.round_keys.as_ref();
396
397        // Warm the cache by touching all round key bytes
398        let mut _warm: u8 = 0;
399        for &b in round_key_bytes {
400            _warm = _warm.wrapping_add(b);
401        }
402        compiler_fence(Ordering::SeqCst);
403
404        // Copy block to state array
405        let mut state = [0u8; 16];
406        state.copy_from_slice(block);
407
408        // Initial round - AddRoundKey
409        Self::add_round_key(&mut state, &round_key_bytes[0..16])?;
410
411        // Main rounds
412        for round in 1..10 {
413            Self::sub_bytes(&mut state);
414            Self::shift_rows(&mut state);
415            Self::mix_columns(&mut state);
416
417            let offset = round * 16;
418            Self::add_round_key(&mut state, &round_key_bytes[offset..offset + 16])?;
419        }
420
421        // Final round
422        Self::sub_bytes(&mut state);
423        Self::shift_rows(&mut state);
424        Self::add_round_key(&mut state, &round_key_bytes[160..176])?;
425
426        // Copy state back to block
427        block.copy_from_slice(&state);
428        Ok(())
429    }
430
431    fn decrypt_block(&self, block: &mut [u8]) -> Result<()> {
432        // Use validation utility for length check
433        validate::length("AES block", block.len(), AES_BLOCK_SIZE)?;
434
435        // Access round keys through SecretBuffer
436        let round_key_bytes = self.round_keys.as_ref();
437
438        // Warm the cache by touching all round key bytes
439        let mut _warm: u8 = 0;
440        for &b in round_key_bytes {
441            _warm = _warm.wrapping_add(b);
442        }
443        compiler_fence(Ordering::SeqCst);
444
445        // Copy block to state array
446        let mut state = [0u8; 16];
447        state.copy_from_slice(block);
448
449        // Initial round - AddRoundKey (final round key)
450        Self::add_round_key(&mut state, &round_key_bytes[160..176])?;
451
452        // Main rounds in reverse
453        for round in (1..10).rev() {
454            Self::inv_shift_rows(&mut state);
455            Self::inv_sub_bytes(&mut state);
456
457            let offset = round * 16;
458            Self::add_round_key(&mut state, &round_key_bytes[offset..offset + 16])?;
459            Self::inv_mix_columns(&mut state);
460        }
461
462        // Final round
463        Self::inv_shift_rows(&mut state);
464        Self::inv_sub_bytes(&mut state);
465        Self::add_round_key(&mut state, &round_key_bytes[0..16])?;
466
467        // Copy state back to block
468        block.copy_from_slice(&state);
469        Ok(())
470    }
471
472    fn generate_key<R: RngCore + CryptoRng>(rng: &mut R) -> Self::Key {
473        let mut key_data = [0u8; AES128_KEY_SIZE];
474        rng.fill_bytes(&mut key_data);
475        SecretBytes::new(key_data)
476    }
477}
478
479// AES-192 implementation
480
481impl Aes192 {
482    /// Performs AES-192 key expansion
483    fn expand_key(key: &[u8]) -> Result<SecretBuffer<208>> {
484        validate::length("AES-192 key", key.len(), AES192_KEY_SIZE)?;
485
486        let mut round_keys_u32 = [0u32; 52];
487
488        // Initial key schedule
489        for i in 0..6 {
490            round_keys_u32[i] = bytes_to_u32(&key[i * 4..(i + 1) * 4]);
491        }
492
493        // Key expansion
494        for i in 6..52 {
495            let mut temp = round_keys_u32[i - 1];
496            if i % 6 == 0 {
497                temp = sub_word(rotate_word(temp)) ^ RCON[i / 6];
498            }
499            round_keys_u32[i] = round_keys_u32[i - 6] ^ temp;
500        }
501
502        // Convert to bytes
503        let mut round_key_bytes = [0u8; 208];
504        for i in 0..52 {
505            let bytes = u32_to_bytes(round_keys_u32[i]);
506            round_key_bytes[i * 4..(i + 1) * 4].copy_from_slice(&bytes);
507        }
508
509        Ok(SecretBuffer::new(round_key_bytes))
510    }
511}
512
513impl BlockCipher for Aes192 {
514    type Algorithm = Aes192Algorithm;
515    type Key = SecretBytes<24>;
516
517    fn new(key: &Self::Key) -> Self {
518        let round_keys =
519            Self::expand_key(key.as_ref()).expect("AES-192 key expansion should not fail");
520
521        Aes192 { round_keys }
522    }
523
524    fn encrypt_block(&self, block: &mut [u8]) -> Result<()> {
525        // Use validation utility for length check
526        validate::length("AES block", block.len(), AES_BLOCK_SIZE)?;
527
528        // Access round keys through SecretBuffer
529        let round_key_bytes = self.round_keys.as_ref();
530
531        // Warm the cache by touching all round key bytes
532        let mut _warm: u8 = 0;
533        for &b in round_key_bytes {
534            _warm = _warm.wrapping_add(b);
535        }
536        compiler_fence(Ordering::SeqCst);
537
538        // Copy block to state array
539        let mut state = [0u8; 16];
540        state.copy_from_slice(block);
541
542        // Initial round - AddRoundKey
543        Aes128::add_round_key(&mut state, &round_key_bytes[0..16])?;
544
545        // Main rounds
546        for round in 1..12 {
547            Aes128::sub_bytes(&mut state);
548            Aes128::shift_rows(&mut state);
549            Aes128::mix_columns(&mut state);
550
551            let offset = round * 16;
552            Aes128::add_round_key(&mut state, &round_key_bytes[offset..offset + 16])?;
553        }
554
555        // Final round
556        Aes128::sub_bytes(&mut state);
557        Aes128::shift_rows(&mut state);
558        Aes128::add_round_key(&mut state, &round_key_bytes[192..208])?;
559
560        // Copy state back to block
561        block.copy_from_slice(&state);
562        Ok(())
563    }
564
565    fn decrypt_block(&self, block: &mut [u8]) -> Result<()> {
566        // Use validation utility for length check
567        validate::length("AES block", block.len(), AES_BLOCK_SIZE)?;
568
569        // Access round keys through SecretBuffer
570        let round_key_bytes = self.round_keys.as_ref();
571
572        // Warm the cache by touching all round key bytes
573        let mut _warm: u8 = 0;
574        for &b in round_key_bytes {
575            _warm = _warm.wrapping_add(b);
576        }
577        compiler_fence(Ordering::SeqCst);
578
579        // Copy block to state array
580        let mut state = [0u8; 16];
581        state.copy_from_slice(block);
582
583        // Initial round - AddRoundKey (final round key)
584        Aes128::add_round_key(&mut state, &round_key_bytes[192..208])?;
585
586        // Main rounds in reverse
587        for round in (1..12).rev() {
588            Aes128::inv_shift_rows(&mut state);
589            Aes128::inv_sub_bytes(&mut state);
590
591            let offset = round * 16;
592            Aes128::add_round_key(&mut state, &round_key_bytes[offset..offset + 16])?;
593            Aes128::inv_mix_columns(&mut state);
594        }
595
596        // Final round
597        Aes128::inv_shift_rows(&mut state);
598        Aes128::inv_sub_bytes(&mut state);
599        Aes128::add_round_key(&mut state, &round_key_bytes[0..16])?;
600
601        // Copy state back to block
602        block.copy_from_slice(&state);
603        Ok(())
604    }
605
606    fn generate_key<R: RngCore + CryptoRng>(rng: &mut R) -> Self::Key {
607        let mut key_data = [0u8; AES192_KEY_SIZE];
608        rng.fill_bytes(&mut key_data);
609        SecretBytes::new(key_data)
610    }
611}
612
613// AES-256 implementation
614
615impl Aes256 {
616    /// Performs AES-256 key expansion
617    fn expand_key(key: &[u8]) -> Result<SecretBuffer<240>> {
618        validate::length("AES-256 key", key.len(), AES256_KEY_SIZE)?;
619
620        let mut round_keys_u32 = [0u32; 60];
621
622        // Initial key schedule
623        for i in 0..8 {
624            round_keys_u32[i] = bytes_to_u32(&key[i * 4..(i + 1) * 4]);
625        }
626
627        // Key expansion
628        for i in 8..60 {
629            let mut temp = round_keys_u32[i - 1];
630            if i % 8 == 0 {
631                temp = sub_word(rotate_word(temp)) ^ RCON[i / 8];
632            } else if i % 8 == 4 {
633                temp = sub_word(temp);
634            }
635            round_keys_u32[i] = round_keys_u32[i - 8] ^ temp;
636        }
637
638        // Convert to bytes
639        let mut round_key_bytes = [0u8; 240];
640        for i in 0..60 {
641            let bytes = u32_to_bytes(round_keys_u32[i]);
642            round_key_bytes[i * 4..(i + 1) * 4].copy_from_slice(&bytes);
643        }
644
645        Ok(SecretBuffer::new(round_key_bytes))
646    }
647}
648
649impl BlockCipher for Aes256 {
650    type Algorithm = Aes256Algorithm;
651    type Key = SecretBytes<32>;
652
653    fn new(key: &Self::Key) -> Self {
654        let round_keys =
655            Self::expand_key(key.as_ref()).expect("AES-256 key expansion should not fail");
656
657        Aes256 { round_keys }
658    }
659
660    fn encrypt_block(&self, block: &mut [u8]) -> Result<()> {
661        // Use validation utility for length check
662        validate::length("AES block", block.len(), AES_BLOCK_SIZE)?;
663
664        // Access round keys through SecretBuffer
665        let round_key_bytes = self.round_keys.as_ref();
666
667        // Warm the cache by touching all round key bytes
668        let mut _warm: u8 = 0;
669        for &b in round_key_bytes {
670            _warm = _warm.wrapping_add(b);
671        }
672        compiler_fence(Ordering::SeqCst);
673
674        // Copy block to state array
675        let mut state = [0u8; 16];
676        state.copy_from_slice(block);
677
678        // Initial round - AddRoundKey
679        Aes128::add_round_key(&mut state, &round_key_bytes[0..16])?;
680
681        // Main rounds
682        for round in 1..14 {
683            Aes128::sub_bytes(&mut state);
684            Aes128::shift_rows(&mut state);
685            Aes128::mix_columns(&mut state);
686
687            let offset = round * 16;
688            Aes128::add_round_key(&mut state, &round_key_bytes[offset..offset + 16])?;
689        }
690
691        // Final round
692        Aes128::sub_bytes(&mut state);
693        Aes128::shift_rows(&mut state);
694        Aes128::add_round_key(&mut state, &round_key_bytes[224..240])?;
695
696        // Copy state back to block
697        block.copy_from_slice(&state);
698        Ok(())
699    }
700
701    fn decrypt_block(&self, block: &mut [u8]) -> Result<()> {
702        // Use validation utility for length check
703        validate::length("AES block", block.len(), AES_BLOCK_SIZE)?;
704
705        // Access round keys through SecretBuffer
706        let round_key_bytes = self.round_keys.as_ref();
707
708        // Warm the cache by touching all round key bytes
709        let mut _warm: u8 = 0;
710        for &b in round_key_bytes {
711            _warm = _warm.wrapping_add(b);
712        }
713        compiler_fence(Ordering::SeqCst);
714
715        // Copy block to state array
716        let mut state = [0u8; 16];
717        state.copy_from_slice(block);
718
719        // Initial round - AddRoundKey (final round key)
720        Aes128::add_round_key(&mut state, &round_key_bytes[224..240])?;
721
722        // Main rounds in reverse
723        for round in (1..14).rev() {
724            Aes128::inv_shift_rows(&mut state);
725            Aes128::inv_sub_bytes(&mut state);
726
727            let offset = round * 16;
728            Aes128::add_round_key(&mut state, &round_key_bytes[offset..offset + 16])?;
729            Aes128::inv_mix_columns(&mut state);
730        }
731
732        // Final round
733        Aes128::inv_shift_rows(&mut state);
734        Aes128::inv_sub_bytes(&mut state);
735        Aes128::add_round_key(&mut state, &round_key_bytes[0..16])?;
736
737        // Copy state back to block
738        block.copy_from_slice(&state);
739        Ok(())
740    }
741
742    fn generate_key<R: RngCore + CryptoRng>(rng: &mut R) -> Self::Key {
743        let mut key_data = [0u8; AES256_KEY_SIZE];
744        rng.fill_bytes(&mut key_data);
745        SecretBytes::new(key_data)
746    }
747}
748
749#[cfg(test)]
750mod tests;