Skip to main content

aes/backends/fixslice/
mix_columns.rs

1use super::{State, Word};
2
3/// Computation of the MixColumns transformation in the fixsliced representation,
4/// with different rotations used according to the round number mod 4.
5///
6/// Based on Käsper-Schwabe, similar to https://github.com/Ko-/aes-armcortexm.
7macro_rules! define_mix_columns {
8    (
9        $name:ident,
10        $name_inv:ident,
11        $first_rotate:path,
12        $second_rotate:path
13    ) => {
14        #[rustfmt::skip]
15        pub(super) fn $name<W: Word>(state: &mut State<W>) {
16            let (a0, a1, a2, a3, a4, a5, a6, a7) = (
17                state[0], state[1], state[2], state[3], state[4], state[5], state[6], state[7]
18            );
19            let (b0, b1, b2, b3, b4, b5, b6, b7) = (
20                $first_rotate(a0),
21                $first_rotate(a1),
22                $first_rotate(a2),
23                $first_rotate(a3),
24                $first_rotate(a4),
25                $first_rotate(a5),
26                $first_rotate(a6),
27                $first_rotate(a7),
28            );
29            let (c0, c1, c2, c3, c4, c5, c6, c7) = (
30                a0 ^ b0,
31                a1 ^ b1,
32                a2 ^ b2,
33                a3 ^ b3,
34                a4 ^ b4,
35                a5 ^ b5,
36                a6 ^ b6,
37                a7 ^ b7,
38            );
39            state[0] = b0      ^ c7 ^ $second_rotate(c0);
40            state[1] = b1 ^ c0 ^ c7 ^ $second_rotate(c1);
41            state[2] = b2 ^ c1      ^ $second_rotate(c2);
42            state[3] = b3 ^ c2 ^ c7 ^ $second_rotate(c3);
43            state[4] = b4 ^ c3 ^ c7 ^ $second_rotate(c4);
44            state[5] = b5 ^ c4      ^ $second_rotate(c5);
45            state[6] = b6 ^ c5      ^ $second_rotate(c6);
46            state[7] = b7 ^ c6      ^ $second_rotate(c7);
47        }
48
49        #[rustfmt::skip]
50        pub(super) fn $name_inv<W: Word>(state: &mut State<W>) {
51            let (a0, a1, a2, a3, a4, a5, a6, a7) = (
52                state[0], state[1], state[2], state[3], state[4], state[5], state[6], state[7]
53            );
54            let (b0, b1, b2, b3, b4, b5, b6, b7) = (
55                $first_rotate(a0),
56                $first_rotate(a1),
57                $first_rotate(a2),
58                $first_rotate(a3),
59                $first_rotate(a4),
60                $first_rotate(a5),
61                $first_rotate(a6),
62                $first_rotate(a7),
63            );
64            let (c0, c1, c2, c3, c4, c5, c6, c7) = (
65                a0 ^ b0,
66                a1 ^ b1,
67                a2 ^ b2,
68                a3 ^ b3,
69                a4 ^ b4,
70                a5 ^ b5,
71                a6 ^ b6,
72                a7 ^ b7,
73            );
74            let (d0, d1, d2, d3, d4, d5, d6, d7) = (
75                a0      ^ c7,
76                a1 ^ c0 ^ c7,
77                a2 ^ c1,
78                a3 ^ c2 ^ c7,
79                a4 ^ c3 ^ c7,
80                a5 ^ c4,
81                a6 ^ c5,
82                a7 ^ c6,
83            );
84            let (e0, e1, e2, e3, e4, e5, e6, e7) = (
85                c0      ^ d6,
86                c1      ^ d6 ^ d7,
87                c2 ^ d0      ^ d7,
88                c3 ^ d1 ^ d6,
89                c4 ^ d2 ^ d6 ^ d7,
90                c5 ^ d3      ^ d7,
91                c6 ^ d4,
92                c7 ^ d5,
93            );
94            state[0] = d0 ^ e0 ^ $second_rotate(e0);
95            state[1] = d1 ^ e1 ^ $second_rotate(e1);
96            state[2] = d2 ^ e2 ^ $second_rotate(e2);
97            state[3] = d3 ^ e3 ^ $second_rotate(e3);
98            state[4] = d4 ^ e4 ^ $second_rotate(e4);
99            state[5] = d5 ^ e5 ^ $second_rotate(e5);
100            state[6] = d6 ^ e6 ^ $second_rotate(e6);
101            state[7] = d7 ^ e7 ^ $second_rotate(e7);
102        }
103    };
104}
105
106define_mix_columns!(
107    mix_columns_0,
108    inv_mix_columns_0,
109    rotate_rows_1,
110    rotate_rows_2
111);
112
113define_mix_columns!(
114    mix_columns_1,
115    inv_mix_columns_1,
116    rotate_rows_and_columns_1_1,
117    rotate_rows_and_columns_2_2
118);
119
120#[cfg(not(aes_backend_soft = "compact"))]
121define_mix_columns!(
122    mix_columns_2,
123    inv_mix_columns_2,
124    rotate_rows_and_columns_1_2,
125    rotate_rows_2
126);
127
128#[cfg(not(aes_backend_soft = "compact"))]
129define_mix_columns!(
130    mix_columns_3,
131    inv_mix_columns_3,
132    rotate_rows_and_columns_1_3,
133    rotate_rows_and_columns_2_2
134);
135
136#[inline(always)]
137fn rotate_rows_1<W: Word>(x: W) -> W {
138    x.ror(W::ror_distance(1, 0))
139}
140
141#[inline(always)]
142fn rotate_rows_2<W: Word>(x: W) -> W {
143    x.ror(W::ror_distance(2, 0))
144}
145
146#[inline(always)]
147fn rotate_rows_and_columns_1_1<W: Word>(x: W) -> W {
148    let a = x.ror(W::ror_distance(1, 1)) & W::uniform_row(0x3f);
149    let b = x.ror(W::ror_distance(0, 1)) & W::uniform_row(0xc0);
150    a | b
151}
152
153#[cfg(not(aes_backend_soft = "compact"))]
154#[inline(always)]
155fn rotate_rows_and_columns_1_2<W: Word>(x: W) -> W {
156    let a = x.ror(W::ror_distance(1, 2)) & W::uniform_row(0x0f);
157    let b = x.ror(W::ror_distance(0, 2)) & W::uniform_row(0xf0);
158    a | b
159}
160
161#[cfg(not(aes_backend_soft = "compact"))]
162#[inline(always)]
163fn rotate_rows_and_columns_1_3<W: Word>(x: W) -> W {
164    let a = x.ror(W::ror_distance(1, 3)) & W::uniform_row(0x03);
165    let b = x.ror(W::ror_distance(0, 3)) & W::uniform_row(0xfc);
166    a | b
167}
168
169#[inline(always)]
170fn rotate_rows_and_columns_2_2<W: Word>(x: W) -> W {
171    let a = x.ror(W::ror_distance(2, 2)) & W::uniform_row(0x0f);
172    let b = x.ror(W::ror_distance(1, 2)) & W::uniform_row(0xf0);
173    a | b
174}