Coverage Report

Created: 2026-08-14 07:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}