Skip to main content

aes/backends/fixslice/
aes192.rs

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