/rust/registry/src/index.crates.io-1949cf8c6b5b557f/aes-0.7.5/src/soft/fixslice64.rs
Line | Count | Source |
1 | | //! Fixsliced implementations of AES-128, AES-192 and AES-256 (64-bit) |
2 | | //! adapted from the C implementation. |
3 | | //! |
4 | | //! All implementations are fully bitsliced and do not rely on any |
5 | | //! Look-Up Table (LUT). |
6 | | //! |
7 | | //! See the paper at <https://eprint.iacr.org/2020/1123.pdf> for more details. |
8 | | //! |
9 | | //! # Author (original C code) |
10 | | //! |
11 | | //! Alexandre Adomnicai, Nanyang Technological University, Singapore |
12 | | //! <alexandre.adomnicai@ntu.edu.sg> |
13 | | //! |
14 | | //! Originally licensed MIT. Relicensed as Apache 2.0+MIT with permission. |
15 | | |
16 | | #![allow(clippy::unreadable_literal)] |
17 | | |
18 | | use crate::Block; |
19 | | use cipher::{ |
20 | | consts::{U16, U24, U32}, |
21 | | generic_array::GenericArray, |
22 | | }; |
23 | | |
24 | | /// AES block batch size for this implementation |
25 | | pub(crate) const FIXSLICE_BLOCKS: usize = 4; |
26 | | |
27 | | /// AES-128 round keys |
28 | | pub(crate) type FixsliceKeys128 = [u64; 88]; |
29 | | |
30 | | /// AES-192 round keys |
31 | | pub(crate) type FixsliceKeys192 = [u64; 104]; |
32 | | |
33 | | /// AES-256 round keys |
34 | | pub(crate) type FixsliceKeys256 = [u64; 120]; |
35 | | |
36 | | /// 512-bit internal state |
37 | | pub(crate) type State = [u64; 8]; |
38 | | |
39 | | /// Fully bitsliced AES-128 key schedule to match the fully-fixsliced representation. |
40 | 0 | pub(crate) fn aes128_key_schedule(key: &GenericArray<u8, U16>) -> FixsliceKeys128 { |
41 | 0 | let mut rkeys = [0u64; 88]; |
42 | | |
43 | 0 | bitslice(&mut rkeys[..8], key, key, key, key); |
44 | | |
45 | 0 | let mut rk_off = 0; |
46 | 0 | for rcon in 0..10 { |
47 | 0 | memshift32(&mut rkeys, rk_off); |
48 | 0 | rk_off += 8; |
49 | | |
50 | 0 | sub_bytes(&mut rkeys[rk_off..(rk_off + 8)]); |
51 | 0 | sub_bytes_nots(&mut rkeys[rk_off..(rk_off + 8)]); |
52 | | |
53 | 0 | if rcon < 8 { |
54 | 0 | add_round_constant_bit(&mut rkeys[rk_off..(rk_off + 8)], rcon); |
55 | 0 | } else { |
56 | 0 | add_round_constant_bit(&mut rkeys[rk_off..(rk_off + 8)], rcon - 8); |
57 | 0 | add_round_constant_bit(&mut rkeys[rk_off..(rk_off + 8)], rcon - 7); |
58 | 0 | add_round_constant_bit(&mut rkeys[rk_off..(rk_off + 8)], rcon - 5); |
59 | 0 | add_round_constant_bit(&mut rkeys[rk_off..(rk_off + 8)], rcon - 4); |
60 | 0 | } |
61 | | |
62 | 0 | xor_columns(&mut rkeys, rk_off, 8, ror_distance(1, 3)); |
63 | | } |
64 | | |
65 | | // Adjust to match fixslicing format |
66 | | #[cfg(feature = "compact")] |
67 | | { |
68 | | for i in (8..88).step_by(16) { |
69 | | inv_shift_rows_1(&mut rkeys[i..(i + 8)]); |
70 | | } |
71 | | } |
72 | | #[cfg(not(feature = "compact"))] |
73 | | { |
74 | 0 | for i in (8..72).step_by(32) { |
75 | 0 | inv_shift_rows_1(&mut rkeys[i..(i + 8)]); |
76 | 0 | inv_shift_rows_2(&mut rkeys[(i + 8)..(i + 16)]); |
77 | 0 | inv_shift_rows_3(&mut rkeys[(i + 16)..(i + 24)]); |
78 | 0 | } |
79 | 0 | inv_shift_rows_1(&mut rkeys[72..80]); |
80 | | } |
81 | | |
82 | | // Account for NOTs removed from sub_bytes |
83 | 0 | for i in 1..11 { |
84 | 0 | sub_bytes_nots(&mut rkeys[(i * 8)..(i * 8 + 8)]); |
85 | 0 | } |
86 | | |
87 | 0 | rkeys |
88 | 0 | } |
89 | | |
90 | | /// Fully bitsliced AES-192 key schedule to match the fully-fixsliced representation. |
91 | 0 | pub(crate) fn aes192_key_schedule(key: &GenericArray<u8, U24>) -> FixsliceKeys192 { |
92 | 0 | let mut rkeys = [0u64; 104]; |
93 | 0 | let mut tmp = [0u64; 8]; |
94 | | |
95 | 0 | bitslice( |
96 | 0 | &mut rkeys[..8], |
97 | 0 | &key[..16], |
98 | 0 | &key[..16], |
99 | 0 | &key[..16], |
100 | 0 | &key[..16], |
101 | | ); |
102 | 0 | bitslice(&mut tmp, &key[8..], &key[8..], &key[8..], &key[8..]); |
103 | | |
104 | 0 | let mut rcon = 0; |
105 | 0 | let mut rk_off = 8; |
106 | | |
107 | | loop { |
108 | 0 | for i in 0..8 { |
109 | 0 | rkeys[rk_off + i] = (0x00ff00ff00ff00ff & (tmp[i] >> 8)) |
110 | 0 | | (0xff00ff00ff00ff00 & (rkeys[(rk_off - 8) + i] << 8)); |
111 | 0 | } |
112 | | |
113 | 0 | sub_bytes(&mut tmp); |
114 | 0 | sub_bytes_nots(&mut tmp); |
115 | | |
116 | 0 | add_round_constant_bit(&mut tmp, rcon); |
117 | 0 | rcon += 1; |
118 | | |
119 | 0 | for i in 0..8 { |
120 | 0 | let mut ti = rkeys[rk_off + i]; |
121 | 0 | ti ^= 0x0f000f000f000f00 & ror(tmp[i], ror_distance(1, 1)); |
122 | 0 | ti ^= 0xf000f000f000f000 & (ti << 4); |
123 | 0 | tmp[i] = ti; |
124 | 0 | } |
125 | 0 | rkeys[rk_off..(rk_off + 8)].copy_from_slice(&tmp); |
126 | 0 | rk_off += 8; |
127 | | |
128 | 0 | for i in 0..8 { |
129 | 0 | let ui = tmp[i]; |
130 | 0 | let mut ti = (0x00ff00ff00ff00ff & (rkeys[(rk_off - 16) + i] >> 8)) |
131 | 0 | | (0xff00ff00ff00ff00 & (ui << 8)); |
132 | 0 | ti ^= 0x000f000f000f000f & (ui >> 12); |
133 | 0 | tmp[i] = ti |
134 | 0 | ^ (0xfff0fff0fff0fff0 & (ti << 4)) |
135 | 0 | ^ (0xff00ff00ff00ff00 & (ti << 8)) |
136 | 0 | ^ (0xf000f000f000f000 & (ti << 12)); |
137 | 0 | } |
138 | 0 | rkeys[rk_off..(rk_off + 8)].copy_from_slice(&tmp); |
139 | 0 | rk_off += 8; |
140 | | |
141 | 0 | sub_bytes(&mut tmp); |
142 | 0 | sub_bytes_nots(&mut tmp); |
143 | | |
144 | 0 | add_round_constant_bit(&mut tmp, rcon); |
145 | 0 | rcon += 1; |
146 | | |
147 | 0 | for i in 0..8 { |
148 | 0 | let mut ti = (0x00ff00ff00ff00ff & (rkeys[(rk_off - 16) + i] >> 8)) |
149 | 0 | | (0xff00ff00ff00ff00 & (rkeys[(rk_off - 8) + i] << 8)); |
150 | 0 | ti ^= 0x000f000f000f000f & ror(tmp[i], ror_distance(1, 3)); |
151 | 0 | rkeys[rk_off + i] = ti |
152 | 0 | ^ (0xfff0fff0fff0fff0 & (ti << 4)) |
153 | 0 | ^ (0xff00ff00ff00ff00 & (ti << 8)) |
154 | 0 | ^ (0xf000f000f000f000 & (ti << 12)); |
155 | 0 | } |
156 | 0 | rk_off += 8; |
157 | | |
158 | 0 | if rcon >= 8 { |
159 | 0 | break; |
160 | 0 | } |
161 | | |
162 | 0 | for i in 0..8 { |
163 | 0 | let ui = rkeys[(rk_off - 8) + i]; |
164 | 0 | let mut ti = rkeys[(rk_off - 16) + i]; |
165 | 0 | ti ^= 0x0f000f000f000f00 & (ui >> 4); |
166 | 0 | ti ^= 0xf000f000f000f000 & (ti << 4); |
167 | 0 | tmp[i] = ti; |
168 | 0 | } |
169 | | } |
170 | | |
171 | | // Adjust to match fixslicing format |
172 | | #[cfg(feature = "compact")] |
173 | | { |
174 | | for i in (8..104).step_by(16) { |
175 | | inv_shift_rows_1(&mut rkeys[i..(i + 8)]); |
176 | | } |
177 | | } |
178 | | #[cfg(not(feature = "compact"))] |
179 | | { |
180 | 0 | for i in (0..96).step_by(32) { |
181 | 0 | inv_shift_rows_1(&mut rkeys[(i + 8)..(i + 16)]); |
182 | 0 | inv_shift_rows_2(&mut rkeys[(i + 16)..(i + 24)]); |
183 | 0 | inv_shift_rows_3(&mut rkeys[(i + 24)..(i + 32)]); |
184 | 0 | } |
185 | | } |
186 | | |
187 | | // Account for NOTs removed from sub_bytes |
188 | 0 | for i in 1..13 { |
189 | 0 | sub_bytes_nots(&mut rkeys[(i * 8)..(i * 8 + 8)]); |
190 | 0 | } |
191 | | |
192 | 0 | rkeys |
193 | 0 | } |
194 | | |
195 | | /// Fully bitsliced AES-256 key schedule to match the fully-fixsliced representation. |
196 | 0 | pub(crate) fn aes256_key_schedule(key: &GenericArray<u8, U32>) -> FixsliceKeys256 { |
197 | 0 | let mut rkeys = [0u64; 120]; |
198 | | |
199 | 0 | bitslice( |
200 | 0 | &mut rkeys[..8], |
201 | 0 | &key[..16], |
202 | 0 | &key[..16], |
203 | 0 | &key[..16], |
204 | 0 | &key[..16], |
205 | | ); |
206 | 0 | bitslice( |
207 | 0 | &mut rkeys[8..16], |
208 | 0 | &key[16..], |
209 | 0 | &key[16..], |
210 | 0 | &key[16..], |
211 | 0 | &key[16..], |
212 | | ); |
213 | | |
214 | 0 | let mut rk_off = 8; |
215 | | |
216 | 0 | let mut rcon = 0; |
217 | | loop { |
218 | 0 | memshift32(&mut rkeys, rk_off); |
219 | 0 | rk_off += 8; |
220 | | |
221 | 0 | sub_bytes(&mut rkeys[rk_off..(rk_off + 8)]); |
222 | 0 | sub_bytes_nots(&mut rkeys[rk_off..(rk_off + 8)]); |
223 | | |
224 | 0 | add_round_constant_bit(&mut rkeys[rk_off..(rk_off + 8)], rcon); |
225 | 0 | xor_columns(&mut rkeys, rk_off, 16, ror_distance(1, 3)); |
226 | 0 | rcon += 1; |
227 | | |
228 | 0 | if rcon == 7 { |
229 | 0 | break; |
230 | 0 | } |
231 | | |
232 | 0 | memshift32(&mut rkeys, rk_off); |
233 | 0 | rk_off += 8; |
234 | | |
235 | 0 | sub_bytes(&mut rkeys[rk_off..(rk_off + 8)]); |
236 | 0 | sub_bytes_nots(&mut rkeys[rk_off..(rk_off + 8)]); |
237 | | |
238 | 0 | xor_columns(&mut rkeys, rk_off, 16, ror_distance(0, 3)); |
239 | | } |
240 | | |
241 | | // Adjust to match fixslicing format |
242 | | #[cfg(feature = "compact")] |
243 | | { |
244 | | for i in (8..120).step_by(16) { |
245 | | inv_shift_rows_1(&mut rkeys[i..(i + 8)]); |
246 | | } |
247 | | } |
248 | | #[cfg(not(feature = "compact"))] |
249 | | { |
250 | 0 | for i in (8..104).step_by(32) { |
251 | 0 | inv_shift_rows_1(&mut rkeys[i..(i + 8)]); |
252 | 0 | inv_shift_rows_2(&mut rkeys[(i + 8)..(i + 16)]); |
253 | 0 | inv_shift_rows_3(&mut rkeys[(i + 16)..(i + 24)]); |
254 | 0 | } |
255 | 0 | inv_shift_rows_1(&mut rkeys[104..112]); |
256 | | } |
257 | | |
258 | | // Account for NOTs removed from sub_bytes |
259 | 0 | for i in 1..15 { |
260 | 0 | sub_bytes_nots(&mut rkeys[(i * 8)..(i * 8 + 8)]); |
261 | 0 | } |
262 | | |
263 | 0 | rkeys |
264 | 0 | } |
265 | | |
266 | | /// Fully-fixsliced AES-128 decryption (the InvShiftRows is completely omitted). |
267 | | /// |
268 | | /// Decrypts four blocks in-place and in parallel. |
269 | 0 | pub(crate) fn aes128_decrypt(rkeys: &FixsliceKeys128, blocks: &mut [Block]) { |
270 | 0 | debug_assert_eq!(blocks.len(), FIXSLICE_BLOCKS); |
271 | 0 | let mut state = State::default(); |
272 | | |
273 | 0 | bitslice(&mut state, &blocks[0], &blocks[1], &blocks[2], &blocks[3]); |
274 | | |
275 | 0 | add_round_key(&mut state, &rkeys[80..]); |
276 | 0 | inv_sub_bytes(&mut state); |
277 | | |
278 | | #[cfg(not(feature = "compact"))] |
279 | 0 | { |
280 | 0 | inv_shift_rows_2(&mut state); |
281 | 0 | } |
282 | | |
283 | 0 | let mut rk_off = 72; |
284 | | loop { |
285 | | #[cfg(feature = "compact")] |
286 | | { |
287 | | inv_shift_rows_2(&mut state); |
288 | | } |
289 | | |
290 | 0 | add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); |
291 | 0 | inv_mix_columns_1(&mut state); |
292 | 0 | inv_sub_bytes(&mut state); |
293 | 0 | rk_off -= 8; |
294 | | |
295 | 0 | if rk_off == 0 { |
296 | 0 | break; |
297 | 0 | } |
298 | | |
299 | 0 | add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); |
300 | 0 | inv_mix_columns_0(&mut state); |
301 | 0 | inv_sub_bytes(&mut state); |
302 | 0 | rk_off -= 8; |
303 | | |
304 | | #[cfg(not(feature = "compact"))] |
305 | 0 | { |
306 | 0 | add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); |
307 | 0 | inv_mix_columns_3(&mut state); |
308 | 0 | inv_sub_bytes(&mut state); |
309 | 0 | rk_off -= 8; |
310 | 0 |
|
311 | 0 | add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); |
312 | 0 | inv_mix_columns_2(&mut state); |
313 | 0 | inv_sub_bytes(&mut state); |
314 | 0 | rk_off -= 8; |
315 | 0 | } |
316 | | } |
317 | | |
318 | 0 | add_round_key(&mut state, &rkeys[..8]); |
319 | | |
320 | 0 | inv_bitslice(&state, blocks); |
321 | 0 | } |
322 | | |
323 | | /// Fully-fixsliced AES-128 encryption (the ShiftRows is completely omitted). |
324 | | /// |
325 | | /// Encrypts four blocks in-place and in parallel. |
326 | 0 | pub(crate) fn aes128_encrypt(rkeys: &FixsliceKeys128, blocks: &mut [Block]) { |
327 | 0 | debug_assert_eq!(blocks.len(), FIXSLICE_BLOCKS); |
328 | 0 | let mut state = State::default(); |
329 | | |
330 | 0 | bitslice(&mut state, &blocks[0], &blocks[1], &blocks[2], &blocks[3]); |
331 | | |
332 | 0 | add_round_key(&mut state, &rkeys[..8]); |
333 | | |
334 | 0 | let mut rk_off = 8; |
335 | | loop { |
336 | 0 | sub_bytes(&mut state); |
337 | 0 | mix_columns_1(&mut state); |
338 | 0 | add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); |
339 | 0 | rk_off += 8; |
340 | | |
341 | | #[cfg(feature = "compact")] |
342 | | { |
343 | | shift_rows_2(&mut state); |
344 | | } |
345 | | |
346 | 0 | if rk_off == 80 { |
347 | 0 | break; |
348 | 0 | } |
349 | | |
350 | | #[cfg(not(feature = "compact"))] |
351 | 0 | { |
352 | 0 | sub_bytes(&mut state); |
353 | 0 | mix_columns_2(&mut state); |
354 | 0 | add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); |
355 | 0 | rk_off += 8; |
356 | 0 |
|
357 | 0 | sub_bytes(&mut state); |
358 | 0 | mix_columns_3(&mut state); |
359 | 0 | add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); |
360 | 0 | rk_off += 8; |
361 | 0 | } |
362 | | |
363 | 0 | sub_bytes(&mut state); |
364 | 0 | mix_columns_0(&mut state); |
365 | 0 | add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); |
366 | 0 | rk_off += 8; |
367 | | } |
368 | | |
369 | | #[cfg(not(feature = "compact"))] |
370 | 0 | { |
371 | 0 | shift_rows_2(&mut state); |
372 | 0 | } |
373 | | |
374 | 0 | sub_bytes(&mut state); |
375 | 0 | add_round_key(&mut state, &rkeys[80..]); |
376 | | |
377 | 0 | inv_bitslice(&state, blocks); |
378 | 0 | } |
379 | | |
380 | | /// Fully-fixsliced AES-192 decryption (the InvShiftRows is completely omitted). |
381 | | /// |
382 | | /// Decrypts four blocks in-place and in parallel. |
383 | 0 | pub(crate) fn aes192_decrypt(rkeys: &FixsliceKeys192, blocks: &mut [Block]) { |
384 | 0 | debug_assert_eq!(blocks.len(), FIXSLICE_BLOCKS); |
385 | 0 | let mut state = State::default(); |
386 | | |
387 | 0 | bitslice(&mut state, &blocks[0], &blocks[1], &blocks[2], &blocks[3]); |
388 | | |
389 | 0 | add_round_key(&mut state, &rkeys[96..]); |
390 | 0 | inv_sub_bytes(&mut state); |
391 | | |
392 | 0 | let mut rk_off = 88; |
393 | | loop { |
394 | | #[cfg(feature = "compact")] |
395 | | { |
396 | | inv_shift_rows_2(&mut state); |
397 | | } |
398 | | #[cfg(not(feature = "compact"))] |
399 | 0 | { |
400 | 0 | add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); |
401 | 0 | inv_mix_columns_3(&mut state); |
402 | 0 | inv_sub_bytes(&mut state); |
403 | 0 | rk_off -= 8; |
404 | 0 |
|
405 | 0 | add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); |
406 | 0 | inv_mix_columns_2(&mut state); |
407 | 0 | inv_sub_bytes(&mut state); |
408 | 0 | rk_off -= 8; |
409 | 0 | } |
410 | | |
411 | 0 | add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); |
412 | 0 | inv_mix_columns_1(&mut state); |
413 | 0 | inv_sub_bytes(&mut state); |
414 | 0 | rk_off -= 8; |
415 | | |
416 | 0 | if rk_off == 0 { |
417 | 0 | break; |
418 | 0 | } |
419 | | |
420 | 0 | add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); |
421 | 0 | inv_mix_columns_0(&mut state); |
422 | 0 | inv_sub_bytes(&mut state); |
423 | 0 | rk_off -= 8; |
424 | | } |
425 | | |
426 | 0 | add_round_key(&mut state, &rkeys[..8]); |
427 | | |
428 | 0 | inv_bitslice(&state, blocks); |
429 | 0 | } |
430 | | |
431 | | /// Fully-fixsliced AES-192 encryption (the ShiftRows is completely omitted). |
432 | | /// |
433 | | /// Encrypts four blocks in-place and in parallel. |
434 | 0 | pub(crate) fn aes192_encrypt(rkeys: &FixsliceKeys192, blocks: &mut [Block]) { |
435 | 0 | debug_assert_eq!(blocks.len(), FIXSLICE_BLOCKS); |
436 | 0 | let mut state = State::default(); |
437 | | |
438 | 0 | bitslice(&mut state, &blocks[0], &blocks[1], &blocks[2], &blocks[3]); |
439 | | |
440 | 0 | add_round_key(&mut state, &rkeys[..8]); |
441 | | |
442 | 0 | let mut rk_off = 8; |
443 | | loop { |
444 | 0 | sub_bytes(&mut state); |
445 | 0 | mix_columns_1(&mut state); |
446 | 0 | add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); |
447 | 0 | rk_off += 8; |
448 | | |
449 | | #[cfg(feature = "compact")] |
450 | | { |
451 | | shift_rows_2(&mut state); |
452 | | } |
453 | | #[cfg(not(feature = "compact"))] |
454 | 0 | { |
455 | 0 | sub_bytes(&mut state); |
456 | 0 | mix_columns_2(&mut state); |
457 | 0 | add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); |
458 | 0 | rk_off += 8; |
459 | 0 |
|
460 | 0 | sub_bytes(&mut state); |
461 | 0 | mix_columns_3(&mut state); |
462 | 0 | add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); |
463 | 0 | rk_off += 8; |
464 | 0 | } |
465 | | |
466 | 0 | if rk_off == 96 { |
467 | 0 | break; |
468 | 0 | } |
469 | | |
470 | 0 | sub_bytes(&mut state); |
471 | 0 | mix_columns_0(&mut state); |
472 | 0 | add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); |
473 | 0 | rk_off += 8; |
474 | | } |
475 | | |
476 | 0 | sub_bytes(&mut state); |
477 | 0 | add_round_key(&mut state, &rkeys[96..]); |
478 | | |
479 | 0 | inv_bitslice(&state, blocks); |
480 | 0 | } |
481 | | |
482 | | /// Fully-fixsliced AES-256 decryption (the InvShiftRows is completely omitted). |
483 | | /// |
484 | | /// Decrypts four blocks in-place and in parallel. |
485 | 0 | pub(crate) fn aes256_decrypt(rkeys: &FixsliceKeys256, blocks: &mut [Block]) { |
486 | 0 | debug_assert_eq!(blocks.len(), FIXSLICE_BLOCKS); |
487 | 0 | let mut state = State::default(); |
488 | | |
489 | 0 | bitslice(&mut state, &blocks[0], &blocks[1], &blocks[2], &blocks[3]); |
490 | | |
491 | 0 | add_round_key(&mut state, &rkeys[112..]); |
492 | 0 | inv_sub_bytes(&mut state); |
493 | | |
494 | | #[cfg(not(feature = "compact"))] |
495 | 0 | { |
496 | 0 | inv_shift_rows_2(&mut state); |
497 | 0 | } |
498 | | |
499 | 0 | let mut rk_off = 104; |
500 | | loop { |
501 | | #[cfg(feature = "compact")] |
502 | | { |
503 | | inv_shift_rows_2(&mut state); |
504 | | } |
505 | | |
506 | 0 | add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); |
507 | 0 | inv_mix_columns_1(&mut state); |
508 | 0 | inv_sub_bytes(&mut state); |
509 | 0 | rk_off -= 8; |
510 | | |
511 | 0 | if rk_off == 0 { |
512 | 0 | break; |
513 | 0 | } |
514 | | |
515 | 0 | add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); |
516 | 0 | inv_mix_columns_0(&mut state); |
517 | 0 | inv_sub_bytes(&mut state); |
518 | 0 | rk_off -= 8; |
519 | | |
520 | | #[cfg(not(feature = "compact"))] |
521 | 0 | { |
522 | 0 | add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); |
523 | 0 | inv_mix_columns_3(&mut state); |
524 | 0 | inv_sub_bytes(&mut state); |
525 | 0 | rk_off -= 8; |
526 | 0 |
|
527 | 0 | add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); |
528 | 0 | inv_mix_columns_2(&mut state); |
529 | 0 | inv_sub_bytes(&mut state); |
530 | 0 | rk_off -= 8; |
531 | 0 | } |
532 | | } |
533 | | |
534 | 0 | add_round_key(&mut state, &rkeys[..8]); |
535 | | |
536 | 0 | inv_bitslice(&state, blocks); |
537 | 0 | } |
538 | | |
539 | | /// Fully-fixsliced AES-256 encryption (the ShiftRows is completely omitted). |
540 | | /// |
541 | | /// Encrypts four blocks in-place and in parallel. |
542 | 0 | pub(crate) fn aes256_encrypt(rkeys: &FixsliceKeys256, blocks: &mut [Block]) { |
543 | 0 | debug_assert_eq!(blocks.len(), FIXSLICE_BLOCKS); |
544 | 0 | let mut state = State::default(); |
545 | | |
546 | 0 | bitslice(&mut state, &blocks[0], &blocks[1], &blocks[2], &blocks[3]); |
547 | | |
548 | 0 | add_round_key(&mut state, &rkeys[..8]); |
549 | | |
550 | 0 | let mut rk_off = 8; |
551 | | loop { |
552 | 0 | sub_bytes(&mut state); |
553 | 0 | mix_columns_1(&mut state); |
554 | 0 | add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); |
555 | 0 | rk_off += 8; |
556 | | |
557 | | #[cfg(feature = "compact")] |
558 | | { |
559 | | shift_rows_2(&mut state); |
560 | | } |
561 | | |
562 | 0 | if rk_off == 112 { |
563 | 0 | break; |
564 | 0 | } |
565 | | |
566 | | #[cfg(not(feature = "compact"))] |
567 | 0 | { |
568 | 0 | sub_bytes(&mut state); |
569 | 0 | mix_columns_2(&mut state); |
570 | 0 | add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); |
571 | 0 | rk_off += 8; |
572 | 0 |
|
573 | 0 | sub_bytes(&mut state); |
574 | 0 | mix_columns_3(&mut state); |
575 | 0 | add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); |
576 | 0 | rk_off += 8; |
577 | 0 | } |
578 | | |
579 | 0 | sub_bytes(&mut state); |
580 | 0 | mix_columns_0(&mut state); |
581 | 0 | add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); |
582 | 0 | rk_off += 8; |
583 | | } |
584 | | |
585 | | #[cfg(not(feature = "compact"))] |
586 | 0 | { |
587 | 0 | shift_rows_2(&mut state); |
588 | 0 | } |
589 | | |
590 | 0 | sub_bytes(&mut state); |
591 | 0 | add_round_key(&mut state, &rkeys[112..]); |
592 | | |
593 | 0 | inv_bitslice(&state, blocks); |
594 | 0 | } |
595 | | |
596 | | /// Note that the 4 bitwise NOT (^= 0xffffffffffffffff) are accounted for here so that it is a true |
597 | | /// inverse of 'sub_bytes'. |
598 | 0 | fn inv_sub_bytes(state: &mut [u64]) { |
599 | 0 | debug_assert_eq!(state.len(), 8); |
600 | | |
601 | | // Scheduled using https://github.com/Ko-/aes-armcortexm/tree/public/scheduler |
602 | | // Inline "stack" comments reflect suggested stores and loads (ARM Cortex-M3 and M4) |
603 | | |
604 | 0 | let u7 = state[0]; |
605 | 0 | let u6 = state[1]; |
606 | 0 | let u5 = state[2]; |
607 | 0 | let u4 = state[3]; |
608 | 0 | let u3 = state[4]; |
609 | 0 | let u2 = state[5]; |
610 | 0 | let u1 = state[6]; |
611 | 0 | let u0 = state[7]; |
612 | | |
613 | 0 | let t23 = u0 ^ u3; |
614 | 0 | let t8 = u1 ^ t23; |
615 | 0 | let m2 = t23 & t8; |
616 | 0 | let t4 = u4 ^ t8; |
617 | 0 | let t22 = u1 ^ u3; |
618 | 0 | let t2 = u0 ^ u1; |
619 | 0 | let t1 = u3 ^ u4; |
620 | | // t23 -> stack |
621 | 0 | let t9 = u7 ^ t1; |
622 | | // t8 -> stack |
623 | 0 | let m7 = t22 & t9; |
624 | | // t9 -> stack |
625 | 0 | let t24 = u4 ^ u7; |
626 | | // m7 -> stack |
627 | 0 | let t10 = t2 ^ t24; |
628 | | // u4 -> stack |
629 | 0 | let m14 = t2 & t10; |
630 | 0 | let r5 = u6 ^ u7; |
631 | | // m2 -> stack |
632 | 0 | let t3 = t1 ^ r5; |
633 | | // t2 -> stack |
634 | 0 | let t13 = t2 ^ r5; |
635 | 0 | let t19 = t22 ^ r5; |
636 | | // t3 -> stack |
637 | 0 | let t17 = u2 ^ t19; |
638 | | // t4 -> stack |
639 | 0 | let t25 = u2 ^ t1; |
640 | 0 | let r13 = u1 ^ u6; |
641 | | // t25 -> stack |
642 | 0 | let t20 = t24 ^ r13; |
643 | | // t17 -> stack |
644 | 0 | let m9 = t20 & t17; |
645 | | // t20 -> stack |
646 | 0 | let r17 = u2 ^ u5; |
647 | | // t22 -> stack |
648 | 0 | let t6 = t22 ^ r17; |
649 | | // t13 -> stack |
650 | 0 | let m1 = t13 & t6; |
651 | 0 | let y5 = u0 ^ r17; |
652 | 0 | let m4 = t19 & y5; |
653 | 0 | let m5 = m4 ^ m1; |
654 | 0 | let m17 = m5 ^ t24; |
655 | 0 | let r18 = u5 ^ u6; |
656 | 0 | let t27 = t1 ^ r18; |
657 | 0 | let t15 = t10 ^ t27; |
658 | | // t6 -> stack |
659 | 0 | let m11 = t1 & t15; |
660 | 0 | let m15 = m14 ^ m11; |
661 | 0 | let m21 = m17 ^ m15; |
662 | | // t1 -> stack |
663 | | // t4 <- stack |
664 | 0 | let m12 = t4 & t27; |
665 | 0 | let m13 = m12 ^ m11; |
666 | 0 | let t14 = t10 ^ r18; |
667 | 0 | let m3 = t14 ^ m1; |
668 | | // m2 <- stack |
669 | 0 | let m16 = m3 ^ m2; |
670 | 0 | let m20 = m16 ^ m13; |
671 | | // u4 <- stack |
672 | 0 | let r19 = u2 ^ u4; |
673 | 0 | let t16 = r13 ^ r19; |
674 | | // t3 <- stack |
675 | 0 | let t26 = t3 ^ t16; |
676 | 0 | let m6 = t3 & t16; |
677 | 0 | let m8 = t26 ^ m6; |
678 | | // t10 -> stack |
679 | | // m7 <- stack |
680 | 0 | let m18 = m8 ^ m7; |
681 | 0 | let m22 = m18 ^ m13; |
682 | 0 | let m25 = m22 & m20; |
683 | 0 | let m26 = m21 ^ m25; |
684 | 0 | let m10 = m9 ^ m6; |
685 | 0 | let m19 = m10 ^ m15; |
686 | | // t25 <- stack |
687 | 0 | let m23 = m19 ^ t25; |
688 | 0 | let m28 = m23 ^ m25; |
689 | 0 | let m24 = m22 ^ m23; |
690 | 0 | let m30 = m26 & m24; |
691 | 0 | let m39 = m23 ^ m30; |
692 | 0 | let m48 = m39 & y5; |
693 | 0 | let m57 = m39 & t19; |
694 | | // m48 -> stack |
695 | 0 | let m36 = m24 ^ m25; |
696 | 0 | let m31 = m20 & m23; |
697 | 0 | let m27 = m20 ^ m21; |
698 | 0 | let m32 = m27 & m31; |
699 | 0 | let m29 = m28 & m27; |
700 | 0 | let m37 = m21 ^ m29; |
701 | | // m39 -> stack |
702 | 0 | let m42 = m37 ^ m39; |
703 | 0 | let m52 = m42 & t15; |
704 | | // t27 -> stack |
705 | | // t1 <- stack |
706 | 0 | let m61 = m42 & t1; |
707 | 0 | let p0 = m52 ^ m61; |
708 | 0 | let p16 = m57 ^ m61; |
709 | | // m57 -> stack |
710 | | // t20 <- stack |
711 | 0 | let m60 = m37 & t20; |
712 | | // p16 -> stack |
713 | | // t17 <- stack |
714 | 0 | let m51 = m37 & t17; |
715 | 0 | let m33 = m27 ^ m25; |
716 | 0 | let m38 = m32 ^ m33; |
717 | 0 | let m43 = m37 ^ m38; |
718 | 0 | let m49 = m43 & t16; |
719 | 0 | let p6 = m49 ^ m60; |
720 | 0 | let p13 = m49 ^ m51; |
721 | 0 | let m58 = m43 & t3; |
722 | | // t9 <- stack |
723 | 0 | let m50 = m38 & t9; |
724 | | // t22 <- stack |
725 | 0 | let m59 = m38 & t22; |
726 | | // p6 -> stack |
727 | 0 | let p1 = m58 ^ m59; |
728 | 0 | let p7 = p0 ^ p1; |
729 | 0 | let m34 = m21 & m22; |
730 | 0 | let m35 = m24 & m34; |
731 | 0 | let m40 = m35 ^ m36; |
732 | 0 | let m41 = m38 ^ m40; |
733 | 0 | let m45 = m42 ^ m41; |
734 | | // t27 <- stack |
735 | 0 | let m53 = m45 & t27; |
736 | 0 | let p8 = m50 ^ m53; |
737 | 0 | let p23 = p7 ^ p8; |
738 | | // t4 <- stack |
739 | 0 | let m62 = m45 & t4; |
740 | 0 | let p14 = m49 ^ m62; |
741 | 0 | let s6 = p14 ^ p23; |
742 | | // t10 <- stack |
743 | 0 | let m54 = m41 & t10; |
744 | 0 | let p2 = m54 ^ m62; |
745 | 0 | let p22 = p2 ^ p7; |
746 | 0 | let s0 = p13 ^ p22; |
747 | 0 | let p17 = m58 ^ p2; |
748 | 0 | let p15 = m54 ^ m59; |
749 | | // t2 <- stack |
750 | 0 | let m63 = m41 & t2; |
751 | | // m39 <- stack |
752 | 0 | let m44 = m39 ^ m40; |
753 | | // p17 -> stack |
754 | | // t6 <- stack |
755 | 0 | let m46 = m44 & t6; |
756 | 0 | let p5 = m46 ^ m51; |
757 | | // p23 -> stack |
758 | 0 | let p18 = m63 ^ p5; |
759 | 0 | let p24 = p5 ^ p7; |
760 | | // m48 <- stack |
761 | 0 | let p12 = m46 ^ m48; |
762 | 0 | let s3 = p12 ^ p22; |
763 | | // t13 <- stack |
764 | 0 | let m55 = m44 & t13; |
765 | 0 | let p9 = m55 ^ m63; |
766 | | // p16 <- stack |
767 | 0 | let s7 = p9 ^ p16; |
768 | | // t8 <- stack |
769 | 0 | let m47 = m40 & t8; |
770 | 0 | let p3 = m47 ^ m50; |
771 | 0 | let p19 = p2 ^ p3; |
772 | 0 | let s5 = p19 ^ p24; |
773 | 0 | let p11 = p0 ^ p3; |
774 | 0 | let p26 = p9 ^ p11; |
775 | | // t23 <- stack |
776 | 0 | let m56 = m40 & t23; |
777 | 0 | let p4 = m48 ^ m56; |
778 | | // p6 <- stack |
779 | 0 | let p20 = p4 ^ p6; |
780 | 0 | let p29 = p15 ^ p20; |
781 | 0 | let s1 = p26 ^ p29; |
782 | | // m57 <- stack |
783 | 0 | let p10 = m57 ^ p4; |
784 | 0 | let p27 = p10 ^ p18; |
785 | | // p23 <- stack |
786 | 0 | let s4 = p23 ^ p27; |
787 | 0 | let p25 = p6 ^ p10; |
788 | 0 | let p28 = p11 ^ p25; |
789 | | // p17 <- stack |
790 | 0 | let s2 = p17 ^ p28; |
791 | | |
792 | 0 | state[0] = s7; |
793 | 0 | state[1] = s6; |
794 | 0 | state[2] = s5; |
795 | 0 | state[3] = s4; |
796 | 0 | state[4] = s3; |
797 | 0 | state[5] = s2; |
798 | 0 | state[6] = s1; |
799 | 0 | state[7] = s0; |
800 | 0 | } |
801 | | |
802 | | /// Bitsliced implementation of the AES Sbox based on Boyar, Peralta and Calik. |
803 | | /// |
804 | | /// See: <http://www.cs.yale.edu/homes/peralta/CircuitStuff/SLP_AES_113.txt> |
805 | | /// |
806 | | /// Note that the 4 bitwise NOT (^= 0xffffffffffffffff) are moved to the key schedule. |
807 | 0 | fn sub_bytes(state: &mut [u64]) { |
808 | 0 | debug_assert_eq!(state.len(), 8); |
809 | | |
810 | | // Scheduled using https://github.com/Ko-/aes-armcortexm/tree/public/scheduler |
811 | | // Inline "stack" comments reflect suggested stores and loads (ARM Cortex-M3 and M4) |
812 | | |
813 | 0 | let u7 = state[0]; |
814 | 0 | let u6 = state[1]; |
815 | 0 | let u5 = state[2]; |
816 | 0 | let u4 = state[3]; |
817 | 0 | let u3 = state[4]; |
818 | 0 | let u2 = state[5]; |
819 | 0 | let u1 = state[6]; |
820 | 0 | let u0 = state[7]; |
821 | | |
822 | 0 | let y14 = u3 ^ u5; |
823 | 0 | let y13 = u0 ^ u6; |
824 | 0 | let y12 = y13 ^ y14; |
825 | 0 | let t1 = u4 ^ y12; |
826 | 0 | let y15 = t1 ^ u5; |
827 | 0 | let t2 = y12 & y15; |
828 | 0 | let y6 = y15 ^ u7; |
829 | 0 | let y20 = t1 ^ u1; |
830 | | // y12 -> stack |
831 | 0 | let y9 = u0 ^ u3; |
832 | | // y20 -> stack |
833 | 0 | let y11 = y20 ^ y9; |
834 | | // y9 -> stack |
835 | 0 | let t12 = y9 & y11; |
836 | | // y6 -> stack |
837 | 0 | let y7 = u7 ^ y11; |
838 | 0 | let y8 = u0 ^ u5; |
839 | 0 | let t0 = u1 ^ u2; |
840 | 0 | let y10 = y15 ^ t0; |
841 | | // y15 -> stack |
842 | 0 | let y17 = y10 ^ y11; |
843 | | // y14 -> stack |
844 | 0 | let t13 = y14 & y17; |
845 | 0 | let t14 = t13 ^ t12; |
846 | | // y17 -> stack |
847 | 0 | let y19 = y10 ^ y8; |
848 | | // y10 -> stack |
849 | 0 | let t15 = y8 & y10; |
850 | 0 | let t16 = t15 ^ t12; |
851 | 0 | let y16 = t0 ^ y11; |
852 | | // y11 -> stack |
853 | 0 | let y21 = y13 ^ y16; |
854 | | // y13 -> stack |
855 | 0 | let t7 = y13 & y16; |
856 | | // y16 -> stack |
857 | 0 | let y18 = u0 ^ y16; |
858 | 0 | let y1 = t0 ^ u7; |
859 | 0 | let y4 = y1 ^ u3; |
860 | | // u7 -> stack |
861 | 0 | let t5 = y4 & u7; |
862 | 0 | let t6 = t5 ^ t2; |
863 | 0 | let t18 = t6 ^ t16; |
864 | 0 | let t22 = t18 ^ y19; |
865 | 0 | let y2 = y1 ^ u0; |
866 | 0 | let t10 = y2 & y7; |
867 | 0 | let t11 = t10 ^ t7; |
868 | 0 | let t20 = t11 ^ t16; |
869 | 0 | let t24 = t20 ^ y18; |
870 | 0 | let y5 = y1 ^ u6; |
871 | 0 | let t8 = y5 & y1; |
872 | 0 | let t9 = t8 ^ t7; |
873 | 0 | let t19 = t9 ^ t14; |
874 | 0 | let t23 = t19 ^ y21; |
875 | 0 | let y3 = y5 ^ y8; |
876 | | // y6 <- stack |
877 | 0 | let t3 = y3 & y6; |
878 | 0 | let t4 = t3 ^ t2; |
879 | | // y20 <- stack |
880 | 0 | let t17 = t4 ^ y20; |
881 | 0 | let t21 = t17 ^ t14; |
882 | 0 | let t26 = t21 & t23; |
883 | 0 | let t27 = t24 ^ t26; |
884 | 0 | let t31 = t22 ^ t26; |
885 | 0 | let t25 = t21 ^ t22; |
886 | | // y4 -> stack |
887 | 0 | let t28 = t25 & t27; |
888 | 0 | let t29 = t28 ^ t22; |
889 | 0 | let z14 = t29 & y2; |
890 | 0 | let z5 = t29 & y7; |
891 | 0 | let t30 = t23 ^ t24; |
892 | 0 | let t32 = t31 & t30; |
893 | 0 | let t33 = t32 ^ t24; |
894 | 0 | let t35 = t27 ^ t33; |
895 | 0 | let t36 = t24 & t35; |
896 | 0 | let t38 = t27 ^ t36; |
897 | 0 | let t39 = t29 & t38; |
898 | 0 | let t40 = t25 ^ t39; |
899 | 0 | let t43 = t29 ^ t40; |
900 | | // y16 <- stack |
901 | 0 | let z3 = t43 & y16; |
902 | 0 | let tc12 = z3 ^ z5; |
903 | | // tc12 -> stack |
904 | | // y13 <- stack |
905 | 0 | let z12 = t43 & y13; |
906 | 0 | let z13 = t40 & y5; |
907 | 0 | let z4 = t40 & y1; |
908 | 0 | let tc6 = z3 ^ z4; |
909 | 0 | let t34 = t23 ^ t33; |
910 | 0 | let t37 = t36 ^ t34; |
911 | 0 | let t41 = t40 ^ t37; |
912 | | // y10 <- stack |
913 | 0 | let z8 = t41 & y10; |
914 | 0 | let z17 = t41 & y8; |
915 | 0 | let t44 = t33 ^ t37; |
916 | | // y15 <- stack |
917 | 0 | let z0 = t44 & y15; |
918 | | // z17 -> stack |
919 | | // y12 <- stack |
920 | 0 | let z9 = t44 & y12; |
921 | 0 | let z10 = t37 & y3; |
922 | 0 | let z1 = t37 & y6; |
923 | 0 | let tc5 = z1 ^ z0; |
924 | 0 | let tc11 = tc6 ^ tc5; |
925 | | // y4 <- stack |
926 | 0 | let z11 = t33 & y4; |
927 | 0 | let t42 = t29 ^ t33; |
928 | 0 | let t45 = t42 ^ t41; |
929 | | // y17 <- stack |
930 | 0 | let z7 = t45 & y17; |
931 | 0 | let tc8 = z7 ^ tc6; |
932 | | // y14 <- stack |
933 | 0 | let z16 = t45 & y14; |
934 | | // y11 <- stack |
935 | 0 | let z6 = t42 & y11; |
936 | 0 | let tc16 = z6 ^ tc8; |
937 | | // z14 -> stack |
938 | | // y9 <- stack |
939 | 0 | let z15 = t42 & y9; |
940 | 0 | let tc20 = z15 ^ tc16; |
941 | 0 | let tc1 = z15 ^ z16; |
942 | 0 | let tc2 = z10 ^ tc1; |
943 | 0 | let tc21 = tc2 ^ z11; |
944 | 0 | let tc3 = z9 ^ tc2; |
945 | 0 | let s0 = tc3 ^ tc16; |
946 | 0 | let s3 = tc3 ^ tc11; |
947 | 0 | let s1 = s3 ^ tc16; |
948 | 0 | let tc13 = z13 ^ tc1; |
949 | | // u7 <- stack |
950 | 0 | let z2 = t33 & u7; |
951 | 0 | let tc4 = z0 ^ z2; |
952 | 0 | let tc7 = z12 ^ tc4; |
953 | 0 | let tc9 = z8 ^ tc7; |
954 | 0 | let tc10 = tc8 ^ tc9; |
955 | | // z14 <- stack |
956 | 0 | let tc17 = z14 ^ tc10; |
957 | 0 | let s5 = tc21 ^ tc17; |
958 | 0 | let tc26 = tc17 ^ tc20; |
959 | | // z17 <- stack |
960 | 0 | let s2 = tc26 ^ z17; |
961 | | // tc12 <- stack |
962 | 0 | let tc14 = tc4 ^ tc12; |
963 | 0 | let tc18 = tc13 ^ tc14; |
964 | 0 | let s6 = tc10 ^ tc18; |
965 | 0 | let s7 = z12 ^ tc18; |
966 | 0 | let s4 = tc14 ^ s3; |
967 | | |
968 | 0 | state[0] = s7; |
969 | 0 | state[1] = s6; |
970 | 0 | state[2] = s5; |
971 | 0 | state[3] = s4; |
972 | 0 | state[4] = s3; |
973 | 0 | state[5] = s2; |
974 | 0 | state[6] = s1; |
975 | 0 | state[7] = s0; |
976 | 0 | } |
977 | | |
978 | | /// NOT operations that are omitted in S-box |
979 | | #[inline] |
980 | 0 | fn sub_bytes_nots(state: &mut [u64]) { |
981 | 0 | debug_assert_eq!(state.len(), 8); |
982 | 0 | state[0] ^= 0xffffffffffffffff; |
983 | 0 | state[1] ^= 0xffffffffffffffff; |
984 | 0 | state[5] ^= 0xffffffffffffffff; |
985 | 0 | state[6] ^= 0xffffffffffffffff; |
986 | 0 | } |
987 | | |
988 | | /// Computation of the MixColumns transformation in the fixsliced representation, with different |
989 | | /// rotations used according to the round number mod 4. |
990 | | /// |
991 | | /// Based on Käsper-Schwabe, similar to https://github.com/Ko-/aes-armcortexm. |
992 | | macro_rules! define_mix_columns { |
993 | | ( |
994 | | $name:ident, |
995 | | $name_inv:ident, |
996 | | $first_rotate:path, |
997 | | $second_rotate:path |
998 | | ) => { |
999 | | #[rustfmt::skip] |
1000 | 0 | fn $name(state: &mut State) { |
1001 | 0 | let (a0, a1, a2, a3, a4, a5, a6, a7) = ( |
1002 | 0 | state[0], state[1], state[2], state[3], state[4], state[5], state[6], state[7] |
1003 | 0 | ); |
1004 | 0 | let (b0, b1, b2, b3, b4, b5, b6, b7) = ( |
1005 | 0 | $first_rotate(a0), |
1006 | 0 | $first_rotate(a1), |
1007 | 0 | $first_rotate(a2), |
1008 | 0 | $first_rotate(a3), |
1009 | 0 | $first_rotate(a4), |
1010 | 0 | $first_rotate(a5), |
1011 | 0 | $first_rotate(a6), |
1012 | 0 | $first_rotate(a7), |
1013 | 0 | ); |
1014 | 0 | let (c0, c1, c2, c3, c4, c5, c6, c7) = ( |
1015 | 0 | a0 ^ b0, |
1016 | 0 | a1 ^ b1, |
1017 | 0 | a2 ^ b2, |
1018 | 0 | a3 ^ b3, |
1019 | 0 | a4 ^ b4, |
1020 | 0 | a5 ^ b5, |
1021 | 0 | a6 ^ b6, |
1022 | 0 | a7 ^ b7, |
1023 | 0 | ); |
1024 | 0 | state[0] = b0 ^ c7 ^ $second_rotate(c0); |
1025 | 0 | state[1] = b1 ^ c0 ^ c7 ^ $second_rotate(c1); |
1026 | 0 | state[2] = b2 ^ c1 ^ $second_rotate(c2); |
1027 | 0 | state[3] = b3 ^ c2 ^ c7 ^ $second_rotate(c3); |
1028 | 0 | state[4] = b4 ^ c3 ^ c7 ^ $second_rotate(c4); |
1029 | 0 | state[5] = b5 ^ c4 ^ $second_rotate(c5); |
1030 | 0 | state[6] = b6 ^ c5 ^ $second_rotate(c6); |
1031 | 0 | state[7] = b7 ^ c6 ^ $second_rotate(c7); |
1032 | 0 | } Unexecuted instantiation: aes::soft::fixslice::mix_columns_0 Unexecuted instantiation: aes::soft::fixslice::mix_columns_1 Unexecuted instantiation: aes::soft::fixslice::mix_columns_2 Unexecuted instantiation: aes::soft::fixslice::mix_columns_3 |
1033 | | |
1034 | | #[rustfmt::skip] |
1035 | 0 | fn $name_inv(state: &mut State) { |
1036 | 0 | let (a0, a1, a2, a3, a4, a5, a6, a7) = ( |
1037 | 0 | state[0], state[1], state[2], state[3], state[4], state[5], state[6], state[7] |
1038 | 0 | ); |
1039 | 0 | let (b0, b1, b2, b3, b4, b5, b6, b7) = ( |
1040 | 0 | $first_rotate(a0), |
1041 | 0 | $first_rotate(a1), |
1042 | 0 | $first_rotate(a2), |
1043 | 0 | $first_rotate(a3), |
1044 | 0 | $first_rotate(a4), |
1045 | 0 | $first_rotate(a5), |
1046 | 0 | $first_rotate(a6), |
1047 | 0 | $first_rotate(a7), |
1048 | 0 | ); |
1049 | 0 | let (c0, c1, c2, c3, c4, c5, c6, c7) = ( |
1050 | 0 | a0 ^ b0, |
1051 | 0 | a1 ^ b1, |
1052 | 0 | a2 ^ b2, |
1053 | 0 | a3 ^ b3, |
1054 | 0 | a4 ^ b4, |
1055 | 0 | a5 ^ b5, |
1056 | 0 | a6 ^ b6, |
1057 | 0 | a7 ^ b7, |
1058 | 0 | ); |
1059 | 0 | let (d0, d1, d2, d3, d4, d5, d6, d7) = ( |
1060 | 0 | a0 ^ c7, |
1061 | 0 | a1 ^ c0 ^ c7, |
1062 | 0 | a2 ^ c1, |
1063 | 0 | a3 ^ c2 ^ c7, |
1064 | 0 | a4 ^ c3 ^ c7, |
1065 | 0 | a5 ^ c4, |
1066 | 0 | a6 ^ c5, |
1067 | 0 | a7 ^ c6, |
1068 | 0 | ); |
1069 | 0 | let (e0, e1, e2, e3, e4, e5, e6, e7) = ( |
1070 | 0 | c0 ^ d6, |
1071 | 0 | c1 ^ d6 ^ d7, |
1072 | 0 | c2 ^ d0 ^ d7, |
1073 | 0 | c3 ^ d1 ^ d6, |
1074 | 0 | c4 ^ d2 ^ d6 ^ d7, |
1075 | 0 | c5 ^ d3 ^ d7, |
1076 | 0 | c6 ^ d4, |
1077 | 0 | c7 ^ d5, |
1078 | 0 | ); |
1079 | 0 | state[0] = d0 ^ e0 ^ $second_rotate(e0); |
1080 | 0 | state[1] = d1 ^ e1 ^ $second_rotate(e1); |
1081 | 0 | state[2] = d2 ^ e2 ^ $second_rotate(e2); |
1082 | 0 | state[3] = d3 ^ e3 ^ $second_rotate(e3); |
1083 | 0 | state[4] = d4 ^ e4 ^ $second_rotate(e4); |
1084 | 0 | state[5] = d5 ^ e5 ^ $second_rotate(e5); |
1085 | 0 | state[6] = d6 ^ e6 ^ $second_rotate(e6); |
1086 | 0 | state[7] = d7 ^ e7 ^ $second_rotate(e7); |
1087 | 0 | } Unexecuted instantiation: aes::soft::fixslice::inv_mix_columns_0 Unexecuted instantiation: aes::soft::fixslice::inv_mix_columns_1 Unexecuted instantiation: aes::soft::fixslice::inv_mix_columns_2 Unexecuted instantiation: aes::soft::fixslice::inv_mix_columns_3 |
1088 | | } |
1089 | | } |
1090 | | |
1091 | | define_mix_columns!( |
1092 | | mix_columns_0, |
1093 | | inv_mix_columns_0, |
1094 | | rotate_rows_1, |
1095 | | rotate_rows_2 |
1096 | | ); |
1097 | | |
1098 | | define_mix_columns!( |
1099 | | mix_columns_1, |
1100 | | inv_mix_columns_1, |
1101 | | rotate_rows_and_columns_1_1, |
1102 | | rotate_rows_and_columns_2_2 |
1103 | | ); |
1104 | | |
1105 | | #[cfg(not(feature = "compact"))] |
1106 | | define_mix_columns!( |
1107 | | mix_columns_2, |
1108 | | inv_mix_columns_2, |
1109 | | rotate_rows_and_columns_1_2, |
1110 | | rotate_rows_2 |
1111 | | ); |
1112 | | |
1113 | | #[cfg(not(feature = "compact"))] |
1114 | | define_mix_columns!( |
1115 | | mix_columns_3, |
1116 | | inv_mix_columns_3, |
1117 | | rotate_rows_and_columns_1_3, |
1118 | | rotate_rows_and_columns_2_2 |
1119 | | ); |
1120 | | |
1121 | | #[inline] |
1122 | 0 | fn delta_swap_1(a: &mut u64, shift: u32, mask: u64) { |
1123 | 0 | let t = (*a ^ ((*a) >> shift)) & mask; |
1124 | 0 | *a ^= t ^ (t << shift); |
1125 | 0 | } |
1126 | | |
1127 | | #[inline] |
1128 | 0 | fn delta_swap_2(a: &mut u64, b: &mut u64, shift: u32, mask: u64) { |
1129 | 0 | let t = (*a ^ ((*b) >> shift)) & mask; |
1130 | 0 | *a ^= t; |
1131 | 0 | *b ^= t << shift; |
1132 | 0 | } |
1133 | | |
1134 | | /// Applies ShiftRows once on an AES state (or key). |
1135 | | #[cfg(any(not(feature = "compact"), feature = "hazmat"))] |
1136 | | #[inline] |
1137 | 0 | fn shift_rows_1(state: &mut [u64]) { |
1138 | 0 | debug_assert_eq!(state.len(), 8); |
1139 | 0 | for x in state.iter_mut() { |
1140 | 0 | delta_swap_1(x, 8, 0x00f000ff000f0000); |
1141 | 0 | delta_swap_1(x, 4, 0x0f0f00000f0f0000); |
1142 | 0 | } |
1143 | 0 | } |
1144 | | |
1145 | | /// Applies ShiftRows twice on an AES state (or key). |
1146 | | #[inline] |
1147 | 0 | fn shift_rows_2(state: &mut [u64]) { |
1148 | 0 | debug_assert_eq!(state.len(), 8); |
1149 | 0 | for x in state.iter_mut() { |
1150 | 0 | delta_swap_1(x, 8, 0x00ff000000ff0000); |
1151 | 0 | } |
1152 | 0 | } |
1153 | | |
1154 | | /// Applies ShiftRows three times on an AES state (or key). |
1155 | | #[inline] |
1156 | 0 | fn shift_rows_3(state: &mut [u64]) { |
1157 | 0 | debug_assert_eq!(state.len(), 8); |
1158 | 0 | for x in state.iter_mut() { |
1159 | 0 | delta_swap_1(x, 8, 0x000f00ff00f00000); |
1160 | 0 | delta_swap_1(x, 4, 0x0f0f00000f0f0000); |
1161 | 0 | } |
1162 | 0 | } |
1163 | | |
1164 | | #[inline(always)] |
1165 | 0 | fn inv_shift_rows_1(state: &mut [u64]) { |
1166 | 0 | shift_rows_3(state); |
1167 | 0 | } |
1168 | | |
1169 | | #[inline(always)] |
1170 | 0 | fn inv_shift_rows_2(state: &mut [u64]) { |
1171 | 0 | shift_rows_2(state); |
1172 | 0 | } |
1173 | | |
1174 | | #[cfg(not(feature = "compact"))] |
1175 | | #[inline(always)] |
1176 | 0 | fn inv_shift_rows_3(state: &mut [u64]) { |
1177 | 0 | shift_rows_1(state); |
1178 | 0 | } |
1179 | | |
1180 | | /// XOR the columns after the S-box during the key schedule round function. |
1181 | | /// |
1182 | | /// The `idx_xor` parameter refers to the index of the previous round key that is |
1183 | | /// involved in the XOR computation (should be 8 and 16 for AES-128 and AES-256, |
1184 | | /// respectively). |
1185 | | /// |
1186 | | /// The `idx_ror` parameter refers to the rotation value, which varies between the |
1187 | | /// different key schedules. |
1188 | 0 | fn xor_columns(rkeys: &mut [u64], offset: usize, idx_xor: usize, idx_ror: u32) { |
1189 | 0 | for i in 0..8 { |
1190 | 0 | let off_i = offset + i; |
1191 | 0 | let rk = rkeys[off_i - idx_xor] ^ (0x000f000f000f000f & ror(rkeys[off_i], idx_ror)); |
1192 | 0 | rkeys[off_i] = rk |
1193 | 0 | ^ (0xfff0fff0fff0fff0 & (rk << 4)) |
1194 | 0 | ^ (0xff00ff00ff00ff00 & (rk << 8)) |
1195 | 0 | ^ (0xf000f000f000f000 & (rk << 12)); |
1196 | 0 | } |
1197 | 0 | } |
1198 | | |
1199 | | /// Bitslice four 128-bit input blocks input0, input1, input2, input3 into a 512-bit internal state. |
1200 | 0 | fn bitslice(output: &mut [u64], input0: &[u8], input1: &[u8], input2: &[u8], input3: &[u8]) { |
1201 | 0 | debug_assert_eq!(output.len(), 8); |
1202 | 0 | debug_assert_eq!(input0.len(), 16); |
1203 | 0 | debug_assert_eq!(input1.len(), 16); |
1204 | 0 | debug_assert_eq!(input2.len(), 16); |
1205 | 0 | debug_assert_eq!(input3.len(), 16); |
1206 | | |
1207 | | // Bitslicing is a bit index manipulation. 512 bits of data means each bit is positioned at a |
1208 | | // 9-bit index. AES data is 4 blocks, each one a 4x4 column-major matrix of bytes, so the |
1209 | | // index is initially ([b]lock, [c]olumn, [r]ow, [p]osition): |
1210 | | // b1 b0 c1 c0 r1 r0 p2 p1 p0 |
1211 | | // |
1212 | | // The desired bitsliced data groups first by bit position, then row, column, block: |
1213 | | // p2 p1 p0 r1 r0 c1 c0 b1 b0 |
1214 | | |
1215 | | #[rustfmt::skip] |
1216 | 0 | fn read_reordered(input: &[u8]) -> u64 { |
1217 | 0 | (u64::from(input[0x0]) ) | |
1218 | 0 | (u64::from(input[0x1]) << 0x10) | |
1219 | 0 | (u64::from(input[0x2]) << 0x20) | |
1220 | 0 | (u64::from(input[0x3]) << 0x30) | |
1221 | 0 | (u64::from(input[0x8]) << 0x08) | |
1222 | 0 | (u64::from(input[0x9]) << 0x18) | |
1223 | 0 | (u64::from(input[0xa]) << 0x28) | |
1224 | 0 | (u64::from(input[0xb]) << 0x38) |
1225 | 0 | } |
1226 | | |
1227 | | // Reorder each block's bytes on input |
1228 | | // __ __ c1 c0 r1 r0 __ __ __ => __ __ c0 r1 r0 c1 __ __ __ |
1229 | | // Reorder by relabeling (note the order of input) |
1230 | | // b1 b0 c0 __ __ __ __ __ __ => c0 b1 b0 __ __ __ __ __ __ |
1231 | 0 | let mut t0 = read_reordered(&input0[0x00..0x0c]); |
1232 | 0 | let mut t4 = read_reordered(&input0[0x04..0x10]); |
1233 | 0 | let mut t1 = read_reordered(&input1[0x00..0x0c]); |
1234 | 0 | let mut t5 = read_reordered(&input1[0x04..0x10]); |
1235 | 0 | let mut t2 = read_reordered(&input2[0x00..0x0c]); |
1236 | 0 | let mut t6 = read_reordered(&input2[0x04..0x10]); |
1237 | 0 | let mut t3 = read_reordered(&input3[0x00..0x0c]); |
1238 | 0 | let mut t7 = read_reordered(&input3[0x04..0x10]); |
1239 | | |
1240 | | // Bit Index Swap 6 <-> 0: |
1241 | | // __ __ b0 __ __ __ __ __ p0 => __ __ p0 __ __ __ __ __ b0 |
1242 | 0 | let m0 = 0x5555555555555555; |
1243 | 0 | delta_swap_2(&mut t1, &mut t0, 1, m0); |
1244 | 0 | delta_swap_2(&mut t3, &mut t2, 1, m0); |
1245 | 0 | delta_swap_2(&mut t5, &mut t4, 1, m0); |
1246 | 0 | delta_swap_2(&mut t7, &mut t6, 1, m0); |
1247 | | |
1248 | | // Bit Index Swap 7 <-> 1: |
1249 | | // __ b1 __ __ __ __ __ p1 __ => __ p1 __ __ __ __ __ b1 __ |
1250 | 0 | let m1 = 0x3333333333333333; |
1251 | 0 | delta_swap_2(&mut t2, &mut t0, 2, m1); |
1252 | 0 | delta_swap_2(&mut t3, &mut t1, 2, m1); |
1253 | 0 | delta_swap_2(&mut t6, &mut t4, 2, m1); |
1254 | 0 | delta_swap_2(&mut t7, &mut t5, 2, m1); |
1255 | | |
1256 | | // Bit Index Swap 8 <-> 2: |
1257 | | // c0 __ __ __ __ __ p2 __ __ => p2 __ __ __ __ __ c0 __ __ |
1258 | 0 | let m2 = 0x0f0f0f0f0f0f0f0f; |
1259 | 0 | delta_swap_2(&mut t4, &mut t0, 4, m2); |
1260 | 0 | delta_swap_2(&mut t5, &mut t1, 4, m2); |
1261 | 0 | delta_swap_2(&mut t6, &mut t2, 4, m2); |
1262 | 0 | delta_swap_2(&mut t7, &mut t3, 4, m2); |
1263 | | |
1264 | | // Final bitsliced bit index, as desired: |
1265 | | // p2 p1 p0 r1 r0 c1 c0 b1 b0 |
1266 | 0 | output[0] = t0; |
1267 | 0 | output[1] = t1; |
1268 | 0 | output[2] = t2; |
1269 | 0 | output[3] = t3; |
1270 | 0 | output[4] = t4; |
1271 | 0 | output[5] = t5; |
1272 | 0 | output[6] = t6; |
1273 | 0 | output[7] = t7; |
1274 | 0 | } |
1275 | | |
1276 | | /// Un-bitslice a 512-bit internal state into four 128-bit blocks of output. |
1277 | 0 | fn inv_bitslice(input: &[u64], output: &mut [Block]) { |
1278 | 0 | debug_assert_eq!(input.len(), 8); |
1279 | 0 | debug_assert_eq!(output.len(), 4); |
1280 | | |
1281 | | // Unbitslicing is a bit index manipulation. 512 bits of data means each bit is positioned at |
1282 | | // a 9-bit index. AES data is 4 blocks, each one a 4x4 column-major matrix of bytes, so the |
1283 | | // desired index for the output is ([b]lock, [c]olumn, [r]ow, [p]osition): |
1284 | | // b1 b0 c1 c0 r1 r0 p2 p1 p0 |
1285 | | // |
1286 | | // The initially bitsliced data groups first by bit position, then row, column, block: |
1287 | | // p2 p1 p0 r1 r0 c1 c0 b1 b0 |
1288 | | |
1289 | 0 | let mut t0 = input[0]; |
1290 | 0 | let mut t1 = input[1]; |
1291 | 0 | let mut t2 = input[2]; |
1292 | 0 | let mut t3 = input[3]; |
1293 | 0 | let mut t4 = input[4]; |
1294 | 0 | let mut t5 = input[5]; |
1295 | 0 | let mut t6 = input[6]; |
1296 | 0 | let mut t7 = input[7]; |
1297 | | |
1298 | | // TODO: these bit index swaps are identical to those in 'packing' |
1299 | | |
1300 | | // Bit Index Swap 6 <-> 0: |
1301 | | // __ __ p0 __ __ __ __ __ b0 => __ __ b0 __ __ __ __ __ p0 |
1302 | 0 | let m0 = 0x5555555555555555; |
1303 | 0 | delta_swap_2(&mut t1, &mut t0, 1, m0); |
1304 | 0 | delta_swap_2(&mut t3, &mut t2, 1, m0); |
1305 | 0 | delta_swap_2(&mut t5, &mut t4, 1, m0); |
1306 | 0 | delta_swap_2(&mut t7, &mut t6, 1, m0); |
1307 | | |
1308 | | // Bit Index Swap 7 <-> 1: |
1309 | | // __ p1 __ __ __ __ __ b1 __ => __ b1 __ __ __ __ __ p1 __ |
1310 | 0 | let m1 = 0x3333333333333333; |
1311 | 0 | delta_swap_2(&mut t2, &mut t0, 2, m1); |
1312 | 0 | delta_swap_2(&mut t3, &mut t1, 2, m1); |
1313 | 0 | delta_swap_2(&mut t6, &mut t4, 2, m1); |
1314 | 0 | delta_swap_2(&mut t7, &mut t5, 2, m1); |
1315 | | |
1316 | | // Bit Index Swap 8 <-> 2: |
1317 | | // p2 __ __ __ __ __ c0 __ __ => c0 __ __ __ __ __ p2 __ __ |
1318 | 0 | let m2 = 0x0f0f0f0f0f0f0f0f; |
1319 | 0 | delta_swap_2(&mut t4, &mut t0, 4, m2); |
1320 | 0 | delta_swap_2(&mut t5, &mut t1, 4, m2); |
1321 | 0 | delta_swap_2(&mut t6, &mut t2, 4, m2); |
1322 | 0 | delta_swap_2(&mut t7, &mut t3, 4, m2); |
1323 | | |
1324 | | #[rustfmt::skip] |
1325 | 0 | fn write_reordered(columns: u64, output: &mut [u8]) { |
1326 | 0 | output[0x0] = (columns ) as u8; |
1327 | 0 | output[0x1] = (columns >> 0x10) as u8; |
1328 | 0 | output[0x2] = (columns >> 0x20) as u8; |
1329 | 0 | output[0x3] = (columns >> 0x30) as u8; |
1330 | 0 | output[0x8] = (columns >> 0x08) as u8; |
1331 | 0 | output[0x9] = (columns >> 0x18) as u8; |
1332 | 0 | output[0xa] = (columns >> 0x28) as u8; |
1333 | 0 | output[0xb] = (columns >> 0x38) as u8; |
1334 | 0 | } |
1335 | | |
1336 | | // Reorder by relabeling (note the order of output) |
1337 | | // c0 b1 b0 __ __ __ __ __ __ => b1 b0 c0 __ __ __ __ __ __ |
1338 | | // Reorder each block's bytes on output |
1339 | | // __ __ c0 r1 r0 c1 __ __ __ => __ __ c1 c0 r1 r0 __ __ __ |
1340 | 0 | write_reordered(t0, &mut output[0][0x00..0x0c]); |
1341 | 0 | write_reordered(t4, &mut output[0][0x04..0x10]); |
1342 | 0 | write_reordered(t1, &mut output[1][0x00..0x0c]); |
1343 | 0 | write_reordered(t5, &mut output[1][0x04..0x10]); |
1344 | 0 | write_reordered(t2, &mut output[2][0x00..0x0c]); |
1345 | 0 | write_reordered(t6, &mut output[2][0x04..0x10]); |
1346 | 0 | write_reordered(t3, &mut output[3][0x00..0x0c]); |
1347 | 0 | write_reordered(t7, &mut output[3][0x04..0x10]); |
1348 | | |
1349 | | // Final AES bit index, as desired: |
1350 | | // b1 b0 c1 c0 r1 r0 p2 p1 p0 |
1351 | 0 | } |
1352 | | |
1353 | | /// Copy 32-bytes within the provided slice to an 8-byte offset |
1354 | 0 | fn memshift32(buffer: &mut [u64], src_offset: usize) { |
1355 | 0 | debug_assert_eq!(src_offset % 8, 0); |
1356 | | |
1357 | 0 | let dst_offset = src_offset + 8; |
1358 | 0 | debug_assert!(dst_offset + 8 <= buffer.len()); |
1359 | | |
1360 | 0 | for i in (0..8).rev() { |
1361 | 0 | buffer[dst_offset + i] = buffer[src_offset + i]; |
1362 | 0 | } |
1363 | 0 | } |
1364 | | |
1365 | | /// XOR the round key to the internal state. The round keys are expected to be |
1366 | | /// pre-computed and to be packed in the fixsliced representation. |
1367 | | #[inline] |
1368 | 0 | fn add_round_key(state: &mut State, rkey: &[u64]) { |
1369 | 0 | debug_assert_eq!(rkey.len(), 8); |
1370 | 0 | for (a, b) in state.iter_mut().zip(rkey) { |
1371 | 0 | *a ^= b; |
1372 | 0 | } |
1373 | 0 | } |
1374 | | |
1375 | | #[inline(always)] |
1376 | 0 | fn add_round_constant_bit(state: &mut [u64], bit: usize) { |
1377 | 0 | state[bit] ^= 0x00000000f0000000; |
1378 | 0 | } |
1379 | | |
1380 | | #[inline(always)] |
1381 | 0 | fn ror(x: u64, y: u32) -> u64 { |
1382 | 0 | x.rotate_right(y) |
1383 | 0 | } |
1384 | | |
1385 | | #[inline(always)] |
1386 | 0 | fn ror_distance(rows: u32, cols: u32) -> u32 { |
1387 | 0 | (rows << 4) + (cols << 2) |
1388 | 0 | } |
1389 | | |
1390 | | #[inline(always)] |
1391 | 0 | fn rotate_rows_1(x: u64) -> u64 { |
1392 | 0 | ror(x, ror_distance(1, 0)) |
1393 | 0 | } |
1394 | | |
1395 | | #[inline(always)] |
1396 | 0 | fn rotate_rows_2(x: u64) -> u64 { |
1397 | 0 | ror(x, ror_distance(2, 0)) |
1398 | 0 | } |
1399 | | |
1400 | | #[inline(always)] |
1401 | | #[rustfmt::skip] |
1402 | 0 | fn rotate_rows_and_columns_1_1(x: u64) -> u64 { |
1403 | 0 | (ror(x, ror_distance(1, 1)) & 0x0fff0fff0fff0fff) | |
1404 | 0 | (ror(x, ror_distance(0, 1)) & 0xf000f000f000f000) |
1405 | 0 | } |
1406 | | |
1407 | | #[cfg(not(feature = "compact"))] |
1408 | | #[inline(always)] |
1409 | | #[rustfmt::skip] |
1410 | 0 | fn rotate_rows_and_columns_1_2(x: u64) -> u64 { |
1411 | 0 | (ror(x, ror_distance(1, 2)) & 0x00ff00ff00ff00ff) | |
1412 | 0 | (ror(x, ror_distance(0, 2)) & 0xff00ff00ff00ff00) |
1413 | 0 | } |
1414 | | |
1415 | | #[cfg(not(feature = "compact"))] |
1416 | | #[inline(always)] |
1417 | | #[rustfmt::skip] |
1418 | 0 | fn rotate_rows_and_columns_1_3(x: u64) -> u64 { |
1419 | 0 | (ror(x, ror_distance(1, 3)) & 0x000f000f000f000f) | |
1420 | 0 | (ror(x, ror_distance(0, 3)) & 0xfff0fff0fff0fff0) |
1421 | 0 | } |
1422 | | |
1423 | | #[inline(always)] |
1424 | | #[rustfmt::skip] |
1425 | 0 | fn rotate_rows_and_columns_2_2(x: u64) -> u64 { |
1426 | 0 | (ror(x, ror_distance(2, 2)) & 0x00ff00ff00ff00ff) | |
1427 | 0 | (ror(x, ror_distance(1, 2)) & 0xff00ff00ff00ff00) |
1428 | 0 | } |
1429 | | |
1430 | | /// Low-level "hazmat" AES functions. |
1431 | | /// |
1432 | | /// Note: this isn't actually used in the `Aes128`/`Aes192`/`Aes256` |
1433 | | /// implementations in this crate, but instead provides raw access to |
1434 | | /// the AES round function gated under the `hazmat` crate feature. |
1435 | | #[cfg(feature = "hazmat")] |
1436 | | pub(crate) mod hazmat { |
1437 | | use super::{ |
1438 | | bitslice, inv_bitslice, inv_mix_columns_0, inv_shift_rows_1, inv_sub_bytes, mix_columns_0, |
1439 | | shift_rows_1, sub_bytes, sub_bytes_nots, State, |
1440 | | }; |
1441 | | use crate::{Block, ParBlocks}; |
1442 | | |
1443 | | /// XOR the `src` block into the `dst` block in-place. |
1444 | | fn xor_in_place(dst: &mut Block, src: &Block) { |
1445 | | for (a, b) in dst.iter_mut().zip(src.as_slice()) { |
1446 | | *a ^= *b; |
1447 | | } |
1448 | | } |
1449 | | |
1450 | | /// Perform a bitslice operation, loading a single block. |
1451 | | fn bitslice_block(block: &Block) -> State { |
1452 | | let mut state = State::default(); |
1453 | | bitslice(&mut state, block, block, block, block); |
1454 | | state |
1455 | | } |
1456 | | |
1457 | | /// Perform an inverse bitslice operation, extracting a single block. |
1458 | | fn inv_bitslice_block(block: &mut Block, state: &State) { |
1459 | | let mut out = [Block::default(); 4]; |
1460 | | inv_bitslice(state, &mut out); |
1461 | | block.copy_from_slice(&out[0]); |
1462 | | } |
1463 | | |
1464 | | /// AES cipher (encrypt) round function. |
1465 | | #[inline] |
1466 | | pub(crate) fn cipher_round(block: &mut Block, round_key: &Block) { |
1467 | | let mut state = bitslice_block(block); |
1468 | | sub_bytes(&mut state); |
1469 | | sub_bytes_nots(&mut state); |
1470 | | shift_rows_1(&mut state); |
1471 | | mix_columns_0(&mut state); |
1472 | | inv_bitslice_block(block, &state); |
1473 | | xor_in_place(block, round_key); |
1474 | | } |
1475 | | |
1476 | | /// AES cipher (encrypt) round function: parallel version. |
1477 | | #[inline] |
1478 | | pub(crate) fn cipher_round_par(blocks: &mut ParBlocks, round_keys: &ParBlocks) { |
1479 | | for (chunk, keys) in blocks.chunks_exact_mut(4).zip(round_keys.chunks_exact(4)) { |
1480 | | let mut state = State::default(); |
1481 | | bitslice(&mut state, &chunk[0], &chunk[1], &chunk[2], &chunk[3]); |
1482 | | sub_bytes(&mut state); |
1483 | | sub_bytes_nots(&mut state); |
1484 | | shift_rows_1(&mut state); |
1485 | | mix_columns_0(&mut state); |
1486 | | inv_bitslice(&state, chunk); |
1487 | | |
1488 | | for i in 0..4 { |
1489 | | xor_in_place(&mut chunk[i], &keys[i]); |
1490 | | } |
1491 | | } |
1492 | | } |
1493 | | |
1494 | | /// AES cipher (encrypt) round function. |
1495 | | #[inline] |
1496 | | pub(crate) fn equiv_inv_cipher_round(block: &mut Block, round_key: &Block) { |
1497 | | let mut state = State::default(); |
1498 | | bitslice(&mut state, &block, &block, &block, &block); |
1499 | | sub_bytes_nots(&mut state); |
1500 | | inv_sub_bytes(&mut state); |
1501 | | inv_shift_rows_1(&mut state); |
1502 | | inv_mix_columns_0(&mut state); |
1503 | | inv_bitslice_block(block, &state); |
1504 | | xor_in_place(block, round_key); |
1505 | | } |
1506 | | |
1507 | | /// AES cipher (encrypt) round function: parallel version. |
1508 | | #[inline] |
1509 | | pub(crate) fn equiv_inv_cipher_round_par(blocks: &mut ParBlocks, round_keys: &ParBlocks) { |
1510 | | for (chunk, keys) in blocks.chunks_exact_mut(4).zip(round_keys.chunks_exact(4)) { |
1511 | | let mut state = State::default(); |
1512 | | bitslice(&mut state, &chunk[0], &chunk[1], &chunk[2], &chunk[3]); |
1513 | | sub_bytes_nots(&mut state); |
1514 | | inv_sub_bytes(&mut state); |
1515 | | inv_shift_rows_1(&mut state); |
1516 | | inv_mix_columns_0(&mut state); |
1517 | | inv_bitslice(&state, chunk); |
1518 | | |
1519 | | for i in 0..4 { |
1520 | | xor_in_place(&mut chunk[i], &keys[i]); |
1521 | | } |
1522 | | } |
1523 | | } |
1524 | | |
1525 | | /// AES mix columns function. |
1526 | | #[inline] |
1527 | | pub(crate) fn mix_columns(block: &mut Block) { |
1528 | | let mut state = bitslice_block(block); |
1529 | | mix_columns_0(&mut state); |
1530 | | inv_bitslice_block(block, &state); |
1531 | | } |
1532 | | |
1533 | | /// AES inverse mix columns function. |
1534 | | #[inline] |
1535 | | pub(crate) fn inv_mix_columns(block: &mut Block) { |
1536 | | let mut state = bitslice_block(block); |
1537 | | inv_mix_columns_0(&mut state); |
1538 | | inv_bitslice_block(block, &state); |
1539 | | } |
1540 | | } |