e7e61ca8a39300919d5bb45f855edd6428fea940
[libgcrypt.git] / cipher / rijndael-aesni.c
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_7_15_variable char win64tmp7_15[16 * 9]
59 # define aesni_prepare() do { } while (0)
60 # define aesni_prepare_2_6()                                            \
61    do { asm volatile ("movdqu %%xmm6, %0\n\t"                           \
62                       : "=m" (*win64tmp)                                \
63                       :                                                 \
64                       : "memory");                                      \
65    } while (0)
66 # define aesni_prepare_7_15()                                           \
67    do { asm volatile ("movdqu %%xmm7,  0*16(%0)\n\t"                    \
68                       "movdqu %%xmm8,  1*16(%0)\n\t"                    \
69                       "movdqu %%xmm9,  2*16(%0)\n\t"                    \
70                       "movdqu %%xmm10, 3*16(%0)\n\t"                    \
71                       "movdqu %%xmm11, 4*16(%0)\n\t"                    \
72                       "movdqu %%xmm12, 5*16(%0)\n\t"                    \
73                       "movdqu %%xmm13, 6*16(%0)\n\t"                    \
74                       "movdqu %%xmm14, 7*16(%0)\n\t"                    \
75                       "movdqu %%xmm15, 8*16(%0)\n\t"                    \
76                       :                                                 \
77                       : "r" (win64tmp7_15)                              \
78                       : "memory");                                      \
79    } 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 ("movdqu %0,   %%xmm6\n\t"                         \
86                       "pxor %%xmm2, %%xmm2\n"                           \
87                       "pxor %%xmm3, %%xmm3\n"                           \
88                       "pxor %%xmm4, %%xmm4\n"                           \
89                       "pxor %%xmm5, %%xmm5\n"                           \
90                       :                                                 \
91                       : "m" (*win64tmp)                                 \
92                       : "memory");                                      \
93    } while (0)
94 # define aesni_cleanup_7_15()                                           \
95    do { asm volatile ("movdqu 0*16(%0), %%xmm7\n\t"                     \
96                       "movdqu 1*16(%0), %%xmm8\n\t"                     \
97                       "movdqu 2*16(%0), %%xmm9\n\t"                     \
98                       "movdqu 3*16(%0), %%xmm10\n\t"                    \
99                       "movdqu 4*16(%0), %%xmm11\n\t"                    \
100                       "movdqu 5*16(%0), %%xmm12\n\t"                    \
101                       "movdqu 6*16(%0), %%xmm13\n\t"                    \
102                       "movdqu 7*16(%0), %%xmm14\n\t"                    \
103                       "movdqu 8*16(%0), %%xmm15\n\t"                    \
104                       :                                                 \
105                       : "r" (win64tmp7_15)                              \
106                       : "memory");                                      \
107    } while (0)
108 #else
109 # define aesni_prepare_2_6_variable
110 # define aesni_prepare() do { } while (0)
111 # define aesni_prepare_2_6() do { } while (0)
112 # define aesni_cleanup()                                                \
113    do { asm volatile ("pxor %%xmm0, %%xmm0\n\t"                         \
114                       "pxor %%xmm1, %%xmm1\n" :: );                     \
115    } while (0)
116 # define aesni_cleanup_2_6()                                            \
117    do { asm volatile ("pxor %%xmm2, %%xmm2\n\t"                         \
118                       "pxor %%xmm3, %%xmm3\n"                           \
119                       "pxor %%xmm4, %%xmm4\n"                           \
120                       "pxor %%xmm5, %%xmm5\n"                           \
121                       "pxor %%xmm6, %%xmm6\n":: );                      \
122    } while (0)
123 # ifdef __x86_64__
124 #  define aesni_prepare_7_15_variable
125 #  define aesni_prepare_7_15() do { } while (0)
126 #  define aesni_cleanup_7_15()                                          \
127    do { asm volatile ("pxor %%xmm7, %%xmm7\n\t"                         \
128                       "pxor %%xmm8, %%xmm8\n"                           \
129                       "pxor %%xmm9, %%xmm9\n"                           \
130                       "pxor %%xmm10, %%xmm10\n"                         \
131                       "pxor %%xmm11, %%xmm11\n"                         \
132                       "pxor %%xmm12, %%xmm12\n"                         \
133                       "pxor %%xmm13, %%xmm13\n"                         \
134                       "pxor %%xmm14, %%xmm14\n"                         \
135                       "pxor %%xmm15, %%xmm15\n":: );                    \
136    } while (0)
137 # endif
138 #endif
139
140 void
141 _gcry_aes_aesni_do_setkey (RIJNDAEL_context *ctx, const byte *key)
142 {
143   aesni_prepare_2_6_variable;
144
145   aesni_prepare();
146   aesni_prepare_2_6();
147
148   if (ctx->rounds < 12)
149     {
150       /* 128-bit key */
151 #define AESKEYGENASSIST_xmm1_xmm2(imm8) \
152         ".byte 0x66, 0x0f, 0x3a, 0xdf, 0xd1, " #imm8 " \n\t"
153 #define AESKEY_EXPAND128 \
154         "pshufd $0xff, %%xmm2, %%xmm2\n\t" \
155         "movdqa %%xmm1, %%xmm3\n\t" \
156         "pslldq $4, %%xmm3\n\t" \
157         "pxor   %%xmm3, %%xmm1\n\t" \
158         "pslldq $4, %%xmm3\n\t" \
159         "pxor   %%xmm3, %%xmm1\n\t" \
160         "pslldq $4, %%xmm3\n\t" \
161         "pxor   %%xmm3, %%xmm2\n\t" \
162         "pxor   %%xmm2, %%xmm1\n\t"
163
164       asm volatile ("movdqu (%[key]), %%xmm1\n\t"     /* xmm1 := key   */
165                     "movdqa %%xmm1, (%[ksch])\n\t"     /* ksch[0] := xmm1  */
166                     AESKEYGENASSIST_xmm1_xmm2(0x01)
167                     AESKEY_EXPAND128
168                     "movdqa %%xmm1, 0x10(%[ksch])\n\t" /* ksch[1] := xmm1  */
169                     AESKEYGENASSIST_xmm1_xmm2(0x02)
170                     AESKEY_EXPAND128
171                     "movdqa %%xmm1, 0x20(%[ksch])\n\t" /* ksch[2] := xmm1  */
172                     AESKEYGENASSIST_xmm1_xmm2(0x04)
173                     AESKEY_EXPAND128
174                     "movdqa %%xmm1, 0x30(%[ksch])\n\t" /* ksch[3] := xmm1  */
175                     AESKEYGENASSIST_xmm1_xmm2(0x08)
176                     AESKEY_EXPAND128
177                     "movdqa %%xmm1, 0x40(%[ksch])\n\t" /* ksch[4] := xmm1  */
178                     AESKEYGENASSIST_xmm1_xmm2(0x10)
179                     AESKEY_EXPAND128
180                     "movdqa %%xmm1, 0x50(%[ksch])\n\t" /* ksch[5] := xmm1  */
181                     AESKEYGENASSIST_xmm1_xmm2(0x20)
182                     AESKEY_EXPAND128
183                     "movdqa %%xmm1, 0x60(%[ksch])\n\t" /* ksch[6] := xmm1  */
184                     AESKEYGENASSIST_xmm1_xmm2(0x40)
185                     AESKEY_EXPAND128
186                     "movdqa %%xmm1, 0x70(%[ksch])\n\t" /* ksch[7] := xmm1  */
187                     AESKEYGENASSIST_xmm1_xmm2(0x80)
188                     AESKEY_EXPAND128
189                     "movdqa %%xmm1, 0x80(%[ksch])\n\t" /* ksch[8] := xmm1  */
190                     AESKEYGENASSIST_xmm1_xmm2(0x1b)
191                     AESKEY_EXPAND128
192                     "movdqa %%xmm1, 0x90(%[ksch])\n\t" /* ksch[9] := xmm1  */
193                     AESKEYGENASSIST_xmm1_xmm2(0x36)
194                     AESKEY_EXPAND128
195                     "movdqa %%xmm1, 0xa0(%[ksch])\n\t" /* ksch[10] := xmm1  */
196                     :
197                     : [key] "r" (key), [ksch] "r" (ctx->keyschenc)
198                     : "cc", "memory" );
199 #undef AESKEYGENASSIST_xmm1_xmm2
200 #undef AESKEY_EXPAND128
201     }
202   else if (ctx->rounds == 12)
203     {
204       /* 192-bit key */
205 #define AESKEYGENASSIST_xmm3_xmm2(imm8) \
206         ".byte 0x66, 0x0f, 0x3a, 0xdf, 0xd3, " #imm8 " \n\t"
207 #define AESKEY_EXPAND192 \
208         "pshufd $0x55, %%xmm2, %%xmm2\n\t" \
209         "movdqu %%xmm1, %%xmm4\n\t" \
210         "pslldq $4, %%xmm4\n\t" \
211         "pxor %%xmm4, %%xmm1\n\t" \
212         "pslldq $4, %%xmm4\n\t" \
213         "pxor %%xmm4, %%xmm1\n\t" \
214         "pslldq $4, %%xmm4\n\t" \
215         "pxor %%xmm4, %%xmm1\n\t" \
216         "pxor %%xmm2, %%xmm1\n\t" \
217         "pshufd $0xff, %%xmm1, %%xmm2\n\t" \
218         "movdqu %%xmm3, %%xmm4\n\t" \
219         "pslldq $4, %%xmm4\n\t" \
220         "pxor %%xmm4, %%xmm3\n\t" \
221         "pxor %%xmm2, %%xmm3\n\t"
222
223       asm volatile ("movdqu (%[key]), %%xmm1\n\t"     /* xmm1 := key[0..15]   */
224                     "movq 16(%[key]), %%xmm3\n\t"     /* xmm3 := key[16..23]  */
225                     "movdqa %%xmm1, (%[ksch])\n\t"    /* ksch[0] := xmm1  */
226                     "movdqa %%xmm3, %%xmm5\n\t"
227
228                     AESKEYGENASSIST_xmm3_xmm2(0x01)
229                     AESKEY_EXPAND192
230                     "shufpd $0, %%xmm1, %%xmm5\n\t"
231                     "movdqa %%xmm5, 0x10(%[ksch])\n\t" /* ksch[1] := xmm5  */
232                     "movdqa %%xmm1, %%xmm6\n\t"
233                     "shufpd $1, %%xmm3, %%xmm6\n\t"
234                     "movdqa %%xmm6, 0x20(%[ksch])\n\t" /* ksch[2] := xmm6  */
235                     AESKEYGENASSIST_xmm3_xmm2(0x02)
236                     AESKEY_EXPAND192
237                     "movdqa %%xmm1, 0x30(%[ksch])\n\t" /* ksch[3] := xmm1  */
238                     "movdqa %%xmm3, %%xmm5\n\t"
239
240                     AESKEYGENASSIST_xmm3_xmm2(0x04)
241                     AESKEY_EXPAND192
242                     "shufpd $0, %%xmm1, %%xmm5\n\t"
243                     "movdqa %%xmm5, 0x40(%[ksch])\n\t" /* ksch[4] := xmm5  */
244                     "movdqa %%xmm1, %%xmm6\n\t"
245                     "shufpd $1, %%xmm3, %%xmm6\n\t"
246                     "movdqa %%xmm6, 0x50(%[ksch])\n\t" /* ksch[5] := xmm6  */
247                     AESKEYGENASSIST_xmm3_xmm2(0x08)
248                     AESKEY_EXPAND192
249                     "movdqa %%xmm1, 0x60(%[ksch])\n\t" /* ksch[6] := xmm1  */
250                     "movdqa %%xmm3, %%xmm5\n\t"
251
252                     AESKEYGENASSIST_xmm3_xmm2(0x10)
253                     AESKEY_EXPAND192
254                     "shufpd $0, %%xmm1, %%xmm5\n\t"
255                     "movdqa %%xmm5, 0x70(%[ksch])\n\t" /* ksch[7] := xmm5  */
256                     "movdqa %%xmm1, %%xmm6\n\t"
257                     "shufpd $1, %%xmm3, %%xmm6\n\t"
258                     "movdqa %%xmm6, 0x80(%[ksch])\n\t" /* ksch[8] := xmm6  */
259                     AESKEYGENASSIST_xmm3_xmm2(0x20)
260                     AESKEY_EXPAND192
261                     "movdqa %%xmm1, 0x90(%[ksch])\n\t" /* ksch[9] := xmm1  */
262                     "movdqa %%xmm3, %%xmm5\n\t"
263
264                     AESKEYGENASSIST_xmm3_xmm2(0x40)
265                     AESKEY_EXPAND192
266                     "shufpd $0, %%xmm1, %%xmm5\n\t"
267                     "movdqa %%xmm5, 0xa0(%[ksch])\n\t" /* ksch[10] := xmm5  */
268                     "movdqa %%xmm1, %%xmm6\n\t"
269                     "shufpd $1, %%xmm3, %%xmm6\n\t"
270                     "movdqa %%xmm6, 0xb0(%[ksch])\n\t" /* ksch[11] := xmm6  */
271                     AESKEYGENASSIST_xmm3_xmm2(0x80)
272                     AESKEY_EXPAND192
273                     "movdqa %%xmm1, 0xc0(%[ksch])\n\t" /* ksch[12] := xmm1  */
274                     :
275                     : [key] "r" (key), [ksch] "r" (ctx->keyschenc)
276                     : "cc", "memory" );
277 #undef AESKEYGENASSIST_xmm3_xmm2
278 #undef AESKEY_EXPAND192
279     }
280   else if (ctx->rounds > 12)
281     {
282       /* 256-bit key */
283 #define AESKEYGENASSIST_xmm1_xmm2(imm8) \
284         ".byte 0x66, 0x0f, 0x3a, 0xdf, 0xd1, " #imm8 " \n\t"
285 #define AESKEYGENASSIST_xmm3_xmm2(imm8) \
286         ".byte 0x66, 0x0f, 0x3a, 0xdf, 0xd3, " #imm8 " \n\t"
287 #define AESKEY_EXPAND256_A \
288         "pshufd $0xff, %%xmm2, %%xmm2\n\t" \
289         "movdqa %%xmm1, %%xmm4\n\t" \
290         "pslldq $4, %%xmm4\n\t" \
291         "pxor %%xmm4, %%xmm1\n\t" \
292         "pslldq $4, %%xmm4\n\t" \
293         "pxor %%xmm4, %%xmm1\n\t" \
294         "pslldq $4, %%xmm4\n\t" \
295         "pxor %%xmm4, %%xmm1\n\t" \
296         "pxor %%xmm2, %%xmm1\n\t"
297 #define AESKEY_EXPAND256_B \
298         "pshufd $0xaa, %%xmm2, %%xmm2\n\t" \
299         "movdqa %%xmm3, %%xmm4\n\t" \
300         "pslldq $4, %%xmm4\n\t" \
301         "pxor %%xmm4, %%xmm3\n\t" \
302         "pslldq $4, %%xmm4\n\t" \
303         "pxor %%xmm4, %%xmm3\n\t" \
304         "pslldq $4, %%xmm4\n\t" \
305         "pxor %%xmm4, %%xmm3\n\t" \
306         "pxor %%xmm2, %%xmm3\n\t"
307
308       asm volatile ("movdqu (%[key]), %%xmm1\n\t"     /* xmm1 := key[0..15]   */
309                     "movdqu 16(%[key]), %%xmm3\n\t"   /* xmm3 := key[16..31]  */
310                     "movdqa %%xmm1, (%[ksch])\n\t"     /* ksch[0] := xmm1  */
311                     "movdqa %%xmm3, 0x10(%[ksch])\n\t" /* ksch[1] := xmm3  */
312
313                     AESKEYGENASSIST_xmm3_xmm2(0x01)
314                     AESKEY_EXPAND256_A
315                     "movdqa %%xmm1, 0x20(%[ksch])\n\t" /* ksch[2] := xmm1  */
316                     AESKEYGENASSIST_xmm1_xmm2(0x00)
317                     AESKEY_EXPAND256_B
318                     "movdqa %%xmm3, 0x30(%[ksch])\n\t" /* ksch[3] := xmm3  */
319
320                     AESKEYGENASSIST_xmm3_xmm2(0x02)
321                     AESKEY_EXPAND256_A
322                     "movdqa %%xmm1, 0x40(%[ksch])\n\t" /* ksch[4] := xmm1  */
323                     AESKEYGENASSIST_xmm1_xmm2(0x00)
324                     AESKEY_EXPAND256_B
325                     "movdqa %%xmm3, 0x50(%[ksch])\n\t" /* ksch[5] := xmm3  */
326
327                     AESKEYGENASSIST_xmm3_xmm2(0x04)
328                     AESKEY_EXPAND256_A
329                     "movdqa %%xmm1, 0x60(%[ksch])\n\t" /* ksch[6] := xmm1  */
330                     AESKEYGENASSIST_xmm1_xmm2(0x00)
331                     AESKEY_EXPAND256_B
332                     "movdqa %%xmm3, 0x70(%[ksch])\n\t" /* ksch[7] := xmm3  */
333
334                     AESKEYGENASSIST_xmm3_xmm2(0x08)
335                     AESKEY_EXPAND256_A
336                     "movdqa %%xmm1, 0x80(%[ksch])\n\t" /* ksch[8] := xmm1  */
337                     AESKEYGENASSIST_xmm1_xmm2(0x00)
338                     AESKEY_EXPAND256_B
339                     "movdqa %%xmm3, 0x90(%[ksch])\n\t" /* ksch[9] := xmm3  */
340
341                     AESKEYGENASSIST_xmm3_xmm2(0x10)
342                     AESKEY_EXPAND256_A
343                     "movdqa %%xmm1, 0xa0(%[ksch])\n\t" /* ksch[10] := xmm1  */
344                     AESKEYGENASSIST_xmm1_xmm2(0x00)
345                     AESKEY_EXPAND256_B
346                     "movdqa %%xmm3, 0xb0(%[ksch])\n\t" /* ksch[11] := xmm3  */
347
348                     AESKEYGENASSIST_xmm3_xmm2(0x20)
349                     AESKEY_EXPAND256_A
350                     "movdqa %%xmm1, 0xc0(%[ksch])\n\t" /* ksch[12] := xmm1  */
351                     AESKEYGENASSIST_xmm1_xmm2(0x00)
352                     AESKEY_EXPAND256_B
353                     "movdqa %%xmm3, 0xd0(%[ksch])\n\t" /* ksch[13] := xmm3  */
354
355                     AESKEYGENASSIST_xmm3_xmm2(0x40)
356                     AESKEY_EXPAND256_A
357                     "movdqa %%xmm1, 0xe0(%[ksch])\n\t" /* ksch[14] := xmm1  */
358
359                     :
360                     : [key] "r" (key), [ksch] "r" (ctx->keyschenc)
361                     : "cc", "memory" );
362 #undef AESKEYGENASSIST_xmm1_xmm2
363 #undef AESKEYGENASSIST_xmm3_xmm2
364 #undef AESKEY_EXPAND256_A
365 #undef AESKEY_EXPAND256_B
366     }
367
368   aesni_cleanup();
369   aesni_cleanup_2_6();
370 }
371
372
373 /* Make a decryption key from an encryption key. */
374 static inline void
375 do_aesni_prepare_decryption (RIJNDAEL_context *ctx)
376 {
377   /* The AES-NI decrypt instructions use the Equivalent Inverse
378      Cipher, thus we can't use the the standard decrypt key
379      preparation.  */
380   u128_t *ekey = (u128_t *)ctx->keyschenc;
381   u128_t *dkey = (u128_t *)ctx->keyschdec;
382   int rr;
383   int r;
384
385 #define DO_AESNI_AESIMC() \
386   asm volatile ("movdqa %[ekey], %%xmm1\n\t" \
387                 /*"aesimc %%xmm1, %%xmm1\n\t"*/ \
388                 ".byte 0x66, 0x0f, 0x38, 0xdb, 0xc9\n\t" \
389                 "movdqa %%xmm1, %[dkey]" \
390                 : [dkey] "=m" (dkey[r]) \
391                 : [ekey] "m" (ekey[rr]) \
392                 : "memory")
393
394   dkey[0] = ekey[ctx->rounds];
395   r=1;
396   rr=ctx->rounds-1;
397   DO_AESNI_AESIMC(); r++; rr--; /* round 1 */
398   DO_AESNI_AESIMC(); r++; rr--; /* round 2 */
399   DO_AESNI_AESIMC(); r++; rr--; /* round 3 */
400   DO_AESNI_AESIMC(); r++; rr--; /* round 4 */
401   DO_AESNI_AESIMC(); r++; rr--; /* round 5 */
402   DO_AESNI_AESIMC(); r++; rr--; /* round 6 */
403   DO_AESNI_AESIMC(); r++; rr--; /* round 7 */
404   DO_AESNI_AESIMC(); r++; rr--; /* round 8 */
405   DO_AESNI_AESIMC(); r++; rr--; /* round 9 */
406   if (ctx->rounds > 10)
407     {
408       DO_AESNI_AESIMC(); r++; rr--; /* round 10 */
409       DO_AESNI_AESIMC(); r++; rr--; /* round 11 */
410       if (ctx->rounds > 12)
411         {
412           DO_AESNI_AESIMC(); r++; rr--; /* round 12 */
413           DO_AESNI_AESIMC(); r++; rr--; /* round 13 */
414         }
415     }
416
417   dkey[r] = ekey[0];
418
419 #undef DO_AESNI_AESIMC
420 }
421
422 void
423 _gcry_aes_aesni_prepare_decryption (RIJNDAEL_context *ctx)
424 {
425   aesni_prepare();
426   do_aesni_prepare_decryption (ctx);
427   aesni_cleanup();
428 }
429
430
431 /* Encrypt one block using the Intel AES-NI instructions.  Block is input
432  * and output through SSE register xmm0. */
433 static inline void
434 do_aesni_enc (const RIJNDAEL_context *ctx)
435 {
436 #define aesenc_xmm1_xmm0      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc1\n\t"
437 #define aesenclast_xmm1_xmm0  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc1\n\t"
438   asm volatile ("movdqa (%[key]), %%xmm1\n\t"    /* xmm1 := key[0] */
439                 "pxor   %%xmm1, %%xmm0\n\t"     /* xmm0 ^= key[0] */
440                 "movdqa 0x10(%[key]), %%xmm1\n\t"
441                 aesenc_xmm1_xmm0
442                 "movdqa 0x20(%[key]), %%xmm1\n\t"
443                 aesenc_xmm1_xmm0
444                 "movdqa 0x30(%[key]), %%xmm1\n\t"
445                 aesenc_xmm1_xmm0
446                 "movdqa 0x40(%[key]), %%xmm1\n\t"
447                 aesenc_xmm1_xmm0
448                 "movdqa 0x50(%[key]), %%xmm1\n\t"
449                 aesenc_xmm1_xmm0
450                 "movdqa 0x60(%[key]), %%xmm1\n\t"
451                 aesenc_xmm1_xmm0
452                 "movdqa 0x70(%[key]), %%xmm1\n\t"
453                 aesenc_xmm1_xmm0
454                 "movdqa 0x80(%[key]), %%xmm1\n\t"
455                 aesenc_xmm1_xmm0
456                 "movdqa 0x90(%[key]), %%xmm1\n\t"
457                 aesenc_xmm1_xmm0
458                 "movdqa 0xa0(%[key]), %%xmm1\n\t"
459                 "cmpl $10, %[rounds]\n\t"
460                 "jz .Lenclast%=\n\t"
461                 aesenc_xmm1_xmm0
462                 "movdqa 0xb0(%[key]), %%xmm1\n\t"
463                 aesenc_xmm1_xmm0
464                 "movdqa 0xc0(%[key]), %%xmm1\n\t"
465                 "cmpl $12, %[rounds]\n\t"
466                 "jz .Lenclast%=\n\t"
467                 aesenc_xmm1_xmm0
468                 "movdqa 0xd0(%[key]), %%xmm1\n\t"
469                 aesenc_xmm1_xmm0
470                 "movdqa 0xe0(%[key]), %%xmm1\n"
471
472                 ".Lenclast%=:\n\t"
473                 aesenclast_xmm1_xmm0
474                 "\n"
475                 :
476                 : [key] "r" (ctx->keyschenc),
477                   [rounds] "r" (ctx->rounds)
478                 : "cc", "memory");
479 #undef aesenc_xmm1_xmm0
480 #undef aesenclast_xmm1_xmm0
481 }
482
483
484 /* Decrypt one block using the Intel AES-NI instructions.  Block is input
485  * and output through SSE register xmm0. */
486 static inline void
487 do_aesni_dec (const RIJNDAEL_context *ctx)
488 {
489 #define aesdec_xmm1_xmm0      ".byte 0x66, 0x0f, 0x38, 0xde, 0xc1\n\t"
490 #define aesdeclast_xmm1_xmm0  ".byte 0x66, 0x0f, 0x38, 0xdf, 0xc1\n\t"
491   asm volatile ("movdqa (%[key]), %%xmm1\n\t"
492                 "pxor   %%xmm1, %%xmm0\n\t"     /* xmm0 ^= key[0] */
493                 "movdqa 0x10(%[key]), %%xmm1\n\t"
494                 aesdec_xmm1_xmm0
495                 "movdqa 0x20(%[key]), %%xmm1\n\t"
496                 aesdec_xmm1_xmm0
497                 "movdqa 0x30(%[key]), %%xmm1\n\t"
498                 aesdec_xmm1_xmm0
499                 "movdqa 0x40(%[key]), %%xmm1\n\t"
500                 aesdec_xmm1_xmm0
501                 "movdqa 0x50(%[key]), %%xmm1\n\t"
502                 aesdec_xmm1_xmm0
503                 "movdqa 0x60(%[key]), %%xmm1\n\t"
504                 aesdec_xmm1_xmm0
505                 "movdqa 0x70(%[key]), %%xmm1\n\t"
506                 aesdec_xmm1_xmm0
507                 "movdqa 0x80(%[key]), %%xmm1\n\t"
508                 aesdec_xmm1_xmm0
509                 "movdqa 0x90(%[key]), %%xmm1\n\t"
510                 aesdec_xmm1_xmm0
511                 "movdqa 0xa0(%[key]), %%xmm1\n\t"
512                 "cmpl $10, %[rounds]\n\t"
513                 "jz .Ldeclast%=\n\t"
514                 aesdec_xmm1_xmm0
515                 "movdqa 0xb0(%[key]), %%xmm1\n\t"
516                 aesdec_xmm1_xmm0
517                 "movdqa 0xc0(%[key]), %%xmm1\n\t"
518                 "cmpl $12, %[rounds]\n\t"
519                 "jz .Ldeclast%=\n\t"
520                 aesdec_xmm1_xmm0
521                 "movdqa 0xd0(%[key]), %%xmm1\n\t"
522                 aesdec_xmm1_xmm0
523                 "movdqa 0xe0(%[key]), %%xmm1\n"
524
525                 ".Ldeclast%=:\n\t"
526                 aesdeclast_xmm1_xmm0
527                 "\n"
528                 :
529                 : [key] "r" (ctx->keyschdec),
530                   [rounds] "r" (ctx->rounds)
531                 : "cc", "memory");
532 #undef aesdec_xmm1_xmm0
533 #undef aesdeclast_xmm1_xmm0
534 }
535
536
537 /* Encrypt four blocks using the Intel AES-NI instructions.  Blocks are input
538  * and output through SSE registers xmm1 to xmm4.  */
539 static inline void
540 do_aesni_enc_vec4 (const RIJNDAEL_context *ctx)
541 {
542 #define aesenc_xmm0_xmm1      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc8\n\t"
543 #define aesenc_xmm0_xmm2      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xd0\n\t"
544 #define aesenc_xmm0_xmm3      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xd8\n\t"
545 #define aesenc_xmm0_xmm4      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xe0\n\t"
546 #define aesenclast_xmm0_xmm1  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc8\n\t"
547 #define aesenclast_xmm0_xmm2  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xd0\n\t"
548 #define aesenclast_xmm0_xmm3  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xd8\n\t"
549 #define aesenclast_xmm0_xmm4  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xe0\n\t"
550   asm volatile ("movdqa (%[key]), %%xmm0\n\t"
551                 "pxor   %%xmm0, %%xmm1\n\t"     /* xmm1 ^= key[0] */
552                 "pxor   %%xmm0, %%xmm2\n\t"     /* xmm2 ^= key[0] */
553                 "pxor   %%xmm0, %%xmm3\n\t"     /* xmm3 ^= key[0] */
554                 "pxor   %%xmm0, %%xmm4\n\t"     /* xmm4 ^= key[0] */
555                 "movdqa 0x10(%[key]), %%xmm0\n\t"
556                 aesenc_xmm0_xmm1
557                 aesenc_xmm0_xmm2
558                 aesenc_xmm0_xmm3
559                 aesenc_xmm0_xmm4
560                 "movdqa 0x20(%[key]), %%xmm0\n\t"
561                 aesenc_xmm0_xmm1
562                 aesenc_xmm0_xmm2
563                 aesenc_xmm0_xmm3
564                 aesenc_xmm0_xmm4
565                 "movdqa 0x30(%[key]), %%xmm0\n\t"
566                 aesenc_xmm0_xmm1
567                 aesenc_xmm0_xmm2
568                 aesenc_xmm0_xmm3
569                 aesenc_xmm0_xmm4
570                 "movdqa 0x40(%[key]), %%xmm0\n\t"
571                 aesenc_xmm0_xmm1
572                 aesenc_xmm0_xmm2
573                 aesenc_xmm0_xmm3
574                 aesenc_xmm0_xmm4
575                 "movdqa 0x50(%[key]), %%xmm0\n\t"
576                 aesenc_xmm0_xmm1
577                 aesenc_xmm0_xmm2
578                 aesenc_xmm0_xmm3
579                 aesenc_xmm0_xmm4
580                 "movdqa 0x60(%[key]), %%xmm0\n\t"
581                 aesenc_xmm0_xmm1
582                 aesenc_xmm0_xmm2
583                 aesenc_xmm0_xmm3
584                 aesenc_xmm0_xmm4
585                 "movdqa 0x70(%[key]), %%xmm0\n\t"
586                 aesenc_xmm0_xmm1
587                 aesenc_xmm0_xmm2
588                 aesenc_xmm0_xmm3
589                 aesenc_xmm0_xmm4
590                 "movdqa 0x80(%[key]), %%xmm0\n\t"
591                 aesenc_xmm0_xmm1
592                 aesenc_xmm0_xmm2
593                 aesenc_xmm0_xmm3
594                 aesenc_xmm0_xmm4
595                 "movdqa 0x90(%[key]), %%xmm0\n\t"
596                 aesenc_xmm0_xmm1
597                 aesenc_xmm0_xmm2
598                 aesenc_xmm0_xmm3
599                 aesenc_xmm0_xmm4
600                 "movdqa 0xa0(%[key]), %%xmm0\n\t"
601                 "cmpl $10, %[rounds]\n\t"
602                 "jz .Ldeclast%=\n\t"
603                 aesenc_xmm0_xmm1
604                 aesenc_xmm0_xmm2
605                 aesenc_xmm0_xmm3
606                 aesenc_xmm0_xmm4
607                 "movdqa 0xb0(%[key]), %%xmm0\n\t"
608                 aesenc_xmm0_xmm1
609                 aesenc_xmm0_xmm2
610                 aesenc_xmm0_xmm3
611                 aesenc_xmm0_xmm4
612                 "movdqa 0xc0(%[key]), %%xmm0\n\t"
613                 "cmpl $12, %[rounds]\n\t"
614                 "jz .Ldeclast%=\n\t"
615                 aesenc_xmm0_xmm1
616                 aesenc_xmm0_xmm2
617                 aesenc_xmm0_xmm3
618                 aesenc_xmm0_xmm4
619                 "movdqa 0xd0(%[key]), %%xmm0\n\t"
620                 aesenc_xmm0_xmm1
621                 aesenc_xmm0_xmm2
622                 aesenc_xmm0_xmm3
623                 aesenc_xmm0_xmm4
624                 "movdqa 0xe0(%[key]), %%xmm0\n"
625
626                 ".Ldeclast%=:\n\t"
627                 aesenclast_xmm0_xmm1
628                 aesenclast_xmm0_xmm2
629                 aesenclast_xmm0_xmm3
630                 aesenclast_xmm0_xmm4
631                 : /* no output */
632                 : [key] "r" (ctx->keyschenc),
633                   [rounds] "r" (ctx->rounds)
634                 : "cc", "memory");
635 #undef aesenc_xmm0_xmm1
636 #undef aesenc_xmm0_xmm2
637 #undef aesenc_xmm0_xmm3
638 #undef aesenc_xmm0_xmm4
639 #undef aesenclast_xmm0_xmm1
640 #undef aesenclast_xmm0_xmm2
641 #undef aesenclast_xmm0_xmm3
642 #undef aesenclast_xmm0_xmm4
643 }
644
645
646 /* Decrypt four blocks using the Intel AES-NI instructions.  Blocks are input
647  * and output through SSE registers xmm1 to xmm4.  */
648 static inline void
649 do_aesni_dec_vec4 (const RIJNDAEL_context *ctx)
650 {
651 #define aesdec_xmm0_xmm1 ".byte 0x66, 0x0f, 0x38, 0xde, 0xc8\n\t"
652 #define aesdec_xmm0_xmm2 ".byte 0x66, 0x0f, 0x38, 0xde, 0xd0\n\t"
653 #define aesdec_xmm0_xmm3 ".byte 0x66, 0x0f, 0x38, 0xde, 0xd8\n\t"
654 #define aesdec_xmm0_xmm4 ".byte 0x66, 0x0f, 0x38, 0xde, 0xe0\n\t"
655 #define aesdeclast_xmm0_xmm1 ".byte 0x66, 0x0f, 0x38, 0xdf, 0xc8\n\t"
656 #define aesdeclast_xmm0_xmm2 ".byte 0x66, 0x0f, 0x38, 0xdf, 0xd0\n\t"
657 #define aesdeclast_xmm0_xmm3 ".byte 0x66, 0x0f, 0x38, 0xdf, 0xd8\n\t"
658 #define aesdeclast_xmm0_xmm4 ".byte 0x66, 0x0f, 0x38, 0xdf, 0xe0\n\t"
659   asm volatile ("movdqa (%[key]), %%xmm0\n\t"
660                 "pxor   %%xmm0, %%xmm1\n\t"     /* xmm1 ^= key[0] */
661                 "pxor   %%xmm0, %%xmm2\n\t"     /* xmm2 ^= key[0] */
662                 "pxor   %%xmm0, %%xmm3\n\t"     /* xmm3 ^= key[0] */
663                 "pxor   %%xmm0, %%xmm4\n\t"     /* xmm4 ^= key[0] */
664                 "movdqa 0x10(%[key]), %%xmm0\n\t"
665                 aesdec_xmm0_xmm1
666                 aesdec_xmm0_xmm2
667                 aesdec_xmm0_xmm3
668                 aesdec_xmm0_xmm4
669                 "movdqa 0x20(%[key]), %%xmm0\n\t"
670                 aesdec_xmm0_xmm1
671                 aesdec_xmm0_xmm2
672                 aesdec_xmm0_xmm3
673                 aesdec_xmm0_xmm4
674                 "movdqa 0x30(%[key]), %%xmm0\n\t"
675                 aesdec_xmm0_xmm1
676                 aesdec_xmm0_xmm2
677                 aesdec_xmm0_xmm3
678                 aesdec_xmm0_xmm4
679                 "movdqa 0x40(%[key]), %%xmm0\n\t"
680                 aesdec_xmm0_xmm1
681                 aesdec_xmm0_xmm2
682                 aesdec_xmm0_xmm3
683                 aesdec_xmm0_xmm4
684                 "movdqa 0x50(%[key]), %%xmm0\n\t"
685                 aesdec_xmm0_xmm1
686                 aesdec_xmm0_xmm2
687                 aesdec_xmm0_xmm3
688                 aesdec_xmm0_xmm4
689                 "movdqa 0x60(%[key]), %%xmm0\n\t"
690                 aesdec_xmm0_xmm1
691                 aesdec_xmm0_xmm2
692                 aesdec_xmm0_xmm3
693                 aesdec_xmm0_xmm4
694                 "movdqa 0x70(%[key]), %%xmm0\n\t"
695                 aesdec_xmm0_xmm1
696                 aesdec_xmm0_xmm2
697                 aesdec_xmm0_xmm3
698                 aesdec_xmm0_xmm4
699                 "movdqa 0x80(%[key]), %%xmm0\n\t"
700                 aesdec_xmm0_xmm1
701                 aesdec_xmm0_xmm2
702                 aesdec_xmm0_xmm3
703                 aesdec_xmm0_xmm4
704                 "movdqa 0x90(%[key]), %%xmm0\n\t"
705                 aesdec_xmm0_xmm1
706                 aesdec_xmm0_xmm2
707                 aesdec_xmm0_xmm3
708                 aesdec_xmm0_xmm4
709                 "movdqa 0xa0(%[key]), %%xmm0\n\t"
710                 "cmpl $10, %[rounds]\n\t"
711                 "jz .Ldeclast%=\n\t"
712                 aesdec_xmm0_xmm1
713                 aesdec_xmm0_xmm2
714                 aesdec_xmm0_xmm3
715                 aesdec_xmm0_xmm4
716                 "movdqa 0xb0(%[key]), %%xmm0\n\t"
717                 aesdec_xmm0_xmm1
718                 aesdec_xmm0_xmm2
719                 aesdec_xmm0_xmm3
720                 aesdec_xmm0_xmm4
721                 "movdqa 0xc0(%[key]), %%xmm0\n\t"
722                 "cmpl $12, %[rounds]\n\t"
723                 "jz .Ldeclast%=\n\t"
724                 aesdec_xmm0_xmm1
725                 aesdec_xmm0_xmm2
726                 aesdec_xmm0_xmm3
727                 aesdec_xmm0_xmm4
728                 "movdqa 0xd0(%[key]), %%xmm0\n\t"
729                 aesdec_xmm0_xmm1
730                 aesdec_xmm0_xmm2
731                 aesdec_xmm0_xmm3
732                 aesdec_xmm0_xmm4
733                 "movdqa 0xe0(%[key]), %%xmm0\n"
734
735                 ".Ldeclast%=:\n\t"
736                 aesdeclast_xmm0_xmm1
737                 aesdeclast_xmm0_xmm2
738                 aesdeclast_xmm0_xmm3
739                 aesdeclast_xmm0_xmm4
740                 : /* no output */
741                 : [key] "r" (ctx->keyschdec),
742                   [rounds] "r" (ctx->rounds)
743                 : "cc", "memory");
744 #undef aesdec_xmm0_xmm1
745 #undef aesdec_xmm0_xmm2
746 #undef aesdec_xmm0_xmm3
747 #undef aesdec_xmm0_xmm4
748 #undef aesdeclast_xmm0_xmm1
749 #undef aesdeclast_xmm0_xmm2
750 #undef aesdeclast_xmm0_xmm3
751 #undef aesdeclast_xmm0_xmm4
752 }
753
754
755 #ifdef __x86_64__
756
757 /* Encrypt eight blocks using the Intel AES-NI instructions.  Blocks are input
758  * and output through SSE registers xmm1 to xmm4 and xmm8 to xmm11.  */
759 static inline void
760 do_aesni_enc_vec8 (const RIJNDAEL_context *ctx)
761 {
762   asm volatile ("movdqa (%[key]), %%xmm0\n\t"
763                 "pxor   %%xmm0, %%xmm1\n\t"     /* xmm1 ^= key[0] */
764                 "pxor   %%xmm0, %%xmm2\n\t"     /* xmm2 ^= key[0] */
765                 "pxor   %%xmm0, %%xmm3\n\t"     /* xmm3 ^= key[0] */
766                 "pxor   %%xmm0, %%xmm4\n\t"     /* xmm4 ^= key[0] */
767                 "pxor   %%xmm0, %%xmm8\n\t"     /* xmm8 ^= key[0] */
768                 "pxor   %%xmm0, %%xmm9\n\t"     /* xmm9 ^= key[0] */
769                 "pxor   %%xmm0, %%xmm10\n\t"     /* xmm10 ^= key[0] */
770                 "pxor   %%xmm0, %%xmm11\n\t"     /* xmm11 ^= key[0] */
771                 "movdqa 0x10(%[key]), %%xmm0\n\t"
772                 "cmpl $12, %[rounds]\n\t"
773                 "aesenc %%xmm0, %%xmm1\n\t"
774                 "aesenc %%xmm0, %%xmm2\n\t"
775                 "aesenc %%xmm0, %%xmm3\n\t"
776                 "aesenc %%xmm0, %%xmm4\n\t"
777                 "aesenc %%xmm0, %%xmm8\n\t"
778                 "aesenc %%xmm0, %%xmm9\n\t"
779                 "aesenc %%xmm0, %%xmm10\n\t"
780                 "aesenc %%xmm0, %%xmm11\n\t"
781                 "movdqa 0x20(%[key]), %%xmm0\n\t"
782                 "aesenc %%xmm0, %%xmm1\n\t"
783                 "aesenc %%xmm0, %%xmm2\n\t"
784                 "aesenc %%xmm0, %%xmm3\n\t"
785                 "aesenc %%xmm0, %%xmm4\n\t"
786                 "aesenc %%xmm0, %%xmm8\n\t"
787                 "aesenc %%xmm0, %%xmm9\n\t"
788                 "aesenc %%xmm0, %%xmm10\n\t"
789                 "aesenc %%xmm0, %%xmm11\n\t"
790                 "movdqa 0x30(%[key]), %%xmm0\n\t"
791                 "aesenc %%xmm0, %%xmm1\n\t"
792                 "aesenc %%xmm0, %%xmm2\n\t"
793                 "aesenc %%xmm0, %%xmm3\n\t"
794                 "aesenc %%xmm0, %%xmm4\n\t"
795                 "aesenc %%xmm0, %%xmm8\n\t"
796                 "aesenc %%xmm0, %%xmm9\n\t"
797                 "aesenc %%xmm0, %%xmm10\n\t"
798                 "aesenc %%xmm0, %%xmm11\n\t"
799                 "movdqa 0x40(%[key]), %%xmm0\n\t"
800                 "aesenc %%xmm0, %%xmm1\n\t"
801                 "aesenc %%xmm0, %%xmm2\n\t"
802                 "aesenc %%xmm0, %%xmm3\n\t"
803                 "aesenc %%xmm0, %%xmm4\n\t"
804                 "aesenc %%xmm0, %%xmm8\n\t"
805                 "aesenc %%xmm0, %%xmm9\n\t"
806                 "aesenc %%xmm0, %%xmm10\n\t"
807                 "aesenc %%xmm0, %%xmm11\n\t"
808                 "movdqa 0x50(%[key]), %%xmm0\n\t"
809                 "aesenc %%xmm0, %%xmm1\n\t"
810                 "aesenc %%xmm0, %%xmm2\n\t"
811                 "aesenc %%xmm0, %%xmm3\n\t"
812                 "aesenc %%xmm0, %%xmm4\n\t"
813                 "aesenc %%xmm0, %%xmm8\n\t"
814                 "aesenc %%xmm0, %%xmm9\n\t"
815                 "aesenc %%xmm0, %%xmm10\n\t"
816                 "aesenc %%xmm0, %%xmm11\n\t"
817                 "movdqa 0x60(%[key]), %%xmm0\n\t"
818                 "aesenc %%xmm0, %%xmm1\n\t"
819                 "aesenc %%xmm0, %%xmm2\n\t"
820                 "aesenc %%xmm0, %%xmm3\n\t"
821                 "aesenc %%xmm0, %%xmm4\n\t"
822                 "aesenc %%xmm0, %%xmm8\n\t"
823                 "aesenc %%xmm0, %%xmm9\n\t"
824                 "aesenc %%xmm0, %%xmm10\n\t"
825                 "aesenc %%xmm0, %%xmm11\n\t"
826                 "movdqa 0x70(%[key]), %%xmm0\n\t"
827                 "aesenc %%xmm0, %%xmm1\n\t"
828                 "aesenc %%xmm0, %%xmm2\n\t"
829                 "aesenc %%xmm0, %%xmm3\n\t"
830                 "aesenc %%xmm0, %%xmm4\n\t"
831                 "aesenc %%xmm0, %%xmm8\n\t"
832                 "aesenc %%xmm0, %%xmm9\n\t"
833                 "aesenc %%xmm0, %%xmm10\n\t"
834                 "aesenc %%xmm0, %%xmm11\n\t"
835                 "movdqa 0x80(%[key]), %%xmm0\n\t"
836                 "aesenc %%xmm0, %%xmm1\n\t"
837                 "aesenc %%xmm0, %%xmm2\n\t"
838                 "aesenc %%xmm0, %%xmm3\n\t"
839                 "aesenc %%xmm0, %%xmm4\n\t"
840                 "aesenc %%xmm0, %%xmm8\n\t"
841                 "aesenc %%xmm0, %%xmm9\n\t"
842                 "aesenc %%xmm0, %%xmm10\n\t"
843                 "aesenc %%xmm0, %%xmm11\n\t"
844                 "movdqa 0x90(%[key]), %%xmm0\n\t"
845                 "aesenc %%xmm0, %%xmm1\n\t"
846                 "aesenc %%xmm0, %%xmm2\n\t"
847                 "aesenc %%xmm0, %%xmm3\n\t"
848                 "aesenc %%xmm0, %%xmm4\n\t"
849                 "aesenc %%xmm0, %%xmm8\n\t"
850                 "aesenc %%xmm0, %%xmm9\n\t"
851                 "aesenc %%xmm0, %%xmm10\n\t"
852                 "aesenc %%xmm0, %%xmm11\n\t"
853                 "movdqa 0xa0(%[key]), %%xmm0\n\t"
854                 "jb .Ldeclast%=\n\t"
855                 "aesenc %%xmm0, %%xmm1\n\t"
856                 "aesenc %%xmm0, %%xmm2\n\t"
857                 "aesenc %%xmm0, %%xmm3\n\t"
858                 "aesenc %%xmm0, %%xmm4\n\t"
859                 "aesenc %%xmm0, %%xmm8\n\t"
860                 "aesenc %%xmm0, %%xmm9\n\t"
861                 "aesenc %%xmm0, %%xmm10\n\t"
862                 "aesenc %%xmm0, %%xmm11\n\t"
863                 "movdqa 0xb0(%[key]), %%xmm0\n\t"
864                 "aesenc %%xmm0, %%xmm1\n\t"
865                 "aesenc %%xmm0, %%xmm2\n\t"
866                 "aesenc %%xmm0, %%xmm3\n\t"
867                 "aesenc %%xmm0, %%xmm4\n\t"
868                 "aesenc %%xmm0, %%xmm8\n\t"
869                 "aesenc %%xmm0, %%xmm9\n\t"
870                 "aesenc %%xmm0, %%xmm10\n\t"
871                 "aesenc %%xmm0, %%xmm11\n\t"
872                 "movdqa 0xc0(%[key]), %%xmm0\n\t"
873                 "je .Ldeclast%=\n\t"
874                 "aesenc %%xmm0, %%xmm1\n\t"
875                 "aesenc %%xmm0, %%xmm2\n\t"
876                 "aesenc %%xmm0, %%xmm3\n\t"
877                 "aesenc %%xmm0, %%xmm4\n\t"
878                 "aesenc %%xmm0, %%xmm8\n\t"
879                 "aesenc %%xmm0, %%xmm9\n\t"
880                 "aesenc %%xmm0, %%xmm10\n\t"
881                 "aesenc %%xmm0, %%xmm11\n\t"
882                 "movdqa 0xd0(%[key]), %%xmm0\n\t"
883                 "aesenc %%xmm0, %%xmm1\n\t"
884                 "aesenc %%xmm0, %%xmm2\n\t"
885                 "aesenc %%xmm0, %%xmm3\n\t"
886                 "aesenc %%xmm0, %%xmm4\n\t"
887                 "aesenc %%xmm0, %%xmm8\n\t"
888                 "aesenc %%xmm0, %%xmm9\n\t"
889                 "aesenc %%xmm0, %%xmm10\n\t"
890                 "aesenc %%xmm0, %%xmm11\n\t"
891                 "movdqa 0xe0(%[key]), %%xmm0\n"
892
893                 ".Ldeclast%=:\n\t"
894                 "aesenclast %%xmm0, %%xmm1\n\t"
895                 "aesenclast %%xmm0, %%xmm2\n\t"
896                 "aesenclast %%xmm0, %%xmm3\n\t"
897                 "aesenclast %%xmm0, %%xmm4\n\t"
898                 "aesenclast %%xmm0, %%xmm8\n\t"
899                 "aesenclast %%xmm0, %%xmm9\n\t"
900                 "aesenclast %%xmm0, %%xmm10\n\t"
901                 "aesenclast %%xmm0, %%xmm11\n\t"
902                 : /* no output */
903                 : [key] "r" (ctx->keyschenc),
904                   [rounds] "r" (ctx->rounds)
905                 : "cc", "memory");
906 }
907
908
909 /* Decrypt eight blocks using the Intel AES-NI instructions.  Blocks are input
910  * and output through SSE registers xmm1 to xmm4 and xmm8 to xmm11.  */
911 static inline void
912 do_aesni_dec_vec8 (const RIJNDAEL_context *ctx)
913 {
914   asm volatile ("movdqa (%[key]), %%xmm0\n\t"
915                 "pxor   %%xmm0, %%xmm1\n\t"     /* xmm1 ^= key[0] */
916                 "pxor   %%xmm0, %%xmm2\n\t"     /* xmm2 ^= key[0] */
917                 "pxor   %%xmm0, %%xmm3\n\t"     /* xmm3 ^= key[0] */
918                 "pxor   %%xmm0, %%xmm4\n\t"     /* xmm4 ^= key[0] */
919                 "pxor   %%xmm0, %%xmm8\n\t"     /* xmm8 ^= key[0] */
920                 "pxor   %%xmm0, %%xmm9\n\t"     /* xmm9 ^= key[0] */
921                 "pxor   %%xmm0, %%xmm10\n\t"    /* xmm10 ^= key[0] */
922                 "pxor   %%xmm0, %%xmm11\n\t"    /* xmm11 ^= key[0] */
923                 "movdqa 0x10(%[key]), %%xmm0\n\t"
924                 "cmpl $12, %[rounds]\n\t"
925                 "aesdec %%xmm0, %%xmm1\n\t"
926                 "aesdec %%xmm0, %%xmm2\n\t"
927                 "aesdec %%xmm0, %%xmm3\n\t"
928                 "aesdec %%xmm0, %%xmm4\n\t"
929                 "aesdec %%xmm0, %%xmm8\n\t"
930                 "aesdec %%xmm0, %%xmm9\n\t"
931                 "aesdec %%xmm0, %%xmm10\n\t"
932                 "aesdec %%xmm0, %%xmm11\n\t"
933                 "movdqa 0x20(%[key]), %%xmm0\n\t"
934                 "aesdec %%xmm0, %%xmm1\n\t"
935                 "aesdec %%xmm0, %%xmm2\n\t"
936                 "aesdec %%xmm0, %%xmm3\n\t"
937                 "aesdec %%xmm0, %%xmm4\n\t"
938                 "aesdec %%xmm0, %%xmm8\n\t"
939                 "aesdec %%xmm0, %%xmm9\n\t"
940                 "aesdec %%xmm0, %%xmm10\n\t"
941                 "aesdec %%xmm0, %%xmm11\n\t"
942                 "movdqa 0x30(%[key]), %%xmm0\n\t"
943                 "aesdec %%xmm0, %%xmm1\n\t"
944                 "aesdec %%xmm0, %%xmm2\n\t"
945                 "aesdec %%xmm0, %%xmm3\n\t"
946                 "aesdec %%xmm0, %%xmm4\n\t"
947                 "aesdec %%xmm0, %%xmm8\n\t"
948                 "aesdec %%xmm0, %%xmm9\n\t"
949                 "aesdec %%xmm0, %%xmm10\n\t"
950                 "aesdec %%xmm0, %%xmm11\n\t"
951                 "movdqa 0x40(%[key]), %%xmm0\n\t"
952                 "aesdec %%xmm0, %%xmm1\n\t"
953                 "aesdec %%xmm0, %%xmm2\n\t"
954                 "aesdec %%xmm0, %%xmm3\n\t"
955                 "aesdec %%xmm0, %%xmm4\n\t"
956                 "aesdec %%xmm0, %%xmm8\n\t"
957                 "aesdec %%xmm0, %%xmm9\n\t"
958                 "aesdec %%xmm0, %%xmm10\n\t"
959                 "aesdec %%xmm0, %%xmm11\n\t"
960                 "movdqa 0x50(%[key]), %%xmm0\n\t"
961                 "aesdec %%xmm0, %%xmm1\n\t"
962                 "aesdec %%xmm0, %%xmm2\n\t"
963                 "aesdec %%xmm0, %%xmm3\n\t"
964                 "aesdec %%xmm0, %%xmm4\n\t"
965                 "aesdec %%xmm0, %%xmm8\n\t"
966                 "aesdec %%xmm0, %%xmm9\n\t"
967                 "aesdec %%xmm0, %%xmm10\n\t"
968                 "aesdec %%xmm0, %%xmm11\n\t"
969                 "movdqa 0x60(%[key]), %%xmm0\n\t"
970                 "aesdec %%xmm0, %%xmm1\n\t"
971                 "aesdec %%xmm0, %%xmm2\n\t"
972                 "aesdec %%xmm0, %%xmm3\n\t"
973                 "aesdec %%xmm0, %%xmm4\n\t"
974                 "aesdec %%xmm0, %%xmm8\n\t"
975                 "aesdec %%xmm0, %%xmm9\n\t"
976                 "aesdec %%xmm0, %%xmm10\n\t"
977                 "aesdec %%xmm0, %%xmm11\n\t"
978                 "movdqa 0x70(%[key]), %%xmm0\n\t"
979                 "aesdec %%xmm0, %%xmm1\n\t"
980                 "aesdec %%xmm0, %%xmm2\n\t"
981                 "aesdec %%xmm0, %%xmm3\n\t"
982                 "aesdec %%xmm0, %%xmm4\n\t"
983                 "aesdec %%xmm0, %%xmm8\n\t"
984                 "aesdec %%xmm0, %%xmm9\n\t"
985                 "aesdec %%xmm0, %%xmm10\n\t"
986                 "aesdec %%xmm0, %%xmm11\n\t"
987                 "movdqa 0x80(%[key]), %%xmm0\n\t"
988                 "aesdec %%xmm0, %%xmm1\n\t"
989                 "aesdec %%xmm0, %%xmm2\n\t"
990                 "aesdec %%xmm0, %%xmm3\n\t"
991                 "aesdec %%xmm0, %%xmm4\n\t"
992                 "aesdec %%xmm0, %%xmm8\n\t"
993                 "aesdec %%xmm0, %%xmm9\n\t"
994                 "aesdec %%xmm0, %%xmm10\n\t"
995                 "aesdec %%xmm0, %%xmm11\n\t"
996                 "movdqa 0x90(%[key]), %%xmm0\n\t"
997                 "aesdec %%xmm0, %%xmm1\n\t"
998                 "aesdec %%xmm0, %%xmm2\n\t"
999                 "aesdec %%xmm0, %%xmm3\n\t"
1000                 "aesdec %%xmm0, %%xmm4\n\t"
1001                 "aesdec %%xmm0, %%xmm8\n\t"
1002                 "aesdec %%xmm0, %%xmm9\n\t"
1003                 "aesdec %%xmm0, %%xmm10\n\t"
1004                 "aesdec %%xmm0, %%xmm11\n\t"
1005                 "movdqa 0xa0(%[key]), %%xmm0\n\t"
1006                 "jb .Ldeclast%=\n\t"
1007                 "aesdec %%xmm0, %%xmm1\n\t"
1008                 "aesdec %%xmm0, %%xmm2\n\t"
1009                 "aesdec %%xmm0, %%xmm3\n\t"
1010                 "aesdec %%xmm0, %%xmm4\n\t"
1011                 "aesdec %%xmm0, %%xmm8\n\t"
1012                 "aesdec %%xmm0, %%xmm9\n\t"
1013                 "aesdec %%xmm0, %%xmm10\n\t"
1014                 "aesdec %%xmm0, %%xmm11\n\t"
1015                 "movdqa 0xb0(%[key]), %%xmm0\n\t"
1016                 "aesdec %%xmm0, %%xmm1\n\t"
1017                 "aesdec %%xmm0, %%xmm2\n\t"
1018                 "aesdec %%xmm0, %%xmm3\n\t"
1019                 "aesdec %%xmm0, %%xmm4\n\t"
1020                 "aesdec %%xmm0, %%xmm8\n\t"
1021                 "aesdec %%xmm0, %%xmm9\n\t"
1022                 "aesdec %%xmm0, %%xmm10\n\t"
1023                 "aesdec %%xmm0, %%xmm11\n\t"
1024                 "movdqa 0xc0(%[key]), %%xmm0\n\t"
1025                 "je .Ldeclast%=\n\t"
1026                 "aesdec %%xmm0, %%xmm1\n\t"
1027                 "aesdec %%xmm0, %%xmm2\n\t"
1028                 "aesdec %%xmm0, %%xmm3\n\t"
1029                 "aesdec %%xmm0, %%xmm4\n\t"
1030                 "aesdec %%xmm0, %%xmm8\n\t"
1031                 "aesdec %%xmm0, %%xmm9\n\t"
1032                 "aesdec %%xmm0, %%xmm10\n\t"
1033                 "aesdec %%xmm0, %%xmm11\n\t"
1034                 "movdqa 0xd0(%[key]), %%xmm0\n\t"
1035                 "aesdec %%xmm0, %%xmm1\n\t"
1036                 "aesdec %%xmm0, %%xmm2\n\t"
1037                 "aesdec %%xmm0, %%xmm3\n\t"
1038                 "aesdec %%xmm0, %%xmm4\n\t"
1039                 "aesdec %%xmm0, %%xmm8\n\t"
1040                 "aesdec %%xmm0, %%xmm9\n\t"
1041                 "aesdec %%xmm0, %%xmm10\n\t"
1042                 "aesdec %%xmm0, %%xmm11\n\t"
1043                 "movdqa 0xe0(%[key]), %%xmm0\n"
1044
1045                 ".Ldeclast%=:\n\t"
1046                 "aesdeclast %%xmm0, %%xmm1\n\t"
1047                 "aesdeclast %%xmm0, %%xmm2\n\t"
1048                 "aesdeclast %%xmm0, %%xmm3\n\t"
1049                 "aesdeclast %%xmm0, %%xmm4\n\t"
1050                 "aesdeclast %%xmm0, %%xmm8\n\t"
1051                 "aesdeclast %%xmm0, %%xmm9\n\t"
1052                 "aesdeclast %%xmm0, %%xmm10\n\t"
1053                 "aesdeclast %%xmm0, %%xmm11\n\t"
1054                 : /* no output */
1055                 : [key] "r" (ctx->keyschdec),
1056                   [rounds] "r" (ctx->rounds)
1057                 : "cc", "memory");
1058 }
1059
1060 #endif /* __x86_64__ */
1061
1062
1063 /* Perform a CTR encryption round using the counter CTR and the input
1064    block A.  Write the result to the output block B and update CTR.
1065    CTR needs to be a 16 byte aligned little-endian value.  */
1066 static void
1067 do_aesni_ctr (const RIJNDAEL_context *ctx,
1068               unsigned char *ctr, unsigned char *b, const unsigned char *a)
1069 {
1070 #define aesenc_xmm1_xmm0      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc1\n\t"
1071 #define aesenclast_xmm1_xmm0  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc1\n\t"
1072
1073   asm volatile ("movdqa %%xmm5, %%xmm0\n\t"     /* xmm0 := CTR (xmm5)  */
1074                 "pcmpeqd %%xmm1, %%xmm1\n\t"
1075                 "psrldq $8, %%xmm1\n\t"         /* xmm1 = -1 */
1076
1077                 "pshufb %%xmm6, %%xmm5\n\t"
1078                 "psubq  %%xmm1, %%xmm5\n\t"     /* xmm5++ (big endian) */
1079
1080                 /* detect if 64-bit carry handling is needed */
1081                 "cmpl   $0xffffffff, 8(%[ctr])\n\t"
1082                 "jne    .Lno_carry%=\n\t"
1083                 "cmpl   $0xffffffff, 12(%[ctr])\n\t"
1084                 "jne    .Lno_carry%=\n\t"
1085
1086                 "pslldq $8, %%xmm1\n\t"         /* move lower 64-bit to high */
1087                 "psubq   %%xmm1, %%xmm5\n\t"    /* add carry to upper 64bits */
1088
1089                 ".Lno_carry%=:\n\t"
1090
1091                 "pshufb %%xmm6, %%xmm5\n\t"
1092                 "movdqa %%xmm5, (%[ctr])\n\t"   /* Update CTR (mem).       */
1093
1094                 "pxor (%[key]), %%xmm0\n\t"     /* xmm1 ^= key[0]    */
1095                 "movdqa 0x10(%[key]), %%xmm1\n\t"
1096                 aesenc_xmm1_xmm0
1097                 "movdqa 0x20(%[key]), %%xmm1\n\t"
1098                 aesenc_xmm1_xmm0
1099                 "movdqa 0x30(%[key]), %%xmm1\n\t"
1100                 aesenc_xmm1_xmm0
1101                 "movdqa 0x40(%[key]), %%xmm1\n\t"
1102                 aesenc_xmm1_xmm0
1103                 "movdqa 0x50(%[key]), %%xmm1\n\t"
1104                 aesenc_xmm1_xmm0
1105                 "movdqa 0x60(%[key]), %%xmm1\n\t"
1106                 aesenc_xmm1_xmm0
1107                 "movdqa 0x70(%[key]), %%xmm1\n\t"
1108                 aesenc_xmm1_xmm0
1109                 "movdqa 0x80(%[key]), %%xmm1\n\t"
1110                 aesenc_xmm1_xmm0
1111                 "movdqa 0x90(%[key]), %%xmm1\n\t"
1112                 aesenc_xmm1_xmm0
1113                 "movdqa 0xa0(%[key]), %%xmm1\n\t"
1114                 "cmpl $10, %[rounds]\n\t"
1115                 "jz .Lenclast%=\n\t"
1116                 aesenc_xmm1_xmm0
1117                 "movdqa 0xb0(%[key]), %%xmm1\n\t"
1118                 aesenc_xmm1_xmm0
1119                 "movdqa 0xc0(%[key]), %%xmm1\n\t"
1120                 "cmpl $12, %[rounds]\n\t"
1121                 "jz .Lenclast%=\n\t"
1122                 aesenc_xmm1_xmm0
1123                 "movdqa 0xd0(%[key]), %%xmm1\n\t"
1124                 aesenc_xmm1_xmm0
1125                 "movdqa 0xe0(%[key]), %%xmm1\n"
1126
1127                 ".Lenclast%=:\n\t"
1128                 aesenclast_xmm1_xmm0
1129                 "movdqu %[src], %%xmm1\n\t"      /* xmm1 := input   */
1130                 "pxor %%xmm1, %%xmm0\n\t"        /* EncCTR ^= input  */
1131                 "movdqu %%xmm0, %[dst]"          /* Store EncCTR.    */
1132
1133                 : [dst] "=m" (*b)
1134                 : [src] "m" (*a),
1135                   [ctr] "r" (ctr),
1136                   [key] "r" (ctx->keyschenc),
1137                   [rounds] "g" (ctx->rounds)
1138                 : "cc", "memory");
1139 #undef aesenc_xmm1_xmm0
1140 #undef aesenclast_xmm1_xmm0
1141 }
1142
1143
1144 /* Four blocks at a time variant of do_aesni_ctr.  */
1145 static void
1146 do_aesni_ctr_4 (const RIJNDAEL_context *ctx,
1147                 unsigned char *ctr, unsigned char *b, const unsigned char *a)
1148 {
1149   static const byte bige_addb_const[4][16] __attribute__ ((aligned (16))) =
1150     {
1151       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
1152       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 },
1153       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3 },
1154       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4 }
1155     };
1156   const void *bige_addb = bige_addb_const;
1157 #define aesenc_xmm1_xmm0      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc1\n\t"
1158 #define aesenc_xmm1_xmm2      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xd1\n\t"
1159 #define aesenc_xmm1_xmm3      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xd9\n\t"
1160 #define aesenc_xmm1_xmm4      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xe1\n\t"
1161 #define aesenclast_xmm1_xmm0  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc1\n\t"
1162 #define aesenclast_xmm1_xmm2  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xd1\n\t"
1163 #define aesenclast_xmm1_xmm3  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xd9\n\t"
1164 #define aesenclast_xmm1_xmm4  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xe1\n\t"
1165
1166   /* Register usage:
1167       [key] keyschedule
1168       xmm0  CTR-0
1169       xmm1  temp / round key
1170       xmm2  CTR-1
1171       xmm3  CTR-2
1172       xmm4  CTR-3
1173       xmm5  copy of *ctr
1174       xmm6  endian swapping mask
1175    */
1176
1177   asm volatile (/* detect if 8-bit carry handling is needed */
1178                 "cmpb   $0xfb, 15(%[ctr])\n\t"
1179                 "ja     .Ladd32bit%=\n\t"
1180
1181                 "movdqa %%xmm5, %%xmm0\n\t"     /* xmm0 := CTR (xmm5) */
1182                 "movdqa 0*16(%[addb]), %%xmm2\n\t"  /* xmm2 := be(1) */
1183                 "movdqa 1*16(%[addb]), %%xmm3\n\t"  /* xmm3 := be(2) */
1184                 "movdqa 2*16(%[addb]), %%xmm4\n\t"  /* xmm4 := be(3) */
1185                 "movdqa 3*16(%[addb]), %%xmm5\n\t"  /* xmm5 := be(4) */
1186                 "paddb  %%xmm0, %%xmm2\n\t"     /* xmm2 := be(1) + CTR (xmm0) */
1187                 "paddb  %%xmm0, %%xmm3\n\t"     /* xmm3 := be(2) + CTR (xmm0) */
1188                 "paddb  %%xmm0, %%xmm4\n\t"     /* xmm4 := be(3) + CTR (xmm0) */
1189                 "paddb  %%xmm0, %%xmm5\n\t"     /* xmm5 := be(4) + CTR (xmm0) */
1190                 "movdqa (%[key]), %%xmm1\n\t"   /* xmm1 := key[0] */
1191                 "jmp    .Lstore_ctr%=\n\t"
1192
1193                 ".Ladd32bit%=:\n\t"
1194                 "movdqa %%xmm5, %%xmm0\n\t"     /* xmm0, xmm2 := CTR (xmm5) */
1195                 "movdqa %%xmm0, %%xmm2\n\t"
1196                 "pcmpeqd %%xmm1, %%xmm1\n\t"
1197                 "psrldq $8, %%xmm1\n\t"         /* xmm1 = -1 */
1198
1199                 "pshufb %%xmm6, %%xmm2\n\t"     /* xmm2 := le(xmm2) */
1200                 "psubq  %%xmm1, %%xmm2\n\t"     /* xmm2++           */
1201                 "movdqa %%xmm2, %%xmm3\n\t"     /* xmm3 := xmm2     */
1202                 "psubq  %%xmm1, %%xmm3\n\t"     /* xmm3++           */
1203                 "movdqa %%xmm3, %%xmm4\n\t"     /* xmm4 := xmm3     */
1204                 "psubq  %%xmm1, %%xmm4\n\t"     /* xmm4++           */
1205                 "movdqa %%xmm4, %%xmm5\n\t"     /* xmm5 := xmm4     */
1206                 "psubq  %%xmm1, %%xmm5\n\t"     /* xmm5++           */
1207
1208                 /* detect if 64-bit carry handling is needed */
1209                 "cmpl   $0xffffffff, 8(%[ctr])\n\t"
1210                 "jne    .Lno_carry%=\n\t"
1211                 "movl   12(%[ctr]), %%esi\n\t"
1212                 "bswapl %%esi\n\t"
1213                 "cmpl   $0xfffffffc, %%esi\n\t"
1214                 "jb     .Lno_carry%=\n\t"       /* no carry */
1215
1216                 "pslldq $8, %%xmm1\n\t"         /* move lower 64-bit to high */
1217                 "je     .Lcarry_xmm5%=\n\t"     /* esi == 0xfffffffc */
1218                 "cmpl   $0xfffffffe, %%esi\n\t"
1219                 "jb     .Lcarry_xmm4%=\n\t"     /* esi == 0xfffffffd */
1220                 "je     .Lcarry_xmm3%=\n\t"     /* esi == 0xfffffffe */
1221                 /* esi == 0xffffffff */
1222
1223                 "psubq   %%xmm1, %%xmm2\n\t"
1224                 ".Lcarry_xmm3%=:\n\t"
1225                 "psubq   %%xmm1, %%xmm3\n\t"
1226                 ".Lcarry_xmm4%=:\n\t"
1227                 "psubq   %%xmm1, %%xmm4\n\t"
1228                 ".Lcarry_xmm5%=:\n\t"
1229                 "psubq   %%xmm1, %%xmm5\n\t"
1230
1231                 ".Lno_carry%=:\n\t"
1232                 "movdqa (%[key]), %%xmm1\n\t"   /* xmm1 := key[0]    */
1233
1234                 "pshufb %%xmm6, %%xmm2\n\t"     /* xmm2 := be(xmm2) */
1235                 "pshufb %%xmm6, %%xmm3\n\t"     /* xmm3 := be(xmm3) */
1236                 "pshufb %%xmm6, %%xmm4\n\t"     /* xmm4 := be(xmm4) */
1237                 "pshufb %%xmm6, %%xmm5\n\t"     /* xmm5 := be(xmm5) */
1238
1239                 ".Lstore_ctr%=:\n\t"
1240                 "movdqa %%xmm5, (%[ctr])\n\t"   /* Update CTR (mem).  */
1241                 :
1242                 : [ctr] "r" (ctr),
1243                   [key] "r" (ctx->keyschenc),
1244                   [addb] "r" (bige_addb)
1245                 : "%esi", "cc", "memory");
1246
1247   asm volatile ("pxor   %%xmm1, %%xmm0\n\t"     /* xmm0 ^= key[0]    */
1248                 "pxor   %%xmm1, %%xmm2\n\t"     /* xmm2 ^= key[0]    */
1249                 "pxor   %%xmm1, %%xmm3\n\t"     /* xmm3 ^= key[0]    */
1250                 "pxor   %%xmm1, %%xmm4\n\t"     /* xmm4 ^= key[0]    */
1251                 "movdqa 0x10(%[key]), %%xmm1\n\t"
1252                 aesenc_xmm1_xmm0
1253                 aesenc_xmm1_xmm2
1254                 aesenc_xmm1_xmm3
1255                 aesenc_xmm1_xmm4
1256                 "movdqa 0x20(%[key]), %%xmm1\n\t"
1257                 aesenc_xmm1_xmm0
1258                 aesenc_xmm1_xmm2
1259                 aesenc_xmm1_xmm3
1260                 aesenc_xmm1_xmm4
1261                 "movdqa 0x30(%[key]), %%xmm1\n\t"
1262                 aesenc_xmm1_xmm0
1263                 aesenc_xmm1_xmm2
1264                 aesenc_xmm1_xmm3
1265                 aesenc_xmm1_xmm4
1266                 "movdqa 0x40(%[key]), %%xmm1\n\t"
1267                 aesenc_xmm1_xmm0
1268                 aesenc_xmm1_xmm2
1269                 aesenc_xmm1_xmm3
1270                 aesenc_xmm1_xmm4
1271                 "movdqa 0x50(%[key]), %%xmm1\n\t"
1272                 aesenc_xmm1_xmm0
1273                 aesenc_xmm1_xmm2
1274                 aesenc_xmm1_xmm3
1275                 aesenc_xmm1_xmm4
1276                 "movdqa 0x60(%[key]), %%xmm1\n\t"
1277                 aesenc_xmm1_xmm0
1278                 aesenc_xmm1_xmm2
1279                 aesenc_xmm1_xmm3
1280                 aesenc_xmm1_xmm4
1281                 "movdqa 0x70(%[key]), %%xmm1\n\t"
1282                 aesenc_xmm1_xmm0
1283                 aesenc_xmm1_xmm2
1284                 aesenc_xmm1_xmm3
1285                 aesenc_xmm1_xmm4
1286                 "movdqa 0x80(%[key]), %%xmm1\n\t"
1287                 aesenc_xmm1_xmm0
1288                 aesenc_xmm1_xmm2
1289                 aesenc_xmm1_xmm3
1290                 aesenc_xmm1_xmm4
1291                 "movdqa 0x90(%[key]), %%xmm1\n\t"
1292                 aesenc_xmm1_xmm0
1293                 aesenc_xmm1_xmm2
1294                 aesenc_xmm1_xmm3
1295                 aesenc_xmm1_xmm4
1296                 "movdqa 0xa0(%[key]), %%xmm1\n\t"
1297                 "cmpl $10, %[rounds]\n\t"
1298                 "jz .Lenclast%=\n\t"
1299                 aesenc_xmm1_xmm0
1300                 aesenc_xmm1_xmm2
1301                 aesenc_xmm1_xmm3
1302                 aesenc_xmm1_xmm4
1303                 "movdqa 0xb0(%[key]), %%xmm1\n\t"
1304                 aesenc_xmm1_xmm0
1305                 aesenc_xmm1_xmm2
1306                 aesenc_xmm1_xmm3
1307                 aesenc_xmm1_xmm4
1308                 "movdqa 0xc0(%[key]), %%xmm1\n\t"
1309                 "cmpl $12, %[rounds]\n\t"
1310                 "jz .Lenclast%=\n\t"
1311                 aesenc_xmm1_xmm0
1312                 aesenc_xmm1_xmm2
1313                 aesenc_xmm1_xmm3
1314                 aesenc_xmm1_xmm4
1315                 "movdqa 0xd0(%[key]), %%xmm1\n\t"
1316                 aesenc_xmm1_xmm0
1317                 aesenc_xmm1_xmm2
1318                 aesenc_xmm1_xmm3
1319                 aesenc_xmm1_xmm4
1320                 "movdqa 0xe0(%[key]), %%xmm1\n"
1321
1322                 ".Lenclast%=:\n\t"
1323                 aesenclast_xmm1_xmm0
1324                 aesenclast_xmm1_xmm2
1325                 aesenclast_xmm1_xmm3
1326                 aesenclast_xmm1_xmm4
1327                 :
1328                 : [key] "r" (ctx->keyschenc),
1329                   [rounds] "r" (ctx->rounds)
1330                 : "cc", "memory");
1331
1332   asm volatile ("movdqu (%[src]), %%xmm1\n\t"    /* Get block 1.      */
1333                 "pxor %%xmm1, %%xmm0\n\t"        /* EncCTR-1 ^= input */
1334                 "movdqu %%xmm0, (%[dst])\n\t"    /* Store block 1     */
1335
1336                 "movdqu 16(%[src]), %%xmm1\n\t"  /* Get block 2.      */
1337                 "pxor %%xmm1, %%xmm2\n\t"        /* EncCTR-2 ^= input */
1338                 "movdqu %%xmm2, 16(%[dst])\n\t"  /* Store block 2.    */
1339
1340                 "movdqu 32(%[src]), %%xmm1\n\t"  /* Get block 3.      */
1341                 "pxor %%xmm1, %%xmm3\n\t"        /* EncCTR-3 ^= input */
1342                 "movdqu %%xmm3, 32(%[dst])\n\t"  /* Store block 3.    */
1343
1344                 "movdqu 48(%[src]), %%xmm1\n\t"  /* Get block 4.      */
1345                 "pxor %%xmm1, %%xmm4\n\t"        /* EncCTR-4 ^= input */
1346                 "movdqu %%xmm4, 48(%[dst])"      /* Store block 4.   */
1347                 :
1348                 : [src] "r" (a),
1349                   [dst] "r" (b)
1350                 : "memory");
1351 #undef aesenc_xmm1_xmm0
1352 #undef aesenc_xmm1_xmm2
1353 #undef aesenc_xmm1_xmm3
1354 #undef aesenc_xmm1_xmm4
1355 #undef aesenclast_xmm1_xmm0
1356 #undef aesenclast_xmm1_xmm2
1357 #undef aesenclast_xmm1_xmm3
1358 #undef aesenclast_xmm1_xmm4
1359 }
1360
1361
1362 #ifdef __x86_64__
1363
1364 /* Eight blocks at a time variant of do_aesni_ctr.  */
1365 static void
1366 do_aesni_ctr_8 (const RIJNDAEL_context *ctx,
1367                 unsigned char *ctr, unsigned char *b, const unsigned char *a)
1368 {
1369   static const byte bige_addb_const[8][16] __attribute__ ((aligned (16))) =
1370     {
1371       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
1372       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 },
1373       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3 },
1374       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4 },
1375       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5 },
1376       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 },
1377       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7 },
1378       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8 }
1379     };
1380   const void *bige_addb = bige_addb_const;
1381
1382   /* Register usage:
1383       [key] keyschedule
1384       xmm0  CTR-0
1385       xmm1  temp / round key
1386       xmm2  CTR-1
1387       xmm3  CTR-2
1388       xmm4  CTR-3
1389       xmm5  copy of *ctr
1390       xmm6  endian swapping mask
1391       xmm8  CTR-4
1392       xmm9  CTR-5
1393       xmm10 CTR-6
1394       xmm11 CTR-7
1395       xmm12 temp
1396       xmm13 temp
1397       xmm14 temp
1398       xmm15 temp
1399    */
1400
1401   asm volatile (/* detect if 8-bit carry handling is needed */
1402                 "cmpb   $0xf7, 15(%[ctr])\n\t"
1403                 "ja     .Ladd32bit%=\n\t"
1404
1405                 "movdqa %%xmm5, %%xmm0\n\t"     /* xmm0 := CTR (xmm5) */
1406                 "movdqa 0*16(%[addb]), %%xmm2\n\t"  /* xmm2 := be(1) */
1407                 "movdqa 1*16(%[addb]), %%xmm3\n\t"  /* xmm3 := be(2) */
1408                 "movdqa 2*16(%[addb]), %%xmm4\n\t"  /* xmm4 := be(3) */
1409                 "movdqa 3*16(%[addb]), %%xmm8\n\t"  /* xmm8 := be(4) */
1410                 "movdqa 4*16(%[addb]), %%xmm9\n\t"  /* xmm9 := be(5) */
1411                 "movdqa 5*16(%[addb]), %%xmm10\n\t" /* xmm10 := be(6) */
1412                 "movdqa 6*16(%[addb]), %%xmm11\n\t" /* xmm11 := be(7) */
1413                 "movdqa 7*16(%[addb]), %%xmm5\n\t"  /* xmm5 := be(8) */
1414                 "movdqa (%[key]), %%xmm1\n\t"   /* xmm1 := key[0] */
1415                 "paddb  %%xmm0, %%xmm2\n\t"     /* xmm2 := be(1) + CTR (xmm0) */
1416                 "paddb  %%xmm0, %%xmm3\n\t"     /* xmm3 := be(2) + CTR (xmm0) */
1417                 "paddb  %%xmm0, %%xmm4\n\t"     /* xmm4 := be(3) + CTR (xmm0) */
1418                 "paddb  %%xmm0, %%xmm8\n\t"     /* xmm8 := be(4) + CTR (xmm0) */
1419                 "paddb  %%xmm0, %%xmm9\n\t"     /* xmm9 := be(5) + CTR (xmm0) */
1420                 "paddb  %%xmm0, %%xmm10\n\t"    /* xmm10 := be(6) + CTR (xmm0) */
1421                 "paddb  %%xmm0, %%xmm11\n\t"    /* xmm11 := be(7) + CTR (xmm0) */
1422                 "paddb  %%xmm0, %%xmm5\n\t"     /* xmm5 := be(8) + CTR (xmm0) */
1423                 "jmp    .Lstore_ctr%=\n\t"
1424
1425                 ".Ladd32bit%=:\n\t"
1426                 "movdqa %%xmm5, %%xmm0\n\t"     /* xmm0, xmm2 := CTR (xmm5) */
1427                 "movdqa %%xmm0, %%xmm2\n\t"
1428                 "pcmpeqd %%xmm1, %%xmm1\n\t"
1429                 "psrldq $8, %%xmm1\n\t"         /* xmm1 = -1 */
1430
1431                 "pshufb %%xmm6, %%xmm2\n\t"     /* xmm2 := le(xmm2) */
1432                 "psubq  %%xmm1, %%xmm2\n\t"     /* xmm2++           */
1433                 "movdqa %%xmm2, %%xmm3\n\t"     /* xmm3 := xmm2     */
1434                 "psubq  %%xmm1, %%xmm3\n\t"     /* xmm3++           */
1435                 "movdqa %%xmm3, %%xmm4\n\t"     /* xmm4 := xmm3     */
1436                 "psubq  %%xmm1, %%xmm4\n\t"     /* xmm4++           */
1437                 "movdqa %%xmm4, %%xmm8\n\t"     /* xmm8 := xmm4     */
1438                 "psubq  %%xmm1, %%xmm8\n\t"     /* xmm8++           */
1439                 "movdqa %%xmm8, %%xmm9\n\t"     /* xmm9 := xmm8     */
1440                 "psubq  %%xmm1, %%xmm9\n\t"     /* xmm9++           */
1441                 "movdqa %%xmm9, %%xmm10\n\t"    /* xmm10 := xmm9    */
1442                 "psubq  %%xmm1, %%xmm10\n\t"    /* xmm10++          */
1443                 "movdqa %%xmm10, %%xmm11\n\t"   /* xmm11 := xmm10   */
1444                 "psubq  %%xmm1, %%xmm11\n\t"    /* xmm11++          */
1445                 "movdqa %%xmm11, %%xmm5\n\t"    /* xmm5 := xmm11    */
1446                 "psubq  %%xmm1, %%xmm5\n\t"     /* xmm5++           */
1447
1448                 /* detect if 64-bit carry handling is needed */
1449                 "cmpl   $0xffffffff, 8(%[ctr])\n\t"
1450                 "jne    .Lno_carry%=\n\t"
1451                 "movl   12(%[ctr]), %%esi\n\t"
1452                 "bswapl %%esi\n\t"
1453                 "cmpl   $0xfffffff8, %%esi\n\t"
1454                 "jb     .Lno_carry%=\n\t"       /* no carry */
1455
1456                 "pslldq $8, %%xmm1\n\t"         /* move lower 64-bit to high */
1457                 "je     .Lcarry_xmm5%=\n\t"     /* esi == 0xfffffff8 */
1458                 "cmpl   $0xfffffffa, %%esi\n\t"
1459                 "jb     .Lcarry_xmm11%=\n\t"     /* esi == 0xfffffff9 */
1460                 "je     .Lcarry_xmm10%=\n\t"     /* esi == 0xfffffffa */
1461                 "cmpl   $0xfffffffc, %%esi\n\t"
1462                 "jb     .Lcarry_xmm9%=\n\t"     /* esi == 0xfffffffb */
1463                 "je     .Lcarry_xmm8%=\n\t"     /* esi == 0xfffffffc */
1464                 "cmpl   $0xfffffffe, %%esi\n\t"
1465                 "jb     .Lcarry_xmm4%=\n\t"     /* esi == 0xfffffffd */
1466                 "je     .Lcarry_xmm3%=\n\t"     /* esi == 0xfffffffe */
1467                 /* esi == 0xffffffff */
1468
1469                 "psubq   %%xmm1, %%xmm2\n\t"
1470                 ".Lcarry_xmm3%=:\n\t"
1471                 "psubq   %%xmm1, %%xmm3\n\t"
1472                 ".Lcarry_xmm4%=:\n\t"
1473                 "psubq   %%xmm1, %%xmm4\n\t"
1474                 ".Lcarry_xmm8%=:\n\t"
1475                 "psubq   %%xmm1, %%xmm8\n\t"
1476                 ".Lcarry_xmm9%=:\n\t"
1477                 "psubq   %%xmm1, %%xmm9\n\t"
1478                 ".Lcarry_xmm10%=:\n\t"
1479                 "psubq   %%xmm1, %%xmm10\n\t"
1480                 ".Lcarry_xmm11%=:\n\t"
1481                 "psubq   %%xmm1, %%xmm11\n\t"
1482                 ".Lcarry_xmm5%=:\n\t"
1483                 "psubq   %%xmm1, %%xmm5\n\t"
1484
1485                 ".Lno_carry%=:\n\t"
1486                 "movdqa (%[key]), %%xmm1\n\t"   /* xmm1 := key[0]    */
1487
1488                 "pshufb %%xmm6, %%xmm2\n\t"     /* xmm2 := be(xmm2) */
1489                 "pshufb %%xmm6, %%xmm3\n\t"     /* xmm3 := be(xmm3) */
1490                 "pshufb %%xmm6, %%xmm4\n\t"     /* xmm4 := be(xmm4) */
1491                 "pshufb %%xmm6, %%xmm5\n\t"     /* xmm5 := be(xmm5) */
1492                 "pshufb %%xmm6, %%xmm8\n\t"     /* xmm8 := be(xmm8) */
1493                 "pshufb %%xmm6, %%xmm9\n\t"     /* xmm9 := be(xmm9) */
1494                 "pshufb %%xmm6, %%xmm10\n\t"    /* xmm10 := be(xmm10) */
1495                 "pshufb %%xmm6, %%xmm11\n\t"    /* xmm11 := be(xmm11) */
1496
1497                 ".Lstore_ctr%=:\n\t"
1498                 "movdqa %%xmm5, (%[ctr])\n\t"   /* Update CTR (mem).  */
1499                 :
1500                 : [ctr] "r" (ctr),
1501                   [key] "r" (ctx->keyschenc),
1502                   [addb] "r" (bige_addb)
1503                 : "%esi", "cc", "memory");
1504
1505   asm volatile ("pxor   %%xmm1, %%xmm0\n\t"     /* xmm0 ^= key[0]    */
1506                 "pxor   %%xmm1, %%xmm2\n\t"     /* xmm2 ^= key[0]    */
1507                 "pxor   %%xmm1, %%xmm3\n\t"     /* xmm3 ^= key[0]    */
1508                 "pxor   %%xmm1, %%xmm4\n\t"     /* xmm4 ^= key[0]    */
1509                 "pxor   %%xmm1, %%xmm8\n\t"     /* xmm8 ^= key[0]    */
1510                 "pxor   %%xmm1, %%xmm9\n\t"     /* xmm9 ^= key[0]    */
1511                 "pxor   %%xmm1, %%xmm10\n\t"    /* xmm10 ^= key[0]   */
1512                 "pxor   %%xmm1, %%xmm11\n\t"    /* xmm11 ^= key[0]   */
1513                 "movdqa 0x10(%[key]), %%xmm1\n\t"
1514                 "cmpl $12, %[rounds]\n\t"
1515                 "aesenc %%xmm1, %%xmm0\n\t"
1516                 "aesenc %%xmm1, %%xmm2\n\t"
1517                 "aesenc %%xmm1, %%xmm3\n\t"
1518                 "aesenc %%xmm1, %%xmm4\n\t"
1519                 "aesenc %%xmm1, %%xmm8\n\t"
1520                 "aesenc %%xmm1, %%xmm9\n\t"
1521                 "aesenc %%xmm1, %%xmm10\n\t"
1522                 "aesenc %%xmm1, %%xmm11\n\t"
1523                 "movdqa 0x20(%[key]), %%xmm1\n\t"
1524                 "aesenc %%xmm1, %%xmm0\n\t"
1525                 "aesenc %%xmm1, %%xmm2\n\t"
1526                 "aesenc %%xmm1, %%xmm3\n\t"
1527                 "aesenc %%xmm1, %%xmm4\n\t"
1528                 "aesenc %%xmm1, %%xmm8\n\t"
1529                 "aesenc %%xmm1, %%xmm9\n\t"
1530                 "aesenc %%xmm1, %%xmm10\n\t"
1531                 "aesenc %%xmm1, %%xmm11\n\t"
1532                 "movdqa 0x30(%[key]), %%xmm1\n\t"
1533                 "aesenc %%xmm1, %%xmm0\n\t"
1534                 "aesenc %%xmm1, %%xmm2\n\t"
1535                 "aesenc %%xmm1, %%xmm3\n\t"
1536                 "aesenc %%xmm1, %%xmm4\n\t"
1537                 "aesenc %%xmm1, %%xmm8\n\t"
1538                 "aesenc %%xmm1, %%xmm9\n\t"
1539                 "aesenc %%xmm1, %%xmm10\n\t"
1540                 "aesenc %%xmm1, %%xmm11\n\t"
1541                 "movdqa 0x40(%[key]), %%xmm1\n\t"
1542                 "aesenc %%xmm1, %%xmm0\n\t"
1543                 "aesenc %%xmm1, %%xmm2\n\t"
1544                 "aesenc %%xmm1, %%xmm3\n\t"
1545                 "aesenc %%xmm1, %%xmm4\n\t"
1546                 "aesenc %%xmm1, %%xmm8\n\t"
1547                 "aesenc %%xmm1, %%xmm9\n\t"
1548                 "aesenc %%xmm1, %%xmm10\n\t"
1549                 "aesenc %%xmm1, %%xmm11\n\t"
1550                 "movdqa 0x50(%[key]), %%xmm1\n\t"
1551                 "aesenc %%xmm1, %%xmm0\n\t"
1552                 "aesenc %%xmm1, %%xmm2\n\t"
1553                 "aesenc %%xmm1, %%xmm3\n\t"
1554                 "aesenc %%xmm1, %%xmm4\n\t"
1555                 "aesenc %%xmm1, %%xmm8\n\t"
1556                 "aesenc %%xmm1, %%xmm9\n\t"
1557                 "aesenc %%xmm1, %%xmm10\n\t"
1558                 "aesenc %%xmm1, %%xmm11\n\t"
1559                 "movdqa 0x60(%[key]), %%xmm1\n\t"
1560                 "aesenc %%xmm1, %%xmm0\n\t"
1561                 "aesenc %%xmm1, %%xmm2\n\t"
1562                 "aesenc %%xmm1, %%xmm3\n\t"
1563                 "aesenc %%xmm1, %%xmm4\n\t"
1564                 "aesenc %%xmm1, %%xmm8\n\t"
1565                 "aesenc %%xmm1, %%xmm9\n\t"
1566                 "aesenc %%xmm1, %%xmm10\n\t"
1567                 "aesenc %%xmm1, %%xmm11\n\t"
1568                 "movdqa 0x70(%[key]), %%xmm1\n\t"
1569                 "aesenc %%xmm1, %%xmm0\n\t"
1570                 "aesenc %%xmm1, %%xmm2\n\t"
1571                 "aesenc %%xmm1, %%xmm3\n\t"
1572                 "aesenc %%xmm1, %%xmm4\n\t"
1573                 "aesenc %%xmm1, %%xmm8\n\t"
1574                 "aesenc %%xmm1, %%xmm9\n\t"
1575                 "aesenc %%xmm1, %%xmm10\n\t"
1576                 "aesenc %%xmm1, %%xmm11\n\t"
1577                 "movdqa 0x80(%[key]), %%xmm1\n\t"
1578                 "aesenc %%xmm1, %%xmm0\n\t"
1579                 "aesenc %%xmm1, %%xmm2\n\t"
1580                 "aesenc %%xmm1, %%xmm3\n\t"
1581                 "aesenc %%xmm1, %%xmm4\n\t"
1582                 "aesenc %%xmm1, %%xmm8\n\t"
1583                 "aesenc %%xmm1, %%xmm9\n\t"
1584                 "aesenc %%xmm1, %%xmm10\n\t"
1585                 "aesenc %%xmm1, %%xmm11\n\t"
1586                 "movdqa 0x90(%[key]), %%xmm1\n\t"
1587                 "aesenc %%xmm1, %%xmm0\n\t"
1588                 "aesenc %%xmm1, %%xmm2\n\t"
1589                 "aesenc %%xmm1, %%xmm3\n\t"
1590                 "aesenc %%xmm1, %%xmm4\n\t"
1591                 "aesenc %%xmm1, %%xmm8\n\t"
1592                 "aesenc %%xmm1, %%xmm9\n\t"
1593                 "aesenc %%xmm1, %%xmm10\n\t"
1594                 "aesenc %%xmm1, %%xmm11\n\t"
1595                 "movdqa 0xa0(%[key]), %%xmm1\n\t"
1596                 "jb .Lenclast%=\n\t"
1597                 "aesenc %%xmm1, %%xmm0\n\t"
1598                 "aesenc %%xmm1, %%xmm2\n\t"
1599                 "aesenc %%xmm1, %%xmm3\n\t"
1600                 "aesenc %%xmm1, %%xmm4\n\t"
1601                 "aesenc %%xmm1, %%xmm8\n\t"
1602                 "aesenc %%xmm1, %%xmm9\n\t"
1603                 "aesenc %%xmm1, %%xmm10\n\t"
1604                 "aesenc %%xmm1, %%xmm11\n\t"
1605                 "movdqa 0xb0(%[key]), %%xmm1\n\t"
1606                 "aesenc %%xmm1, %%xmm0\n\t"
1607                 "aesenc %%xmm1, %%xmm2\n\t"
1608                 "aesenc %%xmm1, %%xmm3\n\t"
1609                 "aesenc %%xmm1, %%xmm4\n\t"
1610                 "aesenc %%xmm1, %%xmm8\n\t"
1611                 "aesenc %%xmm1, %%xmm9\n\t"
1612                 "aesenc %%xmm1, %%xmm10\n\t"
1613                 "aesenc %%xmm1, %%xmm11\n\t"
1614                 "movdqa 0xc0(%[key]), %%xmm1\n\t"
1615                 "je .Lenclast%=\n\t"
1616                 "aesenc %%xmm1, %%xmm0\n\t"
1617                 "aesenc %%xmm1, %%xmm2\n\t"
1618                 "aesenc %%xmm1, %%xmm3\n\t"
1619                 "aesenc %%xmm1, %%xmm4\n\t"
1620                 "aesenc %%xmm1, %%xmm8\n\t"
1621                 "aesenc %%xmm1, %%xmm9\n\t"
1622                 "aesenc %%xmm1, %%xmm10\n\t"
1623                 "aesenc %%xmm1, %%xmm11\n\t"
1624                 "movdqa 0xd0(%[key]), %%xmm1\n\t"
1625                 "aesenc %%xmm1, %%xmm0\n\t"
1626                 "aesenc %%xmm1, %%xmm2\n\t"
1627                 "aesenc %%xmm1, %%xmm3\n\t"
1628                 "aesenc %%xmm1, %%xmm4\n\t"
1629                 "aesenc %%xmm1, %%xmm8\n\t"
1630                 "aesenc %%xmm1, %%xmm9\n\t"
1631                 "aesenc %%xmm1, %%xmm10\n\t"
1632                 "aesenc %%xmm1, %%xmm11\n\t"
1633                 "movdqa 0xe0(%[key]), %%xmm1\n"
1634
1635                 ".Lenclast%=:\n\t"
1636                 "aesenclast %%xmm1, %%xmm0\n\t"
1637                 "aesenclast %%xmm1, %%xmm2\n\t"
1638                 "aesenclast %%xmm1, %%xmm3\n\t"
1639                 "aesenclast %%xmm1, %%xmm4\n\t"
1640                 "aesenclast %%xmm1, %%xmm8\n\t"
1641                 "aesenclast %%xmm1, %%xmm9\n\t"
1642                 "aesenclast %%xmm1, %%xmm10\n\t"
1643                 "aesenclast %%xmm1, %%xmm11\n\t"
1644                 :
1645                 : [key] "r" (ctx->keyschenc),
1646                   [rounds] "r" (ctx->rounds)
1647                 : "cc", "memory");
1648
1649   asm volatile ("movdqu 0*16(%[src]), %%xmm12\n\t" /* Get block 1.      */
1650                 "movdqu 1*16(%[src]), %%xmm13\n\t" /* Get block 2.      */
1651                 "movdqu 2*16(%[src]), %%xmm14\n\t" /* Get block 3.      */
1652                 "movdqu 3*16(%[src]), %%xmm15\n\t" /* Get block 4.      */
1653                 "movdqu 4*16(%[src]), %%xmm1\n\t"  /* Get block 5.      */
1654                 "pxor %%xmm12, %%xmm0\n\t"         /* EncCTR-1 ^= input */
1655                 "movdqu 5*16(%[src]), %%xmm12\n\t" /* Get block 6.      */
1656                 "pxor %%xmm13, %%xmm2\n\t"         /* EncCTR-2 ^= input */
1657                 "movdqu 6*16(%[src]), %%xmm13\n\t" /* Get block 7.      */
1658                 "pxor %%xmm14, %%xmm3\n\t"         /* EncCTR-3 ^= input */
1659                 "movdqu 7*16(%[src]), %%xmm14\n\t" /* Get block 8.      */
1660                 "pxor %%xmm15, %%xmm4\n\t"         /* EncCTR-4 ^= input */
1661                 "movdqu %%xmm0, 0*16(%[dst])\n\t"  /* Store block 1     */
1662                 "pxor %%xmm1,  %%xmm8\n\t"         /* EncCTR-5 ^= input */
1663                 "movdqu %%xmm0, 0*16(%[dst])\n\t"  /* Store block 1     */
1664                 "pxor %%xmm12, %%xmm9\n\t"         /* EncCTR-6 ^= input */
1665                 "movdqu %%xmm2, 1*16(%[dst])\n\t"  /* Store block 2.    */
1666                 "pxor %%xmm13, %%xmm10\n\t"        /* EncCTR-7 ^= input */
1667                 "movdqu %%xmm3, 2*16(%[dst])\n\t"  /* Store block 3.    */
1668                 "pxor %%xmm14, %%xmm11\n\t"        /* EncCTR-8 ^= input */
1669                 "movdqu %%xmm4, 3*16(%[dst])\n\t"  /* Store block 4.    */
1670                 "movdqu %%xmm8, 4*16(%[dst])\n\t"  /* Store block 8.    */
1671                 "movdqu %%xmm9, 5*16(%[dst])\n\t"  /* Store block 9.    */
1672                 "movdqu %%xmm10, 6*16(%[dst])\n\t" /* Store block 10.   */
1673                 "movdqu %%xmm11, 7*16(%[dst])\n\t" /* Store block 11.   */
1674                 :
1675                 : [src] "r" (a),
1676                   [dst] "r" (b)
1677                 : "memory");
1678 }
1679
1680 #endif /* __x86_64__ */
1681
1682
1683 unsigned int
1684 _gcry_aes_aesni_encrypt (const RIJNDAEL_context *ctx, unsigned char *dst,
1685                          const unsigned char *src)
1686 {
1687   aesni_prepare ();
1688   asm volatile ("movdqu %[src], %%xmm0\n\t"
1689                 :
1690                 : [src] "m" (*src)
1691                 : "memory" );
1692   do_aesni_enc (ctx);
1693   asm volatile ("movdqu %%xmm0, %[dst]\n\t"
1694                 : [dst] "=m" (*dst)
1695                 :
1696                 : "memory" );
1697   aesni_cleanup ();
1698   return 0;
1699 }
1700
1701
1702 void
1703 _gcry_aes_aesni_cfb_enc (RIJNDAEL_context *ctx, unsigned char *iv,
1704                          unsigned char *outbuf, const unsigned char *inbuf,
1705                          size_t nblocks)
1706 {
1707   aesni_prepare ();
1708
1709   asm volatile ("movdqu %[iv], %%xmm0\n\t"
1710                 : /* No output */
1711                 : [iv] "m" (*iv)
1712                 : "memory" );
1713
1714   for ( ;nblocks; nblocks-- )
1715     {
1716       do_aesni_enc (ctx);
1717
1718       asm volatile ("movdqu %[inbuf], %%xmm1\n\t"
1719                     "pxor %%xmm1, %%xmm0\n\t"
1720                     "movdqu %%xmm0, %[outbuf]\n\t"
1721                     : [outbuf] "=m" (*outbuf)
1722                     : [inbuf] "m" (*inbuf)
1723                     : "memory" );
1724
1725       outbuf += BLOCKSIZE;
1726       inbuf  += BLOCKSIZE;
1727     }
1728
1729   asm volatile ("movdqu %%xmm0, %[iv]\n\t"
1730                 : [iv] "=m" (*iv)
1731                 :
1732                 : "memory" );
1733
1734   aesni_cleanup ();
1735 }
1736
1737
1738 void
1739 _gcry_aes_aesni_cbc_enc (RIJNDAEL_context *ctx, unsigned char *iv,
1740                          unsigned char *outbuf, const unsigned char *inbuf,
1741                          size_t nblocks, int cbc_mac)
1742 {
1743   aesni_prepare_2_6_variable;
1744
1745   aesni_prepare ();
1746   aesni_prepare_2_6();
1747
1748   asm volatile ("movdqu %[iv], %%xmm5\n\t"
1749                 : /* No output */
1750                 : [iv] "m" (*iv)
1751                 : "memory" );
1752
1753   for ( ;nblocks; nblocks-- )
1754     {
1755       asm volatile ("movdqu %[inbuf], %%xmm0\n\t"
1756                     "pxor %%xmm5, %%xmm0\n\t"
1757                     : /* No output */
1758                     : [inbuf] "m" (*inbuf)
1759                     : "memory" );
1760
1761       do_aesni_enc (ctx);
1762
1763       asm volatile ("movdqa %%xmm0, %%xmm5\n\t"
1764                     "movdqu %%xmm0, %[outbuf]\n\t"
1765                     : [outbuf] "=m" (*outbuf)
1766                     :
1767                     : "memory" );
1768
1769       inbuf += BLOCKSIZE;
1770       if (!cbc_mac)
1771         outbuf += BLOCKSIZE;
1772     }
1773
1774   asm volatile ("movdqu %%xmm5, %[iv]\n\t"
1775                 : [iv] "=m" (*iv)
1776                 :
1777                 : "memory" );
1778
1779   aesni_cleanup ();
1780   aesni_cleanup_2_6 ();
1781 }
1782
1783
1784 void
1785 _gcry_aes_aesni_ctr_enc (RIJNDAEL_context *ctx, unsigned char *ctr,
1786                          unsigned char *outbuf, const unsigned char *inbuf,
1787                          size_t nblocks)
1788 {
1789   static const unsigned char be_mask[16] __attribute__ ((aligned (16))) =
1790     { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
1791   aesni_prepare_2_6_variable;
1792
1793   aesni_prepare ();
1794   aesni_prepare_2_6();
1795
1796   asm volatile ("movdqa %[mask], %%xmm6\n\t" /* Preload mask */
1797                 "movdqa %[ctr], %%xmm5\n\t"  /* Preload CTR */
1798                 : /* No output */
1799                 : [mask] "m" (*be_mask),
1800                   [ctr] "m" (*ctr)
1801                 : "memory");
1802
1803 #ifdef __x86_64__
1804   if (nblocks >= 8)
1805     {
1806       aesni_prepare_7_15_variable;
1807
1808       aesni_prepare_7_15();
1809
1810       for ( ;nblocks >= 8 ; nblocks -= 8 )
1811         {
1812           do_aesni_ctr_8 (ctx, ctr, outbuf, inbuf);
1813           outbuf += 8*BLOCKSIZE;
1814           inbuf  += 8*BLOCKSIZE;
1815         }
1816
1817       aesni_cleanup_7_15();
1818     }
1819 #endif
1820
1821   for ( ;nblocks >= 4 ; nblocks -= 4 )
1822     {
1823       do_aesni_ctr_4 (ctx, ctr, outbuf, inbuf);
1824       outbuf += 4*BLOCKSIZE;
1825       inbuf  += 4*BLOCKSIZE;
1826     }
1827   for ( ;nblocks; nblocks-- )
1828     {
1829       do_aesni_ctr (ctx, ctr, outbuf, inbuf);
1830       outbuf += BLOCKSIZE;
1831       inbuf  += BLOCKSIZE;
1832     }
1833   aesni_cleanup ();
1834   aesni_cleanup_2_6 ();
1835 }
1836
1837
1838 unsigned int
1839 _gcry_aes_aesni_decrypt (const RIJNDAEL_context *ctx, unsigned char *dst,
1840                          const unsigned char *src)
1841 {
1842   aesni_prepare ();
1843   asm volatile ("movdqu %[src], %%xmm0\n\t"
1844                 :
1845                 : [src] "m" (*src)
1846                 : "memory" );
1847   do_aesni_dec (ctx);
1848   asm volatile ("movdqu %%xmm0, %[dst]\n\t"
1849                 : [dst] "=m" (*dst)
1850                 :
1851                 : "memory" );
1852   aesni_cleanup ();
1853   return 0;
1854 }
1855
1856
1857 void
1858 _gcry_aes_aesni_cfb_dec (RIJNDAEL_context *ctx, unsigned char *iv,
1859                          unsigned char *outbuf, const unsigned char *inbuf,
1860                          size_t nblocks)
1861 {
1862   aesni_prepare_2_6_variable;
1863
1864   aesni_prepare ();
1865   aesni_prepare_2_6();
1866
1867   asm volatile ("movdqu %[iv], %%xmm6\n\t"
1868                 : /* No output */
1869                 : [iv] "m" (*iv)
1870                 : "memory" );
1871
1872   /* CFB decryption can be parallelized */
1873
1874 #ifdef __x86_64__
1875   if (nblocks >= 8)
1876     {
1877       aesni_prepare_7_15_variable;
1878
1879       aesni_prepare_7_15();
1880
1881       for ( ;nblocks >= 8; nblocks -= 8)
1882         {
1883           asm volatile
1884             ("movdqu %%xmm6,         %%xmm1\n\t" /* load input blocks */
1885              "movdqu 0*16(%[inbuf]), %%xmm2\n\t"
1886              "movdqu 1*16(%[inbuf]), %%xmm3\n\t"
1887              "movdqu 2*16(%[inbuf]), %%xmm4\n\t"
1888              "movdqu 3*16(%[inbuf]), %%xmm8\n\t"
1889              "movdqu 4*16(%[inbuf]), %%xmm9\n\t"
1890              "movdqu 5*16(%[inbuf]), %%xmm10\n\t"
1891              "movdqu 6*16(%[inbuf]), %%xmm11\n\t"
1892
1893              "movdqu 7*16(%[inbuf]), %%xmm6\n\t" /* update IV */
1894
1895              "movdqa %%xmm2, %%xmm12\n\t"
1896              "movdqa %%xmm3, %%xmm13\n\t"
1897              "movdqa %%xmm4, %%xmm14\n\t"
1898              "movdqa %%xmm8, %%xmm15\n\t"
1899              : /* No output */
1900              : [inbuf] "r" (inbuf)
1901              : "memory");
1902
1903           do_aesni_enc_vec8 (ctx);
1904
1905           asm volatile
1906             (
1907              "pxor %%xmm12, %%xmm1\n\t"
1908              "movdqu 4*16(%[inbuf]), %%xmm12\n\t"
1909              "pxor %%xmm13, %%xmm2\n\t"
1910              "movdqu 5*16(%[inbuf]), %%xmm13\n\t"
1911              "pxor %%xmm14, %%xmm3\n\t"
1912              "movdqu 6*16(%[inbuf]), %%xmm14\n\t"
1913              "pxor %%xmm15, %%xmm4\n\t"
1914              "movdqu 7*16(%[inbuf]), %%xmm15\n\t"
1915
1916              "pxor %%xmm12, %%xmm8\n\t"
1917              "movdqu %%xmm1, 0*16(%[outbuf])\n\t"
1918              "pxor %%xmm13, %%xmm9\n\t"
1919              "movdqu %%xmm2, 1*16(%[outbuf])\n\t"
1920              "pxor %%xmm14, %%xmm10\n\t"
1921              "movdqu %%xmm3, 2*16(%[outbuf])\n\t"
1922              "pxor %%xmm15, %%xmm11\n\t"
1923              "movdqu %%xmm4, 3*16(%[outbuf])\n\t"
1924
1925              "movdqu %%xmm8, 4*16(%[outbuf])\n\t"
1926              "movdqu %%xmm9, 5*16(%[outbuf])\n\t"
1927              "movdqu %%xmm10, 6*16(%[outbuf])\n\t"
1928              "movdqu %%xmm11, 7*16(%[outbuf])\n\t"
1929
1930              : /* No output */
1931              : [inbuf] "r" (inbuf),
1932                [outbuf] "r" (outbuf)
1933              : "memory");
1934
1935           outbuf += 8*BLOCKSIZE;
1936           inbuf  += 8*BLOCKSIZE;
1937         }
1938
1939       aesni_cleanup_7_15();
1940     }
1941 #endif
1942
1943   for ( ;nblocks >= 4; nblocks -= 4)
1944     {
1945       asm volatile
1946         ("movdqu %%xmm6,         %%xmm1\n\t" /* load input blocks */
1947          "movdqu 0*16(%[inbuf]), %%xmm2\n\t"
1948          "movdqu 1*16(%[inbuf]), %%xmm3\n\t"
1949          "movdqu 2*16(%[inbuf]), %%xmm4\n\t"
1950
1951          "movdqu 3*16(%[inbuf]), %%xmm6\n\t" /* update IV */
1952          : /* No output */
1953          : [inbuf] "r" (inbuf)
1954          : "memory");
1955
1956       do_aesni_enc_vec4 (ctx);
1957
1958       asm volatile
1959         ("movdqu 0*16(%[inbuf]), %%xmm5\n\t"
1960          "pxor %%xmm5, %%xmm1\n\t"
1961          "movdqu %%xmm1, 0*16(%[outbuf])\n\t"
1962
1963          "movdqu 1*16(%[inbuf]), %%xmm5\n\t"
1964          "pxor %%xmm5, %%xmm2\n\t"
1965          "movdqu %%xmm2, 1*16(%[outbuf])\n\t"
1966
1967          "movdqu 2*16(%[inbuf]), %%xmm5\n\t"
1968          "pxor %%xmm5, %%xmm3\n\t"
1969          "movdqu %%xmm3, 2*16(%[outbuf])\n\t"
1970
1971          "movdqu 3*16(%[inbuf]), %%xmm5\n\t"
1972          "pxor %%xmm5, %%xmm4\n\t"
1973          "movdqu %%xmm4, 3*16(%[outbuf])\n\t"
1974
1975          : /* No output */
1976          : [inbuf] "r" (inbuf),
1977            [outbuf] "r" (outbuf)
1978          : "memory");
1979
1980       outbuf += 4*BLOCKSIZE;
1981       inbuf  += 4*BLOCKSIZE;
1982     }
1983
1984   asm volatile ("movdqu %%xmm6, %%xmm0\n\t" ::: "cc");
1985
1986   for ( ;nblocks; nblocks-- )
1987     {
1988       do_aesni_enc (ctx);
1989
1990       asm volatile ("movdqa %%xmm0, %%xmm6\n\t"
1991                     "movdqu %[inbuf], %%xmm0\n\t"
1992                     "pxor %%xmm0, %%xmm6\n\t"
1993                     "movdqu %%xmm6, %[outbuf]\n\t"
1994                     : [outbuf] "=m" (*outbuf)
1995                     : [inbuf] "m" (*inbuf)
1996                     : "memory" );
1997
1998       outbuf += BLOCKSIZE;
1999       inbuf  += BLOCKSIZE;
2000     }
2001
2002   asm volatile ("movdqu %%xmm0, %[iv]\n\t"
2003                 : [iv] "=m" (*iv)
2004                 :
2005                 : "memory" );
2006
2007   aesni_cleanup ();
2008   aesni_cleanup_2_6 ();
2009 }
2010
2011
2012 void
2013 _gcry_aes_aesni_cbc_dec (RIJNDAEL_context *ctx, unsigned char *iv,
2014                          unsigned char *outbuf, const unsigned char *inbuf,
2015                          size_t nblocks)
2016 {
2017   aesni_prepare_2_6_variable;
2018
2019   aesni_prepare ();
2020   aesni_prepare_2_6();
2021
2022   if ( !ctx->decryption_prepared )
2023     {
2024       do_aesni_prepare_decryption ( ctx );
2025       ctx->decryption_prepared = 1;
2026     }
2027
2028   asm volatile
2029     ("movdqu %[iv], %%xmm5\n\t" /* use xmm5 as fast IV storage */
2030      : /* No output */
2031      : [iv] "m" (*iv)
2032      : "memory");
2033
2034 #ifdef __x86_64__
2035   if (nblocks >= 8)
2036     {
2037       aesni_prepare_7_15_variable;
2038
2039       aesni_prepare_7_15();
2040
2041       for ( ;nblocks >= 8 ; nblocks -= 8 )
2042         {
2043           asm volatile
2044             ("movdqu 0*16(%[inbuf]), %%xmm1\n\t"        /* load input blocks */
2045              "movdqu 1*16(%[inbuf]), %%xmm2\n\t"
2046              "movdqu 2*16(%[inbuf]), %%xmm3\n\t"
2047              "movdqu 3*16(%[inbuf]), %%xmm4\n\t"
2048              "movdqu 4*16(%[inbuf]), %%xmm8\n\t"
2049              "movdqu 5*16(%[inbuf]), %%xmm9\n\t"
2050              "movdqu 6*16(%[inbuf]), %%xmm10\n\t"
2051              "movdqu 7*16(%[inbuf]), %%xmm11\n\t"
2052
2053              "movdqa %%xmm1, %%xmm12\n\t"
2054              "movdqa %%xmm2, %%xmm13\n\t"
2055              "movdqa %%xmm3, %%xmm14\n\t"
2056              "movdqa %%xmm4, %%xmm15\n\t"
2057
2058              : /* No output */
2059              : [inbuf] "r" (inbuf)
2060              : "memory");
2061
2062           do_aesni_dec_vec8 (ctx);
2063
2064           asm volatile
2065             ("pxor %%xmm5, %%xmm1\n\t"          /* xor IV with output */
2066
2067              "pxor %%xmm12, %%xmm2\n\t"         /* xor IV with output */
2068              "movdqu 4*16(%[inbuf]), %%xmm12\n\t"
2069
2070              "pxor %%xmm13, %%xmm3\n\t"         /* xor IV with output */
2071              "movdqu 5*16(%[inbuf]), %%xmm13\n\t"
2072
2073              "pxor %%xmm14, %%xmm4\n\t"         /* xor IV with output */
2074              "movdqu 6*16(%[inbuf]), %%xmm14\n\t"
2075
2076              "pxor %%xmm15, %%xmm8\n\t"         /* xor IV with output */
2077              "movdqu 7*16(%[inbuf]), %%xmm5\n\t"
2078              "pxor %%xmm12, %%xmm9\n\t"         /* xor IV with output */
2079              "movdqu %%xmm1, 0*16(%[outbuf])\n\t"
2080              "pxor %%xmm13, %%xmm10\n\t"                /* xor IV with output */
2081              "movdqu %%xmm2, 1*16(%[outbuf])\n\t"
2082              "pxor %%xmm14, %%xmm11\n\t"                /* xor IV with output */
2083              "movdqu %%xmm3, 2*16(%[outbuf])\n\t"
2084              "movdqu %%xmm4, 3*16(%[outbuf])\n\t"
2085              "movdqu %%xmm8, 4*16(%[outbuf])\n\t"
2086              "movdqu %%xmm9, 5*16(%[outbuf])\n\t"
2087              "movdqu %%xmm10, 6*16(%[outbuf])\n\t"
2088              "movdqu %%xmm11, 7*16(%[outbuf])\n\t"
2089
2090              : /* No output */
2091              : [inbuf] "r" (inbuf),
2092                [outbuf] "r" (outbuf)
2093              : "memory");
2094
2095           outbuf += 8*BLOCKSIZE;
2096           inbuf  += 8*BLOCKSIZE;
2097         }
2098
2099       aesni_cleanup_7_15();
2100     }
2101 #endif
2102
2103   for ( ;nblocks >= 4 ; nblocks -= 4 )
2104     {
2105       asm volatile
2106         ("movdqu 0*16(%[inbuf]), %%xmm1\n\t"    /* load input blocks */
2107          "movdqu 1*16(%[inbuf]), %%xmm2\n\t"
2108          "movdqu 2*16(%[inbuf]), %%xmm3\n\t"
2109          "movdqu 3*16(%[inbuf]), %%xmm4\n\t"
2110          : /* No output */
2111          : [inbuf] "r" (inbuf)
2112          : "memory");
2113
2114       do_aesni_dec_vec4 (ctx);
2115
2116       asm volatile
2117         ("pxor %%xmm5, %%xmm1\n\t"              /* xor IV with output */
2118          "movdqu 0*16(%[inbuf]), %%xmm5\n\t"    /* load new IV */
2119          "movdqu %%xmm1, 0*16(%[outbuf])\n\t"
2120
2121          "pxor %%xmm5, %%xmm2\n\t"              /* xor IV with output */
2122          "movdqu 1*16(%[inbuf]), %%xmm5\n\t"    /* load new IV */
2123          "movdqu %%xmm2, 1*16(%[outbuf])\n\t"
2124
2125          "pxor %%xmm5, %%xmm3\n\t"              /* xor IV with output */
2126          "movdqu 2*16(%[inbuf]), %%xmm5\n\t"    /* load new IV */
2127          "movdqu %%xmm3, 2*16(%[outbuf])\n\t"
2128
2129          "pxor %%xmm5, %%xmm4\n\t"              /* xor IV with output */
2130          "movdqu 3*16(%[inbuf]), %%xmm5\n\t"    /* load new IV */
2131          "movdqu %%xmm4, 3*16(%[outbuf])\n\t"
2132
2133          : /* No output */
2134          : [inbuf] "r" (inbuf),
2135            [outbuf] "r" (outbuf)
2136          : "memory");
2137
2138       outbuf += 4*BLOCKSIZE;
2139       inbuf  += 4*BLOCKSIZE;
2140     }
2141
2142   for ( ;nblocks; nblocks-- )
2143     {
2144       asm volatile
2145         ("movdqu %[inbuf], %%xmm0\n\t"
2146          "movdqa %%xmm0, %%xmm2\n\t"    /* use xmm2 as savebuf */
2147          : /* No output */
2148          : [inbuf] "m" (*inbuf)
2149          : "memory");
2150
2151       /* uses only xmm0 and xmm1 */
2152       do_aesni_dec (ctx);
2153
2154       asm volatile
2155         ("pxor %%xmm5, %%xmm0\n\t"      /* xor IV with output */
2156          "movdqu %%xmm0, %[outbuf]\n\t"
2157          "movdqu %%xmm2, %%xmm5\n\t"    /* store savebuf as new IV */
2158          : [outbuf] "=m" (*outbuf)
2159          :
2160          : "memory");
2161
2162       outbuf += BLOCKSIZE;
2163       inbuf  += BLOCKSIZE;
2164     }
2165
2166   asm volatile
2167     ("movdqu %%xmm5, %[iv]\n\t" /* store IV */
2168      : /* No output */
2169      : [iv] "m" (*iv)
2170      : "memory");
2171
2172   aesni_cleanup ();
2173   aesni_cleanup_2_6 ();
2174 }
2175
2176
2177 static void
2178 aesni_ocb_enc (gcry_cipher_hd_t c, void *outbuf_arg,
2179                const void *inbuf_arg, size_t nblocks)
2180 {
2181   RIJNDAEL_context *ctx = (void *)&c->context.c;
2182   unsigned char *outbuf = outbuf_arg;
2183   const unsigned char *inbuf = inbuf_arg;
2184   u64 n = c->u_mode.ocb.data_nblocks;
2185   const unsigned char *l;
2186   aesni_prepare_2_6_variable;
2187
2188   aesni_prepare ();
2189   aesni_prepare_2_6 ();
2190
2191   /* Preload Offset and Checksum */
2192   asm volatile ("movdqu %[iv], %%xmm5\n\t"
2193                 "movdqu %[ctr], %%xmm6\n\t"
2194                 : /* No output */
2195                 : [iv] "m" (*c->u_iv.iv),
2196                   [ctr] "m" (*c->u_ctr.ctr)
2197                 : "memory" );
2198
2199
2200   for ( ;nblocks && n % 4; nblocks-- )
2201     {
2202       l = ocb_get_l(c, ++n);
2203
2204       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
2205       /* Checksum_i = Checksum_{i-1} xor P_i  */
2206       /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
2207       asm volatile ("movdqu %[l],     %%xmm1\n\t"
2208                     "movdqu %[inbuf], %%xmm0\n\t"
2209                     "pxor   %%xmm1,   %%xmm5\n\t"
2210                     "pxor   %%xmm0,   %%xmm6\n\t"
2211                     "pxor   %%xmm5,   %%xmm0\n\t"
2212                     :
2213                     : [l] "m" (*l),
2214                       [inbuf] "m" (*inbuf)
2215                     : "memory" );
2216
2217       do_aesni_enc (ctx);
2218
2219       asm volatile ("pxor   %%xmm5, %%xmm0\n\t"
2220                     "movdqu %%xmm0, %[outbuf]\n\t"
2221                     : [outbuf] "=m" (*outbuf)
2222                     :
2223                     : "memory" );
2224
2225       inbuf += BLOCKSIZE;
2226       outbuf += BLOCKSIZE;
2227     }
2228
2229 #ifdef __x86_64__
2230   if (nblocks >= 8)
2231     {
2232       aesni_prepare_7_15_variable;
2233
2234       aesni_prepare_7_15();
2235
2236       asm volatile ("movdqu %[l0], %%xmm7\n\t"
2237                     :
2238                     : [l0] "m" (*c->u_mode.ocb.L[0])
2239                     : "memory" );
2240
2241       for ( ;nblocks >= 8 ; nblocks -= 8 )
2242         {
2243           n += 4;
2244           l = ocb_get_l(c, n);
2245
2246           /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
2247           /* Checksum_i = Checksum_{i-1} xor P_i  */
2248           /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
2249
2250           asm volatile ("movdqu %[l1],     %%xmm10\n\t"
2251                         "movdqu %[inbuf0], %%xmm1\n\t"
2252                         "pxor   %%xmm7,    %%xmm5\n\t"
2253                         "pxor   %%xmm1,    %%xmm6\n\t"
2254                         "pxor   %%xmm5,    %%xmm1\n\t"
2255                         "movdqa %%xmm5,    %%xmm12\n\t"
2256                         :
2257                         : [l1] "m" (*c->u_mode.ocb.L[1]),
2258                           [inbuf0] "m" (*(inbuf + 0 * BLOCKSIZE))
2259                         : "memory" );
2260           asm volatile ("movdqu %[inbuf1], %%xmm2\n\t"
2261                         "pxor   %%xmm10,   %%xmm5\n\t"
2262                         "pxor   %%xmm2,    %%xmm6\n\t"
2263                         "pxor   %%xmm5,    %%xmm2\n\t"
2264                         "movdqa %%xmm5,    %%xmm13\n\t"
2265                         :
2266                         : [inbuf1] "m" (*(inbuf + 1 * BLOCKSIZE))
2267                         : "memory" );
2268           asm volatile ("movdqu %[inbuf2], %%xmm3\n\t"
2269                         "pxor   %%xmm7,    %%xmm5\n\t"
2270                         "pxor   %%xmm3,    %%xmm6\n\t"
2271                         "pxor   %%xmm5,    %%xmm3\n\t"
2272                         "movdqa %%xmm5,    %%xmm14\n\t"
2273                         :
2274                         : [inbuf2] "m" (*(inbuf + 2 * BLOCKSIZE))
2275                         : "memory" );
2276           asm volatile ("movdqu %[l3],     %%xmm15\n\t"
2277                         "movdqu %[inbuf3], %%xmm4\n\t"
2278                         "pxor   %%xmm15,   %%xmm5\n\t"
2279                         "pxor   %%xmm4,    %%xmm6\n\t"
2280                         "pxor   %%xmm5,    %%xmm4\n\t"
2281                         "movdqa %%xmm5,    %%xmm15\n\t"
2282                         :
2283                         : [l3] "m" (*l),
2284                           [inbuf3] "m" (*(inbuf + 3 * BLOCKSIZE))
2285                         : "memory" );
2286
2287           n += 4;
2288           l = ocb_get_l(c, n);
2289
2290           asm volatile ("movdqu %[inbuf4], %%xmm8\n\t"
2291                         "pxor   %%xmm7,    %%xmm5\n\t"
2292                         "pxor   %%xmm8,    %%xmm6\n\t"
2293                         "pxor   %%xmm5,    %%xmm8\n\t"
2294                         "movdqu %%xmm5,    %[outbuf4]\n\t"
2295                         : [outbuf4] "=m" (*(outbuf + 4 * BLOCKSIZE))
2296                         : [inbuf4] "m" (*(inbuf + 4 * BLOCKSIZE))
2297                         : "memory" );
2298           asm volatile ("movdqu %[inbuf5], %%xmm9\n\t"
2299                         "pxor   %%xmm10,   %%xmm5\n\t"
2300                         "pxor   %%xmm9,    %%xmm6\n\t"
2301                         "pxor   %%xmm5,    %%xmm9\n\t"
2302                         "movdqu %%xmm5,    %[outbuf5]\n\t"
2303                         : [outbuf5] "=m" (*(outbuf + 5 * BLOCKSIZE))
2304                         : [inbuf5] "m" (*(inbuf + 5 * BLOCKSIZE))
2305                         : "memory" );
2306           asm volatile ("movdqu %[inbuf6], %%xmm10\n\t"
2307                         "pxor   %%xmm7,    %%xmm5\n\t"
2308                         "pxor   %%xmm10,   %%xmm6\n\t"
2309                         "pxor   %%xmm5,    %%xmm10\n\t"
2310                         "movdqu %%xmm5,    %[outbuf6]\n\t"
2311                         : [outbuf6] "=m" (*(outbuf + 6 * BLOCKSIZE))
2312                         : [inbuf6] "m" (*(inbuf + 6 * BLOCKSIZE))
2313                         : "memory" );
2314           asm volatile ("movdqu %[l7],     %%xmm11\n\t"
2315                         "pxor   %%xmm11,   %%xmm5\n\t"
2316                         "movdqu %[inbuf7], %%xmm11\n\t"
2317                         "pxor   %%xmm11,   %%xmm6\n\t"
2318                         "pxor   %%xmm5,    %%xmm11\n\t"
2319                         :
2320                         : [l7] "m" (*l),
2321                           [inbuf7] "m" (*(inbuf + 7 * BLOCKSIZE))
2322                         : "memory" );
2323
2324           do_aesni_enc_vec8 (ctx);
2325
2326           asm volatile ("pxor   %%xmm12,   %%xmm1\n\t"
2327                         "pxor   %%xmm13,   %%xmm2\n\t"
2328                         "movdqu %[outbuf4],%%xmm0\n\t"
2329                         "movdqu %[outbuf5],%%xmm12\n\t"
2330                         "movdqu %[outbuf6],%%xmm13\n\t"
2331                         "pxor   %%xmm14,   %%xmm3\n\t"
2332                         "pxor   %%xmm15,   %%xmm4\n\t"
2333                         "pxor   %%xmm0,    %%xmm8\n\t"
2334                         "pxor   %%xmm12,   %%xmm9\n\t"
2335                         "pxor   %%xmm13,   %%xmm10\n\t"
2336                         "pxor   %%xmm5,    %%xmm11\n\t"
2337                         "movdqu %%xmm1,    %[outbuf0]\n\t"
2338                         "movdqu %%xmm2,    %[outbuf1]\n\t"
2339                         "movdqu %%xmm3,    %[outbuf2]\n\t"
2340                         "movdqu %%xmm4,    %[outbuf3]\n\t"
2341                         "movdqu %%xmm8,    %[outbuf4]\n\t"
2342                         "movdqu %%xmm9,    %[outbuf5]\n\t"
2343                         "movdqu %%xmm10,   %[outbuf6]\n\t"
2344                         "movdqu %%xmm11,   %[outbuf7]\n\t"
2345                         : [outbuf0] "=m" (*(outbuf + 0 * BLOCKSIZE)),
2346                           [outbuf1] "=m" (*(outbuf + 1 * BLOCKSIZE)),
2347                           [outbuf2] "=m" (*(outbuf + 2 * BLOCKSIZE)),
2348                           [outbuf3] "=m" (*(outbuf + 3 * BLOCKSIZE)),
2349                           [outbuf4] "+m" (*(outbuf + 4 * BLOCKSIZE)),
2350                           [outbuf5] "+m" (*(outbuf + 5 * BLOCKSIZE)),
2351                           [outbuf6] "+m" (*(outbuf + 6 * BLOCKSIZE)),
2352                           [outbuf7] "=m" (*(outbuf + 7 * BLOCKSIZE))
2353                         :
2354                         : "memory" );
2355
2356           outbuf += 8*BLOCKSIZE;
2357           inbuf  += 8*BLOCKSIZE;
2358         }
2359
2360     aesni_cleanup_7_15();
2361   }
2362 #endif
2363
2364   for ( ;nblocks >= 4 ; nblocks -= 4 )
2365     {
2366       n += 4;
2367       l = ocb_get_l(c, n);
2368
2369       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
2370       /* Checksum_i = Checksum_{i-1} xor P_i  */
2371       /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
2372       asm volatile ("movdqu %[l0],     %%xmm4\n\t"
2373                     "movdqu %[inbuf0], %%xmm1\n\t"
2374                     "pxor   %%xmm4,    %%xmm5\n\t"
2375                     "pxor   %%xmm1,    %%xmm6\n\t"
2376                     "pxor   %%xmm5,    %%xmm1\n\t"
2377                     "movdqu %%xmm5,    %[outbuf0]\n\t"
2378                     : [outbuf0] "=m" (*(outbuf + 0 * BLOCKSIZE))
2379                     : [l0] "m" (*c->u_mode.ocb.L[0]),
2380                       [inbuf0] "m" (*(inbuf + 0 * BLOCKSIZE))
2381                     : "memory" );
2382       asm volatile ("movdqu %[l1],     %%xmm0\n\t"
2383                     "movdqu %[inbuf1], %%xmm2\n\t"
2384                     "pxor   %%xmm0,    %%xmm5\n\t"
2385                     "pxor   %%xmm2,    %%xmm6\n\t"
2386                     "pxor   %%xmm5,    %%xmm2\n\t"
2387                     "movdqu %%xmm5,    %[outbuf1]\n\t"
2388                     : [outbuf1] "=m" (*(outbuf + 1 * BLOCKSIZE))
2389                     : [l1] "m" (*c->u_mode.ocb.L[1]),
2390                       [inbuf1] "m" (*(inbuf + 1 * BLOCKSIZE))
2391                     : "memory" );
2392       asm volatile ("movdqu %[inbuf2], %%xmm3\n\t"
2393                     "pxor   %%xmm4,    %%xmm5\n\t"
2394                     "pxor   %%xmm3,    %%xmm6\n\t"
2395                     "pxor   %%xmm5,    %%xmm3\n\t"
2396                     "movdqu %%xmm5,    %[outbuf2]\n\t"
2397                     : [outbuf2] "=m" (*(outbuf + 2 * BLOCKSIZE))
2398                     : [inbuf2] "m" (*(inbuf + 2 * BLOCKSIZE))
2399                     : "memory" );
2400       asm volatile ("movdqu %[l3],     %%xmm4\n\t"
2401                     "pxor   %%xmm4,    %%xmm5\n\t"
2402                     "movdqu %[inbuf3], %%xmm4\n\t"
2403                     "pxor   %%xmm4,    %%xmm6\n\t"
2404                     "pxor   %%xmm5,    %%xmm4\n\t"
2405                     :
2406                     : [l3] "m" (*l),
2407                       [inbuf3] "m" (*(inbuf + 3 * BLOCKSIZE))
2408                     : "memory" );
2409
2410       do_aesni_enc_vec4 (ctx);
2411
2412       asm volatile ("movdqu %[outbuf0],%%xmm0\n\t"
2413                     "pxor   %%xmm0,    %%xmm1\n\t"
2414                     "movdqu %%xmm1,    %[outbuf0]\n\t"
2415                     "movdqu %[outbuf1],%%xmm0\n\t"
2416                     "pxor   %%xmm0,    %%xmm2\n\t"
2417                     "movdqu %%xmm2,    %[outbuf1]\n\t"
2418                     "movdqu %[outbuf2],%%xmm0\n\t"
2419                     "pxor   %%xmm0,    %%xmm3\n\t"
2420                     "movdqu %%xmm3,    %[outbuf2]\n\t"
2421                     "pxor   %%xmm5,    %%xmm4\n\t"
2422                     "movdqu %%xmm4,    %[outbuf3]\n\t"
2423                     : [outbuf0] "+m" (*(outbuf + 0 * BLOCKSIZE)),
2424                       [outbuf1] "+m" (*(outbuf + 1 * BLOCKSIZE)),
2425                       [outbuf2] "+m" (*(outbuf + 2 * BLOCKSIZE)),
2426                       [outbuf3] "=m" (*(outbuf + 3 * BLOCKSIZE))
2427                     :
2428                     : "memory" );
2429
2430       outbuf += 4*BLOCKSIZE;
2431       inbuf  += 4*BLOCKSIZE;
2432     }
2433
2434   for ( ;nblocks; nblocks-- )
2435     {
2436       l = ocb_get_l(c, ++n);
2437
2438       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
2439       /* Checksum_i = Checksum_{i-1} xor P_i  */
2440       /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
2441       asm volatile ("movdqu %[l],     %%xmm1\n\t"
2442                     "movdqu %[inbuf], %%xmm0\n\t"
2443                     "pxor   %%xmm1,   %%xmm5\n\t"
2444                     "pxor   %%xmm0,   %%xmm6\n\t"
2445                     "pxor   %%xmm5,   %%xmm0\n\t"
2446                     :
2447                     : [l] "m" (*l),
2448                       [inbuf] "m" (*inbuf)
2449                     : "memory" );
2450
2451       do_aesni_enc (ctx);
2452
2453       asm volatile ("pxor   %%xmm5, %%xmm0\n\t"
2454                     "movdqu %%xmm0, %[outbuf]\n\t"
2455                     : [outbuf] "=m" (*outbuf)
2456                     :
2457                     : "memory" );
2458
2459       inbuf += BLOCKSIZE;
2460       outbuf += BLOCKSIZE;
2461     }
2462
2463   c->u_mode.ocb.data_nblocks = n;
2464   asm volatile ("movdqu %%xmm5, %[iv]\n\t"
2465                 "movdqu %%xmm6, %[ctr]\n\t"
2466                 : [iv] "=m" (*c->u_iv.iv),
2467                   [ctr] "=m" (*c->u_ctr.ctr)
2468                 :
2469                 : "memory" );
2470
2471   aesni_cleanup ();
2472   aesni_cleanup_2_6 ();
2473 }
2474
2475
2476 static void
2477 aesni_ocb_dec (gcry_cipher_hd_t c, void *outbuf_arg,
2478                const void *inbuf_arg, size_t nblocks)
2479 {
2480   RIJNDAEL_context *ctx = (void *)&c->context.c;
2481   unsigned char *outbuf = outbuf_arg;
2482   const unsigned char *inbuf = inbuf_arg;
2483   u64 n = c->u_mode.ocb.data_nblocks;
2484   const unsigned char *l;
2485   aesni_prepare_2_6_variable;
2486
2487   aesni_prepare ();
2488   aesni_prepare_2_6 ();
2489
2490   if ( !ctx->decryption_prepared )
2491     {
2492       do_aesni_prepare_decryption ( ctx );
2493       ctx->decryption_prepared = 1;
2494     }
2495
2496   /* Preload Offset and Checksum */
2497   asm volatile ("movdqu %[iv], %%xmm5\n\t"
2498                 "movdqu %[ctr], %%xmm6\n\t"
2499                 : /* No output */
2500                 : [iv] "m" (*c->u_iv.iv),
2501                   [ctr] "m" (*c->u_ctr.ctr)
2502                 : "memory" );
2503
2504   for ( ;nblocks && n % 4; nblocks-- )
2505     {
2506       l = ocb_get_l(c, ++n);
2507
2508       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
2509       /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i)  */
2510       /* Checksum_i = Checksum_{i-1} xor P_i  */
2511       asm volatile ("movdqu %[l],     %%xmm1\n\t"
2512                     "movdqu %[inbuf], %%xmm0\n\t"
2513                     "pxor   %%xmm1,   %%xmm5\n\t"
2514                     "pxor   %%xmm5,   %%xmm0\n\t"
2515                     :
2516                     : [l] "m" (*l),
2517                       [inbuf] "m" (*inbuf)
2518                     : "memory" );
2519
2520       do_aesni_dec (ctx);
2521
2522       asm volatile ("pxor   %%xmm5, %%xmm0\n\t"
2523                     "pxor   %%xmm0, %%xmm6\n\t"
2524                     "movdqu %%xmm0, %[outbuf]\n\t"
2525                     : [outbuf] "=m" (*outbuf)
2526                     :
2527                     : "memory" );
2528
2529       inbuf += BLOCKSIZE;
2530       outbuf += BLOCKSIZE;
2531     }
2532
2533 #ifdef __x86_64__
2534   if (nblocks >= 8)
2535     {
2536       aesni_prepare_7_15_variable;
2537
2538       aesni_prepare_7_15();
2539
2540       asm volatile ("movdqu %[l0], %%xmm7\n\t"
2541                     :
2542                     : [l0] "m" (*c->u_mode.ocb.L[0])
2543                     : "memory" );
2544
2545       for ( ;nblocks >= 8 ; nblocks -= 8 )
2546         {
2547           n += 4;
2548           l = ocb_get_l(c, n);
2549
2550           /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
2551           /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i)  */
2552           /* Checksum_i = Checksum_{i-1} xor P_i  */
2553
2554           asm volatile ("movdqu %[l1],     %%xmm10\n\t"
2555                         "movdqu %[inbuf0], %%xmm1\n\t"
2556                         "pxor   %%xmm7,    %%xmm5\n\t"
2557                         "pxor   %%xmm5,    %%xmm1\n\t"
2558                         "movdqa %%xmm5,    %%xmm12\n\t"
2559                         :
2560                         : [l1] "m" (*c->u_mode.ocb.L[1]),
2561                           [inbuf0] "m" (*(inbuf + 0 * BLOCKSIZE))
2562                         : "memory" );
2563           asm volatile ("movdqu %[inbuf1], %%xmm2\n\t"
2564                         "pxor   %%xmm10,   %%xmm5\n\t"
2565                         "pxor   %%xmm5,    %%xmm2\n\t"
2566                         "movdqa %%xmm5,    %%xmm13\n\t"
2567                         :
2568                         : [inbuf1] "m" (*(inbuf + 1 * BLOCKSIZE))
2569                         : "memory" );
2570           asm volatile ("movdqu %[inbuf2], %%xmm3\n\t"
2571                         "pxor   %%xmm7,    %%xmm5\n\t"
2572                         "pxor   %%xmm5,    %%xmm3\n\t"
2573                         "movdqa %%xmm5,    %%xmm14\n\t"
2574                         :
2575                         : [inbuf2] "m" (*(inbuf + 2 * BLOCKSIZE))
2576                         : "memory" );
2577           asm volatile ("movdqu %[l3],     %%xmm0\n\t"
2578                         "movdqu %[inbuf3], %%xmm4\n\t"
2579                         "pxor   %%xmm0,    %%xmm5\n\t"
2580                         "pxor   %%xmm5,    %%xmm4\n\t"
2581                         "movdqa %%xmm5,    %%xmm15\n\t"
2582                         :
2583                         : [l3] "m" (*l),
2584                           [inbuf3] "m" (*(inbuf + 3 * BLOCKSIZE))
2585                         : "memory" );
2586
2587           n += 4;
2588           l = ocb_get_l(c, n);
2589
2590           asm volatile ("movdqu %[inbuf4], %%xmm8\n\t"
2591                         "pxor   %%xmm7,    %%xmm5\n\t"
2592                         "pxor   %%xmm5,    %%xmm8\n\t"
2593                         "movdqu %%xmm5,    %[outbuf4]\n\t"
2594                         : [outbuf4] "=m" (*(outbuf + 4 * BLOCKSIZE))
2595                         : [inbuf4] "m" (*(inbuf + 4 * BLOCKSIZE))
2596                         : "memory" );
2597           asm volatile ("movdqu %[inbuf5], %%xmm9\n\t"
2598                         "pxor   %%xmm10,   %%xmm5\n\t"
2599                         "pxor   %%xmm5,    %%xmm9\n\t"
2600                         "movdqu %%xmm5,    %[outbuf5]\n\t"
2601                         : [outbuf5] "=m" (*(outbuf + 5 * BLOCKSIZE))
2602                         : [inbuf5] "m" (*(inbuf + 5 * BLOCKSIZE))
2603                         : "memory" );
2604           asm volatile ("movdqu %[inbuf6], %%xmm10\n\t"
2605                         "pxor   %%xmm7,    %%xmm5\n\t"
2606                         "pxor   %%xmm5,    %%xmm10\n\t"
2607                         "movdqu %%xmm5,    %[outbuf6]\n\t"
2608                         : [outbuf6] "=m" (*(outbuf + 6 * BLOCKSIZE))
2609                         : [inbuf6] "m" (*(inbuf + 6 * BLOCKSIZE))
2610                         : "memory" );
2611           asm volatile ("movdqu %[l7],     %%xmm0\n\t"
2612                         "movdqu %[inbuf7], %%xmm11\n\t"
2613                         "pxor   %%xmm0,    %%xmm5\n\t"
2614                         "pxor   %%xmm5,    %%xmm11\n\t"
2615                         :
2616                         : [l7] "m" (*l),
2617                           [inbuf7] "m" (*(inbuf + 7 * BLOCKSIZE))
2618                         : "memory" );
2619
2620           do_aesni_dec_vec8 (ctx);
2621
2622           asm volatile ("pxor   %%xmm12,   %%xmm1\n\t"
2623                         "pxor   %%xmm13,   %%xmm2\n\t"
2624                         "movdqu %[outbuf4],%%xmm0\n\t"
2625                         "movdqu %[outbuf5],%%xmm12\n\t"
2626                         "movdqu %[outbuf6],%%xmm13\n\t"
2627                         "pxor   %%xmm14,   %%xmm3\n\t"
2628                         "pxor   %%xmm15,   %%xmm4\n\t"
2629                         "pxor   %%xmm0,    %%xmm8\n\t"
2630                         "pxor   %%xmm12,   %%xmm9\n\t"
2631                         "pxor   %%xmm13,   %%xmm10\n\t"
2632                         "pxor   %%xmm5,    %%xmm11\n\t"
2633                         "movdqu %%xmm1,    %[outbuf0]\n\t"
2634                         "movdqu %%xmm2,    %[outbuf1]\n\t"
2635                         "movdqu %%xmm3,    %[outbuf2]\n\t"
2636                         "movdqu %%xmm4,    %[outbuf3]\n\t"
2637                         "movdqu %%xmm8,    %[outbuf4]\n\t"
2638                         "movdqu %%xmm9,    %[outbuf5]\n\t"
2639                         "movdqu %%xmm10,   %[outbuf6]\n\t"
2640                         "movdqu %%xmm11,   %[outbuf7]\n\t"
2641                         "pxor   %%xmm2,    %%xmm1\n\t"
2642                         "pxor   %%xmm4,    %%xmm1\n\t"
2643                         "pxor   %%xmm9,    %%xmm1\n\t"
2644                         "pxor   %%xmm11,   %%xmm1\n\t"
2645                         "pxor   %%xmm3,    %%xmm6\n\t"
2646                         "pxor   %%xmm8,    %%xmm6\n\t"
2647                         "pxor   %%xmm10,   %%xmm6\n\t"
2648                         "pxor   %%xmm1,    %%xmm6\n\t"
2649                         : [outbuf0] "=m" (*(outbuf + 0 * BLOCKSIZE)),
2650                           [outbuf1] "=m" (*(outbuf + 1 * BLOCKSIZE)),
2651                           [outbuf2] "=m" (*(outbuf + 2 * BLOCKSIZE)),
2652                           [outbuf3] "=m" (*(outbuf + 3 * BLOCKSIZE)),
2653                           [outbuf4] "+m" (*(outbuf + 4 * BLOCKSIZE)),
2654                           [outbuf5] "+m" (*(outbuf + 5 * BLOCKSIZE)),
2655                           [outbuf6] "+m" (*(outbuf + 6 * BLOCKSIZE)),
2656                           [outbuf7] "=m" (*(outbuf + 7 * BLOCKSIZE))
2657                         :
2658                         : "memory" );
2659
2660           outbuf += 8*BLOCKSIZE;
2661           inbuf  += 8*BLOCKSIZE;
2662         }
2663
2664       aesni_cleanup_7_15();
2665     }
2666 #endif
2667
2668   for ( ;nblocks >= 4 ; nblocks -= 4 )
2669     {
2670       n += 4;
2671       l = ocb_get_l(c, n);
2672
2673       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
2674       /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i)  */
2675       /* Checksum_i = Checksum_{i-1} xor P_i  */
2676       asm volatile ("movdqu %[l0],     %%xmm4\n\t"
2677                     "movdqu %[inbuf0], %%xmm1\n\t"
2678                     "pxor   %%xmm4,    %%xmm5\n\t"
2679                     "pxor   %%xmm5,    %%xmm1\n\t"
2680                     "movdqu %%xmm5,    %[outbuf0]\n\t"
2681                     : [outbuf0] "=m" (*(outbuf + 0 * BLOCKSIZE))
2682                     : [l0] "m" (*c->u_mode.ocb.L[0]),
2683                       [inbuf0] "m" (*(inbuf + 0 * BLOCKSIZE))
2684                     : "memory" );
2685       asm volatile ("movdqu %[l1],     %%xmm0\n\t"
2686                     "movdqu %[inbuf1], %%xmm2\n\t"
2687                     "pxor   %%xmm0,    %%xmm5\n\t"
2688                     "pxor   %%xmm5,    %%xmm2\n\t"
2689                     "movdqu %%xmm5,    %[outbuf1]\n\t"
2690                     : [outbuf1] "=m" (*(outbuf + 1 * BLOCKSIZE))
2691                     : [l1] "m" (*c->u_mode.ocb.L[1]),
2692                       [inbuf1] "m" (*(inbuf + 1 * BLOCKSIZE))
2693                     : "memory" );
2694       asm volatile ("movdqu %[inbuf2], %%xmm3\n\t"
2695                     "pxor   %%xmm4,    %%xmm5\n\t"
2696                     "pxor   %%xmm5,    %%xmm3\n\t"
2697                     "movdqu %%xmm5,    %[outbuf2]\n\t"
2698                     : [outbuf2] "=m" (*(outbuf + 2 * BLOCKSIZE))
2699                     : [inbuf2] "m" (*(inbuf + 2 * BLOCKSIZE))
2700                     : "memory" );
2701       asm volatile ("movdqu %[l3],     %%xmm0\n\t"
2702                     "movdqu %[inbuf3], %%xmm4\n\t"
2703                     "pxor   %%xmm0,    %%xmm5\n\t"
2704                     "pxor   %%xmm5,    %%xmm4\n\t"
2705                     :
2706                     : [l3] "m" (*l),
2707                       [inbuf3] "m" (*(inbuf + 3 * BLOCKSIZE))
2708                     : "memory" );
2709
2710       do_aesni_dec_vec4 (ctx);
2711
2712       asm volatile ("movdqu %[outbuf0],%%xmm0\n\t"
2713                     "pxor   %%xmm0,    %%xmm1\n\t"
2714                     "movdqu %%xmm1,    %[outbuf0]\n\t"
2715                     "movdqu %[outbuf1],%%xmm0\n\t"
2716                     "pxor   %%xmm0,    %%xmm2\n\t"
2717                     "movdqu %%xmm2,    %[outbuf1]\n\t"
2718                     "movdqu %[outbuf2],%%xmm0\n\t"
2719                     "pxor   %%xmm0,    %%xmm3\n\t"
2720                     "movdqu %%xmm3,    %[outbuf2]\n\t"
2721                     "pxor   %%xmm5,    %%xmm4\n\t"
2722                     "movdqu %%xmm4,    %[outbuf3]\n\t"
2723                     "pxor   %%xmm1,    %%xmm6\n\t"
2724                     "pxor   %%xmm2,    %%xmm6\n\t"
2725                     "pxor   %%xmm3,    %%xmm6\n\t"
2726                     "pxor   %%xmm4,    %%xmm6\n\t"
2727                     : [outbuf0] "+m" (*(outbuf + 0 * BLOCKSIZE)),
2728                       [outbuf1] "+m" (*(outbuf + 1 * BLOCKSIZE)),
2729                       [outbuf2] "+m" (*(outbuf + 2 * BLOCKSIZE)),
2730                       [outbuf3] "=m" (*(outbuf + 3 * BLOCKSIZE))
2731                     :
2732                     : "memory" );
2733
2734       outbuf += 4*BLOCKSIZE;
2735       inbuf  += 4*BLOCKSIZE;
2736     }
2737
2738   for ( ;nblocks; nblocks-- )
2739     {
2740       l = ocb_get_l(c, ++n);
2741
2742       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
2743       /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i)  */
2744       /* Checksum_i = Checksum_{i-1} xor P_i  */
2745       asm volatile ("movdqu %[l],     %%xmm1\n\t"
2746                     "movdqu %[inbuf], %%xmm0\n\t"
2747                     "pxor   %%xmm1,   %%xmm5\n\t"
2748                     "pxor   %%xmm5,   %%xmm0\n\t"
2749                     :
2750                     : [l] "m" (*l),
2751                       [inbuf] "m" (*inbuf)
2752                     : "memory" );
2753
2754       do_aesni_dec (ctx);
2755
2756       asm volatile ("pxor   %%xmm5, %%xmm0\n\t"
2757                     "pxor   %%xmm0, %%xmm6\n\t"
2758                     "movdqu %%xmm0, %[outbuf]\n\t"
2759                     : [outbuf] "=m" (*outbuf)
2760                     :
2761                     : "memory" );
2762
2763       inbuf += BLOCKSIZE;
2764       outbuf += BLOCKSIZE;
2765     }
2766
2767   c->u_mode.ocb.data_nblocks = n;
2768   asm volatile ("movdqu %%xmm5, %[iv]\n\t"
2769                 "movdqu %%xmm6, %[ctr]\n\t"
2770                 : [iv] "=m" (*c->u_iv.iv),
2771                   [ctr] "=m" (*c->u_ctr.ctr)
2772                 :
2773                 : "memory" );
2774
2775   aesni_cleanup ();
2776   aesni_cleanup_2_6 ();
2777 }
2778
2779
2780 size_t
2781 _gcry_aes_aesni_ocb_crypt(gcry_cipher_hd_t c, void *outbuf_arg,
2782                           const void *inbuf_arg, size_t nblocks, int encrypt)
2783 {
2784   if (encrypt)
2785     aesni_ocb_enc(c, outbuf_arg, inbuf_arg, nblocks);
2786   else
2787     aesni_ocb_dec(c, outbuf_arg, inbuf_arg, nblocks);
2788
2789   return 0;
2790 }
2791
2792
2793 size_t
2794 _gcry_aes_aesni_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
2795                           size_t nblocks)
2796 {
2797   RIJNDAEL_context *ctx = (void *)&c->context.c;
2798   const unsigned char *abuf = abuf_arg;
2799   u64 n = c->u_mode.ocb.aad_nblocks;
2800   const unsigned char *l;
2801   aesni_prepare_2_6_variable;
2802
2803   aesni_prepare ();
2804   aesni_prepare_2_6 ();
2805
2806   /* Preload Offset and Sum */
2807   asm volatile ("movdqu %[iv], %%xmm5\n\t"
2808                 "movdqu %[ctr], %%xmm6\n\t"
2809                 : /* No output */
2810                 : [iv] "m" (*c->u_mode.ocb.aad_offset),
2811                   [ctr] "m" (*c->u_mode.ocb.aad_sum)
2812                 : "memory" );
2813
2814   for ( ;nblocks && n % 4; nblocks-- )
2815     {
2816       l = ocb_get_l(c, ++n);
2817
2818       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
2819       /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i)  */
2820       asm volatile ("movdqu %[l],     %%xmm1\n\t"
2821                     "movdqu %[abuf],  %%xmm0\n\t"
2822                     "pxor   %%xmm1,   %%xmm5\n\t"
2823                     "pxor   %%xmm5,   %%xmm0\n\t"
2824                     :
2825                     : [l] "m" (*l),
2826                       [abuf] "m" (*abuf)
2827                     : "memory" );
2828
2829       do_aesni_enc (ctx);
2830
2831       asm volatile ("pxor   %%xmm0,   %%xmm6\n\t"
2832                     :
2833                     :
2834                     : "memory" );
2835
2836       abuf += BLOCKSIZE;
2837     }
2838
2839 #ifdef __x86_64__
2840   if (nblocks >= 8)
2841     {
2842       aesni_prepare_7_15_variable;
2843
2844       aesni_prepare_7_15();
2845
2846       asm volatile ("movdqu %[l0], %%xmm7\n\t"
2847                     "movdqu %[l1], %%xmm12\n\t"
2848                     :
2849                     : [l0] "m" (*c->u_mode.ocb.L[0]),
2850                       [l1] "m" (*c->u_mode.ocb.L[1])
2851                     : "memory" );
2852
2853       for ( ;nblocks >= 8 ; nblocks -= 8 )
2854         {
2855           n += 4;
2856           l = ocb_get_l(c, n);
2857
2858           /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
2859           /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i)  */
2860           asm volatile ("movdqu %[abuf0],  %%xmm1\n\t"
2861                         "pxor   %%xmm7,    %%xmm5\n\t"
2862                         "pxor   %%xmm5,    %%xmm1\n\t"
2863                         :
2864                         : [abuf0] "m" (*(abuf + 0 * BLOCKSIZE))
2865                         : "memory" );
2866           asm volatile ("movdqu %[abuf1],  %%xmm2\n\t"
2867                         "pxor   %%xmm12,   %%xmm5\n\t"
2868                         "pxor   %%xmm5,    %%xmm2\n\t"
2869                         :
2870                         : [abuf1] "m" (*(abuf + 1 * BLOCKSIZE))
2871                         : "memory" );
2872           asm volatile ("movdqu %[abuf2],  %%xmm3\n\t"
2873                         "pxor   %%xmm7,    %%xmm5\n\t"
2874                         "pxor   %%xmm5,    %%xmm3\n\t"
2875                         :
2876                         : [abuf2] "m" (*(abuf + 2 * BLOCKSIZE))
2877                         : "memory" );
2878           asm volatile ("movdqu %[l3],     %%xmm0\n\t"
2879                         "movdqu %[abuf3],  %%xmm4\n\t"
2880                         "pxor   %%xmm0,    %%xmm5\n\t"
2881                         "pxor   %%xmm5,    %%xmm4\n\t"
2882                         :
2883                         : [l3] "m" (*l),
2884                           [abuf3] "m" (*(abuf + 3 * BLOCKSIZE))
2885                         : "memory" );
2886
2887           n += 4;
2888           l = ocb_get_l(c, n);
2889
2890           asm volatile ("movdqu %[abuf4],  %%xmm8\n\t"
2891                         "pxor   %%xmm7,    %%xmm5\n\t"
2892                         "pxor   %%xmm5,    %%xmm8\n\t"
2893                         :
2894                         : [abuf4] "m" (*(abuf + 4 * BLOCKSIZE))
2895                         : "memory" );
2896           asm volatile ("movdqu %[abuf5],  %%xmm9\n\t"
2897                         "pxor   %%xmm12,   %%xmm5\n\t"
2898                         "pxor   %%xmm5,    %%xmm9\n\t"
2899                         :
2900                         : [abuf5] "m" (*(abuf + 5 * BLOCKSIZE))
2901                         : "memory" );
2902           asm volatile ("movdqu %[abuf6],  %%xmm10\n\t"
2903                         "pxor   %%xmm7,    %%xmm5\n\t"
2904                         "pxor   %%xmm5,    %%xmm10\n\t"
2905                         :
2906                         : [abuf6] "m" (*(abuf + 6 * BLOCKSIZE))
2907                         : "memory" );
2908           asm volatile ("movdqu %[l7],     %%xmm0\n\t"
2909                         "movdqu %[abuf7],  %%xmm11\n\t"
2910                         "pxor   %%xmm0,    %%xmm5\n\t"
2911                         "pxor   %%xmm5,    %%xmm11\n\t"
2912                         :
2913                         : [l7] "m" (*l),
2914                           [abuf7] "m" (*(abuf + 7 * BLOCKSIZE))
2915                         : "memory" );
2916
2917           do_aesni_enc_vec8 (ctx);
2918
2919           asm volatile ("pxor   %%xmm2,   %%xmm1\n\t"
2920                         "pxor   %%xmm3,   %%xmm1\n\t"
2921                         "pxor   %%xmm4,   %%xmm1\n\t"
2922                         "pxor   %%xmm8,   %%xmm1\n\t"
2923                         "pxor   %%xmm9,   %%xmm6\n\t"
2924                         "pxor   %%xmm10,  %%xmm6\n\t"
2925                         "pxor   %%xmm11,  %%xmm6\n\t"
2926                         "pxor   %%xmm1,   %%xmm6\n\t"
2927                         :
2928                         :
2929                         : "memory" );
2930
2931           abuf += 8*BLOCKSIZE;
2932         }
2933
2934       aesni_cleanup_7_15();
2935     }
2936 #endif
2937
2938   for ( ;nblocks >= 4 ; nblocks -= 4 )
2939     {
2940       n += 4;
2941       l = ocb_get_l(c, n);
2942
2943       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
2944       /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i)  */
2945       asm volatile ("movdqu %[l0],     %%xmm4\n\t"
2946                     "movdqu %[abuf0],  %%xmm1\n\t"
2947                     "pxor   %%xmm4,    %%xmm5\n\t"
2948                     "pxor   %%xmm5,    %%xmm1\n\t"
2949                     :
2950                     : [l0] "m" (*c->u_mode.ocb.L[0]),
2951                       [abuf0] "m" (*(abuf + 0 * BLOCKSIZE))
2952                     : "memory" );
2953       asm volatile ("movdqu %[l1],     %%xmm0\n\t"
2954                     "movdqu %[abuf1],  %%xmm2\n\t"
2955                     "pxor   %%xmm0,    %%xmm5\n\t"
2956                     "pxor   %%xmm5,    %%xmm2\n\t"
2957                     :
2958                     : [l1] "m" (*c->u_mode.ocb.L[1]),
2959                       [abuf1] "m" (*(abuf + 1 * BLOCKSIZE))
2960                     : "memory" );
2961       asm volatile ("movdqu %[abuf2],  %%xmm3\n\t"
2962                     "pxor   %%xmm4,    %%xmm5\n\t"
2963                     "pxor   %%xmm5,    %%xmm3\n\t"
2964                     :
2965                     : [l2] "m" (*c->u_mode.ocb.L[0]),
2966                       [abuf2] "m" (*(abuf + 2 * BLOCKSIZE))
2967                     : "memory" );
2968       asm volatile ("movdqu %[l3],     %%xmm0\n\t"
2969                     "movdqu %[abuf3],  %%xmm4\n\t"
2970                     "pxor   %%xmm0,    %%xmm5\n\t"
2971                     "pxor   %%xmm5,    %%xmm4\n\t"
2972                     :
2973                     : [l3] "m" (*l),
2974                       [abuf3] "m" (*(abuf + 3 * BLOCKSIZE))
2975                     : "memory" );
2976
2977       do_aesni_enc_vec4 (ctx);
2978
2979       asm volatile ("pxor   %%xmm1,   %%xmm6\n\t"
2980                     "pxor   %%xmm2,   %%xmm6\n\t"
2981                     "pxor   %%xmm3,   %%xmm6\n\t"
2982                     "pxor   %%xmm4,   %%xmm6\n\t"
2983                     :
2984                     :
2985                     : "memory" );
2986
2987       abuf += 4*BLOCKSIZE;
2988     }
2989
2990   for ( ;nblocks; nblocks-- )
2991     {
2992       l = ocb_get_l(c, ++n);
2993
2994       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
2995       /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i)  */
2996       asm volatile ("movdqu %[l],     %%xmm1\n\t"
2997                     "movdqu %[abuf],  %%xmm0\n\t"
2998                     "pxor   %%xmm1,   %%xmm5\n\t"
2999                     "pxor   %%xmm5,   %%xmm0\n\t"
3000                     :
3001                     : [l] "m" (*l),
3002                       [abuf] "m" (*abuf)
3003                     : "memory" );
3004
3005       do_aesni_enc (ctx);
3006
3007       asm volatile ("pxor   %%xmm0,   %%xmm6\n\t"
3008                     :
3009                     :
3010                     : "memory" );
3011
3012       abuf += BLOCKSIZE;
3013     }
3014
3015   c->u_mode.ocb.aad_nblocks = n;
3016   asm volatile ("movdqu %%xmm5, %[iv]\n\t"
3017                 "movdqu %%xmm6, %[ctr]\n\t"
3018                 : [iv] "=m" (*c->u_mode.ocb.aad_offset),
3019                   [ctr] "=m" (*c->u_mode.ocb.aad_sum)
3020                 :
3021                 : "memory" );
3022
3023   aesni_cleanup ();
3024   aesni_cleanup_2_6 ();
3025
3026   return 0;
3027 }
3028
3029
3030 static const u64 xts_gfmul_const[16] __attribute__ ((aligned (16))) =
3031   { 0x87, 0x01 };
3032
3033
3034 static void
3035 _gcry_aes_aesni_xts_enc (RIJNDAEL_context *ctx, unsigned char *tweak,
3036                          unsigned char *outbuf, const unsigned char *inbuf,
3037                          size_t nblocks)
3038 {
3039   aesni_prepare_2_6_variable;
3040
3041   aesni_prepare ();
3042   aesni_prepare_2_6 ();
3043
3044   /* Preload Tweak */
3045   asm volatile ("movdqu %[tweak], %%xmm5\n\t"
3046                 "movdqa %[gfmul], %%xmm6\n\t"
3047                 :
3048                 : [tweak] "m" (*tweak),
3049                   [gfmul] "m" (*xts_gfmul_const)
3050                 : "memory" );
3051
3052   for ( ;nblocks >= 4; nblocks -= 4 )
3053     {
3054       asm volatile ("pshufd $0x13,     %%xmm5,  %%xmm4\n\t"
3055                     "movdqu %[inbuf0], %%xmm1\n\t"
3056                     "pxor   %%xmm5,    %%xmm1\n\t"
3057                     "movdqu %%xmm5,    %[outbuf0]\n\t"
3058
3059                     "movdqa %%xmm4,    %%xmm0\n\t"
3060                     "paddd  %%xmm4,    %%xmm4\n\t"
3061                     "psrad  $31,       %%xmm0\n\t"
3062                     "paddq  %%xmm5,    %%xmm5\n\t"
3063                     "pand   %%xmm6,    %%xmm0\n\t"
3064                     "pxor   %%xmm0,    %%xmm5\n\t"
3065                     : [outbuf0] "=m" (*(outbuf + 0 * 16))
3066                     : [inbuf0] "m" (*(inbuf + 0 * 16))
3067                     : "memory" );
3068
3069       asm volatile ("movdqu %[inbuf1], %%xmm2\n\t"
3070                     "pxor   %%xmm5,    %%xmm2\n\t"
3071                     "movdqu %%xmm5,    %[outbuf1]\n\t"
3072
3073                     "movdqa %%xmm4,    %%xmm0\n\t"
3074                     "paddd  %%xmm4,    %%xmm4\n\t"
3075                     "psrad  $31,       %%xmm0\n\t"
3076                     "paddq  %%xmm5,    %%xmm5\n\t"
3077                     "pand   %%xmm6,    %%xmm0\n\t"
3078                     "pxor   %%xmm0,    %%xmm5\n\t"
3079                     : [outbuf1] "=m" (*(outbuf + 1 * 16))
3080                     : [inbuf1] "m" (*(inbuf + 1 * 16))
3081                     : "memory" );
3082
3083       asm volatile ("movdqu %[inbuf2], %%xmm3\n\t"
3084                     "pxor   %%xmm5,    %%xmm3\n\t"
3085                     "movdqu %%xmm5,    %[outbuf2]\n\t"
3086
3087                     "movdqa %%xmm4,    %%xmm0\n\t"
3088                     "paddd  %%xmm4,    %%xmm4\n\t"
3089                     "psrad  $31,       %%xmm0\n\t"
3090                     "paddq  %%xmm5,    %%xmm5\n\t"
3091                     "pand   %%xmm6,    %%xmm0\n\t"
3092                     "pxor   %%xmm0,    %%xmm5\n\t"
3093                     : [outbuf2] "=m" (*(outbuf + 2 * 16))
3094                     : [inbuf2] "m" (*(inbuf + 2 * 16))
3095                     : "memory" );
3096
3097       asm volatile ("movdqa %%xmm4,    %%xmm0\n\t"
3098                     "movdqu %[inbuf3], %%xmm4\n\t"
3099                     "pxor   %%xmm5,    %%xmm4\n\t"
3100                     "movdqu %%xmm5,    %[outbuf3]\n\t"
3101
3102                     "psrad  $31,       %%xmm0\n\t"
3103                     "paddq  %%xmm5,    %%xmm5\n\t"
3104                     "pand   %%xmm6,    %%xmm0\n\t"
3105                     "pxor   %%xmm0,    %%xmm5\n\t"
3106                     : [outbuf3] "=m" (*(outbuf + 3 * 16))
3107                     : [inbuf3] "m" (*(inbuf + 3 * 16))
3108                     : "memory" );
3109
3110       do_aesni_enc_vec4 (ctx);
3111
3112       asm volatile ("movdqu %[outbuf0], %%xmm0\n\t"
3113                     "pxor   %%xmm0,     %%xmm1\n\t"
3114                     "movdqu %[outbuf1], %%xmm0\n\t"
3115                     "movdqu %%xmm1,     %[outbuf0]\n\t"
3116                     "movdqu %[outbuf2], %%xmm1\n\t"
3117                     "pxor   %%xmm0,     %%xmm2\n\t"
3118                     "movdqu %[outbuf3], %%xmm0\n\t"
3119                     "pxor   %%xmm1,     %%xmm3\n\t"
3120                     "pxor   %%xmm0,     %%xmm4\n\t"
3121                     "movdqu %%xmm2,     %[outbuf1]\n\t"
3122                     "movdqu %%xmm3,     %[outbuf2]\n\t"
3123                     "movdqu %%xmm4,     %[outbuf3]\n\t"
3124                     : [outbuf0] "+m" (*(outbuf + 0 * 16)),
3125                       [outbuf1] "+m" (*(outbuf + 1 * 16)),
3126                       [outbuf2] "+m" (*(outbuf + 2 * 16)),
3127                       [outbuf3] "+m" (*(outbuf + 3 * 16))
3128                     :
3129                     : "memory" );
3130
3131       outbuf += BLOCKSIZE * 4;
3132       inbuf += BLOCKSIZE * 4;
3133     }
3134
3135   for ( ;nblocks; nblocks-- )
3136     {
3137       asm volatile ("movdqu %[inbuf],  %%xmm0\n\t"
3138                     "pxor   %%xmm5,    %%xmm0\n\t"
3139                     "movdqa %%xmm5,    %%xmm4\n\t"
3140
3141                     "pshufd $0x13,     %%xmm5,  %%xmm1\n\t"
3142                     "psrad  $31,       %%xmm1\n\t"
3143                     "paddq  %%xmm5,    %%xmm5\n\t"
3144                     "pand   %%xmm6,    %%xmm1\n\t"
3145                     "pxor   %%xmm1,    %%xmm5\n\t"
3146                     :
3147                     : [inbuf] "m" (*inbuf)
3148                     : "memory" );
3149
3150       do_aesni_enc (ctx);
3151
3152       asm volatile ("pxor   %%xmm4,    %%xmm0\n\t"
3153                     "movdqu %%xmm0,    %[outbuf]\n\t"
3154                     : [outbuf] "=m" (*outbuf)
3155                     :
3156                     : "memory" );
3157
3158       outbuf += BLOCKSIZE;
3159       inbuf += BLOCKSIZE;
3160     }
3161
3162   asm volatile ("movdqu %%xmm5, %[tweak]\n\t"
3163                 : [tweak] "=m" (*tweak)
3164                 :
3165                 : "memory" );
3166
3167   aesni_cleanup ();
3168   aesni_cleanup_2_6 ();
3169 }
3170
3171
3172 static void
3173 _gcry_aes_aesni_xts_dec (RIJNDAEL_context *ctx, unsigned char *tweak,
3174                          unsigned char *outbuf, const unsigned char *inbuf,
3175                          size_t nblocks)
3176 {
3177   aesni_prepare_2_6_variable;
3178
3179   aesni_prepare ();
3180   aesni_prepare_2_6 ();
3181
3182   if ( !ctx->decryption_prepared )
3183     {
3184       do_aesni_prepare_decryption ( ctx );
3185       ctx->decryption_prepared = 1;
3186     }
3187
3188   /* Preload Tweak */
3189   asm volatile ("movdqu %[tweak], %%xmm5\n\t"
3190                 "movdqa %[gfmul], %%xmm6\n\t"
3191                 :
3192                 : [tweak] "m" (*tweak),
3193                   [gfmul] "m" (*xts_gfmul_const)
3194                 : "memory" );
3195
3196   for ( ;nblocks >= 4; nblocks -= 4 )
3197     {
3198       asm volatile ("pshufd $0x13,     %%xmm5,  %%xmm4\n\t"
3199                     "movdqu %[inbuf0], %%xmm1\n\t"
3200                     "pxor   %%xmm5,    %%xmm1\n\t"
3201                     "movdqu %%xmm5,    %[outbuf0]\n\t"
3202
3203                     "movdqa %%xmm4,    %%xmm0\n\t"
3204                     "paddd  %%xmm4,    %%xmm4\n\t"
3205                     "psrad  $31,       %%xmm0\n\t"
3206                     "paddq  %%xmm5,    %%xmm5\n\t"
3207                     "pand   %%xmm6,    %%xmm0\n\t"
3208                     "pxor   %%xmm0,    %%xmm5\n\t"
3209                     : [outbuf0] "=m" (*(outbuf + 0 * 16))
3210                     : [inbuf0] "m" (*(inbuf + 0 * 16))
3211                     : "memory" );
3212
3213       asm volatile ("movdqu %[inbuf1], %%xmm2\n\t"
3214                     "pxor   %%xmm5,    %%xmm2\n\t"
3215                     "movdqu %%xmm5,    %[outbuf1]\n\t"
3216
3217                     "movdqa %%xmm4,    %%xmm0\n\t"
3218                     "paddd  %%xmm4,    %%xmm4\n\t"
3219                     "psrad  $31,       %%xmm0\n\t"
3220                     "paddq  %%xmm5,    %%xmm5\n\t"
3221                     "pand   %%xmm6,    %%xmm0\n\t"
3222                     "pxor   %%xmm0,    %%xmm5\n\t"
3223                     : [outbuf1] "=m" (*(outbuf + 1 * 16))
3224                     : [inbuf1] "m" (*(inbuf + 1 * 16))
3225                     : "memory" );
3226
3227       asm volatile ("movdqu %[inbuf2], %%xmm3\n\t"
3228                     "pxor   %%xmm5,    %%xmm3\n\t"
3229                     "movdqu %%xmm5,    %[outbuf2]\n\t"
3230
3231                     "movdqa %%xmm4,    %%xmm0\n\t"
3232                     "paddd  %%xmm4,    %%xmm4\n\t"
3233                     "psrad  $31,       %%xmm0\n\t"
3234                     "paddq  %%xmm5,    %%xmm5\n\t"
3235                     "pand   %%xmm6,    %%xmm0\n\t"
3236                     "pxor   %%xmm0,    %%xmm5\n\t"
3237                     : [outbuf2] "=m" (*(outbuf + 2 * 16))
3238                     : [inbuf2] "m" (*(inbuf + 2 * 16))
3239                     : "memory" );
3240
3241       asm volatile ("movdqa %%xmm4,    %%xmm0\n\t"
3242                     "movdqu %[inbuf3], %%xmm4\n\t"
3243                     "pxor   %%xmm5,    %%xmm4\n\t"
3244                     "movdqu %%xmm5,    %[outbuf3]\n\t"
3245
3246                     "psrad  $31,       %%xmm0\n\t"
3247                     "paddq  %%xmm5,    %%xmm5\n\t"
3248                     "pand   %%xmm6,    %%xmm0\n\t"
3249                     "pxor   %%xmm0,    %%xmm5\n\t"
3250                     : [outbuf3] "=m" (*(outbuf + 3 * 16))
3251                     : [inbuf3] "m" (*(inbuf + 3 * 16))
3252                     : "memory" );
3253
3254       do_aesni_dec_vec4 (ctx);
3255
3256       asm volatile ("movdqu %[outbuf0], %%xmm0\n\t"
3257                     "pxor   %%xmm0,     %%xmm1\n\t"
3258                     "movdqu %[outbuf1], %%xmm0\n\t"
3259                     "movdqu %%xmm1,     %[outbuf0]\n\t"
3260                     "movdqu %[outbuf2], %%xmm1\n\t"
3261                     "pxor   %%xmm0,     %%xmm2\n\t"
3262                     "movdqu %[outbuf3], %%xmm0\n\t"
3263                     "pxor   %%xmm1,     %%xmm3\n\t"
3264                     "pxor   %%xmm0,     %%xmm4\n\t"
3265                     "movdqu %%xmm2,     %[outbuf1]\n\t"
3266                     "movdqu %%xmm3,     %[outbuf2]\n\t"
3267                     "movdqu %%xmm4,     %[outbuf3]\n\t"
3268                     : [outbuf0] "+m" (*(outbuf + 0 * 16)),
3269                       [outbuf1] "+m" (*(outbuf + 1 * 16)),
3270                       [outbuf2] "+m" (*(outbuf + 2 * 16)),
3271                       [outbuf3] "+m" (*(outbuf + 3 * 16))
3272                     :
3273                     : "memory" );
3274
3275       outbuf += BLOCKSIZE * 4;
3276       inbuf += BLOCKSIZE * 4;
3277     }
3278
3279   for ( ;nblocks; nblocks-- )
3280     {
3281       asm volatile ("movdqu %[inbuf],  %%xmm0\n\t"
3282                     "pxor   %%xmm5,    %%xmm0\n\t"
3283                     "movdqa %%xmm5,    %%xmm4\n\t"
3284
3285                     "pshufd $0x13,     %%xmm5,  %%xmm1\n\t"
3286                     "psrad  $31,       %%xmm1\n\t"
3287                     "paddq  %%xmm5,    %%xmm5\n\t"
3288                     "pand   %%xmm6,    %%xmm1\n\t"
3289                     "pxor   %%xmm1,    %%xmm5\n\t"
3290                     :
3291                     : [inbuf] "m" (*inbuf)
3292                     : "memory" );
3293
3294       do_aesni_dec (ctx);
3295
3296       asm volatile ("pxor   %%xmm4,    %%xmm0\n\t"
3297                     "movdqu %%xmm0,    %[outbuf]\n\t"
3298                     : [outbuf] "=m" (*outbuf)
3299                     :
3300                     : "memory" );
3301
3302       outbuf += BLOCKSIZE;
3303       inbuf += BLOCKSIZE;
3304     }
3305
3306   asm volatile ("movdqu %%xmm5, %[tweak]\n\t"
3307                 : [tweak] "=m" (*tweak)
3308                 :
3309                 : "memory" );
3310
3311   aesni_cleanup ();
3312   aesni_cleanup_2_6 ();
3313 }
3314
3315
3316 void
3317 _gcry_aes_aesni_xts_crypt (RIJNDAEL_context *ctx, unsigned char *tweak,
3318                            unsigned char *outbuf, const unsigned char *inbuf,
3319                            size_t nblocks, int encrypt)
3320 {
3321   if (encrypt)
3322     _gcry_aes_aesni_xts_enc(ctx, tweak, outbuf, inbuf, nblocks);
3323   else
3324     _gcry_aes_aesni_xts_dec(ctx, tweak, outbuf, inbuf, nblocks);
3325 }
3326
3327 #endif /* USE_AESNI */