/src/BearSSL/src/symcipher/aes_x86ni_ctrcbc.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2017 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 | | #define BR_ENABLE_INTRINSICS 1 |
26 | | #include "inner.h" |
27 | | |
28 | | #if BR_AES_X86NI |
29 | | |
30 | | /* see bearssl_block.h */ |
31 | | const br_block_ctrcbc_class * |
32 | | br_aes_x86ni_ctrcbc_get_vtable(void) |
33 | 285 | { |
34 | 285 | return br_aes_x86ni_supported() ? &br_aes_x86ni_ctrcbc_vtable : NULL; |
35 | 285 | } |
36 | | |
37 | | /* see bearssl_block.h */ |
38 | | void |
39 | | br_aes_x86ni_ctrcbc_init(br_aes_x86ni_ctrcbc_keys *ctx, |
40 | | const void *key, size_t len) |
41 | 282 | { |
42 | 282 | ctx->vtable = &br_aes_x86ni_ctrcbc_vtable; |
43 | 282 | ctx->num_rounds = br_aes_x86ni_keysched_enc(ctx->skey.skni, key, len); |
44 | 282 | } |
45 | | |
46 | | BR_TARGETS_X86_UP |
47 | | |
48 | | /* see bearssl_block.h */ |
49 | | BR_TARGET("sse2,sse4.1,aes") |
50 | | void |
51 | | br_aes_x86ni_ctrcbc_ctr(const br_aes_x86ni_ctrcbc_keys *ctx, |
52 | | void *ctr, void *data, size_t len) |
53 | 496 | { |
54 | 496 | unsigned char *buf; |
55 | 496 | unsigned num_rounds; |
56 | 496 | __m128i sk[15]; |
57 | 496 | __m128i ivx0, ivx1, ivx2, ivx3; |
58 | 496 | __m128i erev, zero, one, four, notthree; |
59 | 496 | unsigned u; |
60 | | |
61 | 496 | buf = data; |
62 | 496 | num_rounds = ctx->num_rounds; |
63 | 7.05k | for (u = 0; u <= num_rounds; u ++) { |
64 | 6.55k | sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4))); |
65 | 6.55k | } |
66 | | |
67 | | /* |
68 | | * Some SSE2 constants. |
69 | | */ |
70 | 496 | erev = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, |
71 | 496 | 8, 9, 10, 11, 12, 13, 14, 15); |
72 | 496 | zero = _mm_setzero_si128(); |
73 | 496 | one = _mm_set_epi64x(0, 1); |
74 | 496 | four = _mm_set_epi64x(0, 4); |
75 | 496 | notthree = _mm_sub_epi64(zero, four); |
76 | | |
77 | | /* |
78 | | * Decode the counter in big-endian and pre-increment the other |
79 | | * three counters. |
80 | | */ |
81 | 496 | ivx0 = _mm_shuffle_epi8(_mm_loadu_si128((void *)ctr), erev); |
82 | 496 | ivx1 = _mm_add_epi64(ivx0, one); |
83 | 496 | ivx1 = _mm_sub_epi64(ivx1, |
84 | 496 | _mm_slli_si128(_mm_cmpeq_epi64(ivx1, zero), 8)); |
85 | 496 | ivx2 = _mm_add_epi64(ivx1, one); |
86 | 496 | ivx2 = _mm_sub_epi64(ivx2, |
87 | 496 | _mm_slli_si128(_mm_cmpeq_epi64(ivx2, zero), 8)); |
88 | 496 | ivx3 = _mm_add_epi64(ivx2, one); |
89 | 496 | ivx3 = _mm_sub_epi64(ivx3, |
90 | 496 | _mm_slli_si128(_mm_cmpeq_epi64(ivx3, zero), 8)); |
91 | 496 | while (len > 0) { |
92 | 496 | __m128i x0, x1, x2, x3; |
93 | | |
94 | | /* |
95 | | * Load counter values; we need to byteswap them because |
96 | | * the specification says that they use big-endian. |
97 | | */ |
98 | 496 | x0 = _mm_shuffle_epi8(ivx0, erev); |
99 | 496 | x1 = _mm_shuffle_epi8(ivx1, erev); |
100 | 496 | x2 = _mm_shuffle_epi8(ivx2, erev); |
101 | 496 | x3 = _mm_shuffle_epi8(ivx3, erev); |
102 | | |
103 | 496 | x0 = _mm_xor_si128(x0, sk[0]); |
104 | 496 | x1 = _mm_xor_si128(x1, sk[0]); |
105 | 496 | x2 = _mm_xor_si128(x2, sk[0]); |
106 | 496 | x3 = _mm_xor_si128(x3, sk[0]); |
107 | 496 | x0 = _mm_aesenc_si128(x0, sk[1]); |
108 | 496 | x1 = _mm_aesenc_si128(x1, sk[1]); |
109 | 496 | x2 = _mm_aesenc_si128(x2, sk[1]); |
110 | 496 | x3 = _mm_aesenc_si128(x3, sk[1]); |
111 | 496 | x0 = _mm_aesenc_si128(x0, sk[2]); |
112 | 496 | x1 = _mm_aesenc_si128(x1, sk[2]); |
113 | 496 | x2 = _mm_aesenc_si128(x2, sk[2]); |
114 | 496 | x3 = _mm_aesenc_si128(x3, sk[2]); |
115 | 496 | x0 = _mm_aesenc_si128(x0, sk[3]); |
116 | 496 | x1 = _mm_aesenc_si128(x1, sk[3]); |
117 | 496 | x2 = _mm_aesenc_si128(x2, sk[3]); |
118 | 496 | x3 = _mm_aesenc_si128(x3, sk[3]); |
119 | 496 | x0 = _mm_aesenc_si128(x0, sk[4]); |
120 | 496 | x1 = _mm_aesenc_si128(x1, sk[4]); |
121 | 496 | x2 = _mm_aesenc_si128(x2, sk[4]); |
122 | 496 | x3 = _mm_aesenc_si128(x3, sk[4]); |
123 | 496 | x0 = _mm_aesenc_si128(x0, sk[5]); |
124 | 496 | x1 = _mm_aesenc_si128(x1, sk[5]); |
125 | 496 | x2 = _mm_aesenc_si128(x2, sk[5]); |
126 | 496 | x3 = _mm_aesenc_si128(x3, sk[5]); |
127 | 496 | x0 = _mm_aesenc_si128(x0, sk[6]); |
128 | 496 | x1 = _mm_aesenc_si128(x1, sk[6]); |
129 | 496 | x2 = _mm_aesenc_si128(x2, sk[6]); |
130 | 496 | x3 = _mm_aesenc_si128(x3, sk[6]); |
131 | 496 | x0 = _mm_aesenc_si128(x0, sk[7]); |
132 | 496 | x1 = _mm_aesenc_si128(x1, sk[7]); |
133 | 496 | x2 = _mm_aesenc_si128(x2, sk[7]); |
134 | 496 | x3 = _mm_aesenc_si128(x3, sk[7]); |
135 | 496 | x0 = _mm_aesenc_si128(x0, sk[8]); |
136 | 496 | x1 = _mm_aesenc_si128(x1, sk[8]); |
137 | 496 | x2 = _mm_aesenc_si128(x2, sk[8]); |
138 | 496 | x3 = _mm_aesenc_si128(x3, sk[8]); |
139 | 496 | x0 = _mm_aesenc_si128(x0, sk[9]); |
140 | 496 | x1 = _mm_aesenc_si128(x1, sk[9]); |
141 | 496 | x2 = _mm_aesenc_si128(x2, sk[9]); |
142 | 496 | x3 = _mm_aesenc_si128(x3, sk[9]); |
143 | 496 | if (num_rounds == 10) { |
144 | 158 | x0 = _mm_aesenclast_si128(x0, sk[10]); |
145 | 158 | x1 = _mm_aesenclast_si128(x1, sk[10]); |
146 | 158 | x2 = _mm_aesenclast_si128(x2, sk[10]); |
147 | 158 | x3 = _mm_aesenclast_si128(x3, sk[10]); |
148 | 338 | } else if (num_rounds == 12) { |
149 | 126 | x0 = _mm_aesenc_si128(x0, sk[10]); |
150 | 126 | x1 = _mm_aesenc_si128(x1, sk[10]); |
151 | 126 | x2 = _mm_aesenc_si128(x2, sk[10]); |
152 | 126 | x3 = _mm_aesenc_si128(x3, sk[10]); |
153 | 126 | x0 = _mm_aesenc_si128(x0, sk[11]); |
154 | 126 | x1 = _mm_aesenc_si128(x1, sk[11]); |
155 | 126 | x2 = _mm_aesenc_si128(x2, sk[11]); |
156 | 126 | x3 = _mm_aesenc_si128(x3, sk[11]); |
157 | 126 | x0 = _mm_aesenclast_si128(x0, sk[12]); |
158 | 126 | x1 = _mm_aesenclast_si128(x1, sk[12]); |
159 | 126 | x2 = _mm_aesenclast_si128(x2, sk[12]); |
160 | 126 | x3 = _mm_aesenclast_si128(x3, sk[12]); |
161 | 212 | } else { |
162 | 212 | x0 = _mm_aesenc_si128(x0, sk[10]); |
163 | 212 | x1 = _mm_aesenc_si128(x1, sk[10]); |
164 | 212 | x2 = _mm_aesenc_si128(x2, sk[10]); |
165 | 212 | x3 = _mm_aesenc_si128(x3, sk[10]); |
166 | 212 | x0 = _mm_aesenc_si128(x0, sk[11]); |
167 | 212 | x1 = _mm_aesenc_si128(x1, sk[11]); |
168 | 212 | x2 = _mm_aesenc_si128(x2, sk[11]); |
169 | 212 | x3 = _mm_aesenc_si128(x3, sk[11]); |
170 | 212 | x0 = _mm_aesenc_si128(x0, sk[12]); |
171 | 212 | x1 = _mm_aesenc_si128(x1, sk[12]); |
172 | 212 | x2 = _mm_aesenc_si128(x2, sk[12]); |
173 | 212 | x3 = _mm_aesenc_si128(x3, sk[12]); |
174 | 212 | x0 = _mm_aesenc_si128(x0, sk[13]); |
175 | 212 | x1 = _mm_aesenc_si128(x1, sk[13]); |
176 | 212 | x2 = _mm_aesenc_si128(x2, sk[13]); |
177 | 212 | x3 = _mm_aesenc_si128(x3, sk[13]); |
178 | 212 | x0 = _mm_aesenclast_si128(x0, sk[14]); |
179 | 212 | x1 = _mm_aesenclast_si128(x1, sk[14]); |
180 | 212 | x2 = _mm_aesenclast_si128(x2, sk[14]); |
181 | 212 | x3 = _mm_aesenclast_si128(x3, sk[14]); |
182 | 212 | } |
183 | 496 | if (len >= 64) { |
184 | 0 | x0 = _mm_xor_si128(x0, |
185 | 0 | _mm_loadu_si128((void *)(buf + 0))); |
186 | 0 | x1 = _mm_xor_si128(x1, |
187 | 0 | _mm_loadu_si128((void *)(buf + 16))); |
188 | 0 | x2 = _mm_xor_si128(x2, |
189 | 0 | _mm_loadu_si128((void *)(buf + 32))); |
190 | 0 | x3 = _mm_xor_si128(x3, |
191 | 0 | _mm_loadu_si128((void *)(buf + 48))); |
192 | 0 | _mm_storeu_si128((void *)(buf + 0), x0); |
193 | 0 | _mm_storeu_si128((void *)(buf + 16), x1); |
194 | 0 | _mm_storeu_si128((void *)(buf + 32), x2); |
195 | 0 | _mm_storeu_si128((void *)(buf + 48), x3); |
196 | 0 | buf += 64; |
197 | 0 | len -= 64; |
198 | 496 | } else { |
199 | 496 | unsigned char tmp[64]; |
200 | | |
201 | 496 | _mm_storeu_si128((void *)(tmp + 0), x0); |
202 | 496 | _mm_storeu_si128((void *)(tmp + 16), x1); |
203 | 496 | _mm_storeu_si128((void *)(tmp + 32), x2); |
204 | 496 | _mm_storeu_si128((void *)(tmp + 48), x3); |
205 | 8.43k | for (u = 0; u < len; u ++) { |
206 | 7.93k | buf[u] ^= tmp[u]; |
207 | 7.93k | } |
208 | 496 | switch (len) { |
209 | 496 | case 16: |
210 | 496 | ivx0 = ivx1; |
211 | 496 | break; |
212 | 0 | case 32: |
213 | 0 | ivx0 = ivx2; |
214 | 0 | break; |
215 | 0 | case 48: |
216 | 0 | ivx0 = ivx3; |
217 | 0 | break; |
218 | 496 | } |
219 | 496 | break; |
220 | 496 | } |
221 | | |
222 | | /* |
223 | | * Add 4 to each counter value. For carry propagation |
224 | | * into the upper 64-bit words, we would need to compare |
225 | | * the results with 4, but SSE2+ has only _signed_ |
226 | | * comparisons. Instead, we mask out the low two bits, |
227 | | * and check whether the remaining bits are zero. |
228 | | */ |
229 | 0 | ivx0 = _mm_add_epi64(ivx0, four); |
230 | 0 | ivx1 = _mm_add_epi64(ivx1, four); |
231 | 0 | ivx2 = _mm_add_epi64(ivx2, four); |
232 | 0 | ivx3 = _mm_add_epi64(ivx3, four); |
233 | 0 | ivx0 = _mm_sub_epi64(ivx0, |
234 | 0 | _mm_slli_si128(_mm_cmpeq_epi64( |
235 | 0 | _mm_and_si128(ivx0, notthree), zero), 8)); |
236 | 0 | ivx1 = _mm_sub_epi64(ivx1, |
237 | 0 | _mm_slli_si128(_mm_cmpeq_epi64( |
238 | 0 | _mm_and_si128(ivx1, notthree), zero), 8)); |
239 | 0 | ivx2 = _mm_sub_epi64(ivx2, |
240 | 0 | _mm_slli_si128(_mm_cmpeq_epi64( |
241 | 0 | _mm_and_si128(ivx2, notthree), zero), 8)); |
242 | 0 | ivx3 = _mm_sub_epi64(ivx3, |
243 | 0 | _mm_slli_si128(_mm_cmpeq_epi64( |
244 | 0 | _mm_and_si128(ivx3, notthree), zero), 8)); |
245 | 0 | } |
246 | | |
247 | | /* |
248 | | * Write back new counter value. The loop took care to put the |
249 | | * right counter value in ivx0. |
250 | | */ |
251 | 496 | _mm_storeu_si128((void *)ctr, _mm_shuffle_epi8(ivx0, erev)); |
252 | 496 | } |
253 | | |
254 | | /* see bearssl_block.h */ |
255 | | BR_TARGET("sse2,sse4.1,aes") |
256 | | void |
257 | | br_aes_x86ni_ctrcbc_mac(const br_aes_x86ni_ctrcbc_keys *ctx, |
258 | | void *cbcmac, const void *data, size_t len) |
259 | 996 | { |
260 | 996 | const unsigned char *buf; |
261 | 996 | unsigned num_rounds; |
262 | 996 | __m128i sk[15], ivx; |
263 | 996 | unsigned u; |
264 | | |
265 | 996 | buf = data; |
266 | 996 | ivx = _mm_loadu_si128(cbcmac); |
267 | 996 | num_rounds = ctx->num_rounds; |
268 | 14.1k | for (u = 0; u <= num_rounds; u ++) { |
269 | 13.1k | sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4))); |
270 | 13.1k | } |
271 | 2.57k | while (len > 0) { |
272 | 1.58k | __m128i x; |
273 | | |
274 | 1.58k | x = _mm_xor_si128(_mm_loadu_si128((void *)buf), ivx); |
275 | 1.58k | x = _mm_xor_si128(x, sk[0]); |
276 | 1.58k | x = _mm_aesenc_si128(x, sk[1]); |
277 | 1.58k | x = _mm_aesenc_si128(x, sk[2]); |
278 | 1.58k | x = _mm_aesenc_si128(x, sk[3]); |
279 | 1.58k | x = _mm_aesenc_si128(x, sk[4]); |
280 | 1.58k | x = _mm_aesenc_si128(x, sk[5]); |
281 | 1.58k | x = _mm_aesenc_si128(x, sk[6]); |
282 | 1.58k | x = _mm_aesenc_si128(x, sk[7]); |
283 | 1.58k | x = _mm_aesenc_si128(x, sk[8]); |
284 | 1.58k | x = _mm_aesenc_si128(x, sk[9]); |
285 | 1.58k | if (num_rounds == 10) { |
286 | 317 | x = _mm_aesenclast_si128(x, sk[10]); |
287 | 1.26k | } else if (num_rounds == 12) { |
288 | 811 | x = _mm_aesenc_si128(x, sk[10]); |
289 | 811 | x = _mm_aesenc_si128(x, sk[11]); |
290 | 811 | x = _mm_aesenclast_si128(x, sk[12]); |
291 | 811 | } else { |
292 | 453 | x = _mm_aesenc_si128(x, sk[10]); |
293 | 453 | x = _mm_aesenc_si128(x, sk[11]); |
294 | 453 | x = _mm_aesenc_si128(x, sk[12]); |
295 | 453 | x = _mm_aesenc_si128(x, sk[13]); |
296 | 453 | x = _mm_aesenclast_si128(x, sk[14]); |
297 | 453 | } |
298 | 1.58k | ivx = x; |
299 | 1.58k | buf += 16; |
300 | 1.58k | len -= 16; |
301 | 1.58k | } |
302 | 996 | _mm_storeu_si128(cbcmac, ivx); |
303 | 996 | } |
304 | | |
305 | | /* see bearssl_block.h */ |
306 | | BR_TARGET("sse2,sse4.1,aes") |
307 | | void |
308 | | br_aes_x86ni_ctrcbc_encrypt(const br_aes_x86ni_ctrcbc_keys *ctx, |
309 | | void *ctr, void *cbcmac, void *data, size_t len) |
310 | 410 | { |
311 | 410 | unsigned char *buf; |
312 | 410 | unsigned num_rounds; |
313 | 410 | __m128i sk[15]; |
314 | 410 | __m128i ivx, cmx; |
315 | 410 | __m128i erev, zero, one; |
316 | 410 | unsigned u; |
317 | 410 | int first_iter; |
318 | | |
319 | 410 | num_rounds = ctx->num_rounds; |
320 | 5.77k | for (u = 0; u <= num_rounds; u ++) { |
321 | 5.36k | sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4))); |
322 | 5.36k | } |
323 | | |
324 | | /* |
325 | | * Some SSE2 constants. |
326 | | */ |
327 | 410 | erev = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, |
328 | 410 | 8, 9, 10, 11, 12, 13, 14, 15); |
329 | 410 | zero = _mm_setzero_si128(); |
330 | 410 | one = _mm_set_epi64x(0, 1); |
331 | | |
332 | | /* |
333 | | * Decode the counter in big-endian. |
334 | | */ |
335 | 410 | ivx = _mm_shuffle_epi8(_mm_loadu_si128(ctr), erev); |
336 | 410 | cmx = _mm_loadu_si128(cbcmac); |
337 | | |
338 | 410 | buf = data; |
339 | 410 | first_iter = 1; |
340 | 989 | while (len > 0) { |
341 | 735 | __m128i dx, x0, x1; |
342 | | |
343 | | /* |
344 | | * Load initial values: |
345 | | * dx encrypted block of data |
346 | | * x0 counter (for CTR encryption) |
347 | | * x1 input for CBC-MAC |
348 | | */ |
349 | 735 | dx = _mm_loadu_si128((void *)buf); |
350 | 735 | x0 = _mm_shuffle_epi8(ivx, erev); |
351 | 735 | x1 = cmx; |
352 | | |
353 | 735 | x0 = _mm_xor_si128(x0, sk[0]); |
354 | 735 | x1 = _mm_xor_si128(x1, sk[0]); |
355 | 735 | x0 = _mm_aesenc_si128(x0, sk[1]); |
356 | 735 | x1 = _mm_aesenc_si128(x1, sk[1]); |
357 | 735 | x0 = _mm_aesenc_si128(x0, sk[2]); |
358 | 735 | x1 = _mm_aesenc_si128(x1, sk[2]); |
359 | 735 | x0 = _mm_aesenc_si128(x0, sk[3]); |
360 | 735 | x1 = _mm_aesenc_si128(x1, sk[3]); |
361 | 735 | x0 = _mm_aesenc_si128(x0, sk[4]); |
362 | 735 | x1 = _mm_aesenc_si128(x1, sk[4]); |
363 | 735 | x0 = _mm_aesenc_si128(x0, sk[5]); |
364 | 735 | x1 = _mm_aesenc_si128(x1, sk[5]); |
365 | 735 | x0 = _mm_aesenc_si128(x0, sk[6]); |
366 | 735 | x1 = _mm_aesenc_si128(x1, sk[6]); |
367 | 735 | x0 = _mm_aesenc_si128(x0, sk[7]); |
368 | 735 | x1 = _mm_aesenc_si128(x1, sk[7]); |
369 | 735 | x0 = _mm_aesenc_si128(x0, sk[8]); |
370 | 735 | x1 = _mm_aesenc_si128(x1, sk[8]); |
371 | 735 | x0 = _mm_aesenc_si128(x0, sk[9]); |
372 | 735 | x1 = _mm_aesenc_si128(x1, sk[9]); |
373 | 735 | if (num_rounds == 10) { |
374 | 166 | x0 = _mm_aesenclast_si128(x0, sk[10]); |
375 | 166 | x1 = _mm_aesenclast_si128(x1, sk[10]); |
376 | 569 | } else if (num_rounds == 12) { |
377 | 165 | x0 = _mm_aesenc_si128(x0, sk[10]); |
378 | 165 | x1 = _mm_aesenc_si128(x1, sk[10]); |
379 | 165 | x0 = _mm_aesenc_si128(x0, sk[11]); |
380 | 165 | x1 = _mm_aesenc_si128(x1, sk[11]); |
381 | 165 | x0 = _mm_aesenclast_si128(x0, sk[12]); |
382 | 165 | x1 = _mm_aesenclast_si128(x1, sk[12]); |
383 | 404 | } else { |
384 | 404 | x0 = _mm_aesenc_si128(x0, sk[10]); |
385 | 404 | x1 = _mm_aesenc_si128(x1, sk[10]); |
386 | 404 | x0 = _mm_aesenc_si128(x0, sk[11]); |
387 | 404 | x1 = _mm_aesenc_si128(x1, sk[11]); |
388 | 404 | x0 = _mm_aesenc_si128(x0, sk[12]); |
389 | 404 | x1 = _mm_aesenc_si128(x1, sk[12]); |
390 | 404 | x0 = _mm_aesenc_si128(x0, sk[13]); |
391 | 404 | x1 = _mm_aesenc_si128(x1, sk[13]); |
392 | 404 | x0 = _mm_aesenclast_si128(x0, sk[14]); |
393 | 404 | x1 = _mm_aesenclast_si128(x1, sk[14]); |
394 | 404 | } |
395 | | |
396 | 735 | x0 = _mm_xor_si128(x0, dx); |
397 | 735 | if (first_iter) { |
398 | 156 | cmx = _mm_xor_si128(cmx, x0); |
399 | 156 | first_iter = 0; |
400 | 579 | } else { |
401 | 579 | cmx = _mm_xor_si128(x1, x0); |
402 | 579 | } |
403 | 735 | _mm_storeu_si128((void *)buf, x0); |
404 | | |
405 | 735 | buf += 16; |
406 | 735 | len -= 16; |
407 | | |
408 | | /* |
409 | | * Increment the counter value. |
410 | | */ |
411 | 735 | ivx = _mm_add_epi64(ivx, one); |
412 | 735 | ivx = _mm_sub_epi64(ivx, |
413 | 735 | _mm_slli_si128(_mm_cmpeq_epi64(ivx, zero), 8)); |
414 | | |
415 | | /* |
416 | | * If this was the last iteration, then compute the |
417 | | * extra block encryption to complete CBC-MAC. |
418 | | */ |
419 | 735 | if (len == 0) { |
420 | 156 | cmx = _mm_xor_si128(cmx, sk[0]); |
421 | 156 | cmx = _mm_aesenc_si128(cmx, sk[1]); |
422 | 156 | cmx = _mm_aesenc_si128(cmx, sk[2]); |
423 | 156 | cmx = _mm_aesenc_si128(cmx, sk[3]); |
424 | 156 | cmx = _mm_aesenc_si128(cmx, sk[4]); |
425 | 156 | cmx = _mm_aesenc_si128(cmx, sk[5]); |
426 | 156 | cmx = _mm_aesenc_si128(cmx, sk[6]); |
427 | 156 | cmx = _mm_aesenc_si128(cmx, sk[7]); |
428 | 156 | cmx = _mm_aesenc_si128(cmx, sk[8]); |
429 | 156 | cmx = _mm_aesenc_si128(cmx, sk[9]); |
430 | 156 | if (num_rounds == 10) { |
431 | 20 | cmx = _mm_aesenclast_si128(cmx, sk[10]); |
432 | 136 | } else if (num_rounds == 12) { |
433 | 71 | cmx = _mm_aesenc_si128(cmx, sk[10]); |
434 | 71 | cmx = _mm_aesenc_si128(cmx, sk[11]); |
435 | 71 | cmx = _mm_aesenclast_si128(cmx, sk[12]); |
436 | 71 | } else { |
437 | 65 | cmx = _mm_aesenc_si128(cmx, sk[10]); |
438 | 65 | cmx = _mm_aesenc_si128(cmx, sk[11]); |
439 | 65 | cmx = _mm_aesenc_si128(cmx, sk[12]); |
440 | 65 | cmx = _mm_aesenc_si128(cmx, sk[13]); |
441 | 65 | cmx = _mm_aesenclast_si128(cmx, sk[14]); |
442 | 65 | } |
443 | 156 | break; |
444 | 156 | } |
445 | 735 | } |
446 | | |
447 | | /* |
448 | | * Write back new counter value and CBC-MAC value. |
449 | | */ |
450 | 410 | _mm_storeu_si128(ctr, _mm_shuffle_epi8(ivx, erev)); |
451 | 410 | _mm_storeu_si128(cbcmac, cmx); |
452 | 410 | } |
453 | | |
454 | | /* see bearssl_block.h */ |
455 | | BR_TARGET("sse2,sse4.1,aes") |
456 | | void |
457 | | br_aes_x86ni_ctrcbc_decrypt(const br_aes_x86ni_ctrcbc_keys *ctx, |
458 | | void *ctr, void *cbcmac, void *data, size_t len) |
459 | 393 | { |
460 | 393 | unsigned char *buf; |
461 | 393 | unsigned num_rounds; |
462 | 393 | __m128i sk[15]; |
463 | 393 | __m128i ivx, cmx; |
464 | 393 | __m128i erev, zero, one; |
465 | 393 | unsigned u; |
466 | | |
467 | 393 | num_rounds = ctx->num_rounds; |
468 | 5.49k | for (u = 0; u <= num_rounds; u ++) { |
469 | 5.09k | sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4))); |
470 | 5.09k | } |
471 | | |
472 | | /* |
473 | | * Some SSE2 constants. |
474 | | */ |
475 | 393 | erev = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, |
476 | 393 | 8, 9, 10, 11, 12, 13, 14, 15); |
477 | 393 | zero = _mm_setzero_si128(); |
478 | 393 | one = _mm_set_epi64x(0, 1); |
479 | | |
480 | | /* |
481 | | * Decode the counter in big-endian. |
482 | | */ |
483 | 393 | ivx = _mm_shuffle_epi8(_mm_loadu_si128(ctr), erev); |
484 | 393 | cmx = _mm_loadu_si128(cbcmac); |
485 | | |
486 | 393 | buf = data; |
487 | 1.38k | while (len > 0) { |
488 | 992 | __m128i dx, x0, x1; |
489 | | |
490 | | /* |
491 | | * Load initial values: |
492 | | * dx encrypted block of data |
493 | | * x0 counter (for CTR encryption) |
494 | | * x1 input for CBC-MAC |
495 | | */ |
496 | 992 | dx = _mm_loadu_si128((void *)buf); |
497 | 992 | x0 = _mm_shuffle_epi8(ivx, erev); |
498 | 992 | x1 = _mm_xor_si128(cmx, dx); |
499 | | |
500 | 992 | x0 = _mm_xor_si128(x0, sk[0]); |
501 | 992 | x1 = _mm_xor_si128(x1, sk[0]); |
502 | 992 | x0 = _mm_aesenc_si128(x0, sk[1]); |
503 | 992 | x1 = _mm_aesenc_si128(x1, sk[1]); |
504 | 992 | x0 = _mm_aesenc_si128(x0, sk[2]); |
505 | 992 | x1 = _mm_aesenc_si128(x1, sk[2]); |
506 | 992 | x0 = _mm_aesenc_si128(x0, sk[3]); |
507 | 992 | x1 = _mm_aesenc_si128(x1, sk[3]); |
508 | 992 | x0 = _mm_aesenc_si128(x0, sk[4]); |
509 | 992 | x1 = _mm_aesenc_si128(x1, sk[4]); |
510 | 992 | x0 = _mm_aesenc_si128(x0, sk[5]); |
511 | 992 | x1 = _mm_aesenc_si128(x1, sk[5]); |
512 | 992 | x0 = _mm_aesenc_si128(x0, sk[6]); |
513 | 992 | x1 = _mm_aesenc_si128(x1, sk[6]); |
514 | 992 | x0 = _mm_aesenc_si128(x0, sk[7]); |
515 | 992 | x1 = _mm_aesenc_si128(x1, sk[7]); |
516 | 992 | x0 = _mm_aesenc_si128(x0, sk[8]); |
517 | 992 | x1 = _mm_aesenc_si128(x1, sk[8]); |
518 | 992 | x0 = _mm_aesenc_si128(x0, sk[9]); |
519 | 992 | x1 = _mm_aesenc_si128(x1, sk[9]); |
520 | 992 | if (num_rounds == 10) { |
521 | 423 | x0 = _mm_aesenclast_si128(x0, sk[10]); |
522 | 423 | x1 = _mm_aesenclast_si128(x1, sk[10]); |
523 | 569 | } else if (num_rounds == 12) { |
524 | 255 | x0 = _mm_aesenc_si128(x0, sk[10]); |
525 | 255 | x1 = _mm_aesenc_si128(x1, sk[10]); |
526 | 255 | x0 = _mm_aesenc_si128(x0, sk[11]); |
527 | 255 | x1 = _mm_aesenc_si128(x1, sk[11]); |
528 | 255 | x0 = _mm_aesenclast_si128(x0, sk[12]); |
529 | 255 | x1 = _mm_aesenclast_si128(x1, sk[12]); |
530 | 314 | } else { |
531 | 314 | x0 = _mm_aesenc_si128(x0, sk[10]); |
532 | 314 | x1 = _mm_aesenc_si128(x1, sk[10]); |
533 | 314 | x0 = _mm_aesenc_si128(x0, sk[11]); |
534 | 314 | x1 = _mm_aesenc_si128(x1, sk[11]); |
535 | 314 | x0 = _mm_aesenc_si128(x0, sk[12]); |
536 | 314 | x1 = _mm_aesenc_si128(x1, sk[12]); |
537 | 314 | x0 = _mm_aesenc_si128(x0, sk[13]); |
538 | 314 | x1 = _mm_aesenc_si128(x1, sk[13]); |
539 | 314 | x0 = _mm_aesenclast_si128(x0, sk[14]); |
540 | 314 | x1 = _mm_aesenclast_si128(x1, sk[14]); |
541 | 314 | } |
542 | 992 | x0 = _mm_xor_si128(x0, dx); |
543 | 992 | cmx = x1; |
544 | 992 | _mm_storeu_si128((void *)buf, x0); |
545 | | |
546 | 992 | buf += 16; |
547 | 992 | len -= 16; |
548 | | |
549 | | /* |
550 | | * Increment the counter value. |
551 | | */ |
552 | 992 | ivx = _mm_add_epi64(ivx, one); |
553 | 992 | ivx = _mm_sub_epi64(ivx, |
554 | 992 | _mm_slli_si128(_mm_cmpeq_epi64(ivx, zero), 8)); |
555 | 992 | } |
556 | | |
557 | | /* |
558 | | * Write back new counter value and CBC-MAC value. |
559 | | */ |
560 | 393 | _mm_storeu_si128(ctr, _mm_shuffle_epi8(ivx, erev)); |
561 | 393 | _mm_storeu_si128(cbcmac, cmx); |
562 | 393 | } |
563 | | |
564 | | BR_TARGETS_X86_DOWN |
565 | | |
566 | | /* see bearssl_block.h */ |
567 | | const br_block_ctrcbc_class br_aes_x86ni_ctrcbc_vtable = { |
568 | | sizeof(br_aes_x86ni_ctrcbc_keys), |
569 | | 16, |
570 | | 4, |
571 | | (void (*)(const br_block_ctrcbc_class **, const void *, size_t)) |
572 | | &br_aes_x86ni_ctrcbc_init, |
573 | | (void (*)(const br_block_ctrcbc_class *const *, |
574 | | void *, void *, void *, size_t)) |
575 | | &br_aes_x86ni_ctrcbc_encrypt, |
576 | | (void (*)(const br_block_ctrcbc_class *const *, |
577 | | void *, void *, void *, size_t)) |
578 | | &br_aes_x86ni_ctrcbc_decrypt, |
579 | | (void (*)(const br_block_ctrcbc_class *const *, |
580 | | void *, void *, size_t)) |
581 | | &br_aes_x86ni_ctrcbc_ctr, |
582 | | (void (*)(const br_block_ctrcbc_class *const *, |
583 | | void *, const void *, size_t)) |
584 | | &br_aes_x86ni_ctrcbc_mac |
585 | | }; |
586 | | |
587 | | #else |
588 | | |
589 | | /* see bearssl_block.h */ |
590 | | const br_block_ctrcbc_class * |
591 | | br_aes_x86ni_ctrcbc_get_vtable(void) |
592 | | { |
593 | | return NULL; |
594 | | } |
595 | | |
596 | | #endif |