Add AES-NI acceleration for AES-XTS
[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 void
375 _gcry_aes_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   aesni_prepare();
386
387 #define DO_AESNI_AESIMC() \
388   asm volatile ("movdqa %[ekey], %%xmm1\n\t" \
389                 /*"aesimc %%xmm1, %%xmm1\n\t"*/ \
390                 ".byte 0x66, 0x0f, 0x38, 0xdb, 0xc9\n\t" \
391                 "movdqa %%xmm1, %[dkey]" \
392                 : [dkey] "=m" (dkey[r]) \
393                 : [ekey] "m" (ekey[rr]) \
394                 : "memory")
395
396   dkey[0] = ekey[ctx->rounds];
397   r=1;
398   rr=ctx->rounds-1;
399   DO_AESNI_AESIMC(); r++; rr--; /* round 1 */
400   DO_AESNI_AESIMC(); r++; rr--; /* round 2 */
401   DO_AESNI_AESIMC(); r++; rr--; /* round 3 */
402   DO_AESNI_AESIMC(); r++; rr--; /* round 4 */
403   DO_AESNI_AESIMC(); r++; rr--; /* round 5 */
404   DO_AESNI_AESIMC(); r++; rr--; /* round 6 */
405   DO_AESNI_AESIMC(); r++; rr--; /* round 7 */
406   DO_AESNI_AESIMC(); r++; rr--; /* round 8 */
407   DO_AESNI_AESIMC(); r++; rr--; /* round 9 */
408   if (ctx->rounds > 10)
409     {
410       DO_AESNI_AESIMC(); r++; rr--; /* round 10 */
411       DO_AESNI_AESIMC(); r++; rr--; /* round 11 */
412       if (ctx->rounds > 12)
413         {
414           DO_AESNI_AESIMC(); r++; rr--; /* round 12 */
415           DO_AESNI_AESIMC(); r++; rr--; /* round 13 */
416         }
417     }
418
419   dkey[r] = ekey[0];
420
421 #undef DO_AESNI_AESIMC
422
423   aesni_cleanup();
424 }
425
426
427 /* Encrypt one block using the Intel AES-NI instructions.  Block is input
428  * and output through SSE register xmm0. */
429 static inline void
430 do_aesni_enc (const RIJNDAEL_context *ctx)
431 {
432 #define aesenc_xmm1_xmm0      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc1\n\t"
433 #define aesenclast_xmm1_xmm0  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc1\n\t"
434   asm volatile ("movdqa (%[key]), %%xmm1\n\t"    /* xmm1 := key[0] */
435                 "pxor   %%xmm1, %%xmm0\n\t"     /* xmm0 ^= key[0] */
436                 "movdqa 0x10(%[key]), %%xmm1\n\t"
437                 aesenc_xmm1_xmm0
438                 "movdqa 0x20(%[key]), %%xmm1\n\t"
439                 aesenc_xmm1_xmm0
440                 "movdqa 0x30(%[key]), %%xmm1\n\t"
441                 aesenc_xmm1_xmm0
442                 "movdqa 0x40(%[key]), %%xmm1\n\t"
443                 aesenc_xmm1_xmm0
444                 "movdqa 0x50(%[key]), %%xmm1\n\t"
445                 aesenc_xmm1_xmm0
446                 "movdqa 0x60(%[key]), %%xmm1\n\t"
447                 aesenc_xmm1_xmm0
448                 "movdqa 0x70(%[key]), %%xmm1\n\t"
449                 aesenc_xmm1_xmm0
450                 "movdqa 0x80(%[key]), %%xmm1\n\t"
451                 aesenc_xmm1_xmm0
452                 "movdqa 0x90(%[key]), %%xmm1\n\t"
453                 aesenc_xmm1_xmm0
454                 "movdqa 0xa0(%[key]), %%xmm1\n\t"
455                 "cmpl $10, %[rounds]\n\t"
456                 "jz .Lenclast%=\n\t"
457                 aesenc_xmm1_xmm0
458                 "movdqa 0xb0(%[key]), %%xmm1\n\t"
459                 aesenc_xmm1_xmm0
460                 "movdqa 0xc0(%[key]), %%xmm1\n\t"
461                 "cmpl $12, %[rounds]\n\t"
462                 "jz .Lenclast%=\n\t"
463                 aesenc_xmm1_xmm0
464                 "movdqa 0xd0(%[key]), %%xmm1\n\t"
465                 aesenc_xmm1_xmm0
466                 "movdqa 0xe0(%[key]), %%xmm1\n"
467
468                 ".Lenclast%=:\n\t"
469                 aesenclast_xmm1_xmm0
470                 "\n"
471                 :
472                 : [key] "r" (ctx->keyschenc),
473                   [rounds] "r" (ctx->rounds)
474                 : "cc", "memory");
475 #undef aesenc_xmm1_xmm0
476 #undef aesenclast_xmm1_xmm0
477 }
478
479
480 /* Decrypt one block using the Intel AES-NI instructions.  Block is input
481  * and output through SSE register xmm0. */
482 static inline void
483 do_aesni_dec (const RIJNDAEL_context *ctx)
484 {
485 #define aesdec_xmm1_xmm0      ".byte 0x66, 0x0f, 0x38, 0xde, 0xc1\n\t"
486 #define aesdeclast_xmm1_xmm0  ".byte 0x66, 0x0f, 0x38, 0xdf, 0xc1\n\t"
487   asm volatile ("movdqa (%[key]), %%xmm1\n\t"
488                 "pxor   %%xmm1, %%xmm0\n\t"     /* xmm0 ^= key[0] */
489                 "movdqa 0x10(%[key]), %%xmm1\n\t"
490                 aesdec_xmm1_xmm0
491                 "movdqa 0x20(%[key]), %%xmm1\n\t"
492                 aesdec_xmm1_xmm0
493                 "movdqa 0x30(%[key]), %%xmm1\n\t"
494                 aesdec_xmm1_xmm0
495                 "movdqa 0x40(%[key]), %%xmm1\n\t"
496                 aesdec_xmm1_xmm0
497                 "movdqa 0x50(%[key]), %%xmm1\n\t"
498                 aesdec_xmm1_xmm0
499                 "movdqa 0x60(%[key]), %%xmm1\n\t"
500                 aesdec_xmm1_xmm0
501                 "movdqa 0x70(%[key]), %%xmm1\n\t"
502                 aesdec_xmm1_xmm0
503                 "movdqa 0x80(%[key]), %%xmm1\n\t"
504                 aesdec_xmm1_xmm0
505                 "movdqa 0x90(%[key]), %%xmm1\n\t"
506                 aesdec_xmm1_xmm0
507                 "movdqa 0xa0(%[key]), %%xmm1\n\t"
508                 "cmpl $10, %[rounds]\n\t"
509                 "jz .Ldeclast%=\n\t"
510                 aesdec_xmm1_xmm0
511                 "movdqa 0xb0(%[key]), %%xmm1\n\t"
512                 aesdec_xmm1_xmm0
513                 "movdqa 0xc0(%[key]), %%xmm1\n\t"
514                 "cmpl $12, %[rounds]\n\t"
515                 "jz .Ldeclast%=\n\t"
516                 aesdec_xmm1_xmm0
517                 "movdqa 0xd0(%[key]), %%xmm1\n\t"
518                 aesdec_xmm1_xmm0
519                 "movdqa 0xe0(%[key]), %%xmm1\n"
520
521                 ".Ldeclast%=:\n\t"
522                 aesdeclast_xmm1_xmm0
523                 "\n"
524                 :
525                 : [key] "r" (ctx->keyschdec),
526                   [rounds] "r" (ctx->rounds)
527                 : "cc", "memory");
528 #undef aesdec_xmm1_xmm0
529 #undef aesdeclast_xmm1_xmm0
530 }
531
532
533 /* Encrypt four blocks using the Intel AES-NI instructions.  Blocks are input
534  * and output through SSE registers xmm1 to xmm4.  */
535 static inline void
536 do_aesni_enc_vec4 (const RIJNDAEL_context *ctx)
537 {
538 #define aesenc_xmm0_xmm1      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc8\n\t"
539 #define aesenc_xmm0_xmm2      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xd0\n\t"
540 #define aesenc_xmm0_xmm3      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xd8\n\t"
541 #define aesenc_xmm0_xmm4      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xe0\n\t"
542 #define aesenclast_xmm0_xmm1  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc8\n\t"
543 #define aesenclast_xmm0_xmm2  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xd0\n\t"
544 #define aesenclast_xmm0_xmm3  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xd8\n\t"
545 #define aesenclast_xmm0_xmm4  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xe0\n\t"
546   asm volatile ("movdqa (%[key]), %%xmm0\n\t"
547                 "pxor   %%xmm0, %%xmm1\n\t"     /* xmm1 ^= key[0] */
548                 "pxor   %%xmm0, %%xmm2\n\t"     /* xmm2 ^= key[0] */
549                 "pxor   %%xmm0, %%xmm3\n\t"     /* xmm3 ^= key[0] */
550                 "pxor   %%xmm0, %%xmm4\n\t"     /* xmm4 ^= key[0] */
551                 "movdqa 0x10(%[key]), %%xmm0\n\t"
552                 aesenc_xmm0_xmm1
553                 aesenc_xmm0_xmm2
554                 aesenc_xmm0_xmm3
555                 aesenc_xmm0_xmm4
556                 "movdqa 0x20(%[key]), %%xmm0\n\t"
557                 aesenc_xmm0_xmm1
558                 aesenc_xmm0_xmm2
559                 aesenc_xmm0_xmm3
560                 aesenc_xmm0_xmm4
561                 "movdqa 0x30(%[key]), %%xmm0\n\t"
562                 aesenc_xmm0_xmm1
563                 aesenc_xmm0_xmm2
564                 aesenc_xmm0_xmm3
565                 aesenc_xmm0_xmm4
566                 "movdqa 0x40(%[key]), %%xmm0\n\t"
567                 aesenc_xmm0_xmm1
568                 aesenc_xmm0_xmm2
569                 aesenc_xmm0_xmm3
570                 aesenc_xmm0_xmm4
571                 "movdqa 0x50(%[key]), %%xmm0\n\t"
572                 aesenc_xmm0_xmm1
573                 aesenc_xmm0_xmm2
574                 aesenc_xmm0_xmm3
575                 aesenc_xmm0_xmm4
576                 "movdqa 0x60(%[key]), %%xmm0\n\t"
577                 aesenc_xmm0_xmm1
578                 aesenc_xmm0_xmm2
579                 aesenc_xmm0_xmm3
580                 aesenc_xmm0_xmm4
581                 "movdqa 0x70(%[key]), %%xmm0\n\t"
582                 aesenc_xmm0_xmm1
583                 aesenc_xmm0_xmm2
584                 aesenc_xmm0_xmm3
585                 aesenc_xmm0_xmm4
586                 "movdqa 0x80(%[key]), %%xmm0\n\t"
587                 aesenc_xmm0_xmm1
588                 aesenc_xmm0_xmm2
589                 aesenc_xmm0_xmm3
590                 aesenc_xmm0_xmm4
591                 "movdqa 0x90(%[key]), %%xmm0\n\t"
592                 aesenc_xmm0_xmm1
593                 aesenc_xmm0_xmm2
594                 aesenc_xmm0_xmm3
595                 aesenc_xmm0_xmm4
596                 "movdqa 0xa0(%[key]), %%xmm0\n\t"
597                 "cmpl $10, %[rounds]\n\t"
598                 "jz .Ldeclast%=\n\t"
599                 aesenc_xmm0_xmm1
600                 aesenc_xmm0_xmm2
601                 aesenc_xmm0_xmm3
602                 aesenc_xmm0_xmm4
603                 "movdqa 0xb0(%[key]), %%xmm0\n\t"
604                 aesenc_xmm0_xmm1
605                 aesenc_xmm0_xmm2
606                 aesenc_xmm0_xmm3
607                 aesenc_xmm0_xmm4
608                 "movdqa 0xc0(%[key]), %%xmm0\n\t"
609                 "cmpl $12, %[rounds]\n\t"
610                 "jz .Ldeclast%=\n\t"
611                 aesenc_xmm0_xmm1
612                 aesenc_xmm0_xmm2
613                 aesenc_xmm0_xmm3
614                 aesenc_xmm0_xmm4
615                 "movdqa 0xd0(%[key]), %%xmm0\n\t"
616                 aesenc_xmm0_xmm1
617                 aesenc_xmm0_xmm2
618                 aesenc_xmm0_xmm3
619                 aesenc_xmm0_xmm4
620                 "movdqa 0xe0(%[key]), %%xmm0\n"
621
622                 ".Ldeclast%=:\n\t"
623                 aesenclast_xmm0_xmm1
624                 aesenclast_xmm0_xmm2
625                 aesenclast_xmm0_xmm3
626                 aesenclast_xmm0_xmm4
627                 : /* no output */
628                 : [key] "r" (ctx->keyschenc),
629                   [rounds] "r" (ctx->rounds)
630                 : "cc", "memory");
631 #undef aesenc_xmm0_xmm1
632 #undef aesenc_xmm0_xmm2
633 #undef aesenc_xmm0_xmm3
634 #undef aesenc_xmm0_xmm4
635 #undef aesenclast_xmm0_xmm1
636 #undef aesenclast_xmm0_xmm2
637 #undef aesenclast_xmm0_xmm3
638 #undef aesenclast_xmm0_xmm4
639 }
640
641
642 /* Decrypt four blocks using the Intel AES-NI instructions.  Blocks are input
643  * and output through SSE registers xmm1 to xmm4.  */
644 static inline void
645 do_aesni_dec_vec4 (const RIJNDAEL_context *ctx)
646 {
647 #define aesdec_xmm0_xmm1 ".byte 0x66, 0x0f, 0x38, 0xde, 0xc8\n\t"
648 #define aesdec_xmm0_xmm2 ".byte 0x66, 0x0f, 0x38, 0xde, 0xd0\n\t"
649 #define aesdec_xmm0_xmm3 ".byte 0x66, 0x0f, 0x38, 0xde, 0xd8\n\t"
650 #define aesdec_xmm0_xmm4 ".byte 0x66, 0x0f, 0x38, 0xde, 0xe0\n\t"
651 #define aesdeclast_xmm0_xmm1 ".byte 0x66, 0x0f, 0x38, 0xdf, 0xc8\n\t"
652 #define aesdeclast_xmm0_xmm2 ".byte 0x66, 0x0f, 0x38, 0xdf, 0xd0\n\t"
653 #define aesdeclast_xmm0_xmm3 ".byte 0x66, 0x0f, 0x38, 0xdf, 0xd8\n\t"
654 #define aesdeclast_xmm0_xmm4 ".byte 0x66, 0x0f, 0x38, 0xdf, 0xe0\n\t"
655   asm volatile ("movdqa (%[key]), %%xmm0\n\t"
656                 "pxor   %%xmm0, %%xmm1\n\t"     /* xmm1 ^= key[0] */
657                 "pxor   %%xmm0, %%xmm2\n\t"     /* xmm2 ^= key[0] */
658                 "pxor   %%xmm0, %%xmm3\n\t"     /* xmm3 ^= key[0] */
659                 "pxor   %%xmm0, %%xmm4\n\t"     /* xmm4 ^= key[0] */
660                 "movdqa 0x10(%[key]), %%xmm0\n\t"
661                 aesdec_xmm0_xmm1
662                 aesdec_xmm0_xmm2
663                 aesdec_xmm0_xmm3
664                 aesdec_xmm0_xmm4
665                 "movdqa 0x20(%[key]), %%xmm0\n\t"
666                 aesdec_xmm0_xmm1
667                 aesdec_xmm0_xmm2
668                 aesdec_xmm0_xmm3
669                 aesdec_xmm0_xmm4
670                 "movdqa 0x30(%[key]), %%xmm0\n\t"
671                 aesdec_xmm0_xmm1
672                 aesdec_xmm0_xmm2
673                 aesdec_xmm0_xmm3
674                 aesdec_xmm0_xmm4
675                 "movdqa 0x40(%[key]), %%xmm0\n\t"
676                 aesdec_xmm0_xmm1
677                 aesdec_xmm0_xmm2
678                 aesdec_xmm0_xmm3
679                 aesdec_xmm0_xmm4
680                 "movdqa 0x50(%[key]), %%xmm0\n\t"
681                 aesdec_xmm0_xmm1
682                 aesdec_xmm0_xmm2
683                 aesdec_xmm0_xmm3
684                 aesdec_xmm0_xmm4
685                 "movdqa 0x60(%[key]), %%xmm0\n\t"
686                 aesdec_xmm0_xmm1
687                 aesdec_xmm0_xmm2
688                 aesdec_xmm0_xmm3
689                 aesdec_xmm0_xmm4
690                 "movdqa 0x70(%[key]), %%xmm0\n\t"
691                 aesdec_xmm0_xmm1
692                 aesdec_xmm0_xmm2
693                 aesdec_xmm0_xmm3
694                 aesdec_xmm0_xmm4
695                 "movdqa 0x80(%[key]), %%xmm0\n\t"
696                 aesdec_xmm0_xmm1
697                 aesdec_xmm0_xmm2
698                 aesdec_xmm0_xmm3
699                 aesdec_xmm0_xmm4
700                 "movdqa 0x90(%[key]), %%xmm0\n\t"
701                 aesdec_xmm0_xmm1
702                 aesdec_xmm0_xmm2
703                 aesdec_xmm0_xmm3
704                 aesdec_xmm0_xmm4
705                 "movdqa 0xa0(%[key]), %%xmm0\n\t"
706                 "cmpl $10, %[rounds]\n\t"
707                 "jz .Ldeclast%=\n\t"
708                 aesdec_xmm0_xmm1
709                 aesdec_xmm0_xmm2
710                 aesdec_xmm0_xmm3
711                 aesdec_xmm0_xmm4
712                 "movdqa 0xb0(%[key]), %%xmm0\n\t"
713                 aesdec_xmm0_xmm1
714                 aesdec_xmm0_xmm2
715                 aesdec_xmm0_xmm3
716                 aesdec_xmm0_xmm4
717                 "movdqa 0xc0(%[key]), %%xmm0\n\t"
718                 "cmpl $12, %[rounds]\n\t"
719                 "jz .Ldeclast%=\n\t"
720                 aesdec_xmm0_xmm1
721                 aesdec_xmm0_xmm2
722                 aesdec_xmm0_xmm3
723                 aesdec_xmm0_xmm4
724                 "movdqa 0xd0(%[key]), %%xmm0\n\t"
725                 aesdec_xmm0_xmm1
726                 aesdec_xmm0_xmm2
727                 aesdec_xmm0_xmm3
728                 aesdec_xmm0_xmm4
729                 "movdqa 0xe0(%[key]), %%xmm0\n"
730
731                 ".Ldeclast%=:\n\t"
732                 aesdeclast_xmm0_xmm1
733                 aesdeclast_xmm0_xmm2
734                 aesdeclast_xmm0_xmm3
735                 aesdeclast_xmm0_xmm4
736                 : /* no output */
737                 : [key] "r" (ctx->keyschdec),
738                   [rounds] "r" (ctx->rounds)
739                 : "cc", "memory");
740 #undef aesdec_xmm0_xmm1
741 #undef aesdec_xmm0_xmm2
742 #undef aesdec_xmm0_xmm3
743 #undef aesdec_xmm0_xmm4
744 #undef aesdeclast_xmm0_xmm1
745 #undef aesdeclast_xmm0_xmm2
746 #undef aesdeclast_xmm0_xmm3
747 #undef aesdeclast_xmm0_xmm4
748 }
749
750
751 #ifdef __x86_64__
752
753 /* Encrypt eight blocks using the Intel AES-NI instructions.  Blocks are input
754  * and output through SSE registers xmm1 to xmm4 and xmm8 to xmm11.  */
755 static inline void
756 do_aesni_enc_vec8 (const RIJNDAEL_context *ctx)
757 {
758   asm volatile ("movdqa (%[key]), %%xmm0\n\t"
759                 "pxor   %%xmm0, %%xmm1\n\t"     /* xmm1 ^= key[0] */
760                 "pxor   %%xmm0, %%xmm2\n\t"     /* xmm2 ^= key[0] */
761                 "pxor   %%xmm0, %%xmm3\n\t"     /* xmm3 ^= key[0] */
762                 "pxor   %%xmm0, %%xmm4\n\t"     /* xmm4 ^= key[0] */
763                 "pxor   %%xmm0, %%xmm8\n\t"     /* xmm8 ^= key[0] */
764                 "pxor   %%xmm0, %%xmm9\n\t"     /* xmm9 ^= key[0] */
765                 "pxor   %%xmm0, %%xmm10\n\t"     /* xmm10 ^= key[0] */
766                 "pxor   %%xmm0, %%xmm11\n\t"     /* xmm11 ^= key[0] */
767                 "movdqa 0x10(%[key]), %%xmm0\n\t"
768                 "cmpl $12, %[rounds]\n\t"
769                 "aesenc %%xmm0, %%xmm1\n\t"
770                 "aesenc %%xmm0, %%xmm2\n\t"
771                 "aesenc %%xmm0, %%xmm3\n\t"
772                 "aesenc %%xmm0, %%xmm4\n\t"
773                 "aesenc %%xmm0, %%xmm8\n\t"
774                 "aesenc %%xmm0, %%xmm9\n\t"
775                 "aesenc %%xmm0, %%xmm10\n\t"
776                 "aesenc %%xmm0, %%xmm11\n\t"
777                 "movdqa 0x20(%[key]), %%xmm0\n\t"
778                 "aesenc %%xmm0, %%xmm1\n\t"
779                 "aesenc %%xmm0, %%xmm2\n\t"
780                 "aesenc %%xmm0, %%xmm3\n\t"
781                 "aesenc %%xmm0, %%xmm4\n\t"
782                 "aesenc %%xmm0, %%xmm8\n\t"
783                 "aesenc %%xmm0, %%xmm9\n\t"
784                 "aesenc %%xmm0, %%xmm10\n\t"
785                 "aesenc %%xmm0, %%xmm11\n\t"
786                 "movdqa 0x30(%[key]), %%xmm0\n\t"
787                 "aesenc %%xmm0, %%xmm1\n\t"
788                 "aesenc %%xmm0, %%xmm2\n\t"
789                 "aesenc %%xmm0, %%xmm3\n\t"
790                 "aesenc %%xmm0, %%xmm4\n\t"
791                 "aesenc %%xmm0, %%xmm8\n\t"
792                 "aesenc %%xmm0, %%xmm9\n\t"
793                 "aesenc %%xmm0, %%xmm10\n\t"
794                 "aesenc %%xmm0, %%xmm11\n\t"
795                 "movdqa 0x40(%[key]), %%xmm0\n\t"
796                 "aesenc %%xmm0, %%xmm1\n\t"
797                 "aesenc %%xmm0, %%xmm2\n\t"
798                 "aesenc %%xmm0, %%xmm3\n\t"
799                 "aesenc %%xmm0, %%xmm4\n\t"
800                 "aesenc %%xmm0, %%xmm8\n\t"
801                 "aesenc %%xmm0, %%xmm9\n\t"
802                 "aesenc %%xmm0, %%xmm10\n\t"
803                 "aesenc %%xmm0, %%xmm11\n\t"
804                 "movdqa 0x50(%[key]), %%xmm0\n\t"
805                 "aesenc %%xmm0, %%xmm1\n\t"
806                 "aesenc %%xmm0, %%xmm2\n\t"
807                 "aesenc %%xmm0, %%xmm3\n\t"
808                 "aesenc %%xmm0, %%xmm4\n\t"
809                 "aesenc %%xmm0, %%xmm8\n\t"
810                 "aesenc %%xmm0, %%xmm9\n\t"
811                 "aesenc %%xmm0, %%xmm10\n\t"
812                 "aesenc %%xmm0, %%xmm11\n\t"
813                 "movdqa 0x60(%[key]), %%xmm0\n\t"
814                 "aesenc %%xmm0, %%xmm1\n\t"
815                 "aesenc %%xmm0, %%xmm2\n\t"
816                 "aesenc %%xmm0, %%xmm3\n\t"
817                 "aesenc %%xmm0, %%xmm4\n\t"
818                 "aesenc %%xmm0, %%xmm8\n\t"
819                 "aesenc %%xmm0, %%xmm9\n\t"
820                 "aesenc %%xmm0, %%xmm10\n\t"
821                 "aesenc %%xmm0, %%xmm11\n\t"
822                 "movdqa 0x70(%[key]), %%xmm0\n\t"
823                 "aesenc %%xmm0, %%xmm1\n\t"
824                 "aesenc %%xmm0, %%xmm2\n\t"
825                 "aesenc %%xmm0, %%xmm3\n\t"
826                 "aesenc %%xmm0, %%xmm4\n\t"
827                 "aesenc %%xmm0, %%xmm8\n\t"
828                 "aesenc %%xmm0, %%xmm9\n\t"
829                 "aesenc %%xmm0, %%xmm10\n\t"
830                 "aesenc %%xmm0, %%xmm11\n\t"
831                 "movdqa 0x80(%[key]), %%xmm0\n\t"
832                 "aesenc %%xmm0, %%xmm1\n\t"
833                 "aesenc %%xmm0, %%xmm2\n\t"
834                 "aesenc %%xmm0, %%xmm3\n\t"
835                 "aesenc %%xmm0, %%xmm4\n\t"
836                 "aesenc %%xmm0, %%xmm8\n\t"
837                 "aesenc %%xmm0, %%xmm9\n\t"
838                 "aesenc %%xmm0, %%xmm10\n\t"
839                 "aesenc %%xmm0, %%xmm11\n\t"
840                 "movdqa 0x90(%[key]), %%xmm0\n\t"
841                 "aesenc %%xmm0, %%xmm1\n\t"
842                 "aesenc %%xmm0, %%xmm2\n\t"
843                 "aesenc %%xmm0, %%xmm3\n\t"
844                 "aesenc %%xmm0, %%xmm4\n\t"
845                 "aesenc %%xmm0, %%xmm8\n\t"
846                 "aesenc %%xmm0, %%xmm9\n\t"
847                 "aesenc %%xmm0, %%xmm10\n\t"
848                 "aesenc %%xmm0, %%xmm11\n\t"
849                 "movdqa 0xa0(%[key]), %%xmm0\n\t"
850                 "jb .Ldeclast%=\n\t"
851                 "aesenc %%xmm0, %%xmm1\n\t"
852                 "aesenc %%xmm0, %%xmm2\n\t"
853                 "aesenc %%xmm0, %%xmm3\n\t"
854                 "aesenc %%xmm0, %%xmm4\n\t"
855                 "aesenc %%xmm0, %%xmm8\n\t"
856                 "aesenc %%xmm0, %%xmm9\n\t"
857                 "aesenc %%xmm0, %%xmm10\n\t"
858                 "aesenc %%xmm0, %%xmm11\n\t"
859                 "movdqa 0xb0(%[key]), %%xmm0\n\t"
860                 "aesenc %%xmm0, %%xmm1\n\t"
861                 "aesenc %%xmm0, %%xmm2\n\t"
862                 "aesenc %%xmm0, %%xmm3\n\t"
863                 "aesenc %%xmm0, %%xmm4\n\t"
864                 "aesenc %%xmm0, %%xmm8\n\t"
865                 "aesenc %%xmm0, %%xmm9\n\t"
866                 "aesenc %%xmm0, %%xmm10\n\t"
867                 "aesenc %%xmm0, %%xmm11\n\t"
868                 "movdqa 0xc0(%[key]), %%xmm0\n\t"
869                 "je .Ldeclast%=\n\t"
870                 "aesenc %%xmm0, %%xmm1\n\t"
871                 "aesenc %%xmm0, %%xmm2\n\t"
872                 "aesenc %%xmm0, %%xmm3\n\t"
873                 "aesenc %%xmm0, %%xmm4\n\t"
874                 "aesenc %%xmm0, %%xmm8\n\t"
875                 "aesenc %%xmm0, %%xmm9\n\t"
876                 "aesenc %%xmm0, %%xmm10\n\t"
877                 "aesenc %%xmm0, %%xmm11\n\t"
878                 "movdqa 0xd0(%[key]), %%xmm0\n\t"
879                 "aesenc %%xmm0, %%xmm1\n\t"
880                 "aesenc %%xmm0, %%xmm2\n\t"
881                 "aesenc %%xmm0, %%xmm3\n\t"
882                 "aesenc %%xmm0, %%xmm4\n\t"
883                 "aesenc %%xmm0, %%xmm8\n\t"
884                 "aesenc %%xmm0, %%xmm9\n\t"
885                 "aesenc %%xmm0, %%xmm10\n\t"
886                 "aesenc %%xmm0, %%xmm11\n\t"
887                 "movdqa 0xe0(%[key]), %%xmm0\n"
888
889                 ".Ldeclast%=:\n\t"
890                 "aesenclast %%xmm0, %%xmm1\n\t"
891                 "aesenclast %%xmm0, %%xmm2\n\t"
892                 "aesenclast %%xmm0, %%xmm3\n\t"
893                 "aesenclast %%xmm0, %%xmm4\n\t"
894                 "aesenclast %%xmm0, %%xmm8\n\t"
895                 "aesenclast %%xmm0, %%xmm9\n\t"
896                 "aesenclast %%xmm0, %%xmm10\n\t"
897                 "aesenclast %%xmm0, %%xmm11\n\t"
898                 : /* no output */
899                 : [key] "r" (ctx->keyschenc),
900                   [rounds] "r" (ctx->rounds)
901                 : "cc", "memory");
902 }
903
904
905 /* Decrypt eight blocks using the Intel AES-NI instructions.  Blocks are input
906  * and output through SSE registers xmm1 to xmm4 and xmm8 to xmm11.  */
907 static inline void
908 do_aesni_dec_vec8 (const RIJNDAEL_context *ctx)
909 {
910   asm volatile ("movdqa (%[key]), %%xmm0\n\t"
911                 "pxor   %%xmm0, %%xmm1\n\t"     /* xmm1 ^= key[0] */
912                 "pxor   %%xmm0, %%xmm2\n\t"     /* xmm2 ^= key[0] */
913                 "pxor   %%xmm0, %%xmm3\n\t"     /* xmm3 ^= key[0] */
914                 "pxor   %%xmm0, %%xmm4\n\t"     /* xmm4 ^= key[0] */
915                 "pxor   %%xmm0, %%xmm8\n\t"     /* xmm8 ^= key[0] */
916                 "pxor   %%xmm0, %%xmm9\n\t"     /* xmm9 ^= key[0] */
917                 "pxor   %%xmm0, %%xmm10\n\t"    /* xmm10 ^= key[0] */
918                 "pxor   %%xmm0, %%xmm11\n\t"    /* xmm11 ^= key[0] */
919                 "movdqa 0x10(%[key]), %%xmm0\n\t"
920                 "cmpl $12, %[rounds]\n\t"
921                 "aesdec %%xmm0, %%xmm1\n\t"
922                 "aesdec %%xmm0, %%xmm2\n\t"
923                 "aesdec %%xmm0, %%xmm3\n\t"
924                 "aesdec %%xmm0, %%xmm4\n\t"
925                 "aesdec %%xmm0, %%xmm8\n\t"
926                 "aesdec %%xmm0, %%xmm9\n\t"
927                 "aesdec %%xmm0, %%xmm10\n\t"
928                 "aesdec %%xmm0, %%xmm11\n\t"
929                 "movdqa 0x20(%[key]), %%xmm0\n\t"
930                 "aesdec %%xmm0, %%xmm1\n\t"
931                 "aesdec %%xmm0, %%xmm2\n\t"
932                 "aesdec %%xmm0, %%xmm3\n\t"
933                 "aesdec %%xmm0, %%xmm4\n\t"
934                 "aesdec %%xmm0, %%xmm8\n\t"
935                 "aesdec %%xmm0, %%xmm9\n\t"
936                 "aesdec %%xmm0, %%xmm10\n\t"
937                 "aesdec %%xmm0, %%xmm11\n\t"
938                 "movdqa 0x30(%[key]), %%xmm0\n\t"
939                 "aesdec %%xmm0, %%xmm1\n\t"
940                 "aesdec %%xmm0, %%xmm2\n\t"
941                 "aesdec %%xmm0, %%xmm3\n\t"
942                 "aesdec %%xmm0, %%xmm4\n\t"
943                 "aesdec %%xmm0, %%xmm8\n\t"
944                 "aesdec %%xmm0, %%xmm9\n\t"
945                 "aesdec %%xmm0, %%xmm10\n\t"
946                 "aesdec %%xmm0, %%xmm11\n\t"
947                 "movdqa 0x40(%[key]), %%xmm0\n\t"
948                 "aesdec %%xmm0, %%xmm1\n\t"
949                 "aesdec %%xmm0, %%xmm2\n\t"
950                 "aesdec %%xmm0, %%xmm3\n\t"
951                 "aesdec %%xmm0, %%xmm4\n\t"
952                 "aesdec %%xmm0, %%xmm8\n\t"
953                 "aesdec %%xmm0, %%xmm9\n\t"
954                 "aesdec %%xmm0, %%xmm10\n\t"
955                 "aesdec %%xmm0, %%xmm11\n\t"
956                 "movdqa 0x50(%[key]), %%xmm0\n\t"
957                 "aesdec %%xmm0, %%xmm1\n\t"
958                 "aesdec %%xmm0, %%xmm2\n\t"
959                 "aesdec %%xmm0, %%xmm3\n\t"
960                 "aesdec %%xmm0, %%xmm4\n\t"
961                 "aesdec %%xmm0, %%xmm8\n\t"
962                 "aesdec %%xmm0, %%xmm9\n\t"
963                 "aesdec %%xmm0, %%xmm10\n\t"
964                 "aesdec %%xmm0, %%xmm11\n\t"
965                 "movdqa 0x60(%[key]), %%xmm0\n\t"
966                 "aesdec %%xmm0, %%xmm1\n\t"
967                 "aesdec %%xmm0, %%xmm2\n\t"
968                 "aesdec %%xmm0, %%xmm3\n\t"
969                 "aesdec %%xmm0, %%xmm4\n\t"
970                 "aesdec %%xmm0, %%xmm8\n\t"
971                 "aesdec %%xmm0, %%xmm9\n\t"
972                 "aesdec %%xmm0, %%xmm10\n\t"
973                 "aesdec %%xmm0, %%xmm11\n\t"
974                 "movdqa 0x70(%[key]), %%xmm0\n\t"
975                 "aesdec %%xmm0, %%xmm1\n\t"
976                 "aesdec %%xmm0, %%xmm2\n\t"
977                 "aesdec %%xmm0, %%xmm3\n\t"
978                 "aesdec %%xmm0, %%xmm4\n\t"
979                 "aesdec %%xmm0, %%xmm8\n\t"
980                 "aesdec %%xmm0, %%xmm9\n\t"
981                 "aesdec %%xmm0, %%xmm10\n\t"
982                 "aesdec %%xmm0, %%xmm11\n\t"
983                 "movdqa 0x80(%[key]), %%xmm0\n\t"
984                 "aesdec %%xmm0, %%xmm1\n\t"
985                 "aesdec %%xmm0, %%xmm2\n\t"
986                 "aesdec %%xmm0, %%xmm3\n\t"
987                 "aesdec %%xmm0, %%xmm4\n\t"
988                 "aesdec %%xmm0, %%xmm8\n\t"
989                 "aesdec %%xmm0, %%xmm9\n\t"
990                 "aesdec %%xmm0, %%xmm10\n\t"
991                 "aesdec %%xmm0, %%xmm11\n\t"
992                 "movdqa 0x90(%[key]), %%xmm0\n\t"
993                 "aesdec %%xmm0, %%xmm1\n\t"
994                 "aesdec %%xmm0, %%xmm2\n\t"
995                 "aesdec %%xmm0, %%xmm3\n\t"
996                 "aesdec %%xmm0, %%xmm4\n\t"
997                 "aesdec %%xmm0, %%xmm8\n\t"
998                 "aesdec %%xmm0, %%xmm9\n\t"
999                 "aesdec %%xmm0, %%xmm10\n\t"
1000                 "aesdec %%xmm0, %%xmm11\n\t"
1001                 "movdqa 0xa0(%[key]), %%xmm0\n\t"
1002                 "jb .Ldeclast%=\n\t"
1003                 "aesdec %%xmm0, %%xmm1\n\t"
1004                 "aesdec %%xmm0, %%xmm2\n\t"
1005                 "aesdec %%xmm0, %%xmm3\n\t"
1006                 "aesdec %%xmm0, %%xmm4\n\t"
1007                 "aesdec %%xmm0, %%xmm8\n\t"
1008                 "aesdec %%xmm0, %%xmm9\n\t"
1009                 "aesdec %%xmm0, %%xmm10\n\t"
1010                 "aesdec %%xmm0, %%xmm11\n\t"
1011                 "movdqa 0xb0(%[key]), %%xmm0\n\t"
1012                 "aesdec %%xmm0, %%xmm1\n\t"
1013                 "aesdec %%xmm0, %%xmm2\n\t"
1014                 "aesdec %%xmm0, %%xmm3\n\t"
1015                 "aesdec %%xmm0, %%xmm4\n\t"
1016                 "aesdec %%xmm0, %%xmm8\n\t"
1017                 "aesdec %%xmm0, %%xmm9\n\t"
1018                 "aesdec %%xmm0, %%xmm10\n\t"
1019                 "aesdec %%xmm0, %%xmm11\n\t"
1020                 "movdqa 0xc0(%[key]), %%xmm0\n\t"
1021                 "je .Ldeclast%=\n\t"
1022                 "aesdec %%xmm0, %%xmm1\n\t"
1023                 "aesdec %%xmm0, %%xmm2\n\t"
1024                 "aesdec %%xmm0, %%xmm3\n\t"
1025                 "aesdec %%xmm0, %%xmm4\n\t"
1026                 "aesdec %%xmm0, %%xmm8\n\t"
1027                 "aesdec %%xmm0, %%xmm9\n\t"
1028                 "aesdec %%xmm0, %%xmm10\n\t"
1029                 "aesdec %%xmm0, %%xmm11\n\t"
1030                 "movdqa 0xd0(%[key]), %%xmm0\n\t"
1031                 "aesdec %%xmm0, %%xmm1\n\t"
1032                 "aesdec %%xmm0, %%xmm2\n\t"
1033                 "aesdec %%xmm0, %%xmm3\n\t"
1034                 "aesdec %%xmm0, %%xmm4\n\t"
1035                 "aesdec %%xmm0, %%xmm8\n\t"
1036                 "aesdec %%xmm0, %%xmm9\n\t"
1037                 "aesdec %%xmm0, %%xmm10\n\t"
1038                 "aesdec %%xmm0, %%xmm11\n\t"
1039                 "movdqa 0xe0(%[key]), %%xmm0\n"
1040
1041                 ".Ldeclast%=:\n\t"
1042                 "aesdeclast %%xmm0, %%xmm1\n\t"
1043                 "aesdeclast %%xmm0, %%xmm2\n\t"
1044                 "aesdeclast %%xmm0, %%xmm3\n\t"
1045                 "aesdeclast %%xmm0, %%xmm4\n\t"
1046                 "aesdeclast %%xmm0, %%xmm8\n\t"
1047                 "aesdeclast %%xmm0, %%xmm9\n\t"
1048                 "aesdeclast %%xmm0, %%xmm10\n\t"
1049                 "aesdeclast %%xmm0, %%xmm11\n\t"
1050                 : /* no output */
1051                 : [key] "r" (ctx->keyschdec),
1052                   [rounds] "r" (ctx->rounds)
1053                 : "cc", "memory");
1054 }
1055
1056 #endif /* __x86_64__ */
1057
1058
1059 /* Perform a CTR encryption round using the counter CTR and the input
1060    block A.  Write the result to the output block B and update CTR.
1061    CTR needs to be a 16 byte aligned little-endian value.  */
1062 static void
1063 do_aesni_ctr (const RIJNDAEL_context *ctx,
1064               unsigned char *ctr, unsigned char *b, const unsigned char *a)
1065 {
1066 #define aesenc_xmm1_xmm0      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc1\n\t"
1067 #define aesenclast_xmm1_xmm0  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc1\n\t"
1068
1069   asm volatile ("movdqa %%xmm5, %%xmm0\n\t"     /* xmm0 := CTR (xmm5)  */
1070                 "pcmpeqd %%xmm1, %%xmm1\n\t"
1071                 "psrldq $8, %%xmm1\n\t"         /* xmm1 = -1 */
1072
1073                 "pshufb %%xmm6, %%xmm5\n\t"
1074                 "psubq  %%xmm1, %%xmm5\n\t"     /* xmm5++ (big endian) */
1075
1076                 /* detect if 64-bit carry handling is needed */
1077                 "cmpl   $0xffffffff, 8(%[ctr])\n\t"
1078                 "jne    .Lno_carry%=\n\t"
1079                 "cmpl   $0xffffffff, 12(%[ctr])\n\t"
1080                 "jne    .Lno_carry%=\n\t"
1081
1082                 "pslldq $8, %%xmm1\n\t"         /* move lower 64-bit to high */
1083                 "psubq   %%xmm1, %%xmm5\n\t"    /* add carry to upper 64bits */
1084
1085                 ".Lno_carry%=:\n\t"
1086
1087                 "pshufb %%xmm6, %%xmm5\n\t"
1088                 "movdqa %%xmm5, (%[ctr])\n\t"   /* Update CTR (mem).       */
1089
1090                 "pxor (%[key]), %%xmm0\n\t"     /* xmm1 ^= key[0]    */
1091                 "movdqa 0x10(%[key]), %%xmm1\n\t"
1092                 aesenc_xmm1_xmm0
1093                 "movdqa 0x20(%[key]), %%xmm1\n\t"
1094                 aesenc_xmm1_xmm0
1095                 "movdqa 0x30(%[key]), %%xmm1\n\t"
1096                 aesenc_xmm1_xmm0
1097                 "movdqa 0x40(%[key]), %%xmm1\n\t"
1098                 aesenc_xmm1_xmm0
1099                 "movdqa 0x50(%[key]), %%xmm1\n\t"
1100                 aesenc_xmm1_xmm0
1101                 "movdqa 0x60(%[key]), %%xmm1\n\t"
1102                 aesenc_xmm1_xmm0
1103                 "movdqa 0x70(%[key]), %%xmm1\n\t"
1104                 aesenc_xmm1_xmm0
1105                 "movdqa 0x80(%[key]), %%xmm1\n\t"
1106                 aesenc_xmm1_xmm0
1107                 "movdqa 0x90(%[key]), %%xmm1\n\t"
1108                 aesenc_xmm1_xmm0
1109                 "movdqa 0xa0(%[key]), %%xmm1\n\t"
1110                 "cmpl $10, %[rounds]\n\t"
1111                 "jz .Lenclast%=\n\t"
1112                 aesenc_xmm1_xmm0
1113                 "movdqa 0xb0(%[key]), %%xmm1\n\t"
1114                 aesenc_xmm1_xmm0
1115                 "movdqa 0xc0(%[key]), %%xmm1\n\t"
1116                 "cmpl $12, %[rounds]\n\t"
1117                 "jz .Lenclast%=\n\t"
1118                 aesenc_xmm1_xmm0
1119                 "movdqa 0xd0(%[key]), %%xmm1\n\t"
1120                 aesenc_xmm1_xmm0
1121                 "movdqa 0xe0(%[key]), %%xmm1\n"
1122
1123                 ".Lenclast%=:\n\t"
1124                 aesenclast_xmm1_xmm0
1125                 "movdqu %[src], %%xmm1\n\t"      /* xmm1 := input   */
1126                 "pxor %%xmm1, %%xmm0\n\t"        /* EncCTR ^= input  */
1127                 "movdqu %%xmm0, %[dst]"          /* Store EncCTR.    */
1128
1129                 : [dst] "=m" (*b)
1130                 : [src] "m" (*a),
1131                   [ctr] "r" (ctr),
1132                   [key] "r" (ctx->keyschenc),
1133                   [rounds] "g" (ctx->rounds)
1134                 : "cc", "memory");
1135 #undef aesenc_xmm1_xmm0
1136 #undef aesenclast_xmm1_xmm0
1137 }
1138
1139
1140 /* Four blocks at a time variant of do_aesni_ctr.  */
1141 static void
1142 do_aesni_ctr_4 (const RIJNDAEL_context *ctx,
1143                 unsigned char *ctr, unsigned char *b, const unsigned char *a)
1144 {
1145   static const byte bige_addb_const[4][16] __attribute__ ((aligned (16))) =
1146     {
1147       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
1148       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 },
1149       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3 },
1150       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4 }
1151     };
1152   const void *bige_addb = bige_addb_const;
1153 #define aesenc_xmm1_xmm0      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc1\n\t"
1154 #define aesenc_xmm1_xmm2      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xd1\n\t"
1155 #define aesenc_xmm1_xmm3      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xd9\n\t"
1156 #define aesenc_xmm1_xmm4      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xe1\n\t"
1157 #define aesenclast_xmm1_xmm0  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc1\n\t"
1158 #define aesenclast_xmm1_xmm2  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xd1\n\t"
1159 #define aesenclast_xmm1_xmm3  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xd9\n\t"
1160 #define aesenclast_xmm1_xmm4  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xe1\n\t"
1161
1162   /* Register usage:
1163       [key] keyschedule
1164       xmm0  CTR-0
1165       xmm1  temp / round key
1166       xmm2  CTR-1
1167       xmm3  CTR-2
1168       xmm4  CTR-3
1169       xmm5  copy of *ctr
1170       xmm6  endian swapping mask
1171    */
1172
1173   asm volatile (/* detect if 8-bit carry handling is needed */
1174                 "cmpb   $0xfb, 15(%[ctr])\n\t"
1175                 "ja     .Ladd32bit%=\n\t"
1176
1177                 "movdqa %%xmm5, %%xmm0\n\t"     /* xmm0 := CTR (xmm5) */
1178                 "movdqa 0*16(%[addb]), %%xmm2\n\t"  /* xmm2 := be(1) */
1179                 "movdqa 1*16(%[addb]), %%xmm3\n\t"  /* xmm3 := be(2) */
1180                 "movdqa 2*16(%[addb]), %%xmm4\n\t"  /* xmm4 := be(3) */
1181                 "movdqa 3*16(%[addb]), %%xmm5\n\t"  /* xmm5 := be(4) */
1182                 "paddb  %%xmm0, %%xmm2\n\t"     /* xmm2 := be(1) + CTR (xmm0) */
1183                 "paddb  %%xmm0, %%xmm3\n\t"     /* xmm3 := be(2) + CTR (xmm0) */
1184                 "paddb  %%xmm0, %%xmm4\n\t"     /* xmm4 := be(3) + CTR (xmm0) */
1185                 "paddb  %%xmm0, %%xmm5\n\t"     /* xmm5 := be(4) + CTR (xmm0) */
1186                 "movdqa (%[key]), %%xmm1\n\t"   /* xmm1 := key[0] */
1187                 "jmp    .Lstore_ctr%=\n\t"
1188
1189                 ".Ladd32bit%=:\n\t"
1190                 "movdqa %%xmm5, %%xmm0\n\t"     /* xmm0, xmm2 := CTR (xmm5) */
1191                 "movdqa %%xmm0, %%xmm2\n\t"
1192                 "pcmpeqd %%xmm1, %%xmm1\n\t"
1193                 "psrldq $8, %%xmm1\n\t"         /* xmm1 = -1 */
1194
1195                 "pshufb %%xmm6, %%xmm2\n\t"     /* xmm2 := le(xmm2) */
1196                 "psubq  %%xmm1, %%xmm2\n\t"     /* xmm2++           */
1197                 "movdqa %%xmm2, %%xmm3\n\t"     /* xmm3 := xmm2     */
1198                 "psubq  %%xmm1, %%xmm3\n\t"     /* xmm3++           */
1199                 "movdqa %%xmm3, %%xmm4\n\t"     /* xmm4 := xmm3     */
1200                 "psubq  %%xmm1, %%xmm4\n\t"     /* xmm4++           */
1201                 "movdqa %%xmm4, %%xmm5\n\t"     /* xmm5 := xmm4     */
1202                 "psubq  %%xmm1, %%xmm5\n\t"     /* xmm5++           */
1203
1204                 /* detect if 64-bit carry handling is needed */
1205                 "cmpl   $0xffffffff, 8(%[ctr])\n\t"
1206                 "jne    .Lno_carry%=\n\t"
1207                 "movl   12(%[ctr]), %%esi\n\t"
1208                 "bswapl %%esi\n\t"
1209                 "cmpl   $0xfffffffc, %%esi\n\t"
1210                 "jb     .Lno_carry%=\n\t"       /* no carry */
1211
1212                 "pslldq $8, %%xmm1\n\t"         /* move lower 64-bit to high */
1213                 "je     .Lcarry_xmm5%=\n\t"     /* esi == 0xfffffffc */
1214                 "cmpl   $0xfffffffe, %%esi\n\t"
1215                 "jb     .Lcarry_xmm4%=\n\t"     /* esi == 0xfffffffd */
1216                 "je     .Lcarry_xmm3%=\n\t"     /* esi == 0xfffffffe */
1217                 /* esi == 0xffffffff */
1218
1219                 "psubq   %%xmm1, %%xmm2\n\t"
1220                 ".Lcarry_xmm3%=:\n\t"
1221                 "psubq   %%xmm1, %%xmm3\n\t"
1222                 ".Lcarry_xmm4%=:\n\t"
1223                 "psubq   %%xmm1, %%xmm4\n\t"
1224                 ".Lcarry_xmm5%=:\n\t"
1225                 "psubq   %%xmm1, %%xmm5\n\t"
1226
1227                 ".Lno_carry%=:\n\t"
1228                 "movdqa (%[key]), %%xmm1\n\t"   /* xmm1 := key[0]    */
1229
1230                 "pshufb %%xmm6, %%xmm2\n\t"     /* xmm2 := be(xmm2) */
1231                 "pshufb %%xmm6, %%xmm3\n\t"     /* xmm3 := be(xmm3) */
1232                 "pshufb %%xmm6, %%xmm4\n\t"     /* xmm4 := be(xmm4) */
1233                 "pshufb %%xmm6, %%xmm5\n\t"     /* xmm5 := be(xmm5) */
1234
1235                 ".Lstore_ctr%=:\n\t"
1236                 "movdqa %%xmm5, (%[ctr])\n\t"   /* Update CTR (mem).  */
1237                 :
1238                 : [ctr] "r" (ctr),
1239                   [key] "r" (ctx->keyschenc),
1240                   [addb] "r" (bige_addb)
1241                 : "%esi", "cc", "memory");
1242
1243   asm volatile ("pxor   %%xmm1, %%xmm0\n\t"     /* xmm0 ^= key[0]    */
1244                 "pxor   %%xmm1, %%xmm2\n\t"     /* xmm2 ^= key[0]    */
1245                 "pxor   %%xmm1, %%xmm3\n\t"     /* xmm3 ^= key[0]    */
1246                 "pxor   %%xmm1, %%xmm4\n\t"     /* xmm4 ^= key[0]    */
1247                 "movdqa 0x10(%[key]), %%xmm1\n\t"
1248                 aesenc_xmm1_xmm0
1249                 aesenc_xmm1_xmm2
1250                 aesenc_xmm1_xmm3
1251                 aesenc_xmm1_xmm4
1252                 "movdqa 0x20(%[key]), %%xmm1\n\t"
1253                 aesenc_xmm1_xmm0
1254                 aesenc_xmm1_xmm2
1255                 aesenc_xmm1_xmm3
1256                 aesenc_xmm1_xmm4
1257                 "movdqa 0x30(%[key]), %%xmm1\n\t"
1258                 aesenc_xmm1_xmm0
1259                 aesenc_xmm1_xmm2
1260                 aesenc_xmm1_xmm3
1261                 aesenc_xmm1_xmm4
1262                 "movdqa 0x40(%[key]), %%xmm1\n\t"
1263                 aesenc_xmm1_xmm0
1264                 aesenc_xmm1_xmm2
1265                 aesenc_xmm1_xmm3
1266                 aesenc_xmm1_xmm4
1267                 "movdqa 0x50(%[key]), %%xmm1\n\t"
1268                 aesenc_xmm1_xmm0
1269                 aesenc_xmm1_xmm2
1270                 aesenc_xmm1_xmm3
1271                 aesenc_xmm1_xmm4
1272                 "movdqa 0x60(%[key]), %%xmm1\n\t"
1273                 aesenc_xmm1_xmm0
1274                 aesenc_xmm1_xmm2
1275                 aesenc_xmm1_xmm3
1276                 aesenc_xmm1_xmm4
1277                 "movdqa 0x70(%[key]), %%xmm1\n\t"
1278                 aesenc_xmm1_xmm0
1279                 aesenc_xmm1_xmm2
1280                 aesenc_xmm1_xmm3
1281                 aesenc_xmm1_xmm4
1282                 "movdqa 0x80(%[key]), %%xmm1\n\t"
1283                 aesenc_xmm1_xmm0
1284                 aesenc_xmm1_xmm2
1285                 aesenc_xmm1_xmm3
1286                 aesenc_xmm1_xmm4
1287                 "movdqa 0x90(%[key]), %%xmm1\n\t"
1288                 aesenc_xmm1_xmm0
1289                 aesenc_xmm1_xmm2
1290                 aesenc_xmm1_xmm3
1291                 aesenc_xmm1_xmm4
1292                 "movdqa 0xa0(%[key]), %%xmm1\n\t"
1293                 "cmpl $10, %[rounds]\n\t"
1294                 "jz .Lenclast%=\n\t"
1295                 aesenc_xmm1_xmm0
1296                 aesenc_xmm1_xmm2
1297                 aesenc_xmm1_xmm3
1298                 aesenc_xmm1_xmm4
1299                 "movdqa 0xb0(%[key]), %%xmm1\n\t"
1300                 aesenc_xmm1_xmm0
1301                 aesenc_xmm1_xmm2
1302                 aesenc_xmm1_xmm3
1303                 aesenc_xmm1_xmm4
1304                 "movdqa 0xc0(%[key]), %%xmm1\n\t"
1305                 "cmpl $12, %[rounds]\n\t"
1306                 "jz .Lenclast%=\n\t"
1307                 aesenc_xmm1_xmm0
1308                 aesenc_xmm1_xmm2
1309                 aesenc_xmm1_xmm3
1310                 aesenc_xmm1_xmm4
1311                 "movdqa 0xd0(%[key]), %%xmm1\n\t"
1312                 aesenc_xmm1_xmm0
1313                 aesenc_xmm1_xmm2
1314                 aesenc_xmm1_xmm3
1315                 aesenc_xmm1_xmm4
1316                 "movdqa 0xe0(%[key]), %%xmm1\n"
1317
1318                 ".Lenclast%=:\n\t"
1319                 aesenclast_xmm1_xmm0
1320                 aesenclast_xmm1_xmm2
1321                 aesenclast_xmm1_xmm3
1322                 aesenclast_xmm1_xmm4
1323                 :
1324                 : [key] "r" (ctx->keyschenc),
1325                   [rounds] "r" (ctx->rounds)
1326                 : "cc", "memory");
1327
1328   asm volatile ("movdqu (%[src]), %%xmm1\n\t"    /* Get block 1.      */
1329                 "pxor %%xmm1, %%xmm0\n\t"        /* EncCTR-1 ^= input */
1330                 "movdqu %%xmm0, (%[dst])\n\t"    /* Store block 1     */
1331
1332                 "movdqu 16(%[src]), %%xmm1\n\t"  /* Get block 2.      */
1333                 "pxor %%xmm1, %%xmm2\n\t"        /* EncCTR-2 ^= input */
1334                 "movdqu %%xmm2, 16(%[dst])\n\t"  /* Store block 2.    */
1335
1336                 "movdqu 32(%[src]), %%xmm1\n\t"  /* Get block 3.      */
1337                 "pxor %%xmm1, %%xmm3\n\t"        /* EncCTR-3 ^= input */
1338                 "movdqu %%xmm3, 32(%[dst])\n\t"  /* Store block 3.    */
1339
1340                 "movdqu 48(%[src]), %%xmm1\n\t"  /* Get block 4.      */
1341                 "pxor %%xmm1, %%xmm4\n\t"        /* EncCTR-4 ^= input */
1342                 "movdqu %%xmm4, 48(%[dst])"      /* Store block 4.   */
1343                 :
1344                 : [src] "r" (a),
1345                   [dst] "r" (b)
1346                 : "memory");
1347 #undef aesenc_xmm1_xmm0
1348 #undef aesenc_xmm1_xmm2
1349 #undef aesenc_xmm1_xmm3
1350 #undef aesenc_xmm1_xmm4
1351 #undef aesenclast_xmm1_xmm0
1352 #undef aesenclast_xmm1_xmm2
1353 #undef aesenclast_xmm1_xmm3
1354 #undef aesenclast_xmm1_xmm4
1355 }
1356
1357
1358 #ifdef __x86_64__
1359
1360 /* Eight blocks at a time variant of do_aesni_ctr.  */
1361 static void
1362 do_aesni_ctr_8 (const RIJNDAEL_context *ctx,
1363                 unsigned char *ctr, unsigned char *b, const unsigned char *a)
1364 {
1365   static const byte bige_addb_const[8][16] __attribute__ ((aligned (16))) =
1366     {
1367       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
1368       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 },
1369       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3 },
1370       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4 },
1371       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5 },
1372       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 },
1373       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7 },
1374       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8 }
1375     };
1376   const void *bige_addb = bige_addb_const;
1377
1378   /* Register usage:
1379       [key] keyschedule
1380       xmm0  CTR-0
1381       xmm1  temp / round key
1382       xmm2  CTR-1
1383       xmm3  CTR-2
1384       xmm4  CTR-3
1385       xmm5  copy of *ctr
1386       xmm6  endian swapping mask
1387       xmm8  CTR-4
1388       xmm9  CTR-5
1389       xmm10 CTR-6
1390       xmm11 CTR-7
1391       xmm12 temp
1392       xmm13 temp
1393       xmm14 temp
1394       xmm15 temp
1395    */
1396
1397   asm volatile (/* detect if 8-bit carry handling is needed */
1398                 "cmpb   $0xf7, 15(%[ctr])\n\t"
1399                 "ja     .Ladd32bit%=\n\t"
1400
1401                 "movdqa %%xmm5, %%xmm0\n\t"     /* xmm0 := CTR (xmm5) */
1402                 "movdqa 0*16(%[addb]), %%xmm2\n\t"  /* xmm2 := be(1) */
1403                 "movdqa 1*16(%[addb]), %%xmm3\n\t"  /* xmm3 := be(2) */
1404                 "movdqa 2*16(%[addb]), %%xmm4\n\t"  /* xmm4 := be(3) */
1405                 "movdqa 3*16(%[addb]), %%xmm8\n\t"  /* xmm8 := be(4) */
1406                 "movdqa 4*16(%[addb]), %%xmm9\n\t"  /* xmm9 := be(5) */
1407                 "movdqa 5*16(%[addb]), %%xmm10\n\t" /* xmm10 := be(6) */
1408                 "movdqa 6*16(%[addb]), %%xmm11\n\t" /* xmm11 := be(7) */
1409                 "movdqa 7*16(%[addb]), %%xmm5\n\t"  /* xmm5 := be(8) */
1410                 "movdqa (%[key]), %%xmm1\n\t"   /* xmm1 := key[0] */
1411                 "paddb  %%xmm0, %%xmm2\n\t"     /* xmm2 := be(1) + CTR (xmm0) */
1412                 "paddb  %%xmm0, %%xmm3\n\t"     /* xmm3 := be(2) + CTR (xmm0) */
1413                 "paddb  %%xmm0, %%xmm4\n\t"     /* xmm4 := be(3) + CTR (xmm0) */
1414                 "paddb  %%xmm0, %%xmm8\n\t"     /* xmm8 := be(4) + CTR (xmm0) */
1415                 "paddb  %%xmm0, %%xmm9\n\t"     /* xmm9 := be(5) + CTR (xmm0) */
1416                 "paddb  %%xmm0, %%xmm10\n\t"    /* xmm10 := be(6) + CTR (xmm0) */
1417                 "paddb  %%xmm0, %%xmm11\n\t"    /* xmm11 := be(7) + CTR (xmm0) */
1418                 "paddb  %%xmm0, %%xmm5\n\t"     /* xmm5 := be(8) + CTR (xmm0) */
1419                 "jmp    .Lstore_ctr%=\n\t"
1420
1421                 ".Ladd32bit%=:\n\t"
1422                 "movdqa %%xmm5, %%xmm0\n\t"     /* xmm0, xmm2 := CTR (xmm5) */
1423                 "movdqa %%xmm0, %%xmm2\n\t"
1424                 "pcmpeqd %%xmm1, %%xmm1\n\t"
1425                 "psrldq $8, %%xmm1\n\t"         /* xmm1 = -1 */
1426
1427                 "pshufb %%xmm6, %%xmm2\n\t"     /* xmm2 := le(xmm2) */
1428                 "psubq  %%xmm1, %%xmm2\n\t"     /* xmm2++           */
1429                 "movdqa %%xmm2, %%xmm3\n\t"     /* xmm3 := xmm2     */
1430                 "psubq  %%xmm1, %%xmm3\n\t"     /* xmm3++           */
1431                 "movdqa %%xmm3, %%xmm4\n\t"     /* xmm4 := xmm3     */
1432                 "psubq  %%xmm1, %%xmm4\n\t"     /* xmm4++           */
1433                 "movdqa %%xmm4, %%xmm8\n\t"     /* xmm8 := xmm4     */
1434                 "psubq  %%xmm1, %%xmm8\n\t"     /* xmm8++           */
1435                 "movdqa %%xmm8, %%xmm9\n\t"     /* xmm9 := xmm8     */
1436                 "psubq  %%xmm1, %%xmm9\n\t"     /* xmm9++           */
1437                 "movdqa %%xmm9, %%xmm10\n\t"    /* xmm10 := xmm9    */
1438                 "psubq  %%xmm1, %%xmm10\n\t"    /* xmm10++          */
1439                 "movdqa %%xmm10, %%xmm11\n\t"   /* xmm11 := xmm10   */
1440                 "psubq  %%xmm1, %%xmm11\n\t"    /* xmm11++          */
1441                 "movdqa %%xmm11, %%xmm5\n\t"    /* xmm5 := xmm11    */
1442                 "psubq  %%xmm1, %%xmm5\n\t"     /* xmm5++           */
1443
1444                 /* detect if 64-bit carry handling is needed */
1445                 "cmpl   $0xffffffff, 8(%[ctr])\n\t"
1446                 "jne    .Lno_carry%=\n\t"
1447                 "movl   12(%[ctr]), %%esi\n\t"
1448                 "bswapl %%esi\n\t"
1449                 "cmpl   $0xfffffff8, %%esi\n\t"
1450                 "jb     .Lno_carry%=\n\t"       /* no carry */
1451
1452                 "pslldq $8, %%xmm1\n\t"         /* move lower 64-bit to high */
1453                 "je     .Lcarry_xmm5%=\n\t"     /* esi == 0xfffffff8 */
1454                 "cmpl   $0xfffffffa, %%esi\n\t"
1455                 "jb     .Lcarry_xmm11%=\n\t"     /* esi == 0xfffffff9 */
1456                 "je     .Lcarry_xmm10%=\n\t"     /* esi == 0xfffffffa */
1457                 "cmpl   $0xfffffffc, %%esi\n\t"
1458                 "jb     .Lcarry_xmm9%=\n\t"     /* esi == 0xfffffffb */
1459                 "je     .Lcarry_xmm8%=\n\t"     /* esi == 0xfffffffc */
1460                 "cmpl   $0xfffffffe, %%esi\n\t"
1461                 "jb     .Lcarry_xmm4%=\n\t"     /* esi == 0xfffffffd */
1462                 "je     .Lcarry_xmm3%=\n\t"     /* esi == 0xfffffffe */
1463                 /* esi == 0xffffffff */
1464
1465                 "psubq   %%xmm1, %%xmm2\n\t"
1466                 ".Lcarry_xmm3%=:\n\t"
1467                 "psubq   %%xmm1, %%xmm3\n\t"
1468                 ".Lcarry_xmm4%=:\n\t"
1469                 "psubq   %%xmm1, %%xmm4\n\t"
1470                 ".Lcarry_xmm8%=:\n\t"
1471                 "psubq   %%xmm1, %%xmm8\n\t"
1472                 ".Lcarry_xmm9%=:\n\t"
1473                 "psubq   %%xmm1, %%xmm9\n\t"
1474                 ".Lcarry_xmm10%=:\n\t"
1475                 "psubq   %%xmm1, %%xmm10\n\t"
1476                 ".Lcarry_xmm11%=:\n\t"
1477                 "psubq   %%xmm1, %%xmm11\n\t"
1478                 ".Lcarry_xmm5%=:\n\t"
1479                 "psubq   %%xmm1, %%xmm5\n\t"
1480
1481                 ".Lno_carry%=:\n\t"
1482                 "movdqa (%[key]), %%xmm1\n\t"   /* xmm1 := key[0]    */
1483
1484                 "pshufb %%xmm6, %%xmm2\n\t"     /* xmm2 := be(xmm2) */
1485                 "pshufb %%xmm6, %%xmm3\n\t"     /* xmm3 := be(xmm3) */
1486                 "pshufb %%xmm6, %%xmm4\n\t"     /* xmm4 := be(xmm4) */
1487                 "pshufb %%xmm6, %%xmm5\n\t"     /* xmm5 := be(xmm5) */
1488                 "pshufb %%xmm6, %%xmm8\n\t"     /* xmm8 := be(xmm8) */
1489                 "pshufb %%xmm6, %%xmm9\n\t"     /* xmm9 := be(xmm9) */
1490                 "pshufb %%xmm6, %%xmm10\n\t"    /* xmm10 := be(xmm10) */
1491                 "pshufb %%xmm6, %%xmm11\n\t"    /* xmm11 := be(xmm11) */
1492
1493                 ".Lstore_ctr%=:\n\t"
1494                 "movdqa %%xmm5, (%[ctr])\n\t"   /* Update CTR (mem).  */
1495                 :
1496                 : [ctr] "r" (ctr),
1497                   [key] "r" (ctx->keyschenc),
1498                   [addb] "r" (bige_addb)
1499                 : "%esi", "cc", "memory");
1500
1501   asm volatile ("pxor   %%xmm1, %%xmm0\n\t"     /* xmm0 ^= key[0]    */
1502                 "pxor   %%xmm1, %%xmm2\n\t"     /* xmm2 ^= key[0]    */
1503                 "pxor   %%xmm1, %%xmm3\n\t"     /* xmm3 ^= key[0]    */
1504                 "pxor   %%xmm1, %%xmm4\n\t"     /* xmm4 ^= key[0]    */
1505                 "pxor   %%xmm1, %%xmm8\n\t"     /* xmm8 ^= key[0]    */
1506                 "pxor   %%xmm1, %%xmm9\n\t"     /* xmm9 ^= key[0]    */
1507                 "pxor   %%xmm1, %%xmm10\n\t"    /* xmm10 ^= key[0]   */
1508                 "pxor   %%xmm1, %%xmm11\n\t"    /* xmm11 ^= key[0]   */
1509                 "movdqa 0x10(%[key]), %%xmm1\n\t"
1510                 "cmpl $12, %[rounds]\n\t"
1511                 "aesenc %%xmm1, %%xmm0\n\t"
1512                 "aesenc %%xmm1, %%xmm2\n\t"
1513                 "aesenc %%xmm1, %%xmm3\n\t"
1514                 "aesenc %%xmm1, %%xmm4\n\t"
1515                 "aesenc %%xmm1, %%xmm8\n\t"
1516                 "aesenc %%xmm1, %%xmm9\n\t"
1517                 "aesenc %%xmm1, %%xmm10\n\t"
1518                 "aesenc %%xmm1, %%xmm11\n\t"
1519                 "movdqa 0x20(%[key]), %%xmm1\n\t"
1520                 "aesenc %%xmm1, %%xmm0\n\t"
1521                 "aesenc %%xmm1, %%xmm2\n\t"
1522                 "aesenc %%xmm1, %%xmm3\n\t"
1523                 "aesenc %%xmm1, %%xmm4\n\t"
1524                 "aesenc %%xmm1, %%xmm8\n\t"
1525                 "aesenc %%xmm1, %%xmm9\n\t"
1526                 "aesenc %%xmm1, %%xmm10\n\t"
1527                 "aesenc %%xmm1, %%xmm11\n\t"
1528                 "movdqa 0x30(%[key]), %%xmm1\n\t"
1529                 "aesenc %%xmm1, %%xmm0\n\t"
1530                 "aesenc %%xmm1, %%xmm2\n\t"
1531                 "aesenc %%xmm1, %%xmm3\n\t"
1532                 "aesenc %%xmm1, %%xmm4\n\t"
1533                 "aesenc %%xmm1, %%xmm8\n\t"
1534                 "aesenc %%xmm1, %%xmm9\n\t"
1535                 "aesenc %%xmm1, %%xmm10\n\t"
1536                 "aesenc %%xmm1, %%xmm11\n\t"
1537                 "movdqa 0x40(%[key]), %%xmm1\n\t"
1538                 "aesenc %%xmm1, %%xmm0\n\t"
1539                 "aesenc %%xmm1, %%xmm2\n\t"
1540                 "aesenc %%xmm1, %%xmm3\n\t"
1541                 "aesenc %%xmm1, %%xmm4\n\t"
1542                 "aesenc %%xmm1, %%xmm8\n\t"
1543                 "aesenc %%xmm1, %%xmm9\n\t"
1544                 "aesenc %%xmm1, %%xmm10\n\t"
1545                 "aesenc %%xmm1, %%xmm11\n\t"
1546                 "movdqa 0x50(%[key]), %%xmm1\n\t"
1547                 "aesenc %%xmm1, %%xmm0\n\t"
1548                 "aesenc %%xmm1, %%xmm2\n\t"
1549                 "aesenc %%xmm1, %%xmm3\n\t"
1550                 "aesenc %%xmm1, %%xmm4\n\t"
1551                 "aesenc %%xmm1, %%xmm8\n\t"
1552                 "aesenc %%xmm1, %%xmm9\n\t"
1553                 "aesenc %%xmm1, %%xmm10\n\t"
1554                 "aesenc %%xmm1, %%xmm11\n\t"
1555                 "movdqa 0x60(%[key]), %%xmm1\n\t"
1556                 "aesenc %%xmm1, %%xmm0\n\t"
1557                 "aesenc %%xmm1, %%xmm2\n\t"
1558                 "aesenc %%xmm1, %%xmm3\n\t"
1559                 "aesenc %%xmm1, %%xmm4\n\t"
1560                 "aesenc %%xmm1, %%xmm8\n\t"
1561                 "aesenc %%xmm1, %%xmm9\n\t"
1562                 "aesenc %%xmm1, %%xmm10\n\t"
1563                 "aesenc %%xmm1, %%xmm11\n\t"
1564                 "movdqa 0x70(%[key]), %%xmm1\n\t"
1565                 "aesenc %%xmm1, %%xmm0\n\t"
1566                 "aesenc %%xmm1, %%xmm2\n\t"
1567                 "aesenc %%xmm1, %%xmm3\n\t"
1568                 "aesenc %%xmm1, %%xmm4\n\t"
1569                 "aesenc %%xmm1, %%xmm8\n\t"
1570                 "aesenc %%xmm1, %%xmm9\n\t"
1571                 "aesenc %%xmm1, %%xmm10\n\t"
1572                 "aesenc %%xmm1, %%xmm11\n\t"
1573                 "movdqa 0x80(%[key]), %%xmm1\n\t"
1574                 "aesenc %%xmm1, %%xmm0\n\t"
1575                 "aesenc %%xmm1, %%xmm2\n\t"
1576                 "aesenc %%xmm1, %%xmm3\n\t"
1577                 "aesenc %%xmm1, %%xmm4\n\t"
1578                 "aesenc %%xmm1, %%xmm8\n\t"
1579                 "aesenc %%xmm1, %%xmm9\n\t"
1580                 "aesenc %%xmm1, %%xmm10\n\t"
1581                 "aesenc %%xmm1, %%xmm11\n\t"
1582                 "movdqa 0x90(%[key]), %%xmm1\n\t"
1583                 "aesenc %%xmm1, %%xmm0\n\t"
1584                 "aesenc %%xmm1, %%xmm2\n\t"
1585                 "aesenc %%xmm1, %%xmm3\n\t"
1586                 "aesenc %%xmm1, %%xmm4\n\t"
1587                 "aesenc %%xmm1, %%xmm8\n\t"
1588                 "aesenc %%xmm1, %%xmm9\n\t"
1589                 "aesenc %%xmm1, %%xmm10\n\t"
1590                 "aesenc %%xmm1, %%xmm11\n\t"
1591                 "movdqa 0xa0(%[key]), %%xmm1\n\t"
1592                 "jb .Lenclast%=\n\t"
1593                 "aesenc %%xmm1, %%xmm0\n\t"
1594                 "aesenc %%xmm1, %%xmm2\n\t"
1595                 "aesenc %%xmm1, %%xmm3\n\t"
1596                 "aesenc %%xmm1, %%xmm4\n\t"
1597                 "aesenc %%xmm1, %%xmm8\n\t"
1598                 "aesenc %%xmm1, %%xmm9\n\t"
1599                 "aesenc %%xmm1, %%xmm10\n\t"
1600                 "aesenc %%xmm1, %%xmm11\n\t"
1601                 "movdqa 0xb0(%[key]), %%xmm1\n\t"
1602                 "aesenc %%xmm1, %%xmm0\n\t"
1603                 "aesenc %%xmm1, %%xmm2\n\t"
1604                 "aesenc %%xmm1, %%xmm3\n\t"
1605                 "aesenc %%xmm1, %%xmm4\n\t"
1606                 "aesenc %%xmm1, %%xmm8\n\t"
1607                 "aesenc %%xmm1, %%xmm9\n\t"
1608                 "aesenc %%xmm1, %%xmm10\n\t"
1609                 "aesenc %%xmm1, %%xmm11\n\t"
1610                 "movdqa 0xc0(%[key]), %%xmm1\n\t"
1611                 "je .Lenclast%=\n\t"
1612                 "aesenc %%xmm1, %%xmm0\n\t"
1613                 "aesenc %%xmm1, %%xmm2\n\t"
1614                 "aesenc %%xmm1, %%xmm3\n\t"
1615                 "aesenc %%xmm1, %%xmm4\n\t"
1616                 "aesenc %%xmm1, %%xmm8\n\t"
1617                 "aesenc %%xmm1, %%xmm9\n\t"
1618                 "aesenc %%xmm1, %%xmm10\n\t"
1619                 "aesenc %%xmm1, %%xmm11\n\t"
1620                 "movdqa 0xd0(%[key]), %%xmm1\n\t"
1621                 "aesenc %%xmm1, %%xmm0\n\t"
1622                 "aesenc %%xmm1, %%xmm2\n\t"
1623                 "aesenc %%xmm1, %%xmm3\n\t"
1624                 "aesenc %%xmm1, %%xmm4\n\t"
1625                 "aesenc %%xmm1, %%xmm8\n\t"
1626                 "aesenc %%xmm1, %%xmm9\n\t"
1627                 "aesenc %%xmm1, %%xmm10\n\t"
1628                 "aesenc %%xmm1, %%xmm11\n\t"
1629                 "movdqa 0xe0(%[key]), %%xmm1\n"
1630
1631                 ".Lenclast%=:\n\t"
1632                 "aesenclast %%xmm1, %%xmm0\n\t"
1633                 "aesenclast %%xmm1, %%xmm2\n\t"
1634                 "aesenclast %%xmm1, %%xmm3\n\t"
1635                 "aesenclast %%xmm1, %%xmm4\n\t"
1636                 "aesenclast %%xmm1, %%xmm8\n\t"
1637                 "aesenclast %%xmm1, %%xmm9\n\t"
1638                 "aesenclast %%xmm1, %%xmm10\n\t"
1639                 "aesenclast %%xmm1, %%xmm11\n\t"
1640                 :
1641                 : [key] "r" (ctx->keyschenc),
1642                   [rounds] "r" (ctx->rounds)
1643                 : "cc", "memory");
1644
1645   asm volatile ("movdqu 0*16(%[src]), %%xmm12\n\t" /* Get block 1.      */
1646                 "movdqu 1*16(%[src]), %%xmm13\n\t" /* Get block 2.      */
1647                 "movdqu 2*16(%[src]), %%xmm14\n\t" /* Get block 3.      */
1648                 "movdqu 3*16(%[src]), %%xmm15\n\t" /* Get block 4.      */
1649                 "movdqu 4*16(%[src]), %%xmm1\n\t"  /* Get block 5.      */
1650                 "pxor %%xmm12, %%xmm0\n\t"         /* EncCTR-1 ^= input */
1651                 "movdqu 5*16(%[src]), %%xmm12\n\t" /* Get block 6.      */
1652                 "pxor %%xmm13, %%xmm2\n\t"         /* EncCTR-2 ^= input */
1653                 "movdqu 6*16(%[src]), %%xmm13\n\t" /* Get block 7.      */
1654                 "pxor %%xmm14, %%xmm3\n\t"         /* EncCTR-3 ^= input */
1655                 "movdqu 7*16(%[src]), %%xmm14\n\t" /* Get block 8.      */
1656                 "pxor %%xmm15, %%xmm4\n\t"         /* EncCTR-4 ^= input */
1657                 "movdqu %%xmm0, 0*16(%[dst])\n\t"  /* Store block 1     */
1658                 "pxor %%xmm1,  %%xmm8\n\t"         /* EncCTR-5 ^= input */
1659                 "movdqu %%xmm0, 0*16(%[dst])\n\t"  /* Store block 1     */
1660                 "pxor %%xmm12, %%xmm9\n\t"         /* EncCTR-6 ^= input */
1661                 "movdqu %%xmm2, 1*16(%[dst])\n\t"  /* Store block 2.    */
1662                 "pxor %%xmm13, %%xmm10\n\t"        /* EncCTR-7 ^= input */
1663                 "movdqu %%xmm3, 2*16(%[dst])\n\t"  /* Store block 3.    */
1664                 "pxor %%xmm14, %%xmm11\n\t"        /* EncCTR-8 ^= input */
1665                 "movdqu %%xmm4, 3*16(%[dst])\n\t"  /* Store block 4.    */
1666                 "movdqu %%xmm8, 4*16(%[dst])\n\t"  /* Store block 8.    */
1667                 "movdqu %%xmm9, 5*16(%[dst])\n\t"  /* Store block 9.    */
1668                 "movdqu %%xmm10, 6*16(%[dst])\n\t" /* Store block 10.   */
1669                 "movdqu %%xmm11, 7*16(%[dst])\n\t" /* Store block 11.   */
1670                 :
1671                 : [src] "r" (a),
1672                   [dst] "r" (b)
1673                 : "memory");
1674 }
1675
1676 #endif /* __x86_64__ */
1677
1678
1679 unsigned int
1680 _gcry_aes_aesni_encrypt (const RIJNDAEL_context *ctx, unsigned char *dst,
1681                          const unsigned char *src)
1682 {
1683   aesni_prepare ();
1684   asm volatile ("movdqu %[src], %%xmm0\n\t"
1685                 :
1686                 : [src] "m" (*src)
1687                 : "memory" );
1688   do_aesni_enc (ctx);
1689   asm volatile ("movdqu %%xmm0, %[dst]\n\t"
1690                 : [dst] "=m" (*dst)
1691                 :
1692                 : "memory" );
1693   aesni_cleanup ();
1694   return 0;
1695 }
1696
1697
1698 void
1699 _gcry_aes_aesni_cfb_enc (RIJNDAEL_context *ctx, unsigned char *outbuf,
1700                          const unsigned char *inbuf, unsigned char *iv,
1701                          size_t nblocks)
1702 {
1703   aesni_prepare ();
1704
1705   asm volatile ("movdqu %[iv], %%xmm0\n\t"
1706                 : /* No output */
1707                 : [iv] "m" (*iv)
1708                 : "memory" );
1709
1710   for ( ;nblocks; nblocks-- )
1711     {
1712       do_aesni_enc (ctx);
1713
1714       asm volatile ("movdqu %[inbuf], %%xmm1\n\t"
1715                     "pxor %%xmm1, %%xmm0\n\t"
1716                     "movdqu %%xmm0, %[outbuf]\n\t"
1717                     : [outbuf] "=m" (*outbuf)
1718                     : [inbuf] "m" (*inbuf)
1719                     : "memory" );
1720
1721       outbuf += BLOCKSIZE;
1722       inbuf  += BLOCKSIZE;
1723     }
1724
1725   asm volatile ("movdqu %%xmm0, %[iv]\n\t"
1726                 : [iv] "=m" (*iv)
1727                 :
1728                 : "memory" );
1729
1730   aesni_cleanup ();
1731 }
1732
1733
1734 void
1735 _gcry_aes_aesni_cbc_enc (RIJNDAEL_context *ctx, unsigned char *outbuf,
1736                          const unsigned char *inbuf, unsigned char *iv,
1737                          size_t nblocks, int cbc_mac)
1738 {
1739   aesni_prepare_2_6_variable;
1740
1741   aesni_prepare ();
1742   aesni_prepare_2_6();
1743
1744   asm volatile ("movdqu %[iv], %%xmm5\n\t"
1745                 : /* No output */
1746                 : [iv] "m" (*iv)
1747                 : "memory" );
1748
1749   for ( ;nblocks; nblocks-- )
1750     {
1751       asm volatile ("movdqu %[inbuf], %%xmm0\n\t"
1752                     "pxor %%xmm5, %%xmm0\n\t"
1753                     : /* No output */
1754                     : [inbuf] "m" (*inbuf)
1755                     : "memory" );
1756
1757       do_aesni_enc (ctx);
1758
1759       asm volatile ("movdqa %%xmm0, %%xmm5\n\t"
1760                     "movdqu %%xmm0, %[outbuf]\n\t"
1761                     : [outbuf] "=m" (*outbuf)
1762                     :
1763                     : "memory" );
1764
1765       inbuf += BLOCKSIZE;
1766       if (!cbc_mac)
1767         outbuf += BLOCKSIZE;
1768     }
1769
1770   asm volatile ("movdqu %%xmm5, %[iv]\n\t"
1771                 : [iv] "=m" (*iv)
1772                 :
1773                 : "memory" );
1774
1775   aesni_cleanup ();
1776   aesni_cleanup_2_6 ();
1777 }
1778
1779
1780 void
1781 _gcry_aes_aesni_ctr_enc (RIJNDAEL_context *ctx, unsigned char *outbuf,
1782                          const unsigned char *inbuf, unsigned char *ctr,
1783                          size_t nblocks)
1784 {
1785   static const unsigned char be_mask[16] __attribute__ ((aligned (16))) =
1786     { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
1787   aesni_prepare_2_6_variable;
1788
1789   aesni_prepare ();
1790   aesni_prepare_2_6();
1791
1792   asm volatile ("movdqa %[mask], %%xmm6\n\t" /* Preload mask */
1793                 "movdqa %[ctr], %%xmm5\n\t"  /* Preload CTR */
1794                 : /* No output */
1795                 : [mask] "m" (*be_mask),
1796                   [ctr] "m" (*ctr)
1797                 : "memory");
1798
1799 #ifdef __x86_64__
1800   if (nblocks >= 8)
1801     {
1802       aesni_prepare_7_15_variable;
1803
1804       aesni_prepare_7_15();
1805
1806       for ( ;nblocks >= 8 ; nblocks -= 8 )
1807         {
1808           do_aesni_ctr_8 (ctx, ctr, outbuf, inbuf);
1809           outbuf += 8*BLOCKSIZE;
1810           inbuf  += 8*BLOCKSIZE;
1811         }
1812
1813       aesni_cleanup_7_15();
1814     }
1815 #endif
1816
1817   for ( ;nblocks >= 4 ; nblocks -= 4 )
1818     {
1819       do_aesni_ctr_4 (ctx, ctr, outbuf, inbuf);
1820       outbuf += 4*BLOCKSIZE;
1821       inbuf  += 4*BLOCKSIZE;
1822     }
1823   for ( ;nblocks; nblocks-- )
1824     {
1825       do_aesni_ctr (ctx, ctr, outbuf, inbuf);
1826       outbuf += BLOCKSIZE;
1827       inbuf  += BLOCKSIZE;
1828     }
1829   aesni_cleanup ();
1830   aesni_cleanup_2_6 ();
1831 }
1832
1833
1834 unsigned int
1835 _gcry_aes_aesni_decrypt (const RIJNDAEL_context *ctx, unsigned char *dst,
1836                          const unsigned char *src)
1837 {
1838   aesni_prepare ();
1839   asm volatile ("movdqu %[src], %%xmm0\n\t"
1840                 :
1841                 : [src] "m" (*src)
1842                 : "memory" );
1843   do_aesni_dec (ctx);
1844   asm volatile ("movdqu %%xmm0, %[dst]\n\t"
1845                 : [dst] "=m" (*dst)
1846                 :
1847                 : "memory" );
1848   aesni_cleanup ();
1849   return 0;
1850 }
1851
1852
1853 void
1854 _gcry_aes_aesni_cfb_dec (RIJNDAEL_context *ctx, unsigned char *outbuf,
1855                          const unsigned char *inbuf, unsigned char *iv,
1856                          size_t nblocks)
1857 {
1858   aesni_prepare_2_6_variable;
1859
1860   aesni_prepare ();
1861   aesni_prepare_2_6();
1862
1863   asm volatile ("movdqu %[iv], %%xmm6\n\t"
1864                 : /* No output */
1865                 : [iv] "m" (*iv)
1866                 : "memory" );
1867
1868   /* CFB decryption can be parallelized */
1869
1870 #ifdef __x86_64__
1871   if (nblocks >= 8)
1872     {
1873       aesni_prepare_7_15_variable;
1874
1875       aesni_prepare_7_15();
1876
1877       for ( ;nblocks >= 8; nblocks -= 8)
1878         {
1879           asm volatile
1880             ("movdqu %%xmm6,         %%xmm1\n\t" /* load input blocks */
1881              "movdqu 0*16(%[inbuf]), %%xmm2\n\t"
1882              "movdqu 1*16(%[inbuf]), %%xmm3\n\t"
1883              "movdqu 2*16(%[inbuf]), %%xmm4\n\t"
1884              "movdqu 3*16(%[inbuf]), %%xmm8\n\t"
1885              "movdqu 4*16(%[inbuf]), %%xmm9\n\t"
1886              "movdqu 5*16(%[inbuf]), %%xmm10\n\t"
1887              "movdqu 6*16(%[inbuf]), %%xmm11\n\t"
1888
1889              "movdqu 7*16(%[inbuf]), %%xmm6\n\t" /* update IV */
1890
1891              "movdqa %%xmm2, %%xmm12\n\t"
1892              "movdqa %%xmm3, %%xmm13\n\t"
1893              "movdqa %%xmm4, %%xmm14\n\t"
1894              "movdqa %%xmm8, %%xmm15\n\t"
1895              : /* No output */
1896              : [inbuf] "r" (inbuf)
1897              : "memory");
1898
1899           do_aesni_enc_vec8 (ctx);
1900
1901           asm volatile
1902             (
1903              "pxor %%xmm12, %%xmm1\n\t"
1904              "movdqu 4*16(%[inbuf]), %%xmm12\n\t"
1905              "pxor %%xmm13, %%xmm2\n\t"
1906              "movdqu 5*16(%[inbuf]), %%xmm13\n\t"
1907              "pxor %%xmm14, %%xmm3\n\t"
1908              "movdqu 6*16(%[inbuf]), %%xmm14\n\t"
1909              "pxor %%xmm15, %%xmm4\n\t"
1910              "movdqu 7*16(%[inbuf]), %%xmm15\n\t"
1911
1912              "pxor %%xmm12, %%xmm8\n\t"
1913              "movdqu %%xmm1, 0*16(%[outbuf])\n\t"
1914              "pxor %%xmm13, %%xmm9\n\t"
1915              "movdqu %%xmm2, 1*16(%[outbuf])\n\t"
1916              "pxor %%xmm14, %%xmm10\n\t"
1917              "movdqu %%xmm3, 2*16(%[outbuf])\n\t"
1918              "pxor %%xmm15, %%xmm11\n\t"
1919              "movdqu %%xmm4, 3*16(%[outbuf])\n\t"
1920
1921              "movdqu %%xmm8, 4*16(%[outbuf])\n\t"
1922              "movdqu %%xmm9, 5*16(%[outbuf])\n\t"
1923              "movdqu %%xmm10, 6*16(%[outbuf])\n\t"
1924              "movdqu %%xmm11, 7*16(%[outbuf])\n\t"
1925
1926              : /* No output */
1927              : [inbuf] "r" (inbuf),
1928                [outbuf] "r" (outbuf)
1929              : "memory");
1930
1931           outbuf += 8*BLOCKSIZE;
1932           inbuf  += 8*BLOCKSIZE;
1933         }
1934
1935       aesni_cleanup_7_15();
1936     }
1937 #endif
1938
1939   for ( ;nblocks >= 4; nblocks -= 4)
1940     {
1941       asm volatile
1942         ("movdqu %%xmm6,         %%xmm1\n\t" /* load input blocks */
1943          "movdqu 0*16(%[inbuf]), %%xmm2\n\t"
1944          "movdqu 1*16(%[inbuf]), %%xmm3\n\t"
1945          "movdqu 2*16(%[inbuf]), %%xmm4\n\t"
1946
1947          "movdqu 3*16(%[inbuf]), %%xmm6\n\t" /* update IV */
1948          : /* No output */
1949          : [inbuf] "r" (inbuf)
1950          : "memory");
1951
1952       do_aesni_enc_vec4 (ctx);
1953
1954       asm volatile
1955         ("movdqu 0*16(%[inbuf]), %%xmm5\n\t"
1956          "pxor %%xmm5, %%xmm1\n\t"
1957          "movdqu %%xmm1, 0*16(%[outbuf])\n\t"
1958
1959          "movdqu 1*16(%[inbuf]), %%xmm5\n\t"
1960          "pxor %%xmm5, %%xmm2\n\t"
1961          "movdqu %%xmm2, 1*16(%[outbuf])\n\t"
1962
1963          "movdqu 2*16(%[inbuf]), %%xmm5\n\t"
1964          "pxor %%xmm5, %%xmm3\n\t"
1965          "movdqu %%xmm3, 2*16(%[outbuf])\n\t"
1966
1967          "movdqu 3*16(%[inbuf]), %%xmm5\n\t"
1968          "pxor %%xmm5, %%xmm4\n\t"
1969          "movdqu %%xmm4, 3*16(%[outbuf])\n\t"
1970
1971          : /* No output */
1972          : [inbuf] "r" (inbuf),
1973            [outbuf] "r" (outbuf)
1974          : "memory");
1975
1976       outbuf += 4*BLOCKSIZE;
1977       inbuf  += 4*BLOCKSIZE;
1978     }
1979
1980   asm volatile ("movdqu %%xmm6, %%xmm0\n\t" ::: "cc");
1981
1982   for ( ;nblocks; nblocks-- )
1983     {
1984       do_aesni_enc (ctx);
1985
1986       asm volatile ("movdqa %%xmm0, %%xmm6\n\t"
1987                     "movdqu %[inbuf], %%xmm0\n\t"
1988                     "pxor %%xmm0, %%xmm6\n\t"
1989                     "movdqu %%xmm6, %[outbuf]\n\t"
1990                     : [outbuf] "=m" (*outbuf)
1991                     : [inbuf] "m" (*inbuf)
1992                     : "memory" );
1993
1994       outbuf += BLOCKSIZE;
1995       inbuf  += BLOCKSIZE;
1996     }
1997
1998   asm volatile ("movdqu %%xmm0, %[iv]\n\t"
1999                 : [iv] "=m" (*iv)
2000                 :
2001                 : "memory" );
2002
2003   aesni_cleanup ();
2004   aesni_cleanup_2_6 ();
2005 }
2006
2007
2008 void
2009 _gcry_aes_aesni_cbc_dec (RIJNDAEL_context *ctx, unsigned char *outbuf,
2010                          const unsigned char *inbuf, unsigned char *iv,
2011                          size_t nblocks)
2012 {
2013   aesni_prepare_2_6_variable;
2014
2015   aesni_prepare ();
2016   aesni_prepare_2_6();
2017
2018   asm volatile
2019     ("movdqu %[iv], %%xmm5\n\t" /* use xmm5 as fast IV storage */
2020      : /* No output */
2021      : [iv] "m" (*iv)
2022      : "memory");
2023
2024 #ifdef __x86_64__
2025   if (nblocks >= 8)
2026     {
2027       aesni_prepare_7_15_variable;
2028
2029       aesni_prepare_7_15();
2030
2031       for ( ;nblocks >= 8 ; nblocks -= 8 )
2032         {
2033           asm volatile
2034             ("movdqu 0*16(%[inbuf]), %%xmm1\n\t"        /* load input blocks */
2035              "movdqu 1*16(%[inbuf]), %%xmm2\n\t"
2036              "movdqu 2*16(%[inbuf]), %%xmm3\n\t"
2037              "movdqu 3*16(%[inbuf]), %%xmm4\n\t"
2038              "movdqu 4*16(%[inbuf]), %%xmm8\n\t"
2039              "movdqu 5*16(%[inbuf]), %%xmm9\n\t"
2040              "movdqu 6*16(%[inbuf]), %%xmm10\n\t"
2041              "movdqu 7*16(%[inbuf]), %%xmm11\n\t"
2042
2043              "movdqa %%xmm1, %%xmm12\n\t"
2044              "movdqa %%xmm2, %%xmm13\n\t"
2045              "movdqa %%xmm3, %%xmm14\n\t"
2046              "movdqa %%xmm4, %%xmm15\n\t"
2047
2048              : /* No output */
2049              : [inbuf] "r" (inbuf)
2050              : "memory");
2051
2052           do_aesni_dec_vec8 (ctx);
2053
2054           asm volatile
2055             ("pxor %%xmm5, %%xmm1\n\t"          /* xor IV with output */
2056
2057              "pxor %%xmm12, %%xmm2\n\t"         /* xor IV with output */
2058              "movdqu 4*16(%[inbuf]), %%xmm12\n\t"
2059
2060              "pxor %%xmm13, %%xmm3\n\t"         /* xor IV with output */
2061              "movdqu 5*16(%[inbuf]), %%xmm13\n\t"
2062
2063              "pxor %%xmm14, %%xmm4\n\t"         /* xor IV with output */
2064              "movdqu 6*16(%[inbuf]), %%xmm14\n\t"
2065
2066              "pxor %%xmm15, %%xmm8\n\t"         /* xor IV with output */
2067              "movdqu 7*16(%[inbuf]), %%xmm5\n\t"
2068              "pxor %%xmm12, %%xmm9\n\t"         /* xor IV with output */
2069              "movdqu %%xmm1, 0*16(%[outbuf])\n\t"
2070              "pxor %%xmm13, %%xmm10\n\t"                /* xor IV with output */
2071              "movdqu %%xmm2, 1*16(%[outbuf])\n\t"
2072              "pxor %%xmm14, %%xmm11\n\t"                /* xor IV with output */
2073              "movdqu %%xmm3, 2*16(%[outbuf])\n\t"
2074              "movdqu %%xmm4, 3*16(%[outbuf])\n\t"
2075              "movdqu %%xmm8, 4*16(%[outbuf])\n\t"
2076              "movdqu %%xmm9, 5*16(%[outbuf])\n\t"
2077              "movdqu %%xmm10, 6*16(%[outbuf])\n\t"
2078              "movdqu %%xmm11, 7*16(%[outbuf])\n\t"
2079
2080              : /* No output */
2081              : [inbuf] "r" (inbuf),
2082                [outbuf] "r" (outbuf)
2083              : "memory");
2084
2085           outbuf += 8*BLOCKSIZE;
2086           inbuf  += 8*BLOCKSIZE;
2087         }
2088
2089       aesni_cleanup_7_15();
2090     }
2091 #endif
2092
2093   for ( ;nblocks >= 4 ; nblocks -= 4 )
2094     {
2095       asm volatile
2096         ("movdqu 0*16(%[inbuf]), %%xmm1\n\t"    /* load input blocks */
2097          "movdqu 1*16(%[inbuf]), %%xmm2\n\t"
2098          "movdqu 2*16(%[inbuf]), %%xmm3\n\t"
2099          "movdqu 3*16(%[inbuf]), %%xmm4\n\t"
2100          : /* No output */
2101          : [inbuf] "r" (inbuf)
2102          : "memory");
2103
2104       do_aesni_dec_vec4 (ctx);
2105
2106       asm volatile
2107         ("pxor %%xmm5, %%xmm1\n\t"              /* xor IV with output */
2108          "movdqu 0*16(%[inbuf]), %%xmm5\n\t"    /* load new IV */
2109          "movdqu %%xmm1, 0*16(%[outbuf])\n\t"
2110
2111          "pxor %%xmm5, %%xmm2\n\t"              /* xor IV with output */
2112          "movdqu 1*16(%[inbuf]), %%xmm5\n\t"    /* load new IV */
2113          "movdqu %%xmm2, 1*16(%[outbuf])\n\t"
2114
2115          "pxor %%xmm5, %%xmm3\n\t"              /* xor IV with output */
2116          "movdqu 2*16(%[inbuf]), %%xmm5\n\t"    /* load new IV */
2117          "movdqu %%xmm3, 2*16(%[outbuf])\n\t"
2118
2119          "pxor %%xmm5, %%xmm4\n\t"              /* xor IV with output */
2120          "movdqu 3*16(%[inbuf]), %%xmm5\n\t"    /* load new IV */
2121          "movdqu %%xmm4, 3*16(%[outbuf])\n\t"
2122
2123          : /* No output */
2124          : [inbuf] "r" (inbuf),
2125            [outbuf] "r" (outbuf)
2126          : "memory");
2127
2128       outbuf += 4*BLOCKSIZE;
2129       inbuf  += 4*BLOCKSIZE;
2130     }
2131
2132   for ( ;nblocks; nblocks-- )
2133     {
2134       asm volatile
2135         ("movdqu %[inbuf], %%xmm0\n\t"
2136          "movdqa %%xmm0, %%xmm2\n\t"    /* use xmm2 as savebuf */
2137          : /* No output */
2138          : [inbuf] "m" (*inbuf)
2139          : "memory");
2140
2141       /* uses only xmm0 and xmm1 */
2142       do_aesni_dec (ctx);
2143
2144       asm volatile
2145         ("pxor %%xmm5, %%xmm0\n\t"      /* xor IV with output */
2146          "movdqu %%xmm0, %[outbuf]\n\t"
2147          "movdqu %%xmm2, %%xmm5\n\t"    /* store savebuf as new IV */
2148          : [outbuf] "=m" (*outbuf)
2149          :
2150          : "memory");
2151
2152       outbuf += BLOCKSIZE;
2153       inbuf  += BLOCKSIZE;
2154     }
2155
2156   asm volatile
2157     ("movdqu %%xmm5, %[iv]\n\t" /* store IV */
2158      : /* No output */
2159      : [iv] "m" (*iv)
2160      : "memory");
2161
2162   aesni_cleanup ();
2163   aesni_cleanup_2_6 ();
2164 }
2165
2166
2167 static void
2168 aesni_ocb_enc (gcry_cipher_hd_t c, void *outbuf_arg,
2169                const void *inbuf_arg, size_t nblocks)
2170 {
2171   RIJNDAEL_context *ctx = (void *)&c->context.c;
2172   unsigned char *outbuf = outbuf_arg;
2173   const unsigned char *inbuf = inbuf_arg;
2174   u64 n = c->u_mode.ocb.data_nblocks;
2175   const unsigned char *l;
2176   aesni_prepare_2_6_variable;
2177
2178   aesni_prepare ();
2179   aesni_prepare_2_6 ();
2180
2181   /* Preload Offset and Checksum */
2182   asm volatile ("movdqu %[iv], %%xmm5\n\t"
2183                 "movdqu %[ctr], %%xmm6\n\t"
2184                 : /* No output */
2185                 : [iv] "m" (*c->u_iv.iv),
2186                   [ctr] "m" (*c->u_ctr.ctr)
2187                 : "memory" );
2188
2189
2190   for ( ;nblocks && n % 4; nblocks-- )
2191     {
2192       l = ocb_get_l(c, ++n);
2193
2194       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
2195       /* Checksum_i = Checksum_{i-1} xor P_i  */
2196       /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
2197       asm volatile ("movdqu %[l],     %%xmm1\n\t"
2198                     "movdqu %[inbuf], %%xmm0\n\t"
2199                     "pxor   %%xmm1,   %%xmm5\n\t"
2200                     "pxor   %%xmm0,   %%xmm6\n\t"
2201                     "pxor   %%xmm5,   %%xmm0\n\t"
2202                     :
2203                     : [l] "m" (*l),
2204                       [inbuf] "m" (*inbuf)
2205                     : "memory" );
2206
2207       do_aesni_enc (ctx);
2208
2209       asm volatile ("pxor   %%xmm5, %%xmm0\n\t"
2210                     "movdqu %%xmm0, %[outbuf]\n\t"
2211                     : [outbuf] "=m" (*outbuf)
2212                     :
2213                     : "memory" );
2214
2215       inbuf += BLOCKSIZE;
2216       outbuf += BLOCKSIZE;
2217     }
2218
2219 #ifdef __x86_64__
2220   if (nblocks >= 8)
2221     {
2222       aesni_prepare_7_15_variable;
2223
2224       aesni_prepare_7_15();
2225
2226       asm volatile ("movdqu %[l0], %%xmm7\n\t"
2227                     :
2228                     : [l0] "m" (*c->u_mode.ocb.L[0])
2229                     : "memory" );
2230
2231       for ( ;nblocks >= 8 ; nblocks -= 8 )
2232         {
2233           n += 4;
2234           l = ocb_get_l(c, n);
2235
2236           /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
2237           /* Checksum_i = Checksum_{i-1} xor P_i  */
2238           /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
2239
2240           asm volatile ("movdqu %[l1],     %%xmm10\n\t"
2241                         "movdqu %[inbuf0], %%xmm1\n\t"
2242                         "pxor   %%xmm7,    %%xmm5\n\t"
2243                         "pxor   %%xmm1,    %%xmm6\n\t"
2244                         "pxor   %%xmm5,    %%xmm1\n\t"
2245                         "movdqa %%xmm5,    %%xmm12\n\t"
2246                         :
2247                         : [l1] "m" (*c->u_mode.ocb.L[1]),
2248                           [inbuf0] "m" (*(inbuf + 0 * BLOCKSIZE))
2249                         : "memory" );
2250           asm volatile ("movdqu %[inbuf1], %%xmm2\n\t"
2251                         "pxor   %%xmm10,   %%xmm5\n\t"
2252                         "pxor   %%xmm2,    %%xmm6\n\t"
2253                         "pxor   %%xmm5,    %%xmm2\n\t"
2254                         "movdqa %%xmm5,    %%xmm13\n\t"
2255                         :
2256                         : [inbuf1] "m" (*(inbuf + 1 * BLOCKSIZE))
2257                         : "memory" );
2258           asm volatile ("movdqu %[inbuf2], %%xmm3\n\t"
2259                         "pxor   %%xmm7,    %%xmm5\n\t"
2260                         "pxor   %%xmm3,    %%xmm6\n\t"
2261                         "pxor   %%xmm5,    %%xmm3\n\t"
2262                         "movdqa %%xmm5,    %%xmm14\n\t"
2263                         :
2264                         : [inbuf2] "m" (*(inbuf + 2 * BLOCKSIZE))
2265                         : "memory" );
2266           asm volatile ("movdqu %[l3],     %%xmm15\n\t"
2267                         "movdqu %[inbuf3], %%xmm4\n\t"
2268                         "pxor   %%xmm15,   %%xmm5\n\t"
2269                         "pxor   %%xmm4,    %%xmm6\n\t"
2270                         "pxor   %%xmm5,    %%xmm4\n\t"
2271                         "movdqa %%xmm5,    %%xmm15\n\t"
2272                         :
2273                         : [l3] "m" (*l),
2274                           [inbuf3] "m" (*(inbuf + 3 * BLOCKSIZE))
2275                         : "memory" );
2276
2277           n += 4;
2278           l = ocb_get_l(c, n);
2279
2280           asm volatile ("movdqu %[inbuf4], %%xmm8\n\t"
2281                         "pxor   %%xmm7,    %%xmm5\n\t"
2282                         "pxor   %%xmm8,    %%xmm6\n\t"
2283                         "pxor   %%xmm5,    %%xmm8\n\t"
2284                         "movdqu %%xmm5,    %[outbuf4]\n\t"
2285                         : [outbuf4] "=m" (*(outbuf + 4 * BLOCKSIZE))
2286                         : [inbuf4] "m" (*(inbuf + 4 * BLOCKSIZE))
2287                         : "memory" );
2288           asm volatile ("movdqu %[inbuf5], %%xmm9\n\t"
2289                         "pxor   %%xmm10,   %%xmm5\n\t"
2290                         "pxor   %%xmm9,    %%xmm6\n\t"
2291                         "pxor   %%xmm5,    %%xmm9\n\t"
2292                         "movdqu %%xmm5,    %[outbuf5]\n\t"
2293                         : [outbuf5] "=m" (*(outbuf + 5 * BLOCKSIZE))
2294                         : [inbuf5] "m" (*(inbuf + 5 * BLOCKSIZE))
2295                         : "memory" );
2296           asm volatile ("movdqu %[inbuf6], %%xmm10\n\t"
2297                         "pxor   %%xmm7,    %%xmm5\n\t"
2298                         "pxor   %%xmm10,   %%xmm6\n\t"
2299                         "pxor   %%xmm5,    %%xmm10\n\t"
2300                         "movdqu %%xmm5,    %[outbuf6]\n\t"
2301                         : [outbuf6] "=m" (*(outbuf + 6 * BLOCKSIZE))
2302                         : [inbuf6] "m" (*(inbuf + 6 * BLOCKSIZE))
2303                         : "memory" );
2304           asm volatile ("movdqu %[l7],     %%xmm11\n\t"
2305                         "pxor   %%xmm11,   %%xmm5\n\t"
2306                         "movdqu %[inbuf7], %%xmm11\n\t"
2307                         "pxor   %%xmm11,   %%xmm6\n\t"
2308                         "pxor   %%xmm5,    %%xmm11\n\t"
2309                         :
2310                         : [l7] "m" (*l),
2311                           [inbuf7] "m" (*(inbuf + 7 * BLOCKSIZE))
2312                         : "memory" );
2313
2314           do_aesni_enc_vec8 (ctx);
2315
2316           asm volatile ("pxor   %%xmm12,   %%xmm1\n\t"
2317                         "pxor   %%xmm13,   %%xmm2\n\t"
2318                         "movdqu %[outbuf4],%%xmm0\n\t"
2319                         "movdqu %[outbuf5],%%xmm12\n\t"
2320                         "movdqu %[outbuf6],%%xmm13\n\t"
2321                         "pxor   %%xmm14,   %%xmm3\n\t"
2322                         "pxor   %%xmm15,   %%xmm4\n\t"
2323                         "pxor   %%xmm0,    %%xmm8\n\t"
2324                         "pxor   %%xmm12,   %%xmm9\n\t"
2325                         "pxor   %%xmm13,   %%xmm10\n\t"
2326                         "pxor   %%xmm5,    %%xmm11\n\t"
2327                         "movdqu %%xmm1,    %[outbuf0]\n\t"
2328                         "movdqu %%xmm2,    %[outbuf1]\n\t"
2329                         "movdqu %%xmm3,    %[outbuf2]\n\t"
2330                         "movdqu %%xmm4,    %[outbuf3]\n\t"
2331                         "movdqu %%xmm8,    %[outbuf4]\n\t"
2332                         "movdqu %%xmm9,    %[outbuf5]\n\t"
2333                         "movdqu %%xmm10,   %[outbuf6]\n\t"
2334                         "movdqu %%xmm11,   %[outbuf7]\n\t"
2335                         : [outbuf0] "=m" (*(outbuf + 0 * BLOCKSIZE)),
2336                           [outbuf1] "=m" (*(outbuf + 1 * BLOCKSIZE)),
2337                           [outbuf2] "=m" (*(outbuf + 2 * BLOCKSIZE)),
2338                           [outbuf3] "=m" (*(outbuf + 3 * BLOCKSIZE)),
2339                           [outbuf4] "+m" (*(outbuf + 4 * BLOCKSIZE)),
2340                           [outbuf5] "+m" (*(outbuf + 5 * BLOCKSIZE)),
2341                           [outbuf6] "+m" (*(outbuf + 6 * BLOCKSIZE)),
2342                           [outbuf7] "=m" (*(outbuf + 7 * BLOCKSIZE))
2343                         :
2344                         : "memory" );
2345
2346           outbuf += 8*BLOCKSIZE;
2347           inbuf  += 8*BLOCKSIZE;
2348         }
2349
2350     aesni_cleanup_7_15();
2351   }
2352 #endif
2353
2354   for ( ;nblocks >= 4 ; nblocks -= 4 )
2355     {
2356       n += 4;
2357       l = ocb_get_l(c, n);
2358
2359       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
2360       /* Checksum_i = Checksum_{i-1} xor P_i  */
2361       /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
2362       asm volatile ("movdqu %[l0],     %%xmm4\n\t"
2363                     "movdqu %[inbuf0], %%xmm1\n\t"
2364                     "pxor   %%xmm4,    %%xmm5\n\t"
2365                     "pxor   %%xmm1,    %%xmm6\n\t"
2366                     "pxor   %%xmm5,    %%xmm1\n\t"
2367                     "movdqu %%xmm5,    %[outbuf0]\n\t"
2368                     : [outbuf0] "=m" (*(outbuf + 0 * BLOCKSIZE))
2369                     : [l0] "m" (*c->u_mode.ocb.L[0]),
2370                       [inbuf0] "m" (*(inbuf + 0 * BLOCKSIZE))
2371                     : "memory" );
2372       asm volatile ("movdqu %[l1],     %%xmm0\n\t"
2373                     "movdqu %[inbuf1], %%xmm2\n\t"
2374                     "pxor   %%xmm0,    %%xmm5\n\t"
2375                     "pxor   %%xmm2,    %%xmm6\n\t"
2376                     "pxor   %%xmm5,    %%xmm2\n\t"
2377                     "movdqu %%xmm5,    %[outbuf1]\n\t"
2378                     : [outbuf1] "=m" (*(outbuf + 1 * BLOCKSIZE))
2379                     : [l1] "m" (*c->u_mode.ocb.L[1]),
2380                       [inbuf1] "m" (*(inbuf + 1 * BLOCKSIZE))
2381                     : "memory" );
2382       asm volatile ("movdqu %[inbuf2], %%xmm3\n\t"
2383                     "pxor   %%xmm4,    %%xmm5\n\t"
2384                     "pxor   %%xmm3,    %%xmm6\n\t"
2385                     "pxor   %%xmm5,    %%xmm3\n\t"
2386                     "movdqu %%xmm5,    %[outbuf2]\n\t"
2387                     : [outbuf2] "=m" (*(outbuf + 2 * BLOCKSIZE))
2388                     : [inbuf2] "m" (*(inbuf + 2 * BLOCKSIZE))
2389                     : "memory" );
2390       asm volatile ("movdqu %[l3],     %%xmm4\n\t"
2391                     "pxor   %%xmm4,    %%xmm5\n\t"
2392                     "movdqu %[inbuf3], %%xmm4\n\t"
2393                     "pxor   %%xmm4,    %%xmm6\n\t"
2394                     "pxor   %%xmm5,    %%xmm4\n\t"
2395                     :
2396                     : [l3] "m" (*l),
2397                       [inbuf3] "m" (*(inbuf + 3 * BLOCKSIZE))
2398                     : "memory" );
2399
2400       do_aesni_enc_vec4 (ctx);
2401
2402       asm volatile ("movdqu %[outbuf0],%%xmm0\n\t"
2403                     "pxor   %%xmm0,    %%xmm1\n\t"
2404                     "movdqu %%xmm1,    %[outbuf0]\n\t"
2405                     "movdqu %[outbuf1],%%xmm0\n\t"
2406                     "pxor   %%xmm0,    %%xmm2\n\t"
2407                     "movdqu %%xmm2,    %[outbuf1]\n\t"
2408                     "movdqu %[outbuf2],%%xmm0\n\t"
2409                     "pxor   %%xmm0,    %%xmm3\n\t"
2410                     "movdqu %%xmm3,    %[outbuf2]\n\t"
2411                     "pxor   %%xmm5,    %%xmm4\n\t"
2412                     "movdqu %%xmm4,    %[outbuf3]\n\t"
2413                     : [outbuf0] "+m" (*(outbuf + 0 * BLOCKSIZE)),
2414                       [outbuf1] "+m" (*(outbuf + 1 * BLOCKSIZE)),
2415                       [outbuf2] "+m" (*(outbuf + 2 * BLOCKSIZE)),
2416                       [outbuf3] "=m" (*(outbuf + 3 * BLOCKSIZE))
2417                     :
2418                     : "memory" );
2419
2420       outbuf += 4*BLOCKSIZE;
2421       inbuf  += 4*BLOCKSIZE;
2422     }
2423
2424   for ( ;nblocks; nblocks-- )
2425     {
2426       l = ocb_get_l(c, ++n);
2427
2428       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
2429       /* Checksum_i = Checksum_{i-1} xor P_i  */
2430       /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
2431       asm volatile ("movdqu %[l],     %%xmm1\n\t"
2432                     "movdqu %[inbuf], %%xmm0\n\t"
2433                     "pxor   %%xmm1,   %%xmm5\n\t"
2434                     "pxor   %%xmm0,   %%xmm6\n\t"
2435                     "pxor   %%xmm5,   %%xmm0\n\t"
2436                     :
2437                     : [l] "m" (*l),
2438                       [inbuf] "m" (*inbuf)
2439                     : "memory" );
2440
2441       do_aesni_enc (ctx);
2442
2443       asm volatile ("pxor   %%xmm5, %%xmm0\n\t"
2444                     "movdqu %%xmm0, %[outbuf]\n\t"
2445                     : [outbuf] "=m" (*outbuf)
2446                     :
2447                     : "memory" );
2448
2449       inbuf += BLOCKSIZE;
2450       outbuf += BLOCKSIZE;
2451     }
2452
2453   c->u_mode.ocb.data_nblocks = n;
2454   asm volatile ("movdqu %%xmm5, %[iv]\n\t"
2455                 "movdqu %%xmm6, %[ctr]\n\t"
2456                 : [iv] "=m" (*c->u_iv.iv),
2457                   [ctr] "=m" (*c->u_ctr.ctr)
2458                 :
2459                 : "memory" );
2460
2461   aesni_cleanup ();
2462   aesni_cleanup_2_6 ();
2463 }
2464
2465
2466 static void
2467 aesni_ocb_dec (gcry_cipher_hd_t c, void *outbuf_arg,
2468                const void *inbuf_arg, size_t nblocks)
2469 {
2470   RIJNDAEL_context *ctx = (void *)&c->context.c;
2471   unsigned char *outbuf = outbuf_arg;
2472   const unsigned char *inbuf = inbuf_arg;
2473   u64 n = c->u_mode.ocb.data_nblocks;
2474   const unsigned char *l;
2475   aesni_prepare_2_6_variable;
2476
2477   aesni_prepare ();
2478   aesni_prepare_2_6 ();
2479
2480   /* Preload Offset and Checksum */
2481   asm volatile ("movdqu %[iv], %%xmm5\n\t"
2482                 "movdqu %[ctr], %%xmm6\n\t"
2483                 : /* No output */
2484                 : [iv] "m" (*c->u_iv.iv),
2485                   [ctr] "m" (*c->u_ctr.ctr)
2486                 : "memory" );
2487
2488   for ( ;nblocks && n % 4; nblocks-- )
2489     {
2490       l = ocb_get_l(c, ++n);
2491
2492       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
2493       /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i)  */
2494       /* Checksum_i = Checksum_{i-1} xor P_i  */
2495       asm volatile ("movdqu %[l],     %%xmm1\n\t"
2496                     "movdqu %[inbuf], %%xmm0\n\t"
2497                     "pxor   %%xmm1,   %%xmm5\n\t"
2498                     "pxor   %%xmm5,   %%xmm0\n\t"
2499                     :
2500                     : [l] "m" (*l),
2501                       [inbuf] "m" (*inbuf)
2502                     : "memory" );
2503
2504       do_aesni_dec (ctx);
2505
2506       asm volatile ("pxor   %%xmm5, %%xmm0\n\t"
2507                     "pxor   %%xmm0, %%xmm6\n\t"
2508                     "movdqu %%xmm0, %[outbuf]\n\t"
2509                     : [outbuf] "=m" (*outbuf)
2510                     :
2511                     : "memory" );
2512
2513       inbuf += BLOCKSIZE;
2514       outbuf += BLOCKSIZE;
2515     }
2516
2517 #ifdef __x86_64__
2518   if (nblocks >= 8)
2519     {
2520       aesni_prepare_7_15_variable;
2521
2522       aesni_prepare_7_15();
2523
2524       asm volatile ("movdqu %[l0], %%xmm7\n\t"
2525                     :
2526                     : [l0] "m" (*c->u_mode.ocb.L[0])
2527                     : "memory" );
2528
2529       for ( ;nblocks >= 8 ; nblocks -= 8 )
2530         {
2531           n += 4;
2532           l = ocb_get_l(c, n);
2533
2534           /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
2535           /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i)  */
2536           /* Checksum_i = Checksum_{i-1} xor P_i  */
2537
2538           asm volatile ("movdqu %[l1],     %%xmm10\n\t"
2539                         "movdqu %[inbuf0], %%xmm1\n\t"
2540                         "pxor   %%xmm7,    %%xmm5\n\t"
2541                         "pxor   %%xmm5,    %%xmm1\n\t"
2542                         "movdqa %%xmm5,    %%xmm12\n\t"
2543                         :
2544                         : [l1] "m" (*c->u_mode.ocb.L[1]),
2545                           [inbuf0] "m" (*(inbuf + 0 * BLOCKSIZE))
2546                         : "memory" );
2547           asm volatile ("movdqu %[inbuf1], %%xmm2\n\t"
2548                         "pxor   %%xmm10,   %%xmm5\n\t"
2549                         "pxor   %%xmm5,    %%xmm2\n\t"
2550                         "movdqa %%xmm5,    %%xmm13\n\t"
2551                         :
2552                         : [inbuf1] "m" (*(inbuf + 1 * BLOCKSIZE))
2553                         : "memory" );
2554           asm volatile ("movdqu %[inbuf2], %%xmm3\n\t"
2555                         "pxor   %%xmm7,    %%xmm5\n\t"
2556                         "pxor   %%xmm5,    %%xmm3\n\t"
2557                         "movdqa %%xmm5,    %%xmm14\n\t"
2558                         :
2559                         : [inbuf2] "m" (*(inbuf + 2 * BLOCKSIZE))
2560                         : "memory" );
2561           asm volatile ("movdqu %[l3],     %%xmm0\n\t"
2562                         "movdqu %[inbuf3], %%xmm4\n\t"
2563                         "pxor   %%xmm0,    %%xmm5\n\t"
2564                         "pxor   %%xmm5,    %%xmm4\n\t"
2565                         "movdqa %%xmm5,    %%xmm15\n\t"
2566                         :
2567                         : [l3] "m" (*l),
2568                           [inbuf3] "m" (*(inbuf + 3 * BLOCKSIZE))
2569                         : "memory" );
2570
2571           n += 4;
2572           l = ocb_get_l(c, n);
2573
2574           asm volatile ("movdqu %[inbuf4], %%xmm8\n\t"
2575                         "pxor   %%xmm7,    %%xmm5\n\t"
2576                         "pxor   %%xmm5,    %%xmm8\n\t"
2577                         "movdqu %%xmm5,    %[outbuf4]\n\t"
2578                         : [outbuf4] "=m" (*(outbuf + 4 * BLOCKSIZE))
2579                         : [inbuf4] "m" (*(inbuf + 4 * BLOCKSIZE))
2580                         : "memory" );
2581           asm volatile ("movdqu %[inbuf5], %%xmm9\n\t"
2582                         "pxor   %%xmm10,   %%xmm5\n\t"
2583                         "pxor   %%xmm5,    %%xmm9\n\t"
2584                         "movdqu %%xmm5,    %[outbuf5]\n\t"
2585                         : [outbuf5] "=m" (*(outbuf + 5 * BLOCKSIZE))
2586                         : [inbuf5] "m" (*(inbuf + 5 * BLOCKSIZE))
2587                         : "memory" );
2588           asm volatile ("movdqu %[inbuf6], %%xmm10\n\t"
2589                         "pxor   %%xmm7,    %%xmm5\n\t"
2590                         "pxor   %%xmm5,    %%xmm10\n\t"
2591                         "movdqu %%xmm5,    %[outbuf6]\n\t"
2592                         : [outbuf6] "=m" (*(outbuf + 6 * BLOCKSIZE))
2593                         : [inbuf6] "m" (*(inbuf + 6 * BLOCKSIZE))
2594                         : "memory" );
2595           asm volatile ("movdqu %[l7],     %%xmm0\n\t"
2596                         "movdqu %[inbuf7], %%xmm11\n\t"
2597                         "pxor   %%xmm0,    %%xmm5\n\t"
2598                         "pxor   %%xmm5,    %%xmm11\n\t"
2599                         :
2600                         : [l7] "m" (*l),
2601                           [inbuf7] "m" (*(inbuf + 7 * BLOCKSIZE))
2602                         : "memory" );
2603
2604           do_aesni_dec_vec8 (ctx);
2605
2606           asm volatile ("pxor   %%xmm12,   %%xmm1\n\t"
2607                         "pxor   %%xmm13,   %%xmm2\n\t"
2608                         "movdqu %[outbuf4],%%xmm0\n\t"
2609                         "movdqu %[outbuf5],%%xmm12\n\t"
2610                         "movdqu %[outbuf6],%%xmm13\n\t"
2611                         "pxor   %%xmm14,   %%xmm3\n\t"
2612                         "pxor   %%xmm15,   %%xmm4\n\t"
2613                         "pxor   %%xmm0,    %%xmm8\n\t"
2614                         "pxor   %%xmm12,   %%xmm9\n\t"
2615                         "pxor   %%xmm13,   %%xmm10\n\t"
2616                         "pxor   %%xmm5,    %%xmm11\n\t"
2617                         "movdqu %%xmm1,    %[outbuf0]\n\t"
2618                         "movdqu %%xmm2,    %[outbuf1]\n\t"
2619                         "movdqu %%xmm3,    %[outbuf2]\n\t"
2620                         "movdqu %%xmm4,    %[outbuf3]\n\t"
2621                         "movdqu %%xmm8,    %[outbuf4]\n\t"
2622                         "movdqu %%xmm9,    %[outbuf5]\n\t"
2623                         "movdqu %%xmm10,   %[outbuf6]\n\t"
2624                         "movdqu %%xmm11,   %[outbuf7]\n\t"
2625                         "pxor   %%xmm2,    %%xmm1\n\t"
2626                         "pxor   %%xmm4,    %%xmm1\n\t"
2627                         "pxor   %%xmm9,    %%xmm1\n\t"
2628                         "pxor   %%xmm11,   %%xmm1\n\t"
2629                         "pxor   %%xmm3,    %%xmm6\n\t"
2630                         "pxor   %%xmm8,    %%xmm6\n\t"
2631                         "pxor   %%xmm10,   %%xmm6\n\t"
2632                         "pxor   %%xmm1,    %%xmm6\n\t"
2633                         : [outbuf0] "=m" (*(outbuf + 0 * BLOCKSIZE)),
2634                           [outbuf1] "=m" (*(outbuf + 1 * BLOCKSIZE)),
2635                           [outbuf2] "=m" (*(outbuf + 2 * BLOCKSIZE)),
2636                           [outbuf3] "=m" (*(outbuf + 3 * BLOCKSIZE)),
2637                           [outbuf4] "+m" (*(outbuf + 4 * BLOCKSIZE)),
2638                           [outbuf5] "+m" (*(outbuf + 5 * BLOCKSIZE)),
2639                           [outbuf6] "+m" (*(outbuf + 6 * BLOCKSIZE)),
2640                           [outbuf7] "=m" (*(outbuf + 7 * BLOCKSIZE))
2641                         :
2642                         : "memory" );
2643
2644           outbuf += 8*BLOCKSIZE;
2645           inbuf  += 8*BLOCKSIZE;
2646         }
2647
2648       aesni_cleanup_7_15();
2649     }
2650 #endif
2651
2652   for ( ;nblocks >= 4 ; nblocks -= 4 )
2653     {
2654       n += 4;
2655       l = ocb_get_l(c, n);
2656
2657       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
2658       /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i)  */
2659       /* Checksum_i = Checksum_{i-1} xor P_i  */
2660       asm volatile ("movdqu %[l0],     %%xmm4\n\t"
2661                     "movdqu %[inbuf0], %%xmm1\n\t"
2662                     "pxor   %%xmm4,    %%xmm5\n\t"
2663                     "pxor   %%xmm5,    %%xmm1\n\t"
2664                     "movdqu %%xmm5,    %[outbuf0]\n\t"
2665                     : [outbuf0] "=m" (*(outbuf + 0 * BLOCKSIZE))
2666                     : [l0] "m" (*c->u_mode.ocb.L[0]),
2667                       [inbuf0] "m" (*(inbuf + 0 * BLOCKSIZE))
2668                     : "memory" );
2669       asm volatile ("movdqu %[l1],     %%xmm0\n\t"
2670                     "movdqu %[inbuf1], %%xmm2\n\t"
2671                     "pxor   %%xmm0,    %%xmm5\n\t"
2672                     "pxor   %%xmm5,    %%xmm2\n\t"
2673                     "movdqu %%xmm5,    %[outbuf1]\n\t"
2674                     : [outbuf1] "=m" (*(outbuf + 1 * BLOCKSIZE))
2675                     : [l1] "m" (*c->u_mode.ocb.L[1]),
2676                       [inbuf1] "m" (*(inbuf + 1 * BLOCKSIZE))
2677                     : "memory" );
2678       asm volatile ("movdqu %[inbuf2], %%xmm3\n\t"
2679                     "pxor   %%xmm4,    %%xmm5\n\t"
2680                     "pxor   %%xmm5,    %%xmm3\n\t"
2681                     "movdqu %%xmm5,    %[outbuf2]\n\t"
2682                     : [outbuf2] "=m" (*(outbuf + 2 * BLOCKSIZE))
2683                     : [inbuf2] "m" (*(inbuf + 2 * BLOCKSIZE))
2684                     : "memory" );
2685       asm volatile ("movdqu %[l3],     %%xmm0\n\t"
2686                     "movdqu %[inbuf3], %%xmm4\n\t"
2687                     "pxor   %%xmm0,    %%xmm5\n\t"
2688                     "pxor   %%xmm5,    %%xmm4\n\t"
2689                     :
2690                     : [l3] "m" (*l),
2691                       [inbuf3] "m" (*(inbuf + 3 * BLOCKSIZE))
2692                     : "memory" );
2693
2694       do_aesni_dec_vec4 (ctx);
2695
2696       asm volatile ("movdqu %[outbuf0],%%xmm0\n\t"
2697                     "pxor   %%xmm0,    %%xmm1\n\t"
2698                     "movdqu %%xmm1,    %[outbuf0]\n\t"
2699                     "movdqu %[outbuf1],%%xmm0\n\t"
2700                     "pxor   %%xmm0,    %%xmm2\n\t"
2701                     "movdqu %%xmm2,    %[outbuf1]\n\t"
2702                     "movdqu %[outbuf2],%%xmm0\n\t"
2703                     "pxor   %%xmm0,    %%xmm3\n\t"
2704                     "movdqu %%xmm3,    %[outbuf2]\n\t"
2705                     "pxor   %%xmm5,    %%xmm4\n\t"
2706                     "movdqu %%xmm4,    %[outbuf3]\n\t"
2707                     "pxor   %%xmm1,    %%xmm6\n\t"
2708                     "pxor   %%xmm2,    %%xmm6\n\t"
2709                     "pxor   %%xmm3,    %%xmm6\n\t"
2710                     "pxor   %%xmm4,    %%xmm6\n\t"
2711                     : [outbuf0] "+m" (*(outbuf + 0 * BLOCKSIZE)),
2712                       [outbuf1] "+m" (*(outbuf + 1 * BLOCKSIZE)),
2713                       [outbuf2] "+m" (*(outbuf + 2 * BLOCKSIZE)),
2714                       [outbuf3] "=m" (*(outbuf + 3 * BLOCKSIZE))
2715                     :
2716                     : "memory" );
2717
2718       outbuf += 4*BLOCKSIZE;
2719       inbuf  += 4*BLOCKSIZE;
2720     }
2721
2722   for ( ;nblocks; nblocks-- )
2723     {
2724       l = ocb_get_l(c, ++n);
2725
2726       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
2727       /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i)  */
2728       /* Checksum_i = Checksum_{i-1} xor P_i  */
2729       asm volatile ("movdqu %[l],     %%xmm1\n\t"
2730                     "movdqu %[inbuf], %%xmm0\n\t"
2731                     "pxor   %%xmm1,   %%xmm5\n\t"
2732                     "pxor   %%xmm5,   %%xmm0\n\t"
2733                     :
2734                     : [l] "m" (*l),
2735                       [inbuf] "m" (*inbuf)
2736                     : "memory" );
2737
2738       do_aesni_dec (ctx);
2739
2740       asm volatile ("pxor   %%xmm5, %%xmm0\n\t"
2741                     "pxor   %%xmm0, %%xmm6\n\t"
2742                     "movdqu %%xmm0, %[outbuf]\n\t"
2743                     : [outbuf] "=m" (*outbuf)
2744                     :
2745                     : "memory" );
2746
2747       inbuf += BLOCKSIZE;
2748       outbuf += BLOCKSIZE;
2749     }
2750
2751   c->u_mode.ocb.data_nblocks = n;
2752   asm volatile ("movdqu %%xmm5, %[iv]\n\t"
2753                 "movdqu %%xmm6, %[ctr]\n\t"
2754                 : [iv] "=m" (*c->u_iv.iv),
2755                   [ctr] "=m" (*c->u_ctr.ctr)
2756                 :
2757                 : "memory" );
2758
2759   aesni_cleanup ();
2760   aesni_cleanup_2_6 ();
2761 }
2762
2763
2764 void
2765 _gcry_aes_aesni_ocb_crypt(gcry_cipher_hd_t c, void *outbuf_arg,
2766                           const void *inbuf_arg, size_t nblocks, int encrypt)
2767 {
2768   if (encrypt)
2769     aesni_ocb_enc(c, outbuf_arg, inbuf_arg, nblocks);
2770   else
2771     aesni_ocb_dec(c, outbuf_arg, inbuf_arg, nblocks);
2772 }
2773
2774
2775 void
2776 _gcry_aes_aesni_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
2777                           size_t nblocks)
2778 {
2779   RIJNDAEL_context *ctx = (void *)&c->context.c;
2780   const unsigned char *abuf = abuf_arg;
2781   u64 n = c->u_mode.ocb.aad_nblocks;
2782   const unsigned char *l;
2783   aesni_prepare_2_6_variable;
2784
2785   aesni_prepare ();
2786   aesni_prepare_2_6 ();
2787
2788   /* Preload Offset and Sum */
2789   asm volatile ("movdqu %[iv], %%xmm5\n\t"
2790                 "movdqu %[ctr], %%xmm6\n\t"
2791                 : /* No output */
2792                 : [iv] "m" (*c->u_mode.ocb.aad_offset),
2793                   [ctr] "m" (*c->u_mode.ocb.aad_sum)
2794                 : "memory" );
2795
2796   for ( ;nblocks && n % 4; nblocks-- )
2797     {
2798       l = ocb_get_l(c, ++n);
2799
2800       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
2801       /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i)  */
2802       asm volatile ("movdqu %[l],     %%xmm1\n\t"
2803                     "movdqu %[abuf],  %%xmm0\n\t"
2804                     "pxor   %%xmm1,   %%xmm5\n\t"
2805                     "pxor   %%xmm5,   %%xmm0\n\t"
2806                     :
2807                     : [l] "m" (*l),
2808                       [abuf] "m" (*abuf)
2809                     : "memory" );
2810
2811       do_aesni_enc (ctx);
2812
2813       asm volatile ("pxor   %%xmm0,   %%xmm6\n\t"
2814                     :
2815                     :
2816                     : "memory" );
2817
2818       abuf += BLOCKSIZE;
2819     }
2820
2821 #ifdef __x86_64__
2822   if (nblocks >= 8)
2823     {
2824       aesni_prepare_7_15_variable;
2825
2826       aesni_prepare_7_15();
2827
2828       asm volatile ("movdqu %[l0], %%xmm7\n\t"
2829                     "movdqu %[l1], %%xmm12\n\t"
2830                     :
2831                     : [l0] "m" (*c->u_mode.ocb.L[0]),
2832                       [l1] "m" (*c->u_mode.ocb.L[1])
2833                     : "memory" );
2834
2835       for ( ;nblocks >= 8 ; nblocks -= 8 )
2836         {
2837           n += 4;
2838           l = ocb_get_l(c, n);
2839
2840           /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
2841           /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i)  */
2842           asm volatile ("movdqu %[abuf0],  %%xmm1\n\t"
2843                         "pxor   %%xmm7,    %%xmm5\n\t"
2844                         "pxor   %%xmm5,    %%xmm1\n\t"
2845                         :
2846                         : [abuf0] "m" (*(abuf + 0 * BLOCKSIZE))
2847                         : "memory" );
2848           asm volatile ("movdqu %[abuf1],  %%xmm2\n\t"
2849                         "pxor   %%xmm12,   %%xmm5\n\t"
2850                         "pxor   %%xmm5,    %%xmm2\n\t"
2851                         :
2852                         : [abuf1] "m" (*(abuf + 1 * BLOCKSIZE))
2853                         : "memory" );
2854           asm volatile ("movdqu %[abuf2],  %%xmm3\n\t"
2855                         "pxor   %%xmm7,    %%xmm5\n\t"
2856                         "pxor   %%xmm5,    %%xmm3\n\t"
2857                         :
2858                         : [abuf2] "m" (*(abuf + 2 * BLOCKSIZE))
2859                         : "memory" );
2860           asm volatile ("movdqu %[l3],     %%xmm0\n\t"
2861                         "movdqu %[abuf3],  %%xmm4\n\t"
2862                         "pxor   %%xmm0,    %%xmm5\n\t"
2863                         "pxor   %%xmm5,    %%xmm4\n\t"
2864                         :
2865                         : [l3] "m" (*l),
2866                           [abuf3] "m" (*(abuf + 3 * BLOCKSIZE))
2867                         : "memory" );
2868
2869           n += 4;
2870           l = ocb_get_l(c, n);
2871
2872           asm volatile ("movdqu %[abuf4],  %%xmm8\n\t"
2873                         "pxor   %%xmm7,    %%xmm5\n\t"
2874                         "pxor   %%xmm5,    %%xmm8\n\t"
2875                         :
2876                         : [abuf4] "m" (*(abuf + 4 * BLOCKSIZE))
2877                         : "memory" );
2878           asm volatile ("movdqu %[abuf5],  %%xmm9\n\t"
2879                         "pxor   %%xmm12,   %%xmm5\n\t"
2880                         "pxor   %%xmm5,    %%xmm9\n\t"
2881                         :
2882                         : [abuf5] "m" (*(abuf + 5 * BLOCKSIZE))
2883                         : "memory" );
2884           asm volatile ("movdqu %[abuf6],  %%xmm10\n\t"
2885                         "pxor   %%xmm7,    %%xmm5\n\t"
2886                         "pxor   %%xmm5,    %%xmm10\n\t"
2887                         :
2888                         : [abuf6] "m" (*(abuf + 6 * BLOCKSIZE))
2889                         : "memory" );
2890           asm volatile ("movdqu %[l7],     %%xmm0\n\t"
2891                         "movdqu %[abuf7],  %%xmm11\n\t"
2892                         "pxor   %%xmm0,    %%xmm5\n\t"
2893                         "pxor   %%xmm5,    %%xmm11\n\t"
2894                         :
2895                         : [l7] "m" (*l),
2896                           [abuf7] "m" (*(abuf + 7 * BLOCKSIZE))
2897                         : "memory" );
2898
2899           do_aesni_enc_vec8 (ctx);
2900
2901           asm volatile ("pxor   %%xmm2,   %%xmm1\n\t"
2902                         "pxor   %%xmm3,   %%xmm1\n\t"
2903                         "pxor   %%xmm4,   %%xmm1\n\t"
2904                         "pxor   %%xmm8,   %%xmm1\n\t"
2905                         "pxor   %%xmm9,   %%xmm6\n\t"
2906                         "pxor   %%xmm10,  %%xmm6\n\t"
2907                         "pxor   %%xmm11,  %%xmm6\n\t"
2908                         "pxor   %%xmm1,   %%xmm6\n\t"
2909                         :
2910                         :
2911                         : "memory" );
2912
2913           abuf += 8*BLOCKSIZE;
2914         }
2915
2916       aesni_cleanup_7_15();
2917     }
2918 #endif
2919
2920   for ( ;nblocks >= 4 ; nblocks -= 4 )
2921     {
2922       n += 4;
2923       l = ocb_get_l(c, n);
2924
2925       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
2926       /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i)  */
2927       asm volatile ("movdqu %[l0],     %%xmm4\n\t"
2928                     "movdqu %[abuf0],  %%xmm1\n\t"
2929                     "pxor   %%xmm4,    %%xmm5\n\t"
2930                     "pxor   %%xmm5,    %%xmm1\n\t"
2931                     :
2932                     : [l0] "m" (*c->u_mode.ocb.L[0]),
2933                       [abuf0] "m" (*(abuf + 0 * BLOCKSIZE))
2934                     : "memory" );
2935       asm volatile ("movdqu %[l1],     %%xmm0\n\t"
2936                     "movdqu %[abuf1],  %%xmm2\n\t"
2937                     "pxor   %%xmm0,    %%xmm5\n\t"
2938                     "pxor   %%xmm5,    %%xmm2\n\t"
2939                     :
2940                     : [l1] "m" (*c->u_mode.ocb.L[1]),
2941                       [abuf1] "m" (*(abuf + 1 * BLOCKSIZE))
2942                     : "memory" );
2943       asm volatile ("movdqu %[abuf2],  %%xmm3\n\t"
2944                     "pxor   %%xmm4,    %%xmm5\n\t"
2945                     "pxor   %%xmm5,    %%xmm3\n\t"
2946                     :