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