Skip to main content

aes/backends/fixslice/
aes256.rs

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