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