/src/BearSSL/src/symcipher/aes_ct64.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org> |
3 | | * |
4 | | * Permission is hereby granted, free of charge, to any person obtaining |
5 | | * a copy of this software and associated documentation files (the |
6 | | * "Software"), to deal in the Software without restriction, including |
7 | | * without limitation the rights to use, copy, modify, merge, publish, |
8 | | * distribute, sublicense, and/or sell copies of the Software, and to |
9 | | * permit persons to whom the Software is furnished to do so, subject to |
10 | | * the following conditions: |
11 | | * |
12 | | * The above copyright notice and this permission notice shall be |
13 | | * included in all copies or substantial portions of the Software. |
14 | | * |
15 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
16 | | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
17 | | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
18 | | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
19 | | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
20 | | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
21 | | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
22 | | * SOFTWARE. |
23 | | */ |
24 | | |
25 | | #include "inner.h" |
26 | | |
27 | | /* see inner.h */ |
28 | | void |
29 | | br_aes_ct64_bitslice_Sbox(uint64_t *q) |
30 | 110k | { |
31 | | /* |
32 | | * This S-box implementation is a straightforward translation of |
33 | | * the circuit described by Boyar and Peralta in "A new |
34 | | * combinational logic minimization technique with applications |
35 | | * to cryptology" (https://eprint.iacr.org/2009/191.pdf). |
36 | | * |
37 | | * Note that variables x* (input) and s* (output) are numbered |
38 | | * in "reverse" order (x0 is the high bit, x7 is the low bit). |
39 | | */ |
40 | | |
41 | 110k | uint64_t x0, x1, x2, x3, x4, x5, x6, x7; |
42 | 110k | uint64_t y1, y2, y3, y4, y5, y6, y7, y8, y9; |
43 | 110k | uint64_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; |
44 | 110k | uint64_t y20, y21; |
45 | 110k | uint64_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; |
46 | 110k | uint64_t z10, z11, z12, z13, z14, z15, z16, z17; |
47 | 110k | uint64_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; |
48 | 110k | uint64_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; |
49 | 110k | uint64_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; |
50 | 110k | uint64_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; |
51 | 110k | uint64_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; |
52 | 110k | uint64_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; |
53 | 110k | uint64_t t60, t61, t62, t63, t64, t65, t66, t67; |
54 | 110k | uint64_t s0, s1, s2, s3, s4, s5, s6, s7; |
55 | | |
56 | 110k | x0 = q[7]; |
57 | 110k | x1 = q[6]; |
58 | 110k | x2 = q[5]; |
59 | 110k | x3 = q[4]; |
60 | 110k | x4 = q[3]; |
61 | 110k | x5 = q[2]; |
62 | 110k | x6 = q[1]; |
63 | 110k | x7 = q[0]; |
64 | | |
65 | | /* |
66 | | * Top linear transformation. |
67 | | */ |
68 | 110k | y14 = x3 ^ x5; |
69 | 110k | y13 = x0 ^ x6; |
70 | 110k | y9 = x0 ^ x3; |
71 | 110k | y8 = x0 ^ x5; |
72 | 110k | t0 = x1 ^ x2; |
73 | 110k | y1 = t0 ^ x7; |
74 | 110k | y4 = y1 ^ x3; |
75 | 110k | y12 = y13 ^ y14; |
76 | 110k | y2 = y1 ^ x0; |
77 | 110k | y5 = y1 ^ x6; |
78 | 110k | y3 = y5 ^ y8; |
79 | 110k | t1 = x4 ^ y12; |
80 | 110k | y15 = t1 ^ x5; |
81 | 110k | y20 = t1 ^ x1; |
82 | 110k | y6 = y15 ^ x7; |
83 | 110k | y10 = y15 ^ t0; |
84 | 110k | y11 = y20 ^ y9; |
85 | 110k | y7 = x7 ^ y11; |
86 | 110k | y17 = y10 ^ y11; |
87 | 110k | y19 = y10 ^ y8; |
88 | 110k | y16 = t0 ^ y11; |
89 | 110k | y21 = y13 ^ y16; |
90 | 110k | y18 = x0 ^ y16; |
91 | | |
92 | | /* |
93 | | * Non-linear section. |
94 | | */ |
95 | 110k | t2 = y12 & y15; |
96 | 110k | t3 = y3 & y6; |
97 | 110k | t4 = t3 ^ t2; |
98 | 110k | t5 = y4 & x7; |
99 | 110k | t6 = t5 ^ t2; |
100 | 110k | t7 = y13 & y16; |
101 | 110k | t8 = y5 & y1; |
102 | 110k | t9 = t8 ^ t7; |
103 | 110k | t10 = y2 & y7; |
104 | 110k | t11 = t10 ^ t7; |
105 | 110k | t12 = y9 & y11; |
106 | 110k | t13 = y14 & y17; |
107 | 110k | t14 = t13 ^ t12; |
108 | 110k | t15 = y8 & y10; |
109 | 110k | t16 = t15 ^ t12; |
110 | 110k | t17 = t4 ^ t14; |
111 | 110k | t18 = t6 ^ t16; |
112 | 110k | t19 = t9 ^ t14; |
113 | 110k | t20 = t11 ^ t16; |
114 | 110k | t21 = t17 ^ y20; |
115 | 110k | t22 = t18 ^ y19; |
116 | 110k | t23 = t19 ^ y21; |
117 | 110k | t24 = t20 ^ y18; |
118 | | |
119 | 110k | t25 = t21 ^ t22; |
120 | 110k | t26 = t21 & t23; |
121 | 110k | t27 = t24 ^ t26; |
122 | 110k | t28 = t25 & t27; |
123 | 110k | t29 = t28 ^ t22; |
124 | 110k | t30 = t23 ^ t24; |
125 | 110k | t31 = t22 ^ t26; |
126 | 110k | t32 = t31 & t30; |
127 | 110k | t33 = t32 ^ t24; |
128 | 110k | t34 = t23 ^ t33; |
129 | 110k | t35 = t27 ^ t33; |
130 | 110k | t36 = t24 & t35; |
131 | 110k | t37 = t36 ^ t34; |
132 | 110k | t38 = t27 ^ t36; |
133 | 110k | t39 = t29 & t38; |
134 | 110k | t40 = t25 ^ t39; |
135 | | |
136 | 110k | t41 = t40 ^ t37; |
137 | 110k | t42 = t29 ^ t33; |
138 | 110k | t43 = t29 ^ t40; |
139 | 110k | t44 = t33 ^ t37; |
140 | 110k | t45 = t42 ^ t41; |
141 | 110k | z0 = t44 & y15; |
142 | 110k | z1 = t37 & y6; |
143 | 110k | z2 = t33 & x7; |
144 | 110k | z3 = t43 & y16; |
145 | 110k | z4 = t40 & y1; |
146 | 110k | z5 = t29 & y7; |
147 | 110k | z6 = t42 & y11; |
148 | 110k | z7 = t45 & y17; |
149 | 110k | z8 = t41 & y10; |
150 | 110k | z9 = t44 & y12; |
151 | 110k | z10 = t37 & y3; |
152 | 110k | z11 = t33 & y4; |
153 | 110k | z12 = t43 & y13; |
154 | 110k | z13 = t40 & y5; |
155 | 110k | z14 = t29 & y2; |
156 | 110k | z15 = t42 & y9; |
157 | 110k | z16 = t45 & y14; |
158 | 110k | z17 = t41 & y8; |
159 | | |
160 | | /* |
161 | | * Bottom linear transformation. |
162 | | */ |
163 | 110k | t46 = z15 ^ z16; |
164 | 110k | t47 = z10 ^ z11; |
165 | 110k | t48 = z5 ^ z13; |
166 | 110k | t49 = z9 ^ z10; |
167 | 110k | t50 = z2 ^ z12; |
168 | 110k | t51 = z2 ^ z5; |
169 | 110k | t52 = z7 ^ z8; |
170 | 110k | t53 = z0 ^ z3; |
171 | 110k | t54 = z6 ^ z7; |
172 | 110k | t55 = z16 ^ z17; |
173 | 110k | t56 = z12 ^ t48; |
174 | 110k | t57 = t50 ^ t53; |
175 | 110k | t58 = z4 ^ t46; |
176 | 110k | t59 = z3 ^ t54; |
177 | 110k | t60 = t46 ^ t57; |
178 | 110k | t61 = z14 ^ t57; |
179 | 110k | t62 = t52 ^ t58; |
180 | 110k | t63 = t49 ^ t58; |
181 | 110k | t64 = z4 ^ t59; |
182 | 110k | t65 = t61 ^ t62; |
183 | 110k | t66 = z1 ^ t63; |
184 | 110k | s0 = t59 ^ t63; |
185 | 110k | s6 = t56 ^ ~t62; |
186 | 110k | s7 = t48 ^ ~t60; |
187 | 110k | t67 = t64 ^ t65; |
188 | 110k | s3 = t53 ^ t66; |
189 | 110k | s4 = t51 ^ t66; |
190 | 110k | s5 = t47 ^ t65; |
191 | 110k | s1 = t64 ^ ~s3; |
192 | 110k | s2 = t55 ^ ~t67; |
193 | | |
194 | 110k | q[7] = s0; |
195 | 110k | q[6] = s1; |
196 | 110k | q[5] = s2; |
197 | 110k | q[4] = s3; |
198 | 110k | q[3] = s4; |
199 | 110k | q[2] = s5; |
200 | 110k | q[1] = s6; |
201 | 110k | q[0] = s7; |
202 | 110k | } |
203 | | |
204 | | /* see inner.h */ |
205 | | void |
206 | | br_aes_ct64_ortho(uint64_t *q) |
207 | 35.9k | { |
208 | 431k | #define SWAPN(cl, ch, s, x, y) do { \ |
209 | 431k | uint64_t a, b; \ |
210 | 431k | a = (x); \ |
211 | 431k | b = (y); \ |
212 | 431k | (x) = (a & (uint64_t)cl) | ((b & (uint64_t)cl) << (s)); \ |
213 | 431k | (y) = ((a & (uint64_t)ch) >> (s)) | (b & (uint64_t)ch); \ |
214 | 431k | } while (0) |
215 | | |
216 | 143k | #define SWAP2(x, y) SWAPN(0x5555555555555555, 0xAAAAAAAAAAAAAAAA, 1, x, y) |
217 | 143k | #define SWAP4(x, y) SWAPN(0x3333333333333333, 0xCCCCCCCCCCCCCCCC, 2, x, y) |
218 | 143k | #define SWAP8(x, y) SWAPN(0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0, 4, x, y) |
219 | | |
220 | 35.9k | SWAP2(q[0], q[1]); |
221 | 35.9k | SWAP2(q[2], q[3]); |
222 | 35.9k | SWAP2(q[4], q[5]); |
223 | 35.9k | SWAP2(q[6], q[7]); |
224 | | |
225 | 35.9k | SWAP4(q[0], q[2]); |
226 | 35.9k | SWAP4(q[1], q[3]); |
227 | 35.9k | SWAP4(q[4], q[6]); |
228 | 35.9k | SWAP4(q[5], q[7]); |
229 | | |
230 | 35.9k | SWAP8(q[0], q[4]); |
231 | 35.9k | SWAP8(q[1], q[5]); |
232 | 35.9k | SWAP8(q[2], q[6]); |
233 | 35.9k | SWAP8(q[3], q[7]); |
234 | 35.9k | } |
235 | | |
236 | | /* see inner.h */ |
237 | | void |
238 | | br_aes_ct64_interleave_in(uint64_t *q0, uint64_t *q1, const uint32_t *w) |
239 | 23.9k | { |
240 | 23.9k | uint64_t x0, x1, x2, x3; |
241 | | |
242 | 23.9k | x0 = w[0]; |
243 | 23.9k | x1 = w[1]; |
244 | 23.9k | x2 = w[2]; |
245 | 23.9k | x3 = w[3]; |
246 | 23.9k | x0 |= (x0 << 16); |
247 | 23.9k | x1 |= (x1 << 16); |
248 | 23.9k | x2 |= (x2 << 16); |
249 | 23.9k | x3 |= (x3 << 16); |
250 | 23.9k | x0 &= (uint64_t)0x0000FFFF0000FFFF; |
251 | 23.9k | x1 &= (uint64_t)0x0000FFFF0000FFFF; |
252 | 23.9k | x2 &= (uint64_t)0x0000FFFF0000FFFF; |
253 | 23.9k | x3 &= (uint64_t)0x0000FFFF0000FFFF; |
254 | 23.9k | x0 |= (x0 << 8); |
255 | 23.9k | x1 |= (x1 << 8); |
256 | 23.9k | x2 |= (x2 << 8); |
257 | 23.9k | x3 |= (x3 << 8); |
258 | 23.9k | x0 &= (uint64_t)0x00FF00FF00FF00FF; |
259 | 23.9k | x1 &= (uint64_t)0x00FF00FF00FF00FF; |
260 | 23.9k | x2 &= (uint64_t)0x00FF00FF00FF00FF; |
261 | 23.9k | x3 &= (uint64_t)0x00FF00FF00FF00FF; |
262 | 23.9k | *q0 = x0 | (x2 << 8); |
263 | 23.9k | *q1 = x1 | (x3 << 8); |
264 | 23.9k | } |
265 | | |
266 | | /* see inner.h */ |
267 | | void |
268 | | br_aes_ct64_interleave_out(uint32_t *w, uint64_t q0, uint64_t q1) |
269 | 17.3k | { |
270 | 17.3k | uint64_t x0, x1, x2, x3; |
271 | | |
272 | 17.3k | x0 = q0 & (uint64_t)0x00FF00FF00FF00FF; |
273 | 17.3k | x1 = q1 & (uint64_t)0x00FF00FF00FF00FF; |
274 | 17.3k | x2 = (q0 >> 8) & (uint64_t)0x00FF00FF00FF00FF; |
275 | 17.3k | x3 = (q1 >> 8) & (uint64_t)0x00FF00FF00FF00FF; |
276 | 17.3k | x0 |= (x0 >> 8); |
277 | 17.3k | x1 |= (x1 >> 8); |
278 | 17.3k | x2 |= (x2 >> 8); |
279 | 17.3k | x3 |= (x3 >> 8); |
280 | 17.3k | x0 &= (uint64_t)0x0000FFFF0000FFFF; |
281 | 17.3k | x1 &= (uint64_t)0x0000FFFF0000FFFF; |
282 | 17.3k | x2 &= (uint64_t)0x0000FFFF0000FFFF; |
283 | 17.3k | x3 &= (uint64_t)0x0000FFFF0000FFFF; |
284 | 17.3k | w[0] = (uint32_t)x0 | (uint32_t)(x0 >> 16); |
285 | 17.3k | w[1] = (uint32_t)x1 | (uint32_t)(x1 >> 16); |
286 | 17.3k | w[2] = (uint32_t)x2 | (uint32_t)(x2 >> 16); |
287 | 17.3k | w[3] = (uint32_t)x3 | (uint32_t)(x3 >> 16); |
288 | 17.3k | } |
289 | | |
290 | | static const unsigned char Rcon[] = { |
291 | | 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36 |
292 | | }; |
293 | | |
294 | | static uint32_t |
295 | | sub_word(uint32_t x) |
296 | 5.45k | { |
297 | 5.45k | uint64_t q[8]; |
298 | | |
299 | 5.45k | memset(q, 0, sizeof q); |
300 | 5.45k | q[0] = x; |
301 | 5.45k | br_aes_ct64_ortho(q); |
302 | 5.45k | br_aes_ct64_bitslice_Sbox(q); |
303 | 5.45k | br_aes_ct64_ortho(q); |
304 | 5.45k | return (uint32_t)q[0]; |
305 | 5.45k | } |
306 | | |
307 | | /* see inner.h */ |
308 | | unsigned |
309 | | br_aes_ct64_keysched(uint64_t *comp_skey, const void *key, size_t key_len) |
310 | 501 | { |
311 | 501 | unsigned num_rounds; |
312 | 501 | int i, j, k, nk, nkf; |
313 | 501 | uint32_t tmp; |
314 | 501 | uint32_t skey[60]; |
315 | | |
316 | 501 | switch (key_len) { |
317 | 202 | case 16: |
318 | 202 | num_rounds = 10; |
319 | 202 | break; |
320 | 90 | case 24: |
321 | 90 | num_rounds = 12; |
322 | 90 | break; |
323 | 209 | case 32: |
324 | 209 | num_rounds = 14; |
325 | 209 | break; |
326 | 0 | default: |
327 | | /* abort(); */ |
328 | 0 | return 0; |
329 | 501 | } |
330 | 501 | nk = (int)(key_len >> 2); |
331 | 501 | nkf = (int)((num_rounds + 1) << 2); |
332 | 501 | br_range_dec32le(skey, (key_len >> 2), key); |
333 | 501 | tmp = skey[(key_len >> 2) - 1]; |
334 | 23.5k | for (i = nk, j = 0, k = 0; i < nkf; i ++) { |
335 | 23.0k | if (j == 0) { |
336 | 4.20k | tmp = (tmp << 24) | (tmp >> 8); |
337 | 4.20k | tmp = sub_word(tmp) ^ Rcon[k]; |
338 | 18.8k | } else if (nk > 6 && j == 4) { |
339 | 1.25k | tmp = sub_word(tmp); |
340 | 1.25k | } |
341 | 23.0k | tmp ^= skey[i - nk]; |
342 | 23.0k | skey[i] = tmp; |
343 | 23.0k | if (++ j == nk) { |
344 | 3.90k | j = 0; |
345 | 3.90k | k ++; |
346 | 3.90k | } |
347 | 23.0k | } |
348 | | |
349 | 7.02k | for (i = 0, j = 0; i < nkf; i += 4, j += 2) { |
350 | 6.52k | uint64_t q[8]; |
351 | | |
352 | 6.52k | br_aes_ct64_interleave_in(&q[0], &q[4], skey + i); |
353 | 6.52k | q[1] = q[0]; |
354 | 6.52k | q[2] = q[0]; |
355 | 6.52k | q[3] = q[0]; |
356 | 6.52k | q[5] = q[4]; |
357 | 6.52k | q[6] = q[4]; |
358 | 6.52k | q[7] = q[4]; |
359 | 6.52k | br_aes_ct64_ortho(q); |
360 | 6.52k | comp_skey[j + 0] = |
361 | 6.52k | (q[0] & (uint64_t)0x1111111111111111) |
362 | 6.52k | | (q[1] & (uint64_t)0x2222222222222222) |
363 | 6.52k | | (q[2] & (uint64_t)0x4444444444444444) |
364 | 6.52k | | (q[3] & (uint64_t)0x8888888888888888); |
365 | 6.52k | comp_skey[j + 1] = |
366 | 6.52k | (q[4] & (uint64_t)0x1111111111111111) |
367 | 6.52k | | (q[5] & (uint64_t)0x2222222222222222) |
368 | 6.52k | | (q[6] & (uint64_t)0x4444444444444444) |
369 | 6.52k | | (q[7] & (uint64_t)0x8888888888888888); |
370 | 6.52k | } |
371 | 501 | return num_rounds; |
372 | 501 | } |
373 | | |
374 | | /* see inner.h */ |
375 | | void |
376 | | br_aes_ct64_skey_expand(uint64_t *skey, |
377 | | unsigned num_rounds, const uint64_t *comp_skey) |
378 | 4.55k | { |
379 | 4.55k | unsigned u, v, n; |
380 | | |
381 | 4.55k | n = (num_rounds + 1) << 1; |
382 | 127k | for (u = 0, v = 0; u < n; u ++, v += 4) { |
383 | 123k | uint64_t x0, x1, x2, x3; |
384 | | |
385 | 123k | x0 = x1 = x2 = x3 = comp_skey[u]; |
386 | 123k | x0 &= (uint64_t)0x1111111111111111; |
387 | 123k | x1 &= (uint64_t)0x2222222222222222; |
388 | 123k | x2 &= (uint64_t)0x4444444444444444; |
389 | 123k | x3 &= (uint64_t)0x8888888888888888; |
390 | 123k | x1 >>= 1; |
391 | 123k | x2 >>= 2; |
392 | 123k | x3 >>= 3; |
393 | 123k | skey[v + 0] = (x0 << 4) - x0; |
394 | 123k | skey[v + 1] = (x1 << 4) - x1; |
395 | 123k | skey[v + 2] = (x2 << 4) - x2; |
396 | 123k | skey[v + 3] = (x3 << 4) - x3; |
397 | 123k | } |
398 | 4.55k | } |