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