xref: /freebsd/contrib/bearssl/src/symcipher/aes_x86ni_ctrcbc.c (revision e6bfd18d21b225af6a0ed67ceeaf1293b7b9eba5)
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 {
34 	return br_aes_x86ni_supported() ? &br_aes_x86ni_ctrcbc_vtable : NULL;
35 }
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 {
42 	ctx->vtable = &br_aes_x86ni_ctrcbc_vtable;
43 	ctx->num_rounds = br_aes_x86ni_keysched_enc(ctx->skey.skni, key, len);
44 }
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 {
54 	unsigned char *buf;
55 	unsigned num_rounds;
56 	__m128i sk[15];
57 	__m128i ivx0, ivx1, ivx2, ivx3;
58 	__m128i erev, zero, one, four, notthree;
59 	unsigned u;
60 
61 	buf = data;
62 	num_rounds = ctx->num_rounds;
63 	for (u = 0; u <= num_rounds; u ++) {
64 		sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4)));
65 	}
66 
67 	/*
68 	 * Some SSE2 constants.
69 	 */
70 	erev = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7,
71 		8, 9, 10, 11, 12, 13, 14, 15);
72 	zero = _mm_setzero_si128();
73 	one = _mm_set_epi64x(0, 1);
74 	four = _mm_set_epi64x(0, 4);
75 	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 	ivx0 = _mm_shuffle_epi8(_mm_loadu_si128((void *)ctr), erev);
82 	ivx1 = _mm_add_epi64(ivx0, one);
83 	ivx1 = _mm_sub_epi64(ivx1,
84 		_mm_slli_si128(_mm_cmpeq_epi64(ivx1, zero), 8));
85 	ivx2 = _mm_add_epi64(ivx1, one);
86 	ivx2 = _mm_sub_epi64(ivx2,
87 		_mm_slli_si128(_mm_cmpeq_epi64(ivx2, zero), 8));
88 	ivx3 = _mm_add_epi64(ivx2, one);
89 	ivx3 = _mm_sub_epi64(ivx3,
90 		_mm_slli_si128(_mm_cmpeq_epi64(ivx3, zero), 8));
91 	while (len > 0) {
92 		__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 		x0 = _mm_shuffle_epi8(ivx0, erev);
99 		x1 = _mm_shuffle_epi8(ivx1, erev);
100 		x2 = _mm_shuffle_epi8(ivx2, erev);
101 		x3 = _mm_shuffle_epi8(ivx3, erev);
102 
103 		x0 = _mm_xor_si128(x0, sk[0]);
104 		x1 = _mm_xor_si128(x1, sk[0]);
105 		x2 = _mm_xor_si128(x2, sk[0]);
106 		x3 = _mm_xor_si128(x3, sk[0]);
107 		x0 = _mm_aesenc_si128(x0, sk[1]);
108 		x1 = _mm_aesenc_si128(x1, sk[1]);
109 		x2 = _mm_aesenc_si128(x2, sk[1]);
110 		x3 = _mm_aesenc_si128(x3, sk[1]);
111 		x0 = _mm_aesenc_si128(x0, sk[2]);
112 		x1 = _mm_aesenc_si128(x1, sk[2]);
113 		x2 = _mm_aesenc_si128(x2, sk[2]);
114 		x3 = _mm_aesenc_si128(x3, sk[2]);
115 		x0 = _mm_aesenc_si128(x0, sk[3]);
116 		x1 = _mm_aesenc_si128(x1, sk[3]);
117 		x2 = _mm_aesenc_si128(x2, sk[3]);
118 		x3 = _mm_aesenc_si128(x3, sk[3]);
119 		x0 = _mm_aesenc_si128(x0, sk[4]);
120 		x1 = _mm_aesenc_si128(x1, sk[4]);
121 		x2 = _mm_aesenc_si128(x2, sk[4]);
122 		x3 = _mm_aesenc_si128(x3, sk[4]);
123 		x0 = _mm_aesenc_si128(x0, sk[5]);
124 		x1 = _mm_aesenc_si128(x1, sk[5]);
125 		x2 = _mm_aesenc_si128(x2, sk[5]);
126 		x3 = _mm_aesenc_si128(x3, sk[5]);
127 		x0 = _mm_aesenc_si128(x0, sk[6]);
128 		x1 = _mm_aesenc_si128(x1, sk[6]);
129 		x2 = _mm_aesenc_si128(x2, sk[6]);
130 		x3 = _mm_aesenc_si128(x3, sk[6]);
131 		x0 = _mm_aesenc_si128(x0, sk[7]);
132 		x1 = _mm_aesenc_si128(x1, sk[7]);
133 		x2 = _mm_aesenc_si128(x2, sk[7]);
134 		x3 = _mm_aesenc_si128(x3, sk[7]);
135 		x0 = _mm_aesenc_si128(x0, sk[8]);
136 		x1 = _mm_aesenc_si128(x1, sk[8]);
137 		x2 = _mm_aesenc_si128(x2, sk[8]);
138 		x3 = _mm_aesenc_si128(x3, sk[8]);
139 		x0 = _mm_aesenc_si128(x0, sk[9]);
140 		x1 = _mm_aesenc_si128(x1, sk[9]);
141 		x2 = _mm_aesenc_si128(x2, sk[9]);
142 		x3 = _mm_aesenc_si128(x3, sk[9]);
143 		if (num_rounds == 10) {
144 			x0 = _mm_aesenclast_si128(x0, sk[10]);
145 			x1 = _mm_aesenclast_si128(x1, sk[10]);
146 			x2 = _mm_aesenclast_si128(x2, sk[10]);
147 			x3 = _mm_aesenclast_si128(x3, sk[10]);
148 		} else if (num_rounds == 12) {
149 			x0 = _mm_aesenc_si128(x0, sk[10]);
150 			x1 = _mm_aesenc_si128(x1, sk[10]);
151 			x2 = _mm_aesenc_si128(x2, sk[10]);
152 			x3 = _mm_aesenc_si128(x3, sk[10]);
153 			x0 = _mm_aesenc_si128(x0, sk[11]);
154 			x1 = _mm_aesenc_si128(x1, sk[11]);
155 			x2 = _mm_aesenc_si128(x2, sk[11]);
156 			x3 = _mm_aesenc_si128(x3, sk[11]);
157 			x0 = _mm_aesenclast_si128(x0, sk[12]);
158 			x1 = _mm_aesenclast_si128(x1, sk[12]);
159 			x2 = _mm_aesenclast_si128(x2, sk[12]);
160 			x3 = _mm_aesenclast_si128(x3, sk[12]);
161 		} else {
162 			x0 = _mm_aesenc_si128(x0, sk[10]);
163 			x1 = _mm_aesenc_si128(x1, sk[10]);
164 			x2 = _mm_aesenc_si128(x2, sk[10]);
165 			x3 = _mm_aesenc_si128(x3, sk[10]);
166 			x0 = _mm_aesenc_si128(x0, sk[11]);
167 			x1 = _mm_aesenc_si128(x1, sk[11]);
168 			x2 = _mm_aesenc_si128(x2, sk[11]);
169 			x3 = _mm_aesenc_si128(x3, sk[11]);
170 			x0 = _mm_aesenc_si128(x0, sk[12]);
171 			x1 = _mm_aesenc_si128(x1, sk[12]);
172 			x2 = _mm_aesenc_si128(x2, sk[12]);
173 			x3 = _mm_aesenc_si128(x3, sk[12]);
174 			x0 = _mm_aesenc_si128(x0, sk[13]);
175 			x1 = _mm_aesenc_si128(x1, sk[13]);
176 			x2 = _mm_aesenc_si128(x2, sk[13]);
177 			x3 = _mm_aesenc_si128(x3, sk[13]);
178 			x0 = _mm_aesenclast_si128(x0, sk[14]);
179 			x1 = _mm_aesenclast_si128(x1, sk[14]);
180 			x2 = _mm_aesenclast_si128(x2, sk[14]);
181 			x3 = _mm_aesenclast_si128(x3, sk[14]);
182 		}
183 		if (len >= 64) {
184 			x0 = _mm_xor_si128(x0,
185 				_mm_loadu_si128((void *)(buf +  0)));
186 			x1 = _mm_xor_si128(x1,
187 				_mm_loadu_si128((void *)(buf + 16)));
188 			x2 = _mm_xor_si128(x2,
189 				_mm_loadu_si128((void *)(buf + 32)));
190 			x3 = _mm_xor_si128(x3,
191 				_mm_loadu_si128((void *)(buf + 48)));
192 			_mm_storeu_si128((void *)(buf +  0), x0);
193 			_mm_storeu_si128((void *)(buf + 16), x1);
194 			_mm_storeu_si128((void *)(buf + 32), x2);
195 			_mm_storeu_si128((void *)(buf + 48), x3);
196 			buf += 64;
197 			len -= 64;
198 		} else {
199 			unsigned char tmp[64];
200 
201 			_mm_storeu_si128((void *)(tmp +  0), x0);
202 			_mm_storeu_si128((void *)(tmp + 16), x1);
203 			_mm_storeu_si128((void *)(tmp + 32), x2);
204 			_mm_storeu_si128((void *)(tmp + 48), x3);
205 			for (u = 0; u < len; u ++) {
206 				buf[u] ^= tmp[u];
207 			}
208 			switch (len) {
209 			case 16:
210 				ivx0 = ivx1;
211 				break;
212 			case 32:
213 				ivx0 = ivx2;
214 				break;
215 			case 48:
216 				ivx0 = ivx3;
217 				break;
218 			}
219 			break;
220 		}
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 		ivx0 = _mm_add_epi64(ivx0, four);
230 		ivx1 = _mm_add_epi64(ivx1, four);
231 		ivx2 = _mm_add_epi64(ivx2, four);
232 		ivx3 = _mm_add_epi64(ivx3, four);
233 		ivx0 = _mm_sub_epi64(ivx0,
234 			_mm_slli_si128(_mm_cmpeq_epi64(
235 				_mm_and_si128(ivx0, notthree), zero), 8));
236 		ivx1 = _mm_sub_epi64(ivx1,
237 			_mm_slli_si128(_mm_cmpeq_epi64(
238 				_mm_and_si128(ivx1, notthree), zero), 8));
239 		ivx2 = _mm_sub_epi64(ivx2,
240 			_mm_slli_si128(_mm_cmpeq_epi64(
241 				_mm_and_si128(ivx2, notthree), zero), 8));
242 		ivx3 = _mm_sub_epi64(ivx3,
243 			_mm_slli_si128(_mm_cmpeq_epi64(
244 				_mm_and_si128(ivx3, notthree), zero), 8));
245 	}
246 
247 	/*
248 	 * Write back new counter value. The loop took care to put the
249 	 * right counter value in ivx0.
250 	 */
251 	_mm_storeu_si128((void *)ctr, _mm_shuffle_epi8(ivx0, erev));
252 }
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 {
260 	const unsigned char *buf;
261 	unsigned num_rounds;
262 	__m128i sk[15], ivx;
263 	unsigned u;
264 
265 	buf = data;
266 	ivx = _mm_loadu_si128(cbcmac);
267 	num_rounds = ctx->num_rounds;
268 	for (u = 0; u <= num_rounds; u ++) {
269 		sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4)));
270 	}
271 	while (len > 0) {
272 		__m128i x;
273 
274 		x = _mm_xor_si128(_mm_loadu_si128((void *)buf), ivx);
275 		x = _mm_xor_si128(x, sk[0]);
276 		x = _mm_aesenc_si128(x, sk[1]);
277 		x = _mm_aesenc_si128(x, sk[2]);
278 		x = _mm_aesenc_si128(x, sk[3]);
279 		x = _mm_aesenc_si128(x, sk[4]);
280 		x = _mm_aesenc_si128(x, sk[5]);
281 		x = _mm_aesenc_si128(x, sk[6]);
282 		x = _mm_aesenc_si128(x, sk[7]);
283 		x = _mm_aesenc_si128(x, sk[8]);
284 		x = _mm_aesenc_si128(x, sk[9]);
285 		if (num_rounds == 10) {
286 			x = _mm_aesenclast_si128(x, sk[10]);
287 		} else if (num_rounds == 12) {
288 			x = _mm_aesenc_si128(x, sk[10]);
289 			x = _mm_aesenc_si128(x, sk[11]);
290 			x = _mm_aesenclast_si128(x, sk[12]);
291 		} else {
292 			x = _mm_aesenc_si128(x, sk[10]);
293 			x = _mm_aesenc_si128(x, sk[11]);
294 			x = _mm_aesenc_si128(x, sk[12]);
295 			x = _mm_aesenc_si128(x, sk[13]);
296 			x = _mm_aesenclast_si128(x, sk[14]);
297 		}
298 		ivx = x;
299 		buf += 16;
300 		len -= 16;
301 	}
302 	_mm_storeu_si128(cbcmac, ivx);
303 }
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 {
311 	unsigned char *buf;
312 	unsigned num_rounds;
313 	__m128i sk[15];
314 	__m128i ivx, cmx;
315 	__m128i erev, zero, one;
316 	unsigned u;
317 	int first_iter;
318 
319 	num_rounds = ctx->num_rounds;
320 	for (u = 0; u <= num_rounds; u ++) {
321 		sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4)));
322 	}
323 
324 	/*
325 	 * Some SSE2 constants.
326 	 */
327 	erev = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7,
328 		8, 9, 10, 11, 12, 13, 14, 15);
329 	zero = _mm_setzero_si128();
330 	one = _mm_set_epi64x(0, 1);
331 
332 	/*
333 	 * Decode the counter in big-endian.
334 	 */
335 	ivx = _mm_shuffle_epi8(_mm_loadu_si128(ctr), erev);
336 	cmx = _mm_loadu_si128(cbcmac);
337 
338 	buf = data;
339 	first_iter = 1;
340 	while (len > 0) {
341 		__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 		dx = _mm_loadu_si128((void *)buf);
350 		x0 = _mm_shuffle_epi8(ivx, erev);
351 		x1 = cmx;
352 
353 		x0 = _mm_xor_si128(x0, sk[0]);
354 		x1 = _mm_xor_si128(x1, sk[0]);
355 		x0 = _mm_aesenc_si128(x0, sk[1]);
356 		x1 = _mm_aesenc_si128(x1, sk[1]);
357 		x0 = _mm_aesenc_si128(x0, sk[2]);
358 		x1 = _mm_aesenc_si128(x1, sk[2]);
359 		x0 = _mm_aesenc_si128(x0, sk[3]);
360 		x1 = _mm_aesenc_si128(x1, sk[3]);
361 		x0 = _mm_aesenc_si128(x0, sk[4]);
362 		x1 = _mm_aesenc_si128(x1, sk[4]);
363 		x0 = _mm_aesenc_si128(x0, sk[5]);
364 		x1 = _mm_aesenc_si128(x1, sk[5]);
365 		x0 = _mm_aesenc_si128(x0, sk[6]);
366 		x1 = _mm_aesenc_si128(x1, sk[6]);
367 		x0 = _mm_aesenc_si128(x0, sk[7]);
368 		x1 = _mm_aesenc_si128(x1, sk[7]);
369 		x0 = _mm_aesenc_si128(x0, sk[8]);
370 		x1 = _mm_aesenc_si128(x1, sk[8]);
371 		x0 = _mm_aesenc_si128(x0, sk[9]);
372 		x1 = _mm_aesenc_si128(x1, sk[9]);
373 		if (num_rounds == 10) {
374 			x0 = _mm_aesenclast_si128(x0, sk[10]);
375 			x1 = _mm_aesenclast_si128(x1, sk[10]);
376 		} else if (num_rounds == 12) {
377 			x0 = _mm_aesenc_si128(x0, sk[10]);
378 			x1 = _mm_aesenc_si128(x1, sk[10]);
379 			x0 = _mm_aesenc_si128(x0, sk[11]);
380 			x1 = _mm_aesenc_si128(x1, sk[11]);
381 			x0 = _mm_aesenclast_si128(x0, sk[12]);
382 			x1 = _mm_aesenclast_si128(x1, sk[12]);
383 		} else {
384 			x0 = _mm_aesenc_si128(x0, sk[10]);
385 			x1 = _mm_aesenc_si128(x1, sk[10]);
386 			x0 = _mm_aesenc_si128(x0, sk[11]);
387 			x1 = _mm_aesenc_si128(x1, sk[11]);
388 			x0 = _mm_aesenc_si128(x0, sk[12]);
389 			x1 = _mm_aesenc_si128(x1, sk[12]);
390 			x0 = _mm_aesenc_si128(x0, sk[13]);
391 			x1 = _mm_aesenc_si128(x1, sk[13]);
392 			x0 = _mm_aesenclast_si128(x0, sk[14]);
393 			x1 = _mm_aesenclast_si128(x1, sk[14]);
394 		}
395 
396 		x0 = _mm_xor_si128(x0, dx);
397 		if (first_iter) {
398 			cmx = _mm_xor_si128(cmx, x0);
399 			first_iter = 0;
400 		} else {
401 			cmx = _mm_xor_si128(x1, x0);
402 		}
403 		_mm_storeu_si128((void *)buf, x0);
404 
405 		buf += 16;
406 		len -= 16;
407 
408 		/*
409 		 * Increment the counter value.
410 		 */
411 		ivx = _mm_add_epi64(ivx, one);
412 		ivx = _mm_sub_epi64(ivx,
413 			_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 		if (len == 0) {
420 			cmx = _mm_xor_si128(cmx, sk[0]);
421 			cmx = _mm_aesenc_si128(cmx, sk[1]);
422 			cmx = _mm_aesenc_si128(cmx, sk[2]);
423 			cmx = _mm_aesenc_si128(cmx, sk[3]);
424 			cmx = _mm_aesenc_si128(cmx, sk[4]);
425 			cmx = _mm_aesenc_si128(cmx, sk[5]);
426 			cmx = _mm_aesenc_si128(cmx, sk[6]);
427 			cmx = _mm_aesenc_si128(cmx, sk[7]);
428 			cmx = _mm_aesenc_si128(cmx, sk[8]);
429 			cmx = _mm_aesenc_si128(cmx, sk[9]);
430 			if (num_rounds == 10) {
431 				cmx = _mm_aesenclast_si128(cmx, sk[10]);
432 			} else if (num_rounds == 12) {
433 				cmx = _mm_aesenc_si128(cmx, sk[10]);
434 				cmx = _mm_aesenc_si128(cmx, sk[11]);
435 				cmx = _mm_aesenclast_si128(cmx, sk[12]);
436 			} else {
437 				cmx = _mm_aesenc_si128(cmx, sk[10]);
438 				cmx = _mm_aesenc_si128(cmx, sk[11]);
439 				cmx = _mm_aesenc_si128(cmx, sk[12]);
440 				cmx = _mm_aesenc_si128(cmx, sk[13]);
441 				cmx = _mm_aesenclast_si128(cmx, sk[14]);
442 			}
443 			break;
444 		}
445 	}
446 
447 	/*
448 	 * Write back new counter value and CBC-MAC value.
449 	 */
450 	_mm_storeu_si128(ctr, _mm_shuffle_epi8(ivx, erev));
451 	_mm_storeu_si128(cbcmac, cmx);
452 }
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 {
460 	unsigned char *buf;
461 	unsigned num_rounds;
462 	__m128i sk[15];
463 	__m128i ivx, cmx;
464 	__m128i erev, zero, one;
465 	unsigned u;
466 
467 	num_rounds = ctx->num_rounds;
468 	for (u = 0; u <= num_rounds; u ++) {
469 		sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4)));
470 	}
471 
472 	/*
473 	 * Some SSE2 constants.
474 	 */
475 	erev = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7,
476 		8, 9, 10, 11, 12, 13, 14, 15);
477 	zero = _mm_setzero_si128();
478 	one = _mm_set_epi64x(0, 1);
479 
480 	/*
481 	 * Decode the counter in big-endian.
482 	 */
483 	ivx = _mm_shuffle_epi8(_mm_loadu_si128(ctr), erev);
484 	cmx = _mm_loadu_si128(cbcmac);
485 
486 	buf = data;
487 	while (len > 0) {
488 		__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 		dx = _mm_loadu_si128((void *)buf);
497 		x0 = _mm_shuffle_epi8(ivx, erev);
498 		x1 = _mm_xor_si128(cmx, dx);
499 
500 		x0 = _mm_xor_si128(x0, sk[0]);
501 		x1 = _mm_xor_si128(x1, sk[0]);
502 		x0 = _mm_aesenc_si128(x0, sk[1]);
503 		x1 = _mm_aesenc_si128(x1, sk[1]);
504 		x0 = _mm_aesenc_si128(x0, sk[2]);
505 		x1 = _mm_aesenc_si128(x1, sk[2]);
506 		x0 = _mm_aesenc_si128(x0, sk[3]);
507 		x1 = _mm_aesenc_si128(x1, sk[3]);
508 		x0 = _mm_aesenc_si128(x0, sk[4]);
509 		x1 = _mm_aesenc_si128(x1, sk[4]);
510 		x0 = _mm_aesenc_si128(x0, sk[5]);
511 		x1 = _mm_aesenc_si128(x1, sk[5]);
512 		x0 = _mm_aesenc_si128(x0, sk[6]);
513 		x1 = _mm_aesenc_si128(x1, sk[6]);
514 		x0 = _mm_aesenc_si128(x0, sk[7]);
515 		x1 = _mm_aesenc_si128(x1, sk[7]);
516 		x0 = _mm_aesenc_si128(x0, sk[8]);
517 		x1 = _mm_aesenc_si128(x1, sk[8]);
518 		x0 = _mm_aesenc_si128(x0, sk[9]);
519 		x1 = _mm_aesenc_si128(x1, sk[9]);
520 		if (num_rounds == 10) {
521 			x0 = _mm_aesenclast_si128(x0, sk[10]);
522 			x1 = _mm_aesenclast_si128(x1, sk[10]);
523 		} else if (num_rounds == 12) {
524 			x0 = _mm_aesenc_si128(x0, sk[10]);
525 			x1 = _mm_aesenc_si128(x1, sk[10]);
526 			x0 = _mm_aesenc_si128(x0, sk[11]);
527 			x1 = _mm_aesenc_si128(x1, sk[11]);
528 			x0 = _mm_aesenclast_si128(x0, sk[12]);
529 			x1 = _mm_aesenclast_si128(x1, sk[12]);
530 		} else {
531 			x0 = _mm_aesenc_si128(x0, sk[10]);
532 			x1 = _mm_aesenc_si128(x1, sk[10]);
533 			x0 = _mm_aesenc_si128(x0, sk[11]);
534 			x1 = _mm_aesenc_si128(x1, sk[11]);
535 			x0 = _mm_aesenc_si128(x0, sk[12]);
536 			x1 = _mm_aesenc_si128(x1, sk[12]);
537 			x0 = _mm_aesenc_si128(x0, sk[13]);
538 			x1 = _mm_aesenc_si128(x1, sk[13]);
539 			x0 = _mm_aesenclast_si128(x0, sk[14]);
540 			x1 = _mm_aesenclast_si128(x1, sk[14]);
541 		}
542 		x0 = _mm_xor_si128(x0, dx);
543 		cmx = x1;
544 		_mm_storeu_si128((void *)buf, x0);
545 
546 		buf += 16;
547 		len -= 16;
548 
549 		/*
550 		 * Increment the counter value.
551 		 */
552 		ivx = _mm_add_epi64(ivx, one);
553 		ivx = _mm_sub_epi64(ivx,
554 			_mm_slli_si128(_mm_cmpeq_epi64(ivx, zero), 8));
555 	}
556 
557 	/*
558 	 * Write back new counter value and CBC-MAC value.
559 	 */
560 	_mm_storeu_si128(ctr, _mm_shuffle_epi8(ivx, erev));
561 	_mm_storeu_si128(cbcmac, cmx);
562 }
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
597