Skip to main content

aes/backends/fixslice/
aes128.rs

1use super::{BatchBlocks, State, Word, mix_columns::*, sbox::*, utils::*};
2
3/// AES-128 round keys
4pub(crate) type RoundKeys<W> = [W; 88];
5
6/// Fully bitsliced AES-128 key schedule to match the fully-fixsliced representation.
7pub(crate) fn key_schedule<W: Word>(key: &[u8; 16]) -> RoundKeys<W> {
8    let mut rkeys = [W::default(); 88];
9
10    W::bitslice(&mut rkeys[..8], &broadcast::<W>(key));
11
12    let mut rk_off = 0;
13    for rcon in 0..10 {
14        memshift32(&mut rkeys, rk_off);
15        rk_off += 8;
16
17        sub_bytes(&mut rkeys[rk_off..(rk_off + 8)]);
18        sub_bytes_nots(&mut rkeys[rk_off..(rk_off + 8)]);
19
20        if rcon < 8 {
21            add_round_constant_bit(&mut rkeys[rk_off..(rk_off + 8)], rcon);
22        } else {
23            add_round_constant_bit(&mut rkeys[rk_off..(rk_off + 8)], rcon - 8);
24            add_round_constant_bit(&mut rkeys[rk_off..(rk_off + 8)], rcon - 7);
25            add_round_constant_bit(&mut rkeys[rk_off..(rk_off + 8)], rcon - 5);
26            add_round_constant_bit(&mut rkeys[rk_off..(rk_off + 8)], rcon - 4);
27        }
28
29        xor_columns(&mut rkeys, rk_off, 8, W::ror_distance(1, 3));
30    }
31
32    // Adjust to match fixslicing format
33    #[cfg(aes_backend_soft = "compact")]
34    {
35        for i in (8..88).step_by(16) {
36            inv_shift_rows_1(&mut rkeys[i..(i + 8)]);
37        }
38    }
39    #[cfg(not(aes_backend_soft = "compact"))]
40    {
41        for i in (8..72).step_by(32) {
42            inv_shift_rows_1(&mut rkeys[i..(i + 8)]);
43            inv_shift_rows_2(&mut rkeys[(i + 8)..(i + 16)]);
44            inv_shift_rows_3(&mut rkeys[(i + 16)..(i + 24)]);
45        }
46        inv_shift_rows_1(&mut rkeys[72..80]);
47    }
48
49    // Account for NOTs removed from sub_bytes
50    for i in 1..11 {
51        sub_bytes_nots(&mut rkeys[(i * 8)..(i * 8 + 8)]);
52    }
53
54    rkeys
55}
56
57/// Fully-fixsliced AES-128 encryption (the ShiftRows is completely omitted).
58///
59/// Encrypts four blocks in-place and in parallel.
60pub(crate) fn encrypt<W: Word>(rkeys: &RoundKeys<W>, blocks: &BatchBlocks<W>) -> BatchBlocks<W> {
61    let mut state = State::<W>::default();
62
63    W::bitslice(&mut state, blocks);
64
65    add_round_key(&mut state, &rkeys[..8]);
66
67    let mut rk_off = 8;
68    loop {
69        sub_bytes(&mut state);
70        mix_columns_1(&mut state);
71        add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]);
72        rk_off += 8;
73
74        #[cfg(aes_backend_soft = "compact")]
75        {
76            shift_rows_2(&mut state);
77        }
78
79        if rk_off == 80 {
80            break;
81        }
82
83        #[cfg(not(aes_backend_soft = "compact"))]
84        {
85            sub_bytes(&mut state);
86            mix_columns_2(&mut state);
87            add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]);
88            rk_off += 8;
89
90            sub_bytes(&mut state);
91            mix_columns_3(&mut state);
92            add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]);
93            rk_off += 8;
94        }
95
96        sub_bytes(&mut state);
97        mix_columns_0(&mut state);
98        add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]);
99        rk_off += 8;
100    }
101
102    #[cfg(not(aes_backend_soft = "compact"))]
103    {
104        shift_rows_2(&mut state);
105    }
106
107    sub_bytes(&mut state);
108    add_round_key(&mut state, &rkeys[80..]);
109
110    W::inv_bitslice(&state)
111}
112
113/// Fully-fixsliced AES-128 decryption (the InvShiftRows is completely omitted).
114///
115/// Decrypts four blocks in-place and in parallel.
116pub(crate) fn decrypt<W: Word>(rkeys: &RoundKeys<W>, blocks: &BatchBlocks<W>) -> BatchBlocks<W> {
117    let mut state = State::<W>::default();
118
119    W::bitslice(&mut state, blocks);
120
121    add_round_key(&mut state, &rkeys[80..]);
122    inv_sub_bytes(&mut state);
123
124    #[cfg(not(aes_backend_soft = "compact"))]
125    {
126        inv_shift_rows_2(&mut state);
127    }
128
129    let mut rk_off = 72;
130    loop {
131        #[cfg(aes_backend_soft = "compact")]
132        {
133            inv_shift_rows_2(&mut state);
134        }
135
136        add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]);
137        inv_mix_columns_1(&mut state);
138        inv_sub_bytes(&mut state);
139        rk_off -= 8;
140
141        if rk_off == 0 {
142            break;
143        }
144
145        add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]);
146        inv_mix_columns_0(&mut state);
147        inv_sub_bytes(&mut state);
148        rk_off -= 8;
149
150        #[cfg(not(aes_backend_soft = "compact"))]
151        {
152            add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]);
153            inv_mix_columns_3(&mut state);
154            inv_sub_bytes(&mut state);
155            rk_off -= 8;
156
157            add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]);
158            inv_mix_columns_2(&mut state);
159            inv_sub_bytes(&mut state);
160            rk_off -= 8;
161        }
162    }
163
164    add_round_key(&mut state, &rkeys[..8]);
165
166    W::inv_bitslice(&state)
167}