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