Line data Source code
1 : /* AES-NI accelerated AES for Libgcrypt
2 : * Copyright (C) 2000, 2001, 2002, 2003, 2007,
3 : * 2008, 2011, 2012 Free Software Foundation, Inc.
4 : *
5 : * This file is part of Libgcrypt.
6 : *
7 : * Libgcrypt is free software; you can redistribute it and/or modify
8 : * it under the terms of the GNU Lesser General Public License as
9 : * published by the Free Software Foundation; either version 2.1 of
10 : * the License, or (at your option) any later version.
11 : *
12 : * Libgcrypt is distributed in the hope that it will be useful,
13 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : * GNU Lesser General Public License for more details.
16 : *
17 : * You should have received a copy of the GNU Lesser General Public
18 : * License along with this program; if not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include <config.h>
22 : #include <stdio.h>
23 : #include <stdlib.h>
24 : #include <string.h> /* for memcmp() */
25 :
26 : #include "types.h" /* for byte and u32 typedefs */
27 : #include "g10lib.h"
28 : #include "cipher.h"
29 : #include "bufhelp.h"
30 : #include "cipher-selftest.h"
31 : #include "rijndael-internal.h"
32 : #include "./cipher-internal.h"
33 :
34 :
35 : #ifdef USE_AESNI
36 :
37 :
38 : #if _GCRY_GCC_VERSION >= 40400 /* 4.4 */
39 : /* Prevent compiler from issuing SSE instructions between asm blocks. */
40 : # pragma GCC target("no-sse")
41 : #endif
42 :
43 :
44 : typedef struct u128_s
45 : {
46 : u32 a, b, c, d;
47 : } __attribute__((packed, aligned(1), may_alias)) u128_t;
48 :
49 :
50 : /* Two macros to be called prior and after the use of AESNI
51 : instructions. There should be no external function calls between
52 : the use of these macros. There purpose is to make sure that the
53 : SSE regsiters are cleared and won't reveal any information about
54 : the key or the data. */
55 : #ifdef __WIN64__
56 : /* XMM6-XMM15 are callee-saved registers on WIN64. */
57 : # define aesni_prepare_2_6_variable char win64tmp[16]
58 : # define aesni_prepare() do { } while (0)
59 : # define aesni_prepare_2_6() \
60 : do { asm volatile ("movdqu %%xmm6, %0\n\t" \
61 : : "=m" (*win64tmp) \
62 : : \
63 : : "memory"); \
64 : } while (0)
65 : # define aesni_cleanup() \
66 : do { asm volatile ("pxor %%xmm0, %%xmm0\n\t" \
67 : "pxor %%xmm1, %%xmm1\n" :: ); \
68 : } while (0)
69 : # define aesni_cleanup_2_6() \
70 : do { asm volatile ("movdqu %0, %%xmm6\n\t" \
71 : "pxor %%xmm2, %%xmm2\n" \
72 : "pxor %%xmm3, %%xmm3\n" \
73 : "pxor %%xmm4, %%xmm4\n" \
74 : "pxor %%xmm5, %%xmm5\n" \
75 : : \
76 : : "m" (*win64tmp) \
77 : : "memory"); \
78 : } while (0)
79 : #else
80 : # define aesni_prepare_2_6_variable
81 : # define aesni_prepare() do { } while (0)
82 : # define aesni_prepare_2_6() do { } while (0)
83 : # define aesni_cleanup() \
84 : do { asm volatile ("pxor %%xmm0, %%xmm0\n\t" \
85 : "pxor %%xmm1, %%xmm1\n" :: ); \
86 : } while (0)
87 : # define aesni_cleanup_2_6() \
88 : do { asm volatile ("pxor %%xmm2, %%xmm2\n\t" \
89 : "pxor %%xmm3, %%xmm3\n" \
90 : "pxor %%xmm4, %%xmm4\n" \
91 : "pxor %%xmm5, %%xmm5\n" \
92 : "pxor %%xmm6, %%xmm6\n":: ); \
93 : } while (0)
94 : #endif
95 :
96 : void
97 1558 : _gcry_aes_aesni_do_setkey (RIJNDAEL_context *ctx, const byte *key)
98 : {
99 : aesni_prepare_2_6_variable;
100 :
101 : aesni_prepare();
102 : aesni_prepare_2_6();
103 :
104 1558 : if (ctx->rounds < 12)
105 : {
106 : /* 128-bit key */
107 : #define AESKEYGENASSIST_xmm1_xmm2(imm8) \
108 : ".byte 0x66, 0x0f, 0x3a, 0xdf, 0xd1, " #imm8 " \n\t"
109 : #define AESKEY_EXPAND128 \
110 : "pshufd $0xff, %%xmm2, %%xmm2\n\t" \
111 : "movdqa %%xmm1, %%xmm3\n\t" \
112 : "pslldq $4, %%xmm3\n\t" \
113 : "pxor %%xmm3, %%xmm1\n\t" \
114 : "pslldq $4, %%xmm3\n\t" \
115 : "pxor %%xmm3, %%xmm1\n\t" \
116 : "pslldq $4, %%xmm3\n\t" \
117 : "pxor %%xmm3, %%xmm2\n\t" \
118 : "pxor %%xmm2, %%xmm1\n\t"
119 :
120 931 : asm volatile ("movdqu (%[key]), %%xmm1\n\t" /* xmm1 := key */
121 : "movdqa %%xmm1, (%[ksch])\n\t" /* ksch[0] := xmm1 */
122 : AESKEYGENASSIST_xmm1_xmm2(0x01)
123 : AESKEY_EXPAND128
124 : "movdqa %%xmm1, 0x10(%[ksch])\n\t" /* ksch[1] := xmm1 */
125 : AESKEYGENASSIST_xmm1_xmm2(0x02)
126 : AESKEY_EXPAND128
127 : "movdqa %%xmm1, 0x20(%[ksch])\n\t" /* ksch[2] := xmm1 */
128 : AESKEYGENASSIST_xmm1_xmm2(0x04)
129 : AESKEY_EXPAND128
130 : "movdqa %%xmm1, 0x30(%[ksch])\n\t" /* ksch[3] := xmm1 */
131 : AESKEYGENASSIST_xmm1_xmm2(0x08)
132 : AESKEY_EXPAND128
133 : "movdqa %%xmm1, 0x40(%[ksch])\n\t" /* ksch[4] := xmm1 */
134 : AESKEYGENASSIST_xmm1_xmm2(0x10)
135 : AESKEY_EXPAND128
136 : "movdqa %%xmm1, 0x50(%[ksch])\n\t" /* ksch[5] := xmm1 */
137 : AESKEYGENASSIST_xmm1_xmm2(0x20)
138 : AESKEY_EXPAND128
139 : "movdqa %%xmm1, 0x60(%[ksch])\n\t" /* ksch[6] := xmm1 */
140 : AESKEYGENASSIST_xmm1_xmm2(0x40)
141 : AESKEY_EXPAND128
142 : "movdqa %%xmm1, 0x70(%[ksch])\n\t" /* ksch[7] := xmm1 */
143 : AESKEYGENASSIST_xmm1_xmm2(0x80)
144 : AESKEY_EXPAND128
145 : "movdqa %%xmm1, 0x80(%[ksch])\n\t" /* ksch[8] := xmm1 */
146 : AESKEYGENASSIST_xmm1_xmm2(0x1b)
147 : AESKEY_EXPAND128
148 : "movdqa %%xmm1, 0x90(%[ksch])\n\t" /* ksch[9] := xmm1 */
149 : AESKEYGENASSIST_xmm1_xmm2(0x36)
150 : AESKEY_EXPAND128
151 : "movdqa %%xmm1, 0xa0(%[ksch])\n\t" /* ksch[10] := xmm1 */
152 : :
153 : : [key] "r" (key), [ksch] "r" (ctx->keyschenc)
154 : : "cc", "memory" );
155 : #undef AESKEYGENASSIST_xmm1_xmm2
156 : #undef AESKEY_EXPAND128
157 : }
158 627 : else if (ctx->rounds == 12)
159 : {
160 : /* 192-bit key */
161 : #define AESKEYGENASSIST_xmm3_xmm2(imm8) \
162 : ".byte 0x66, 0x0f, 0x3a, 0xdf, 0xd3, " #imm8 " \n\t"
163 : #define AESKEY_EXPAND192 \
164 : "pshufd $0x55, %%xmm2, %%xmm2\n\t" \
165 : "movdqu %%xmm1, %%xmm4\n\t" \
166 : "pslldq $4, %%xmm4\n\t" \
167 : "pxor %%xmm4, %%xmm1\n\t" \
168 : "pslldq $4, %%xmm4\n\t" \
169 : "pxor %%xmm4, %%xmm1\n\t" \
170 : "pslldq $4, %%xmm4\n\t" \
171 : "pxor %%xmm4, %%xmm1\n\t" \
172 : "pxor %%xmm2, %%xmm1\n\t" \
173 : "pshufd $0xff, %%xmm1, %%xmm2\n\t" \
174 : "movdqu %%xmm3, %%xmm4\n\t" \
175 : "pslldq $4, %%xmm4\n\t" \
176 : "pxor %%xmm4, %%xmm3\n\t" \
177 : "pxor %%xmm2, %%xmm3\n\t"
178 :
179 280 : asm volatile ("movdqu (%[key]), %%xmm1\n\t" /* xmm1 := key[0..15] */
180 : "movq 16(%[key]), %%xmm3\n\t" /* xmm3 := key[16..23] */
181 : "movdqa %%xmm1, (%[ksch])\n\t" /* ksch[0] := xmm1 */
182 : "movdqa %%xmm3, %%xmm5\n\t"
183 :
184 : AESKEYGENASSIST_xmm3_xmm2(0x01)
185 : AESKEY_EXPAND192
186 : "shufpd $0, %%xmm1, %%xmm5\n\t"
187 : "movdqa %%xmm5, 0x10(%[ksch])\n\t" /* ksch[1] := xmm5 */
188 : "movdqa %%xmm1, %%xmm6\n\t"
189 : "shufpd $1, %%xmm3, %%xmm6\n\t"
190 : "movdqa %%xmm6, 0x20(%[ksch])\n\t" /* ksch[2] := xmm6 */
191 : AESKEYGENASSIST_xmm3_xmm2(0x02)
192 : AESKEY_EXPAND192
193 : "movdqa %%xmm1, 0x30(%[ksch])\n\t" /* ksch[3] := xmm1 */
194 : "movdqa %%xmm3, %%xmm5\n\t"
195 :
196 : AESKEYGENASSIST_xmm3_xmm2(0x04)
197 : AESKEY_EXPAND192
198 : "shufpd $0, %%xmm1, %%xmm5\n\t"
199 : "movdqa %%xmm5, 0x40(%[ksch])\n\t" /* ksch[4] := xmm5 */
200 : "movdqa %%xmm1, %%xmm6\n\t"
201 : "shufpd $1, %%xmm3, %%xmm6\n\t"
202 : "movdqa %%xmm6, 0x50(%[ksch])\n\t" /* ksch[5] := xmm6 */
203 : AESKEYGENASSIST_xmm3_xmm2(0x08)
204 : AESKEY_EXPAND192
205 : "movdqa %%xmm1, 0x60(%[ksch])\n\t" /* ksch[6] := xmm1 */
206 : "movdqa %%xmm3, %%xmm5\n\t"
207 :
208 : AESKEYGENASSIST_xmm3_xmm2(0x10)
209 : AESKEY_EXPAND192
210 : "shufpd $0, %%xmm1, %%xmm5\n\t"
211 : "movdqa %%xmm5, 0x70(%[ksch])\n\t" /* ksch[7] := xmm5 */
212 : "movdqa %%xmm1, %%xmm6\n\t"
213 : "shufpd $1, %%xmm3, %%xmm6\n\t"
214 : "movdqa %%xmm6, 0x80(%[ksch])\n\t" /* ksch[8] := xmm6 */
215 : AESKEYGENASSIST_xmm3_xmm2(0x20)
216 : AESKEY_EXPAND192
217 : "movdqa %%xmm1, 0x90(%[ksch])\n\t" /* ksch[9] := xmm1 */
218 : "movdqa %%xmm3, %%xmm5\n\t"
219 :
220 : AESKEYGENASSIST_xmm3_xmm2(0x40)
221 : AESKEY_EXPAND192
222 : "shufpd $0, %%xmm1, %%xmm5\n\t"
223 : "movdqa %%xmm5, 0xa0(%[ksch])\n\t" /* ksch[10] := xmm5 */
224 : "movdqa %%xmm1, %%xmm6\n\t"
225 : "shufpd $1, %%xmm3, %%xmm6\n\t"
226 : "movdqa %%xmm6, 0xb0(%[ksch])\n\t" /* ksch[11] := xmm6 */
227 : AESKEYGENASSIST_xmm3_xmm2(0x80)
228 : AESKEY_EXPAND192
229 : "movdqa %%xmm1, 0xc0(%[ksch])\n\t" /* ksch[12] := xmm1 */
230 : :
231 : : [key] "r" (key), [ksch] "r" (ctx->keyschenc)
232 : : "cc", "memory" );
233 : #undef AESKEYGENASSIST_xmm3_xmm2
234 : #undef AESKEY_EXPAND192
235 : }
236 347 : else if (ctx->rounds > 12)
237 : {
238 : /* 256-bit key */
239 : #define AESKEYGENASSIST_xmm1_xmm2(imm8) \
240 : ".byte 0x66, 0x0f, 0x3a, 0xdf, 0xd1, " #imm8 " \n\t"
241 : #define AESKEYGENASSIST_xmm3_xmm2(imm8) \
242 : ".byte 0x66, 0x0f, 0x3a, 0xdf, 0xd3, " #imm8 " \n\t"
243 : #define AESKEY_EXPAND256_A \
244 : "pshufd $0xff, %%xmm2, %%xmm2\n\t" \
245 : "movdqa %%xmm1, %%xmm4\n\t" \
246 : "pslldq $4, %%xmm4\n\t" \
247 : "pxor %%xmm4, %%xmm1\n\t" \
248 : "pslldq $4, %%xmm4\n\t" \
249 : "pxor %%xmm4, %%xmm1\n\t" \
250 : "pslldq $4, %%xmm4\n\t" \
251 : "pxor %%xmm4, %%xmm1\n\t" \
252 : "pxor %%xmm2, %%xmm1\n\t"
253 : #define AESKEY_EXPAND256_B \
254 : "pshufd $0xaa, %%xmm2, %%xmm2\n\t" \
255 : "movdqa %%xmm3, %%xmm4\n\t" \
256 : "pslldq $4, %%xmm4\n\t" \
257 : "pxor %%xmm4, %%xmm3\n\t" \
258 : "pslldq $4, %%xmm4\n\t" \
259 : "pxor %%xmm4, %%xmm3\n\t" \
260 : "pslldq $4, %%xmm4\n\t" \
261 : "pxor %%xmm4, %%xmm3\n\t" \
262 : "pxor %%xmm2, %%xmm3\n\t"
263 :
264 347 : asm volatile ("movdqu (%[key]), %%xmm1\n\t" /* xmm1 := key[0..15] */
265 : "movdqu 16(%[key]), %%xmm3\n\t" /* xmm3 := key[16..31] */
266 : "movdqa %%xmm1, (%[ksch])\n\t" /* ksch[0] := xmm1 */
267 : "movdqa %%xmm3, 0x10(%[ksch])\n\t" /* ksch[1] := xmm3 */
268 :
269 : AESKEYGENASSIST_xmm3_xmm2(0x01)
270 : AESKEY_EXPAND256_A
271 : "movdqa %%xmm1, 0x20(%[ksch])\n\t" /* ksch[2] := xmm1 */
272 : AESKEYGENASSIST_xmm1_xmm2(0x00)
273 : AESKEY_EXPAND256_B
274 : "movdqa %%xmm3, 0x30(%[ksch])\n\t" /* ksch[3] := xmm3 */
275 :
276 : AESKEYGENASSIST_xmm3_xmm2(0x02)
277 : AESKEY_EXPAND256_A
278 : "movdqa %%xmm1, 0x40(%[ksch])\n\t" /* ksch[4] := xmm1 */
279 : AESKEYGENASSIST_xmm1_xmm2(0x00)
280 : AESKEY_EXPAND256_B
281 : "movdqa %%xmm3, 0x50(%[ksch])\n\t" /* ksch[5] := xmm3 */
282 :
283 : AESKEYGENASSIST_xmm3_xmm2(0x04)
284 : AESKEY_EXPAND256_A
285 : "movdqa %%xmm1, 0x60(%[ksch])\n\t" /* ksch[6] := xmm1 */
286 : AESKEYGENASSIST_xmm1_xmm2(0x00)
287 : AESKEY_EXPAND256_B
288 : "movdqa %%xmm3, 0x70(%[ksch])\n\t" /* ksch[7] := xmm3 */
289 :
290 : AESKEYGENASSIST_xmm3_xmm2(0x08)
291 : AESKEY_EXPAND256_A
292 : "movdqa %%xmm1, 0x80(%[ksch])\n\t" /* ksch[8] := xmm1 */
293 : AESKEYGENASSIST_xmm1_xmm2(0x00)
294 : AESKEY_EXPAND256_B
295 : "movdqa %%xmm3, 0x90(%[ksch])\n\t" /* ksch[9] := xmm3 */
296 :
297 : AESKEYGENASSIST_xmm3_xmm2(0x10)
298 : AESKEY_EXPAND256_A
299 : "movdqa %%xmm1, 0xa0(%[ksch])\n\t" /* ksch[10] := xmm1 */
300 : AESKEYGENASSIST_xmm1_xmm2(0x00)
301 : AESKEY_EXPAND256_B
302 : "movdqa %%xmm3, 0xb0(%[ksch])\n\t" /* ksch[11] := xmm3 */
303 :
304 : AESKEYGENASSIST_xmm3_xmm2(0x20)
305 : AESKEY_EXPAND256_A
306 : "movdqa %%xmm1, 0xc0(%[ksch])\n\t" /* ksch[12] := xmm1 */
307 : AESKEYGENASSIST_xmm1_xmm2(0x00)
308 : AESKEY_EXPAND256_B
309 : "movdqa %%xmm3, 0xd0(%[ksch])\n\t" /* ksch[13] := xmm3 */
310 :
311 : AESKEYGENASSIST_xmm3_xmm2(0x40)
312 : AESKEY_EXPAND256_A
313 : "movdqa %%xmm1, 0xe0(%[ksch])\n\t" /* ksch[14] := xmm1 */
314 :
315 : :
316 : : [key] "r" (key), [ksch] "r" (ctx->keyschenc)
317 : : "cc", "memory" );
318 : #undef AESKEYGENASSIST_xmm1_xmm2
319 : #undef AESKEYGENASSIST_xmm3_xmm2
320 : #undef AESKEY_EXPAND256_A
321 : #undef AESKEY_EXPAND256_B
322 : }
323 :
324 1558 : aesni_cleanup();
325 1558 : aesni_cleanup_2_6();
326 1558 : }
327 :
328 :
329 : /* Make a decryption key from an encryption key. */
330 : void
331 1082 : _gcry_aes_aesni_prepare_decryption (RIJNDAEL_context *ctx)
332 : {
333 : /* The AES-NI decrypt instructions use the Equivalent Inverse
334 : Cipher, thus we can't use the the standard decrypt key
335 : preparation. */
336 1082 : u128_t *ekey = (u128_t *)ctx->keyschenc;
337 1082 : u128_t *dkey = (u128_t *)ctx->keyschdec;
338 : int rr;
339 : int r;
340 :
341 : aesni_prepare();
342 :
343 : #define DO_AESNI_AESIMC() \
344 : asm volatile ("movdqa %[ekey], %%xmm1\n\t" \
345 : /*"aesimc %%xmm1, %%xmm1\n\t"*/ \
346 : ".byte 0x66, 0x0f, 0x38, 0xdb, 0xc9\n\t" \
347 : "movdqa %%xmm1, %[dkey]" \
348 : : [dkey] "=m" (dkey[r]) \
349 : : [ekey] "m" (ekey[rr]) \
350 : : "memory")
351 :
352 1082 : dkey[0] = ekey[ctx->rounds];
353 1082 : r=1;
354 1082 : rr=ctx->rounds-1;
355 1082 : DO_AESNI_AESIMC(); r++; rr--; /* round 1 */
356 1082 : DO_AESNI_AESIMC(); r++; rr--; /* round 2 */
357 1082 : DO_AESNI_AESIMC(); r++; rr--; /* round 3 */
358 1082 : DO_AESNI_AESIMC(); r++; rr--; /* round 4 */
359 1082 : DO_AESNI_AESIMC(); r++; rr--; /* round 5 */
360 1082 : DO_AESNI_AESIMC(); r++; rr--; /* round 6 */
361 1082 : DO_AESNI_AESIMC(); r++; rr--; /* round 7 */
362 1082 : DO_AESNI_AESIMC(); r++; rr--; /* round 8 */
363 1082 : DO_AESNI_AESIMC(); r++; rr--; /* round 9 */
364 1082 : if (ctx->rounds > 10)
365 : {
366 699 : DO_AESNI_AESIMC(); r++; rr--; /* round 10 */
367 699 : DO_AESNI_AESIMC(); r++; rr--; /* round 11 */
368 699 : if (ctx->rounds > 12)
369 : {
370 360 : DO_AESNI_AESIMC(); r++; rr--; /* round 12 */
371 360 : DO_AESNI_AESIMC(); r++; rr--; /* round 13 */
372 : }
373 : }
374 :
375 1082 : dkey[r] = ekey[0];
376 :
377 : #undef DO_AESNI_AESIMC
378 :
379 1082 : aesni_cleanup();
380 1082 : }
381 :
382 :
383 : /* Encrypt one block using the Intel AES-NI instructions. Block is input
384 : * and output through SSE register xmm0. */
385 : static inline void
386 11490668 : do_aesni_enc (const RIJNDAEL_context *ctx)
387 : {
388 : #define aesenc_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc1\n\t"
389 : #define aesenclast_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc1\n\t"
390 22981336 : asm volatile ("movdqa (%[key]), %%xmm1\n\t" /* xmm1 := key[0] */
391 : "pxor %%xmm1, %%xmm0\n\t" /* xmm0 ^= key[0] */
392 : "movdqa 0x10(%[key]), %%xmm1\n\t"
393 : aesenc_xmm1_xmm0
394 : "movdqa 0x20(%[key]), %%xmm1\n\t"
395 : aesenc_xmm1_xmm0
396 : "movdqa 0x30(%[key]), %%xmm1\n\t"
397 : aesenc_xmm1_xmm0
398 : "movdqa 0x40(%[key]), %%xmm1\n\t"
399 : aesenc_xmm1_xmm0
400 : "movdqa 0x50(%[key]), %%xmm1\n\t"
401 : aesenc_xmm1_xmm0
402 : "movdqa 0x60(%[key]), %%xmm1\n\t"
403 : aesenc_xmm1_xmm0
404 : "movdqa 0x70(%[key]), %%xmm1\n\t"
405 : aesenc_xmm1_xmm0
406 : "movdqa 0x80(%[key]), %%xmm1\n\t"
407 : aesenc_xmm1_xmm0
408 : "movdqa 0x90(%[key]), %%xmm1\n\t"
409 : aesenc_xmm1_xmm0
410 : "movdqa 0xa0(%[key]), %%xmm1\n\t"
411 : "cmpl $10, %[rounds]\n\t"
412 : "jz .Lenclast%=\n\t"
413 : aesenc_xmm1_xmm0
414 : "movdqa 0xb0(%[key]), %%xmm1\n\t"
415 : aesenc_xmm1_xmm0
416 : "movdqa 0xc0(%[key]), %%xmm1\n\t"
417 : "cmpl $12, %[rounds]\n\t"
418 : "jz .Lenclast%=\n\t"
419 : aesenc_xmm1_xmm0
420 : "movdqa 0xd0(%[key]), %%xmm1\n\t"
421 : aesenc_xmm1_xmm0
422 : "movdqa 0xe0(%[key]), %%xmm1\n"
423 :
424 : ".Lenclast%=:\n\t"
425 : aesenclast_xmm1_xmm0
426 : "\n"
427 : :
428 : : [key] "r" (ctx->keyschenc),
429 11490668 : [rounds] "r" (ctx->rounds)
430 : : "cc", "memory");
431 : #undef aesenc_xmm1_xmm0
432 : #undef aesenclast_xmm1_xmm0
433 11490668 : }
434 :
435 :
436 : /* Decrypt one block using the Intel AES-NI instructions. Block is input
437 : * and output through SSE register xmm0. */
438 : static inline void
439 1943721 : do_aesni_dec (const RIJNDAEL_context *ctx)
440 : {
441 : #define aesdec_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xde, 0xc1\n\t"
442 : #define aesdeclast_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdf, 0xc1\n\t"
443 3887442 : asm volatile ("movdqa (%[key]), %%xmm1\n\t"
444 : "pxor %%xmm1, %%xmm0\n\t" /* xmm0 ^= key[0] */
445 : "movdqa 0x10(%[key]), %%xmm1\n\t"
446 : aesdec_xmm1_xmm0
447 : "movdqa 0x20(%[key]), %%xmm1\n\t"
448 : aesdec_xmm1_xmm0
449 : "movdqa 0x30(%[key]), %%xmm1\n\t"
450 : aesdec_xmm1_xmm0
451 : "movdqa 0x40(%[key]), %%xmm1\n\t"
452 : aesdec_xmm1_xmm0
453 : "movdqa 0x50(%[key]), %%xmm1\n\t"
454 : aesdec_xmm1_xmm0
455 : "movdqa 0x60(%[key]), %%xmm1\n\t"
456 : aesdec_xmm1_xmm0
457 : "movdqa 0x70(%[key]), %%xmm1\n\t"
458 : aesdec_xmm1_xmm0
459 : "movdqa 0x80(%[key]), %%xmm1\n\t"
460 : aesdec_xmm1_xmm0
461 : "movdqa 0x90(%[key]), %%xmm1\n\t"
462 : aesdec_xmm1_xmm0
463 : "movdqa 0xa0(%[key]), %%xmm1\n\t"
464 : "cmpl $10, %[rounds]\n\t"
465 : "jz .Ldeclast%=\n\t"
466 : aesdec_xmm1_xmm0
467 : "movdqa 0xb0(%[key]), %%xmm1\n\t"
468 : aesdec_xmm1_xmm0
469 : "movdqa 0xc0(%[key]), %%xmm1\n\t"
470 : "cmpl $12, %[rounds]\n\t"
471 : "jz .Ldeclast%=\n\t"
472 : aesdec_xmm1_xmm0
473 : "movdqa 0xd0(%[key]), %%xmm1\n\t"
474 : aesdec_xmm1_xmm0
475 : "movdqa 0xe0(%[key]), %%xmm1\n"
476 :
477 : ".Ldeclast%=:\n\t"
478 : aesdeclast_xmm1_xmm0
479 : "\n"
480 : :
481 : : [key] "r" (ctx->keyschdec),
482 1943721 : [rounds] "r" (ctx->rounds)
483 : : "cc", "memory");
484 : #undef aesdec_xmm1_xmm0
485 : #undef aesdeclast_xmm1_xmm0
486 1943721 : }
487 :
488 :
489 : /* Encrypt four blocks using the Intel AES-NI instructions. Blocks are input
490 : * and output through SSE registers xmm1 to xmm4. */
491 : static inline void
492 1763767 : do_aesni_enc_vec4 (const RIJNDAEL_context *ctx)
493 : {
494 : #define aesenc_xmm0_xmm1 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc8\n\t"
495 : #define aesenc_xmm0_xmm2 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xd0\n\t"
496 : #define aesenc_xmm0_xmm3 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xd8\n\t"
497 : #define aesenc_xmm0_xmm4 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xe0\n\t"
498 : #define aesenclast_xmm0_xmm1 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc8\n\t"
499 : #define aesenclast_xmm0_xmm2 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xd0\n\t"
500 : #define aesenclast_xmm0_xmm3 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xd8\n\t"
501 : #define aesenclast_xmm0_xmm4 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xe0\n\t"
502 3527534 : asm volatile ("movdqa (%[key]), %%xmm0\n\t"
503 : "pxor %%xmm0, %%xmm1\n\t" /* xmm1 ^= key[0] */
504 : "pxor %%xmm0, %%xmm2\n\t" /* xmm2 ^= key[0] */
505 : "pxor %%xmm0, %%xmm3\n\t" /* xmm3 ^= key[0] */
506 : "pxor %%xmm0, %%xmm4\n\t" /* xmm4 ^= key[0] */
507 : "movdqa 0x10(%[key]), %%xmm0\n\t"
508 : aesenc_xmm0_xmm1
509 : aesenc_xmm0_xmm2
510 : aesenc_xmm0_xmm3
511 : aesenc_xmm0_xmm4
512 : "movdqa 0x20(%[key]), %%xmm0\n\t"
513 : aesenc_xmm0_xmm1
514 : aesenc_xmm0_xmm2
515 : aesenc_xmm0_xmm3
516 : aesenc_xmm0_xmm4
517 : "movdqa 0x30(%[key]), %%xmm0\n\t"
518 : aesenc_xmm0_xmm1
519 : aesenc_xmm0_xmm2
520 : aesenc_xmm0_xmm3
521 : aesenc_xmm0_xmm4
522 : "movdqa 0x40(%[key]), %%xmm0\n\t"
523 : aesenc_xmm0_xmm1
524 : aesenc_xmm0_xmm2
525 : aesenc_xmm0_xmm3
526 : aesenc_xmm0_xmm4
527 : "movdqa 0x50(%[key]), %%xmm0\n\t"
528 : aesenc_xmm0_xmm1
529 : aesenc_xmm0_xmm2
530 : aesenc_xmm0_xmm3
531 : aesenc_xmm0_xmm4
532 : "movdqa 0x60(%[key]), %%xmm0\n\t"
533 : aesenc_xmm0_xmm1
534 : aesenc_xmm0_xmm2
535 : aesenc_xmm0_xmm3
536 : aesenc_xmm0_xmm4
537 : "movdqa 0x70(%[key]), %%xmm0\n\t"
538 : aesenc_xmm0_xmm1
539 : aesenc_xmm0_xmm2
540 : aesenc_xmm0_xmm3
541 : aesenc_xmm0_xmm4
542 : "movdqa 0x80(%[key]), %%xmm0\n\t"
543 : aesenc_xmm0_xmm1
544 : aesenc_xmm0_xmm2
545 : aesenc_xmm0_xmm3
546 : aesenc_xmm0_xmm4
547 : "movdqa 0x90(%[key]), %%xmm0\n\t"
548 : aesenc_xmm0_xmm1
549 : aesenc_xmm0_xmm2
550 : aesenc_xmm0_xmm3
551 : aesenc_xmm0_xmm4
552 : "movdqa 0xa0(%[key]), %%xmm0\n\t"
553 : "cmpl $10, %[rounds]\n\t"
554 : "jz .Ldeclast%=\n\t"
555 : aesenc_xmm0_xmm1
556 : aesenc_xmm0_xmm2
557 : aesenc_xmm0_xmm3
558 : aesenc_xmm0_xmm4
559 : "movdqa 0xb0(%[key]), %%xmm0\n\t"
560 : aesenc_xmm0_xmm1
561 : aesenc_xmm0_xmm2
562 : aesenc_xmm0_xmm3
563 : aesenc_xmm0_xmm4
564 : "movdqa 0xc0(%[key]), %%xmm0\n\t"
565 : "cmpl $12, %[rounds]\n\t"
566 : "jz .Ldeclast%=\n\t"
567 : aesenc_xmm0_xmm1
568 : aesenc_xmm0_xmm2
569 : aesenc_xmm0_xmm3
570 : aesenc_xmm0_xmm4
571 : "movdqa 0xd0(%[key]), %%xmm0\n\t"
572 : aesenc_xmm0_xmm1
573 : aesenc_xmm0_xmm2
574 : aesenc_xmm0_xmm3
575 : aesenc_xmm0_xmm4
576 : "movdqa 0xe0(%[key]), %%xmm0\n"
577 :
578 : ".Ldeclast%=:\n\t"
579 : aesenclast_xmm0_xmm1
580 : aesenclast_xmm0_xmm2
581 : aesenclast_xmm0_xmm3
582 : aesenclast_xmm0_xmm4
583 : : /* no output */
584 : : [key] "r" (ctx->keyschenc),
585 1763767 : [rounds] "r" (ctx->rounds)
586 : : "cc", "memory");
587 : #undef aesenc_xmm0_xmm1
588 : #undef aesenc_xmm0_xmm2
589 : #undef aesenc_xmm0_xmm3
590 : #undef aesenc_xmm0_xmm4
591 : #undef aesenclast_xmm0_xmm1
592 : #undef aesenclast_xmm0_xmm2
593 : #undef aesenclast_xmm0_xmm3
594 : #undef aesenclast_xmm0_xmm4
595 1763767 : }
596 :
597 :
598 : /* Decrypt four blocks using the Intel AES-NI instructions. Blocks are input
599 : * and output through SSE registers xmm1 to xmm4. */
600 : static inline void
601 1017713 : do_aesni_dec_vec4 (const RIJNDAEL_context *ctx)
602 : {
603 : #define aesdec_xmm0_xmm1 ".byte 0x66, 0x0f, 0x38, 0xde, 0xc8\n\t"
604 : #define aesdec_xmm0_xmm2 ".byte 0x66, 0x0f, 0x38, 0xde, 0xd0\n\t"
605 : #define aesdec_xmm0_xmm3 ".byte 0x66, 0x0f, 0x38, 0xde, 0xd8\n\t"
606 : #define aesdec_xmm0_xmm4 ".byte 0x66, 0x0f, 0x38, 0xde, 0xe0\n\t"
607 : #define aesdeclast_xmm0_xmm1 ".byte 0x66, 0x0f, 0x38, 0xdf, 0xc8\n\t"
608 : #define aesdeclast_xmm0_xmm2 ".byte 0x66, 0x0f, 0x38, 0xdf, 0xd0\n\t"
609 : #define aesdeclast_xmm0_xmm3 ".byte 0x66, 0x0f, 0x38, 0xdf, 0xd8\n\t"
610 : #define aesdeclast_xmm0_xmm4 ".byte 0x66, 0x0f, 0x38, 0xdf, 0xe0\n\t"
611 2035426 : asm volatile ("movdqa (%[key]), %%xmm0\n\t"
612 : "pxor %%xmm0, %%xmm1\n\t" /* xmm1 ^= key[0] */
613 : "pxor %%xmm0, %%xmm2\n\t" /* xmm2 ^= key[0] */
614 : "pxor %%xmm0, %%xmm3\n\t" /* xmm3 ^= key[0] */
615 : "pxor %%xmm0, %%xmm4\n\t" /* xmm4 ^= key[0] */
616 : "movdqa 0x10(%[key]), %%xmm0\n\t"
617 : aesdec_xmm0_xmm1
618 : aesdec_xmm0_xmm2
619 : aesdec_xmm0_xmm3
620 : aesdec_xmm0_xmm4
621 : "movdqa 0x20(%[key]), %%xmm0\n\t"
622 : aesdec_xmm0_xmm1
623 : aesdec_xmm0_xmm2
624 : aesdec_xmm0_xmm3
625 : aesdec_xmm0_xmm4
626 : "movdqa 0x30(%[key]), %%xmm0\n\t"
627 : aesdec_xmm0_xmm1
628 : aesdec_xmm0_xmm2
629 : aesdec_xmm0_xmm3
630 : aesdec_xmm0_xmm4
631 : "movdqa 0x40(%[key]), %%xmm0\n\t"
632 : aesdec_xmm0_xmm1
633 : aesdec_xmm0_xmm2
634 : aesdec_xmm0_xmm3
635 : aesdec_xmm0_xmm4
636 : "movdqa 0x50(%[key]), %%xmm0\n\t"
637 : aesdec_xmm0_xmm1
638 : aesdec_xmm0_xmm2
639 : aesdec_xmm0_xmm3
640 : aesdec_xmm0_xmm4
641 : "movdqa 0x60(%[key]), %%xmm0\n\t"
642 : aesdec_xmm0_xmm1
643 : aesdec_xmm0_xmm2
644 : aesdec_xmm0_xmm3
645 : aesdec_xmm0_xmm4
646 : "movdqa 0x70(%[key]), %%xmm0\n\t"
647 : aesdec_xmm0_xmm1
648 : aesdec_xmm0_xmm2
649 : aesdec_xmm0_xmm3
650 : aesdec_xmm0_xmm4
651 : "movdqa 0x80(%[key]), %%xmm0\n\t"
652 : aesdec_xmm0_xmm1
653 : aesdec_xmm0_xmm2
654 : aesdec_xmm0_xmm3
655 : aesdec_xmm0_xmm4
656 : "movdqa 0x90(%[key]), %%xmm0\n\t"
657 : aesdec_xmm0_xmm1
658 : aesdec_xmm0_xmm2
659 : aesdec_xmm0_xmm3
660 : aesdec_xmm0_xmm4
661 : "movdqa 0xa0(%[key]), %%xmm0\n\t"
662 : "cmpl $10, %[rounds]\n\t"
663 : "jz .Ldeclast%=\n\t"
664 : aesdec_xmm0_xmm1
665 : aesdec_xmm0_xmm2
666 : aesdec_xmm0_xmm3
667 : aesdec_xmm0_xmm4
668 : "movdqa 0xb0(%[key]), %%xmm0\n\t"
669 : aesdec_xmm0_xmm1
670 : aesdec_xmm0_xmm2
671 : aesdec_xmm0_xmm3
672 : aesdec_xmm0_xmm4
673 : "movdqa 0xc0(%[key]), %%xmm0\n\t"
674 : "cmpl $12, %[rounds]\n\t"
675 : "jz .Ldeclast%=\n\t"
676 : aesdec_xmm0_xmm1
677 : aesdec_xmm0_xmm2
678 : aesdec_xmm0_xmm3
679 : aesdec_xmm0_xmm4
680 : "movdqa 0xd0(%[key]), %%xmm0\n\t"
681 : aesdec_xmm0_xmm1
682 : aesdec_xmm0_xmm2
683 : aesdec_xmm0_xmm3
684 : aesdec_xmm0_xmm4
685 : "movdqa 0xe0(%[key]), %%xmm0\n"
686 :
687 : ".Ldeclast%=:\n\t"
688 : aesdeclast_xmm0_xmm1
689 : aesdeclast_xmm0_xmm2
690 : aesdeclast_xmm0_xmm3
691 : aesdeclast_xmm0_xmm4
692 : : /* no output */
693 : : [key] "r" (ctx->keyschdec),
694 1017713 : [rounds] "r" (ctx->rounds)
695 : : "cc", "memory");
696 : #undef aesdec_xmm0_xmm1
697 : #undef aesdec_xmm0_xmm2
698 : #undef aesdec_xmm0_xmm3
699 : #undef aesdec_xmm0_xmm4
700 : #undef aesdeclast_xmm0_xmm1
701 : #undef aesdeclast_xmm0_xmm2
702 : #undef aesdeclast_xmm0_xmm3
703 : #undef aesdeclast_xmm0_xmm4
704 1017713 : }
705 :
706 :
707 : /* Perform a CTR encryption round using the counter CTR and the input
708 : block A. Write the result to the output block B and update CTR.
709 : CTR needs to be a 16 byte aligned little-endian value. */
710 : static void
711 57810 : do_aesni_ctr (const RIJNDAEL_context *ctx,
712 : unsigned char *ctr, unsigned char *b, const unsigned char *a)
713 : {
714 : #define aesenc_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc1\n\t"
715 : #define aesenclast_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc1\n\t"
716 :
717 115620 : asm volatile ("movdqa %%xmm5, %%xmm0\n\t" /* xmm0 := CTR (xmm5) */
718 : "pcmpeqd %%xmm1, %%xmm1\n\t"
719 : "psrldq $8, %%xmm1\n\t" /* xmm1 = -1 */
720 :
721 : "pshufb %%xmm6, %%xmm5\n\t"
722 : "psubq %%xmm1, %%xmm5\n\t" /* xmm5++ (big endian) */
723 :
724 : /* detect if 64-bit carry handling is needed */
725 : "cmpl $0xffffffff, 8(%[ctr])\n\t"
726 : "jne .Lno_carry%=\n\t"
727 : "cmpl $0xffffffff, 12(%[ctr])\n\t"
728 : "jne .Lno_carry%=\n\t"
729 :
730 : "pslldq $8, %%xmm1\n\t" /* move lower 64-bit to high */
731 : "psubq %%xmm1, %%xmm5\n\t" /* add carry to upper 64bits */
732 :
733 : ".Lno_carry%=:\n\t"
734 :
735 : "pshufb %%xmm6, %%xmm5\n\t"
736 : "movdqa %%xmm5, (%[ctr])\n\t" /* Update CTR (mem). */
737 :
738 : "pxor (%[key]), %%xmm0\n\t" /* xmm1 ^= key[0] */
739 : "movdqa 0x10(%[key]), %%xmm1\n\t"
740 : aesenc_xmm1_xmm0
741 : "movdqa 0x20(%[key]), %%xmm1\n\t"
742 : aesenc_xmm1_xmm0
743 : "movdqa 0x30(%[key]), %%xmm1\n\t"
744 : aesenc_xmm1_xmm0
745 : "movdqa 0x40(%[key]), %%xmm1\n\t"
746 : aesenc_xmm1_xmm0
747 : "movdqa 0x50(%[key]), %%xmm1\n\t"
748 : aesenc_xmm1_xmm0
749 : "movdqa 0x60(%[key]), %%xmm1\n\t"
750 : aesenc_xmm1_xmm0
751 : "movdqa 0x70(%[key]), %%xmm1\n\t"
752 : aesenc_xmm1_xmm0
753 : "movdqa 0x80(%[key]), %%xmm1\n\t"
754 : aesenc_xmm1_xmm0
755 : "movdqa 0x90(%[key]), %%xmm1\n\t"
756 : aesenc_xmm1_xmm0
757 : "movdqa 0xa0(%[key]), %%xmm1\n\t"
758 : "cmpl $10, %[rounds]\n\t"
759 : "jz .Lenclast%=\n\t"
760 : aesenc_xmm1_xmm0
761 : "movdqa 0xb0(%[key]), %%xmm1\n\t"
762 : aesenc_xmm1_xmm0
763 : "movdqa 0xc0(%[key]), %%xmm1\n\t"
764 : "cmpl $12, %[rounds]\n\t"
765 : "jz .Lenclast%=\n\t"
766 : aesenc_xmm1_xmm0
767 : "movdqa 0xd0(%[key]), %%xmm1\n\t"
768 : aesenc_xmm1_xmm0
769 : "movdqa 0xe0(%[key]), %%xmm1\n"
770 :
771 : ".Lenclast%=:\n\t"
772 : aesenclast_xmm1_xmm0
773 : "movdqu %[src], %%xmm1\n\t" /* xmm1 := input */
774 : "pxor %%xmm1, %%xmm0\n\t" /* EncCTR ^= input */
775 : "movdqu %%xmm0, %[dst]" /* Store EncCTR. */
776 :
777 : : [dst] "=m" (*b)
778 : : [src] "m" (*a),
779 : [ctr] "r" (ctr),
780 : [key] "r" (ctx->keyschenc),
781 57810 : [rounds] "g" (ctx->rounds)
782 : : "cc", "memory");
783 : #undef aesenc_xmm1_xmm0
784 : #undef aesenclast_xmm1_xmm0
785 57810 : }
786 :
787 :
788 : /* Four blocks at a time variant of do_aesni_ctr. */
789 : static void
790 1649512 : do_aesni_ctr_4 (const RIJNDAEL_context *ctx,
791 : unsigned char *ctr, unsigned char *b, const unsigned char *a)
792 : {
793 : static const byte bige_addb_const[4][16] __attribute__ ((aligned (16))) =
794 : {
795 : { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
796 : { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 },
797 : { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3 },
798 : { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4 }
799 : };
800 1649512 : const void *bige_addb = bige_addb_const;
801 : #define aesenc_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc1\n\t"
802 : #define aesenc_xmm1_xmm2 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xd1\n\t"
803 : #define aesenc_xmm1_xmm3 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xd9\n\t"
804 : #define aesenc_xmm1_xmm4 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xe1\n\t"
805 : #define aesenclast_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc1\n\t"
806 : #define aesenclast_xmm1_xmm2 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xd1\n\t"
807 : #define aesenclast_xmm1_xmm3 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xd9\n\t"
808 : #define aesenclast_xmm1_xmm4 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xe1\n\t"
809 :
810 : /* Register usage:
811 : esi keyschedule
812 : xmm0 CTR-0
813 : xmm1 temp / round key
814 : xmm2 CTR-1
815 : xmm3 CTR-2
816 : xmm4 CTR-3
817 : xmm5 copy of *ctr
818 : xmm6 endian swapping mask
819 : */
820 :
821 1649512 : asm volatile (/* detect if 8-bit carry handling is needed */
822 : "cmpb $0xfb, 15(%[ctr])\n\t"
823 : "ja .Ladd32bit%=\n\t"
824 :
825 : "movdqa %%xmm5, %%xmm0\n\t" /* xmm0 := CTR (xmm5) */
826 : "movdqa 0*16(%[addb]), %%xmm2\n\t" /* xmm2 := be(1) */
827 : "movdqa 1*16(%[addb]), %%xmm3\n\t" /* xmm3 := be(2) */
828 : "movdqa 2*16(%[addb]), %%xmm4\n\t" /* xmm4 := be(3) */
829 : "movdqa 3*16(%[addb]), %%xmm5\n\t" /* xmm5 := be(4) */
830 : "paddb %%xmm0, %%xmm2\n\t" /* xmm2 := be(1) + CTR (xmm0) */
831 : "paddb %%xmm0, %%xmm3\n\t" /* xmm3 := be(2) + CTR (xmm0) */
832 : "paddb %%xmm0, %%xmm4\n\t" /* xmm4 := be(3) + CTR (xmm0) */
833 : "paddb %%xmm0, %%xmm5\n\t" /* xmm5 := be(4) + CTR (xmm0) */
834 : "movdqa (%[key]), %%xmm1\n\t" /* xmm1 := key[0] */
835 : "jmp .Lstore_ctr%=\n\t"
836 :
837 : ".Ladd32bit%=:\n\t"
838 : "movdqa %%xmm5, %%xmm0\n\t" /* xmm0, xmm2 := CTR (xmm5) */
839 : "movdqa %%xmm0, %%xmm2\n\t"
840 : "pcmpeqd %%xmm1, %%xmm1\n\t"
841 : "psrldq $8, %%xmm1\n\t" /* xmm1 = -1 */
842 :
843 : "pshufb %%xmm6, %%xmm2\n\t" /* xmm2 := le(xmm2) */
844 : "psubq %%xmm1, %%xmm2\n\t" /* xmm2++ */
845 : "movdqa %%xmm2, %%xmm3\n\t" /* xmm3 := xmm2 */
846 : "psubq %%xmm1, %%xmm3\n\t" /* xmm3++ */
847 : "movdqa %%xmm3, %%xmm4\n\t" /* xmm4 := xmm3 */
848 : "psubq %%xmm1, %%xmm4\n\t" /* xmm4++ */
849 : "movdqa %%xmm4, %%xmm5\n\t" /* xmm5 := xmm4 */
850 : "psubq %%xmm1, %%xmm5\n\t" /* xmm5++ */
851 :
852 : /* detect if 64-bit carry handling is needed */
853 : "cmpl $0xffffffff, 8(%[ctr])\n\t"
854 : "jne .Lno_carry%=\n\t"
855 : "movl 12(%[ctr]), %%esi\n\t"
856 : "bswapl %%esi\n\t"
857 : "cmpl $0xfffffffc, %%esi\n\t"
858 : "jb .Lno_carry%=\n\t" /* no carry */
859 :
860 : "pslldq $8, %%xmm1\n\t" /* move lower 64-bit to high */
861 : "je .Lcarry_xmm5%=\n\t" /* esi == 0xfffffffc */
862 : "cmpl $0xfffffffe, %%esi\n\t"
863 : "jb .Lcarry_xmm4%=\n\t" /* esi == 0xfffffffd */
864 : "je .Lcarry_xmm3%=\n\t" /* esi == 0xfffffffe */
865 : /* esi == 0xffffffff */
866 :
867 : "psubq %%xmm1, %%xmm2\n\t"
868 : ".Lcarry_xmm3%=:\n\t"
869 : "psubq %%xmm1, %%xmm3\n\t"
870 : ".Lcarry_xmm4%=:\n\t"
871 : "psubq %%xmm1, %%xmm4\n\t"
872 : ".Lcarry_xmm5%=:\n\t"
873 : "psubq %%xmm1, %%xmm5\n\t"
874 :
875 : ".Lno_carry%=:\n\t"
876 : "movdqa (%[key]), %%xmm1\n\t" /* xmm1 := key[0] */
877 :
878 : "pshufb %%xmm6, %%xmm2\n\t" /* xmm2 := be(xmm2) */
879 : "pshufb %%xmm6, %%xmm3\n\t" /* xmm3 := be(xmm3) */
880 : "pshufb %%xmm6, %%xmm4\n\t" /* xmm4 := be(xmm4) */
881 : "pshufb %%xmm6, %%xmm5\n\t" /* xmm5 := be(xmm5) */
882 :
883 : ".Lstore_ctr%=:\n\t"
884 : "movdqa %%xmm5, (%[ctr])\n\t" /* Update CTR (mem). */
885 : :
886 : : [ctr] "r" (ctr),
887 : [key] "r" (ctx->keyschenc),
888 : [addb] "r" (bige_addb)
889 : : "%esi", "cc", "memory");
890 :
891 3299024 : asm volatile ("pxor %%xmm1, %%xmm0\n\t" /* xmm0 ^= key[0] */
892 : "pxor %%xmm1, %%xmm2\n\t" /* xmm2 ^= key[0] */
893 : "pxor %%xmm1, %%xmm3\n\t" /* xmm3 ^= key[0] */
894 : "pxor %%xmm1, %%xmm4\n\t" /* xmm4 ^= key[0] */
895 : "movdqa 0x10(%[key]), %%xmm1\n\t"
896 : aesenc_xmm1_xmm0
897 : aesenc_xmm1_xmm2
898 : aesenc_xmm1_xmm3
899 : aesenc_xmm1_xmm4
900 : "movdqa 0x20(%[key]), %%xmm1\n\t"
901 : aesenc_xmm1_xmm0
902 : aesenc_xmm1_xmm2
903 : aesenc_xmm1_xmm3
904 : aesenc_xmm1_xmm4
905 : "movdqa 0x30(%[key]), %%xmm1\n\t"
906 : aesenc_xmm1_xmm0
907 : aesenc_xmm1_xmm2
908 : aesenc_xmm1_xmm3
909 : aesenc_xmm1_xmm4
910 : "movdqa 0x40(%[key]), %%xmm1\n\t"
911 : aesenc_xmm1_xmm0
912 : aesenc_xmm1_xmm2
913 : aesenc_xmm1_xmm3
914 : aesenc_xmm1_xmm4
915 : "movdqa 0x50(%[key]), %%xmm1\n\t"
916 : aesenc_xmm1_xmm0
917 : aesenc_xmm1_xmm2
918 : aesenc_xmm1_xmm3
919 : aesenc_xmm1_xmm4
920 : "movdqa 0x60(%[key]), %%xmm1\n\t"
921 : aesenc_xmm1_xmm0
922 : aesenc_xmm1_xmm2
923 : aesenc_xmm1_xmm3
924 : aesenc_xmm1_xmm4
925 : "movdqa 0x70(%[key]), %%xmm1\n\t"
926 : aesenc_xmm1_xmm0
927 : aesenc_xmm1_xmm2
928 : aesenc_xmm1_xmm3
929 : aesenc_xmm1_xmm4
930 : "movdqa 0x80(%[key]), %%xmm1\n\t"
931 : aesenc_xmm1_xmm0
932 : aesenc_xmm1_xmm2
933 : aesenc_xmm1_xmm3
934 : aesenc_xmm1_xmm4
935 : "movdqa 0x90(%[key]), %%xmm1\n\t"
936 : aesenc_xmm1_xmm0
937 : aesenc_xmm1_xmm2
938 : aesenc_xmm1_xmm3
939 : aesenc_xmm1_xmm4
940 : "movdqa 0xa0(%[key]), %%xmm1\n\t"
941 : "cmpl $10, %[rounds]\n\t"
942 : "jz .Lenclast%=\n\t"
943 : aesenc_xmm1_xmm0
944 : aesenc_xmm1_xmm2
945 : aesenc_xmm1_xmm3
946 : aesenc_xmm1_xmm4
947 : "movdqa 0xb0(%[key]), %%xmm1\n\t"
948 : aesenc_xmm1_xmm0
949 : aesenc_xmm1_xmm2
950 : aesenc_xmm1_xmm3
951 : aesenc_xmm1_xmm4
952 : "movdqa 0xc0(%[key]), %%xmm1\n\t"
953 : "cmpl $12, %[rounds]\n\t"
954 : "jz .Lenclast%=\n\t"
955 : aesenc_xmm1_xmm0
956 : aesenc_xmm1_xmm2
957 : aesenc_xmm1_xmm3
958 : aesenc_xmm1_xmm4
959 : "movdqa 0xd0(%[key]), %%xmm1\n\t"
960 : aesenc_xmm1_xmm0
961 : aesenc_xmm1_xmm2
962 : aesenc_xmm1_xmm3
963 : aesenc_xmm1_xmm4
964 : "movdqa 0xe0(%[key]), %%xmm1\n"
965 :
966 : ".Lenclast%=:\n\t"
967 : aesenclast_xmm1_xmm0
968 : aesenclast_xmm1_xmm2
969 : aesenclast_xmm1_xmm3
970 : aesenclast_xmm1_xmm4
971 : :
972 : : [key] "r" (ctx->keyschenc),
973 1649512 : [rounds] "r" (ctx->rounds)
974 : : "cc", "memory");
975 :
976 1649512 : asm volatile ("movdqu (%[src]), %%xmm1\n\t" /* Get block 1. */
977 : "pxor %%xmm1, %%xmm0\n\t" /* EncCTR-1 ^= input */
978 : "movdqu %%xmm0, (%[dst])\n\t" /* Store block 1 */
979 :
980 : "movdqu 16(%[src]), %%xmm1\n\t" /* Get block 2. */
981 : "pxor %%xmm1, %%xmm2\n\t" /* EncCTR-2 ^= input */
982 : "movdqu %%xmm2, 16(%[dst])\n\t" /* Store block 2. */
983 :
984 : "movdqu 32(%[src]), %%xmm1\n\t" /* Get block 3. */
985 : "pxor %%xmm1, %%xmm3\n\t" /* EncCTR-3 ^= input */
986 : "movdqu %%xmm3, 32(%[dst])\n\t" /* Store block 3. */
987 :
988 : "movdqu 48(%[src]), %%xmm1\n\t" /* Get block 4. */
989 : "pxor %%xmm1, %%xmm4\n\t" /* EncCTR-4 ^= input */
990 : "movdqu %%xmm4, 48(%[dst])" /* Store block 4. */
991 : :
992 : : [src] "r" (a),
993 : [dst] "r" (b)
994 : : "memory");
995 : #undef aesenc_xmm1_xmm0
996 : #undef aesenc_xmm1_xmm2
997 : #undef aesenc_xmm1_xmm3
998 : #undef aesenc_xmm1_xmm4
999 : #undef aesenclast_xmm1_xmm0
1000 : #undef aesenclast_xmm1_xmm2
1001 : #undef aesenclast_xmm1_xmm3
1002 : #undef aesenclast_xmm1_xmm4
1003 1649512 : }
1004 :
1005 :
1006 : unsigned int
1007 4571555 : _gcry_aes_aesni_encrypt (const RIJNDAEL_context *ctx, unsigned char *dst,
1008 : const unsigned char *src)
1009 : {
1010 : aesni_prepare ();
1011 4571555 : asm volatile ("movdqu %[src], %%xmm0\n\t"
1012 : :
1013 : : [src] "m" (*src)
1014 : : "memory" );
1015 4571555 : do_aesni_enc (ctx);
1016 4571555 : asm volatile ("movdqu %%xmm0, %[dst]\n\t"
1017 : : [dst] "=m" (*dst)
1018 : :
1019 : : "memory" );
1020 4571555 : aesni_cleanup ();
1021 4571555 : return 0;
1022 : }
1023 :
1024 :
1025 : void
1026 12635 : _gcry_aes_aesni_cfb_enc (RIJNDAEL_context *ctx, unsigned char *outbuf,
1027 : const unsigned char *inbuf, unsigned char *iv,
1028 : size_t nblocks)
1029 : {
1030 : aesni_prepare ();
1031 :
1032 12635 : asm volatile ("movdqu %[iv], %%xmm0\n\t"
1033 : : /* No output */
1034 : : [iv] "m" (*iv)
1035 : : "memory" );
1036 :
1037 1391079 : for ( ;nblocks; nblocks-- )
1038 : {
1039 1378444 : do_aesni_enc (ctx);
1040 :
1041 1378444 : asm volatile ("movdqu %[inbuf], %%xmm1\n\t"
1042 : "pxor %%xmm1, %%xmm0\n\t"
1043 : "movdqu %%xmm0, %[outbuf]\n\t"
1044 : : [outbuf] "=m" (*outbuf)
1045 : : [inbuf] "m" (*inbuf)
1046 : : "memory" );
1047 :
1048 1378444 : outbuf += BLOCKSIZE;
1049 1378444 : inbuf += BLOCKSIZE;
1050 : }
1051 :
1052 12635 : asm volatile ("movdqu %%xmm0, %[iv]\n\t"
1053 : : [iv] "=m" (*iv)
1054 : :
1055 : : "memory" );
1056 :
1057 12635 : aesni_cleanup ();
1058 12635 : }
1059 :
1060 :
1061 : void
1062 121504 : _gcry_aes_aesni_cbc_enc (RIJNDAEL_context *ctx, unsigned char *outbuf,
1063 : const unsigned char *inbuf, unsigned char *iv,
1064 : size_t nblocks, int cbc_mac)
1065 : {
1066 : aesni_prepare_2_6_variable;
1067 :
1068 : aesni_prepare ();
1069 : aesni_prepare_2_6();
1070 :
1071 121504 : asm volatile ("movdqu %[iv], %%xmm5\n\t"
1072 : : /* No output */
1073 : : [iv] "m" (*iv)
1074 : : "memory" );
1075 :
1076 5643648 : for ( ;nblocks; nblocks-- )
1077 : {
1078 5522144 : asm volatile ("movdqu %[inbuf], %%xmm0\n\t"
1079 : "pxor %%xmm5, %%xmm0\n\t"
1080 : : /* No output */
1081 : : [inbuf] "m" (*inbuf)
1082 : : "memory" );
1083 :
1084 5522144 : do_aesni_enc (ctx);
1085 :
1086 5522144 : asm volatile ("movdqa %%xmm0, %%xmm5\n\t"
1087 : "movdqu %%xmm0, %[outbuf]\n\t"
1088 : : [outbuf] "=m" (*outbuf)
1089 : :
1090 : : "memory" );
1091 :
1092 5522144 : inbuf += BLOCKSIZE;
1093 5522144 : if (!cbc_mac)
1094 1964932 : outbuf += BLOCKSIZE;
1095 : }
1096 :
1097 121504 : asm volatile ("movdqu %%xmm5, %[iv]\n\t"
1098 : : [iv] "=m" (*iv)
1099 : :
1100 : : "memory" );
1101 :
1102 121504 : aesni_cleanup ();
1103 121504 : aesni_cleanup_2_6 ();
1104 121504 : }
1105 :
1106 :
1107 : void
1108 71318 : _gcry_aes_aesni_ctr_enc (RIJNDAEL_context *ctx, unsigned char *outbuf,
1109 : const unsigned char *inbuf, unsigned char *ctr,
1110 : size_t nblocks)
1111 : {
1112 : static const unsigned char be_mask[16] __attribute__ ((aligned (16))) =
1113 : { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
1114 : aesni_prepare_2_6_variable;
1115 :
1116 : aesni_prepare ();
1117 : aesni_prepare_2_6();
1118 :
1119 71318 : asm volatile ("movdqa %[mask], %%xmm6\n\t" /* Preload mask */
1120 : "movdqa %[ctr], %%xmm5\n\t" /* Preload CTR */
1121 : : /* No output */
1122 : : [mask] "m" (*be_mask),
1123 : [ctr] "m" (*ctr)
1124 : : "memory");
1125 :
1126 1720830 : for ( ;nblocks > 3 ; nblocks -= 4 )
1127 : {
1128 1649512 : do_aesni_ctr_4 (ctx, ctr, outbuf, inbuf);
1129 1649512 : outbuf += 4*BLOCKSIZE;
1130 1649512 : inbuf += 4*BLOCKSIZE;
1131 : }
1132 129128 : for ( ;nblocks; nblocks-- )
1133 : {
1134 57810 : do_aesni_ctr (ctx, ctr, outbuf, inbuf);
1135 57810 : outbuf += BLOCKSIZE;
1136 57810 : inbuf += BLOCKSIZE;
1137 : }
1138 71318 : aesni_cleanup ();
1139 71318 : aesni_cleanup_2_6 ();
1140 71318 : }
1141 :
1142 :
1143 : unsigned int
1144 1920069 : _gcry_aes_aesni_decrypt (const RIJNDAEL_context *ctx, unsigned char *dst,
1145 : const unsigned char *src)
1146 : {
1147 : aesni_prepare ();
1148 1920069 : asm volatile ("movdqu %[src], %%xmm0\n\t"
1149 : :
1150 : : [src] "m" (*src)
1151 : : "memory" );
1152 1920069 : do_aesni_dec (ctx);
1153 1920069 : asm volatile ("movdqu %%xmm0, %[dst]\n\t"
1154 : : [dst] "=m" (*dst)
1155 : :
1156 : : "memory" );
1157 1920069 : aesni_cleanup ();
1158 1920069 : return 0;
1159 : }
1160 :
1161 :
1162 : void
1163 12259 : _gcry_aes_aesni_cfb_dec (RIJNDAEL_context *ctx, unsigned char *outbuf,
1164 : const unsigned char *inbuf, unsigned char *iv,
1165 : size_t nblocks)
1166 : {
1167 : aesni_prepare_2_6_variable;
1168 :
1169 : aesni_prepare ();
1170 : aesni_prepare_2_6();
1171 :
1172 12259 : asm volatile ("movdqu %[iv], %%xmm6\n\t"
1173 : : /* No output */
1174 : : [iv] "m" (*iv)
1175 : : "memory" );
1176 :
1177 : /* CFB decryption can be parallelized */
1178 341942 : for ( ;nblocks >= 4; nblocks -= 4)
1179 : {
1180 329683 : asm volatile
1181 : ("movdqu %%xmm6, %%xmm1\n\t" /* load input blocks */
1182 : "movdqu 0*16(%[inbuf]), %%xmm2\n\t"
1183 : "movdqu 1*16(%[inbuf]), %%xmm3\n\t"
1184 : "movdqu 2*16(%[inbuf]), %%xmm4\n\t"
1185 :
1186 : "movdqu 3*16(%[inbuf]), %%xmm6\n\t" /* update IV */
1187 : : /* No output */
1188 : : [inbuf] "r" (inbuf)
1189 : : "memory");
1190 :
1191 329683 : do_aesni_enc_vec4 (ctx);
1192 :
1193 329683 : asm volatile
1194 : ("movdqu 0*16(%[inbuf]), %%xmm5\n\t"
1195 : "pxor %%xmm5, %%xmm1\n\t"
1196 : "movdqu %%xmm1, 0*16(%[outbuf])\n\t"
1197 :
1198 : "movdqu 1*16(%[inbuf]), %%xmm5\n\t"
1199 : "pxor %%xmm5, %%xmm2\n\t"
1200 : "movdqu %%xmm2, 1*16(%[outbuf])\n\t"
1201 :
1202 : "movdqu 2*16(%[inbuf]), %%xmm5\n\t"
1203 : "pxor %%xmm5, %%xmm3\n\t"
1204 : "movdqu %%xmm3, 2*16(%[outbuf])\n\t"
1205 :
1206 : "movdqu 3*16(%[inbuf]), %%xmm5\n\t"
1207 : "pxor %%xmm5, %%xmm4\n\t"
1208 : "movdqu %%xmm4, 3*16(%[outbuf])\n\t"
1209 :
1210 : : /* No output */
1211 : : [inbuf] "r" (inbuf),
1212 : [outbuf] "r" (outbuf)
1213 : : "memory");
1214 :
1215 329683 : outbuf += 4*BLOCKSIZE;
1216 329683 : inbuf += 4*BLOCKSIZE;
1217 : }
1218 :
1219 12259 : asm volatile ("movdqu %%xmm6, %%xmm0\n\t" ::: "cc");
1220 :
1221 21711 : for ( ;nblocks; nblocks-- )
1222 : {
1223 9452 : do_aesni_enc (ctx);
1224 :
1225 9452 : asm volatile ("movdqa %%xmm0, %%xmm6\n\t"
1226 : "movdqu %[inbuf], %%xmm0\n\t"
1227 : "pxor %%xmm0, %%xmm6\n\t"
1228 : "movdqu %%xmm6, %[outbuf]\n\t"
1229 : : [outbuf] "=m" (*outbuf)
1230 : : [inbuf] "m" (*inbuf)
1231 : : "memory" );
1232 :
1233 9452 : outbuf += BLOCKSIZE;
1234 9452 : inbuf += BLOCKSIZE;
1235 : }
1236 :
1237 12259 : asm volatile ("movdqu %%xmm0, %[iv]\n\t"
1238 : : [iv] "=m" (*iv)
1239 : :
1240 : : "memory" );
1241 :
1242 12259 : aesni_cleanup ();
1243 12259 : aesni_cleanup_2_6 ();
1244 12259 : }
1245 :
1246 :
1247 : void
1248 21431 : _gcry_aes_aesni_cbc_dec (RIJNDAEL_context *ctx, unsigned char *outbuf,
1249 : const unsigned char *inbuf, unsigned char *iv,
1250 : size_t nblocks)
1251 : {
1252 : aesni_prepare_2_6_variable;
1253 :
1254 : aesni_prepare ();
1255 : aesni_prepare_2_6();
1256 :
1257 21431 : asm volatile
1258 : ("movdqu %[iv], %%xmm5\n\t" /* use xmm5 as fast IV storage */
1259 : : /* No output */
1260 : : [iv] "m" (*iv)
1261 : : "memory");
1262 :
1263 512074 : for ( ;nblocks > 3 ; nblocks -= 4 )
1264 : {
1265 490643 : asm volatile
1266 : ("movdqu 0*16(%[inbuf]), %%xmm1\n\t" /* load input blocks */
1267 : "movdqu 1*16(%[inbuf]), %%xmm2\n\t"
1268 : "movdqu 2*16(%[inbuf]), %%xmm3\n\t"
1269 : "movdqu 3*16(%[inbuf]), %%xmm4\n\t"
1270 : : /* No output */
1271 : : [inbuf] "r" (inbuf)
1272 : : "memory");
1273 :
1274 490643 : do_aesni_dec_vec4 (ctx);
1275 :
1276 490643 : asm volatile
1277 : ("pxor %%xmm5, %%xmm1\n\t" /* xor IV with output */
1278 : "movdqu 0*16(%[inbuf]), %%xmm5\n\t" /* load new IV */
1279 : "movdqu %%xmm1, 0*16(%[outbuf])\n\t"
1280 :
1281 : "pxor %%xmm5, %%xmm2\n\t" /* xor IV with output */
1282 : "movdqu 1*16(%[inbuf]), %%xmm5\n\t" /* load new IV */
1283 : "movdqu %%xmm2, 1*16(%[outbuf])\n\t"
1284 :
1285 : "pxor %%xmm5, %%xmm3\n\t" /* xor IV with output */
1286 : "movdqu 2*16(%[inbuf]), %%xmm5\n\t" /* load new IV */
1287 : "movdqu %%xmm3, 2*16(%[outbuf])\n\t"
1288 :
1289 : "pxor %%xmm5, %%xmm4\n\t" /* xor IV with output */
1290 : "movdqu 3*16(%[inbuf]), %%xmm5\n\t" /* load new IV */
1291 : "movdqu %%xmm4, 3*16(%[outbuf])\n\t"
1292 :
1293 : : /* No output */
1294 : : [inbuf] "r" (inbuf),
1295 : [outbuf] "r" (outbuf)
1296 : : "memory");
1297 :
1298 490643 : outbuf += 4*BLOCKSIZE;
1299 490643 : inbuf += 4*BLOCKSIZE;
1300 : }
1301 :
1302 40437 : for ( ;nblocks; nblocks-- )
1303 : {
1304 19006 : asm volatile
1305 : ("movdqu %[inbuf], %%xmm0\n\t"
1306 : "movdqa %%xmm0, %%xmm2\n\t" /* use xmm2 as savebuf */
1307 : : /* No output */
1308 : : [inbuf] "m" (*inbuf)
1309 : : "memory");
1310 :
1311 : /* uses only xmm0 and xmm1 */
1312 19006 : do_aesni_dec (ctx);
1313 :
1314 19006 : asm volatile
1315 : ("pxor %%xmm5, %%xmm0\n\t" /* xor IV with output */
1316 : "movdqu %%xmm0, %[outbuf]\n\t"
1317 : "movdqu %%xmm2, %%xmm5\n\t" /* store savebuf as new IV */
1318 : : [outbuf] "=m" (*outbuf)
1319 : :
1320 : : "memory");
1321 :
1322 19006 : outbuf += BLOCKSIZE;
1323 19006 : inbuf += BLOCKSIZE;
1324 : }
1325 :
1326 21431 : asm volatile
1327 : ("movdqu %%xmm5, %[iv]\n\t" /* store IV */
1328 : : /* No output */
1329 : : [iv] "m" (*iv)
1330 : : "memory");
1331 :
1332 21431 : aesni_cleanup ();
1333 21431 : aesni_cleanup_2_6 ();
1334 21431 : }
1335 :
1336 :
1337 : static void
1338 8078 : aesni_ocb_enc (gcry_cipher_hd_t c, void *outbuf_arg,
1339 : const void *inbuf_arg, size_t nblocks)
1340 : {
1341 8078 : RIJNDAEL_context *ctx = (void *)&c->context.c;
1342 8078 : unsigned char *outbuf = outbuf_arg;
1343 8078 : const unsigned char *inbuf = inbuf_arg;
1344 8078 : u64 n = c->u_mode.ocb.data_nblocks;
1345 : const unsigned char *l;
1346 : aesni_prepare_2_6_variable;
1347 :
1348 : aesni_prepare ();
1349 : aesni_prepare_2_6 ();
1350 :
1351 : /* Preload Offset and Checksum */
1352 8078 : asm volatile ("movdqu %[iv], %%xmm5\n\t"
1353 : "movdqu %[ctr], %%xmm6\n\t"
1354 : : /* No output */
1355 : : [iv] "m" (*c->u_iv.iv),
1356 : [ctr] "m" (*c->u_ctr.ctr)
1357 : : "memory" );
1358 :
1359 :
1360 8956 : for ( ;nblocks && n % 4; nblocks-- )
1361 : {
1362 878 : l = ocb_get_l(c, ++n);
1363 :
1364 : /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
1365 : /* Checksum_i = Checksum_{i-1} xor P_i */
1366 : /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) */
1367 878 : asm volatile ("movdqu %[l], %%xmm1\n\t"
1368 : "movdqu %[inbuf], %%xmm0\n\t"
1369 : "pxor %%xmm1, %%xmm5\n\t"
1370 : "pxor %%xmm0, %%xmm6\n\t"
1371 : "pxor %%xmm5, %%xmm0\n\t"
1372 : :
1373 : : [l] "m" (*l),
1374 : [inbuf] "m" (*inbuf)
1375 : : "memory" );
1376 :
1377 878 : do_aesni_enc (ctx);
1378 :
1379 878 : asm volatile ("pxor %%xmm5, %%xmm0\n\t"
1380 : "movdqu %%xmm0, %[outbuf]\n\t"
1381 : : [outbuf] "=m" (*outbuf)
1382 : :
1383 : : "memory" );
1384 :
1385 878 : inbuf += BLOCKSIZE;
1386 878 : outbuf += BLOCKSIZE;
1387 : }
1388 :
1389 576748 : for ( ;nblocks > 3 ; nblocks -= 4 )
1390 : {
1391 568670 : n += 4;
1392 568670 : l = ocb_get_l(c, n);
1393 :
1394 : /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
1395 : /* Checksum_i = Checksum_{i-1} xor P_i */
1396 : /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) */
1397 568670 : asm volatile ("movdqu %[l0], %%xmm0\n\t"
1398 : "movdqu %[inbuf0], %%xmm1\n\t"
1399 : "pxor %%xmm0, %%xmm5\n\t"
1400 : "pxor %%xmm1, %%xmm6\n\t"
1401 : "pxor %%xmm5, %%xmm1\n\t"
1402 : "movdqu %%xmm5, %[outbuf0]\n\t"
1403 : : [outbuf0] "=m" (*(outbuf + 0 * BLOCKSIZE))
1404 : : [l0] "m" (*c->u_mode.ocb.L[0]),
1405 : [inbuf0] "m" (*(inbuf + 0 * BLOCKSIZE))
1406 : : "memory" );
1407 568670 : asm volatile ("movdqu %[l1], %%xmm0\n\t"
1408 : "movdqu %[inbuf1], %%xmm2\n\t"
1409 : "pxor %%xmm0, %%xmm5\n\t"
1410 : "pxor %%xmm2, %%xmm6\n\t"
1411 : "pxor %%xmm5, %%xmm2\n\t"
1412 : "movdqu %%xmm5, %[outbuf1]\n\t"
1413 568670 : : [outbuf1] "=m" (*(outbuf + 1 * BLOCKSIZE))
1414 : : [l1] "m" (*c->u_mode.ocb.L[1]),
1415 568670 : [inbuf1] "m" (*(inbuf + 1 * BLOCKSIZE))
1416 : : "memory" );
1417 568670 : asm volatile ("movdqu %[l2], %%xmm0\n\t"
1418 : "movdqu %[inbuf2], %%xmm3\n\t"
1419 : "pxor %%xmm0, %%xmm5\n\t"
1420 : "pxor %%xmm3, %%xmm6\n\t"
1421 : "pxor %%xmm5, %%xmm3\n\t"
1422 : "movdqu %%xmm5, %[outbuf2]\n\t"
1423 568670 : : [outbuf2] "=m" (*(outbuf + 2 * BLOCKSIZE))
1424 : : [l2] "m" (*c->u_mode.ocb.L[0]),
1425 568670 : [inbuf2] "m" (*(inbuf + 2 * BLOCKSIZE))
1426 : : "memory" );
1427 568670 : asm volatile ("movdqu %[l3], %%xmm0\n\t"
1428 : "movdqu %[inbuf3], %%xmm4\n\t"
1429 : "pxor %%xmm0, %%xmm5\n\t"
1430 : "pxor %%xmm4, %%xmm6\n\t"
1431 : "pxor %%xmm5, %%xmm4\n\t"
1432 : :
1433 : : [l3] "m" (*l),
1434 568670 : [inbuf3] "m" (*(inbuf + 3 * BLOCKSIZE))
1435 : : "memory" );
1436 :
1437 568670 : do_aesni_enc_vec4 (ctx);
1438 :
1439 568670 : asm volatile ("movdqu %[outbuf0],%%xmm0\n\t"
1440 : "pxor %%xmm0, %%xmm1\n\t"
1441 : "movdqu %%xmm1, %[outbuf0]\n\t"
1442 : "movdqu %[outbuf1],%%xmm0\n\t"
1443 : "pxor %%xmm0, %%xmm2\n\t"
1444 : "movdqu %%xmm2, %[outbuf1]\n\t"
1445 : "movdqu %[outbuf2],%%xmm0\n\t"
1446 : "pxor %%xmm0, %%xmm3\n\t"
1447 : "movdqu %%xmm3, %[outbuf2]\n\t"
1448 : "pxor %%xmm5, %%xmm4\n\t"
1449 : "movdqu %%xmm4, %[outbuf3]\n\t"
1450 : : [outbuf0] "+m" (*(outbuf + 0 * BLOCKSIZE)),
1451 568670 : [outbuf1] "+m" (*(outbuf + 1 * BLOCKSIZE)),
1452 568670 : [outbuf2] "+m" (*(outbuf + 2 * BLOCKSIZE)),
1453 568670 : [outbuf3] "=m" (*(outbuf + 3 * BLOCKSIZE))
1454 : :
1455 : : "memory" );
1456 :
1457 568670 : outbuf += 4*BLOCKSIZE;
1458 568670 : inbuf += 4*BLOCKSIZE;
1459 : }
1460 :
1461 13354 : for ( ;nblocks; nblocks-- )
1462 : {
1463 5276 : l = ocb_get_l(c, ++n);
1464 :
1465 : /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
1466 : /* Checksum_i = Checksum_{i-1} xor P_i */
1467 : /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) */
1468 5276 : asm volatile ("movdqu %[l], %%xmm1\n\t"
1469 : "movdqu %[inbuf], %%xmm0\n\t"
1470 : "pxor %%xmm1, %%xmm5\n\t"
1471 : "pxor %%xmm0, %%xmm6\n\t"
1472 : "pxor %%xmm5, %%xmm0\n\t"
1473 : :
1474 : : [l] "m" (*l),
1475 : [inbuf] "m" (*inbuf)
1476 : : "memory" );
1477 :
1478 5276 : do_aesni_enc (ctx);
1479 :
1480 5276 : asm volatile ("pxor %%xmm5, %%xmm0\n\t"
1481 : "movdqu %%xmm0, %[outbuf]\n\t"
1482 : : [outbuf] "=m" (*outbuf)
1483 : :
1484 : : "memory" );
1485 :
1486 5276 : inbuf += BLOCKSIZE;
1487 5276 : outbuf += BLOCKSIZE;
1488 : }
1489 :
1490 8078 : c->u_mode.ocb.data_nblocks = n;
1491 8078 : asm volatile ("movdqu %%xmm5, %[iv]\n\t"
1492 : "movdqu %%xmm6, %[ctr]\n\t"
1493 : : [iv] "=m" (*c->u_iv.iv),
1494 : [ctr] "=m" (*c->u_ctr.ctr)
1495 : :
1496 : : "memory" );
1497 :
1498 8078 : aesni_cleanup ();
1499 8078 : aesni_cleanup_2_6 ();
1500 8078 : }
1501 :
1502 :
1503 : static void
1504 6586 : aesni_ocb_dec (gcry_cipher_hd_t c, void *outbuf_arg,
1505 : const void *inbuf_arg, size_t nblocks)
1506 : {
1507 6586 : RIJNDAEL_context *ctx = (void *)&c->context.c;
1508 6586 : unsigned char *outbuf = outbuf_arg;
1509 6586 : const unsigned char *inbuf = inbuf_arg;
1510 6586 : u64 n = c->u_mode.ocb.data_nblocks;
1511 : const unsigned char *l;
1512 : aesni_prepare_2_6_variable;
1513 :
1514 : aesni_prepare ();
1515 : aesni_prepare_2_6 ();
1516 :
1517 : /* Preload Offset and Checksum */
1518 6586 : asm volatile ("movdqu %[iv], %%xmm5\n\t"
1519 : "movdqu %[ctr], %%xmm6\n\t"
1520 : : /* No output */
1521 : : [iv] "m" (*c->u_iv.iv),
1522 : [ctr] "m" (*c->u_ctr.ctr)
1523 : : "memory" );
1524 :
1525 7464 : for ( ;nblocks && n % 4; nblocks-- )
1526 : {
1527 878 : l = ocb_get_l(c, ++n);
1528 :
1529 : /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
1530 : /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i) */
1531 : /* Checksum_i = Checksum_{i-1} xor P_i */
1532 878 : asm volatile ("movdqu %[l], %%xmm1\n\t"
1533 : "movdqu %[inbuf], %%xmm0\n\t"
1534 : "pxor %%xmm1, %%xmm5\n\t"
1535 : "pxor %%xmm5, %%xmm0\n\t"
1536 : :
1537 : : [l] "m" (*l),
1538 : [inbuf] "m" (*inbuf)
1539 : : "memory" );
1540 :
1541 878 : do_aesni_dec (ctx);
1542 :
1543 878 : asm volatile ("pxor %%xmm5, %%xmm0\n\t"
1544 : "pxor %%xmm0, %%xmm6\n\t"
1545 : "movdqu %%xmm0, %[outbuf]\n\t"
1546 : : [outbuf] "=m" (*outbuf)
1547 : :
1548 : : "memory" );
1549 :
1550 878 : inbuf += BLOCKSIZE;
1551 878 : outbuf += BLOCKSIZE;
1552 : }
1553 :
1554 533656 : for ( ;nblocks > 3 ; nblocks -= 4 )
1555 : {
1556 527070 : n += 4;
1557 527070 : l = ocb_get_l(c, n);
1558 :
1559 : /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
1560 : /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i) */
1561 : /* Checksum_i = Checksum_{i-1} xor P_i */
1562 527070 : asm volatile ("movdqu %[l0], %%xmm0\n\t"
1563 : "movdqu %[inbuf0], %%xmm1\n\t"
1564 : "pxor %%xmm0, %%xmm5\n\t"
1565 : "pxor %%xmm5, %%xmm1\n\t"
1566 : "movdqu %%xmm5, %[outbuf0]\n\t"
1567 : : [outbuf0] "=m" (*(outbuf + 0 * BLOCKSIZE))
1568 : : [l0] "m" (*c->u_mode.ocb.L[0]),
1569 : [inbuf0] "m" (*(inbuf + 0 * BLOCKSIZE))
1570 : : "memory" );
1571 527070 : asm volatile ("movdqu %[l1], %%xmm0\n\t"
1572 : "movdqu %[inbuf1], %%xmm2\n\t"
1573 : "pxor %%xmm0, %%xmm5\n\t"
1574 : "pxor %%xmm5, %%xmm2\n\t"
1575 : "movdqu %%xmm5, %[outbuf1]\n\t"
1576 527070 : : [outbuf1] "=m" (*(outbuf + 1 * BLOCKSIZE))
1577 : : [l1] "m" (*c->u_mode.ocb.L[1]),
1578 527070 : [inbuf1] "m" (*(inbuf + 1 * BLOCKSIZE))
1579 : : "memory" );
1580 527070 : asm volatile ("movdqu %[l2], %%xmm0\n\t"
1581 : "movdqu %[inbuf2], %%xmm3\n\t"
1582 : "pxor %%xmm0, %%xmm5\n\t"
1583 : "pxor %%xmm5, %%xmm3\n\t"
1584 : "movdqu %%xmm5, %[outbuf2]\n\t"
1585 527070 : : [outbuf2] "=m" (*(outbuf + 2 * BLOCKSIZE))
1586 : : [l2] "m" (*c->u_mode.ocb.L[0]),
1587 527070 : [inbuf2] "m" (*(inbuf + 2 * BLOCKSIZE))
1588 : : "memory" );
1589 527070 : asm volatile ("movdqu %[l3], %%xmm0\n\t"
1590 : "movdqu %[inbuf3], %%xmm4\n\t"
1591 : "pxor %%xmm0, %%xmm5\n\t"
1592 : "pxor %%xmm5, %%xmm4\n\t"
1593 : :
1594 : : [l3] "m" (*l),
1595 527070 : [inbuf3] "m" (*(inbuf + 3 * BLOCKSIZE))
1596 : : "memory" );
1597 :
1598 527070 : do_aesni_dec_vec4 (ctx);
1599 :
1600 527070 : asm volatile ("movdqu %[outbuf0],%%xmm0\n\t"
1601 : "pxor %%xmm0, %%xmm1\n\t"
1602 : "movdqu %%xmm1, %[outbuf0]\n\t"
1603 : "movdqu %[outbuf1],%%xmm0\n\t"
1604 : "pxor %%xmm0, %%xmm2\n\t"
1605 : "movdqu %%xmm2, %[outbuf1]\n\t"
1606 : "movdqu %[outbuf2],%%xmm0\n\t"
1607 : "pxor %%xmm0, %%xmm3\n\t"
1608 : "movdqu %%xmm3, %[outbuf2]\n\t"
1609 : "pxor %%xmm5, %%xmm4\n\t"
1610 : "movdqu %%xmm4, %[outbuf3]\n\t"
1611 : "pxor %%xmm1, %%xmm6\n\t"
1612 : "pxor %%xmm2, %%xmm6\n\t"
1613 : "pxor %%xmm3, %%xmm6\n\t"
1614 : "pxor %%xmm4, %%xmm6\n\t"
1615 : : [outbuf0] "+m" (*(outbuf + 0 * BLOCKSIZE)),
1616 527070 : [outbuf1] "+m" (*(outbuf + 1 * BLOCKSIZE)),
1617 527070 : [outbuf2] "+m" (*(outbuf + 2 * BLOCKSIZE)),
1618 527070 : [outbuf3] "=m" (*(outbuf + 3 * BLOCKSIZE))
1619 : :
1620 : : "memory" );
1621 :
1622 527070 : outbuf += 4*BLOCKSIZE;
1623 527070 : inbuf += 4*BLOCKSIZE;
1624 : }
1625 :
1626 10354 : for ( ;nblocks; nblocks-- )
1627 : {
1628 3768 : l = ocb_get_l(c, ++n);
1629 :
1630 : /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
1631 : /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i) */
1632 : /* Checksum_i = Checksum_{i-1} xor P_i */
1633 3768 : asm volatile ("movdqu %[l], %%xmm1\n\t"
1634 : "movdqu %[inbuf], %%xmm0\n\t"
1635 : "pxor %%xmm1, %%xmm5\n\t"
1636 : "pxor %%xmm5, %%xmm0\n\t"
1637 : :
1638 : : [l] "m" (*l),
1639 : [inbuf] "m" (*inbuf)
1640 : : "memory" );
1641 :
1642 3768 : do_aesni_dec (ctx);
1643 :
1644 3768 : asm volatile ("pxor %%xmm5, %%xmm0\n\t"
1645 : "pxor %%xmm0, %%xmm6\n\t"
1646 : "movdqu %%xmm0, %[outbuf]\n\t"
1647 : : [outbuf] "=m" (*outbuf)
1648 : :
1649 : : "memory" );
1650 :
1651 3768 : inbuf += BLOCKSIZE;
1652 3768 : outbuf += BLOCKSIZE;
1653 : }
1654 :
1655 6586 : c->u_mode.ocb.data_nblocks = n;
1656 6586 : asm volatile ("movdqu %%xmm5, %[iv]\n\t"
1657 : "movdqu %%xmm6, %[ctr]\n\t"
1658 : : [iv] "=m" (*c->u_iv.iv),
1659 : [ctr] "=m" (*c->u_ctr.ctr)
1660 : :
1661 : : "memory" );
1662 :
1663 6586 : aesni_cleanup ();
1664 6586 : aesni_cleanup_2_6 ();
1665 6586 : }
1666 :
1667 :
1668 : void
1669 14664 : _gcry_aes_aesni_ocb_crypt(gcry_cipher_hd_t c, void *outbuf_arg,
1670 : const void *inbuf_arg, size_t nblocks, int encrypt)
1671 : {
1672 14664 : if (encrypt)
1673 8078 : aesni_ocb_enc(c, outbuf_arg, inbuf_arg, nblocks);
1674 : else
1675 6586 : aesni_ocb_dec(c, outbuf_arg, inbuf_arg, nblocks);
1676 14664 : }
1677 :
1678 :
1679 : void
1680 2748 : _gcry_aes_aesni_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
1681 : size_t nblocks)
1682 : {
1683 2748 : RIJNDAEL_context *ctx = (void *)&c->context.c;
1684 2748 : const unsigned char *abuf = abuf_arg;
1685 2748 : u64 n = c->u_mode.ocb.aad_nblocks;
1686 : const unsigned char *l;
1687 : aesni_prepare_2_6_variable;
1688 :
1689 : aesni_prepare ();
1690 : aesni_prepare_2_6 ();
1691 :
1692 : /* Preload Offset and Sum */
1693 2748 : asm volatile ("movdqu %[iv], %%xmm5\n\t"
1694 : "movdqu %[ctr], %%xmm6\n\t"
1695 : : /* No output */
1696 : : [iv] "m" (*c->u_mode.ocb.aad_offset),
1697 : [ctr] "m" (*c->u_mode.ocb.aad_sum)
1698 : : "memory" );
1699 :
1700 2771 : for ( ;nblocks && n % 4; nblocks-- )
1701 : {
1702 23 : l = ocb_get_l(c, ++n);
1703 :
1704 : /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
1705 : /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i) */
1706 23 : asm volatile ("movdqu %[l], %%xmm1\n\t"
1707 : "movdqu %[abuf], %%xmm0\n\t"
1708 : "pxor %%xmm1, %%xmm5\n\t"
1709 : "pxor %%xmm5, %%xmm0\n\t"
1710 : :
1711 : : [l] "m" (*l),
1712 : [abuf] "m" (*abuf)
1713 : : "memory" );
1714 :
1715 23 : do_aesni_enc (ctx);
1716 :
1717 23 : asm volatile ("pxor %%xmm0, %%xmm6\n\t"
1718 : :
1719 : :
1720 : : "memory" );
1721 :
1722 23 : abuf += BLOCKSIZE;
1723 : }
1724 :
1725 868162 : for ( ;nblocks > 3 ; nblocks -= 4 )
1726 : {
1727 865414 : n += 4;
1728 865414 : l = ocb_get_l(c, n);
1729 :
1730 : /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
1731 : /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i) */
1732 865414 : asm volatile ("movdqu %[l0], %%xmm0\n\t"
1733 : "movdqu %[abuf0], %%xmm1\n\t"
1734 : "pxor %%xmm0, %%xmm5\n\t"
1735 : "pxor %%xmm5, %%xmm1\n\t"
1736 : :
1737 : : [l0] "m" (*c->u_mode.ocb.L[0]),
1738 : [abuf0] "m" (*(abuf + 0 * BLOCKSIZE))
1739 : : "memory" );
1740 865414 : asm volatile ("movdqu %[l1], %%xmm0\n\t"
1741 : "movdqu %[abuf1], %%xmm2\n\t"
1742 : "pxor %%xmm0, %%xmm5\n\t"
1743 : "pxor %%xmm5, %%xmm2\n\t"
1744 : :
1745 : : [l1] "m" (*c->u_mode.ocb.L[1]),
1746 865414 : [abuf1] "m" (*(abuf + 1 * BLOCKSIZE))
1747 : : "memory" );
1748 865414 : asm volatile ("movdqu %[l2], %%xmm0\n\t"
1749 : "movdqu %[abuf2], %%xmm3\n\t"
1750 : "pxor %%xmm0, %%xmm5\n\t"
1751 : "pxor %%xmm5, %%xmm3\n\t"
1752 : :
1753 : : [l2] "m" (*c->u_mode.ocb.L[0]),
1754 865414 : [abuf2] "m" (*(abuf + 2 * BLOCKSIZE))
1755 : : "memory" );
1756 865414 : asm volatile ("movdqu %[l3], %%xmm0\n\t"
1757 : "movdqu %[abuf3], %%xmm4\n\t"
1758 : "pxor %%xmm0, %%xmm5\n\t"
1759 : "pxor %%xmm5, %%xmm4\n\t"
1760 : :
1761 : : [l3] "m" (*l),
1762 865414 : [abuf3] "m" (*(abuf + 3 * BLOCKSIZE))
1763 : : "memory" );
1764 :
1765 865414 : do_aesni_enc_vec4 (ctx);
1766 :
1767 865414 : asm volatile ("pxor %%xmm1, %%xmm6\n\t"
1768 : "pxor %%xmm2, %%xmm6\n\t"
1769 : "pxor %%xmm3, %%xmm6\n\t"
1770 : "pxor %%xmm4, %%xmm6\n\t"
1771 : :
1772 : :
1773 : : "memory" );
1774 :
1775 865414 : abuf += 4*BLOCKSIZE;
1776 : }
1777 :
1778 5644 : for ( ;nblocks; nblocks-- )
1779 : {
1780 2896 : l = ocb_get_l(c, ++n);
1781 :
1782 : /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
1783 : /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i) */
1784 2896 : asm volatile ("movdqu %[l], %%xmm1\n\t"
1785 : "movdqu %[abuf], %%xmm0\n\t"
1786 : "pxor %%xmm1, %%xmm5\n\t"
1787 : "pxor %%xmm5, %%xmm0\n\t"
1788 : :
1789 : : [l] "m" (*l),
1790 : [abuf] "m" (*abuf)
1791 : : "memory" );
1792 :
1793 2896 : do_aesni_enc (ctx);
1794 :
1795 2896 : asm volatile ("pxor %%xmm0, %%xmm6\n\t"
1796 : :
1797 : :
1798 : : "memory" );
1799 :
1800 2896 : abuf += BLOCKSIZE;
1801 : }
1802 :
1803 2748 : c->u_mode.ocb.aad_nblocks = n;
1804 2748 : asm volatile ("movdqu %%xmm5, %[iv]\n\t"
1805 : "movdqu %%xmm6, %[ctr]\n\t"
1806 : : [iv] "=m" (*c->u_mode.ocb.aad_offset),
1807 : [ctr] "=m" (*c->u_mode.ocb.aad_sum)
1808 : :
1809 : : "memory" );
1810 :
1811 2748 : aesni_cleanup ();
1812 2748 : aesni_cleanup_2_6 ();
1813 2748 : }
1814 :
1815 :
1816 : #endif /* USE_AESNI */
|