More optimized CRC 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 { u32 a, b, c, d; } u128_t;
45
46
47 /* Two macros to be called prior and after the use of AESNI
48    instructions.  There should be no external function calls between
49    the use of these macros.  There purpose is to make sure that the
50    SSE regsiters are cleared and won't reveal any information about
51    the key or the data.  */
52 #ifdef __WIN64__
53 /* XMM6-XMM15 are callee-saved registers on WIN64. */
54 # define aesni_prepare_2_6_variable char win64tmp[16]
55 # define aesni_prepare() do { } while (0)
56 # define aesni_prepare_2_6()                                            \
57    do { asm volatile ("movdqu %%xmm6, %0\n\t"                           \
58                       : "=m" (*win64tmp)                                \
59                       :                                                 \
60                       : "memory");                                      \
61    } while (0)
62 # define aesni_cleanup()                                                \
63    do { asm volatile ("pxor %%xmm0, %%xmm0\n\t"                         \
64                       "pxor %%xmm1, %%xmm1\n" :: );                     \
65    } while (0)
66 # define aesni_cleanup_2_6()                                            \
67    do { asm volatile ("movdqu %0,   %%xmm6\n\t"                         \
68                       "pxor %%xmm2, %%xmm2\n"                           \
69                       "pxor %%xmm3, %%xmm3\n"                           \
70                       "pxor %%xmm4, %%xmm4\n"                           \
71                       "pxor %%xmm5, %%xmm5\n"                           \
72                       :                                                 \
73                       : "m" (*win64tmp)                                 \
74                       : "memory");                                      \
75    } while (0)
76 #else
77 # define aesni_prepare_2_6_variable
78 # define aesni_prepare() do { } while (0)
79 # define aesni_prepare_2_6() do { } while (0)
80 # define aesni_cleanup()                                                \
81    do { asm volatile ("pxor %%xmm0, %%xmm0\n\t"                         \
82                       "pxor %%xmm1, %%xmm1\n" :: );                     \
83    } while (0)
84 # define aesni_cleanup_2_6()                                            \
85    do { asm volatile ("pxor %%xmm2, %%xmm2\n\t"                         \
86                       "pxor %%xmm3, %%xmm3\n"                           \
87                       "pxor %%xmm4, %%xmm4\n"                           \
88                       "pxor %%xmm5, %%xmm5\n"                           \
89                       "pxor %%xmm6, %%xmm6\n":: );                      \
90    } while (0)
91 #endif
92
93 void
94 _gcry_aes_aesni_do_setkey (RIJNDAEL_context *ctx, const byte *key)
95 {
96   aesni_prepare_2_6_variable;
97
98   aesni_prepare();
99   aesni_prepare_2_6();
100
101   if (ctx->rounds < 12)
102     {
103       /* 128-bit key */
104 #define AESKEYGENASSIST_xmm1_xmm2(imm8) \
105         ".byte 0x66, 0x0f, 0x3a, 0xdf, 0xd1, " #imm8 " \n\t"
106 #define AESKEY_EXPAND128 \
107         "pshufd $0xff, %%xmm2, %%xmm2\n\t" \
108         "movdqa %%xmm1, %%xmm3\n\t" \
109         "pslldq $4, %%xmm3\n\t" \
110         "pxor   %%xmm3, %%xmm1\n\t" \
111         "pslldq $4, %%xmm3\n\t" \
112         "pxor   %%xmm3, %%xmm1\n\t" \
113         "pslldq $4, %%xmm3\n\t" \
114         "pxor   %%xmm3, %%xmm2\n\t" \
115         "pxor   %%xmm2, %%xmm1\n\t"
116
117       asm volatile ("movdqu (%[key]), %%xmm1\n\t"     /* xmm1 := key   */
118                     "movdqa %%xmm1, (%[ksch])\n\t"     /* ksch[0] := xmm1  */
119                     AESKEYGENASSIST_xmm1_xmm2(0x01)
120                     AESKEY_EXPAND128
121                     "movdqa %%xmm1, 0x10(%[ksch])\n\t" /* ksch[1] := xmm1  */
122                     AESKEYGENASSIST_xmm1_xmm2(0x02)
123                     AESKEY_EXPAND128
124                     "movdqa %%xmm1, 0x20(%[ksch])\n\t" /* ksch[2] := xmm1  */
125                     AESKEYGENASSIST_xmm1_xmm2(0x04)
126                     AESKEY_EXPAND128
127                     "movdqa %%xmm1, 0x30(%[ksch])\n\t" /* ksch[3] := xmm1  */
128                     AESKEYGENASSIST_xmm1_xmm2(0x08)
129                     AESKEY_EXPAND128
130                     "movdqa %%xmm1, 0x40(%[ksch])\n\t" /* ksch[4] := xmm1  */
131                     AESKEYGENASSIST_xmm1_xmm2(0x10)
132                     AESKEY_EXPAND128
133                     "movdqa %%xmm1, 0x50(%[ksch])\n\t" /* ksch[5] := xmm1  */
134                     AESKEYGENASSIST_xmm1_xmm2(0x20)
135                     AESKEY_EXPAND128
136                     "movdqa %%xmm1, 0x60(%[ksch])\n\t" /* ksch[6] := xmm1  */
137                     AESKEYGENASSIST_xmm1_xmm2(0x40)
138                     AESKEY_EXPAND128
139                     "movdqa %%xmm1, 0x70(%[ksch])\n\t" /* ksch[7] := xmm1  */
140                     AESKEYGENASSIST_xmm1_xmm2(0x80)
141                     AESKEY_EXPAND128
142                     "movdqa %%xmm1, 0x80(%[ksch])\n\t" /* ksch[8] := xmm1  */
143                     AESKEYGENASSIST_xmm1_xmm2(0x1b)
144                     AESKEY_EXPAND128
145                     "movdqa %%xmm1, 0x90(%[ksch])\n\t" /* ksch[9] := xmm1  */
146                     AESKEYGENASSIST_xmm1_xmm2(0x36)
147                     AESKEY_EXPAND128
148                     "movdqa %%xmm1, 0xa0(%[ksch])\n\t" /* ksch[10] := xmm1  */
149                     :
150                     : [key] "r" (key), [ksch] "r" (ctx->keyschenc)
151                     : "cc", "memory" );
152 #undef AESKEYGENASSIST_xmm1_xmm2
153 #undef AESKEY_EXPAND128
154     }
155   else if (ctx->rounds == 12)
156     {
157       /* 192-bit key */
158 #define AESKEYGENASSIST_xmm3_xmm2(imm8) \
159         ".byte 0x66, 0x0f, 0x3a, 0xdf, 0xd3, " #imm8 " \n\t"
160 #define AESKEY_EXPAND192 \
161         "pshufd $0x55, %%xmm2, %%xmm2\n\t" \
162         "movdqu %%xmm1, %%xmm4\n\t" \
163         "pslldq $4, %%xmm4\n\t" \
164         "pxor %%xmm4, %%xmm1\n\t" \
165         "pslldq $4, %%xmm4\n\t" \
166         "pxor %%xmm4, %%xmm1\n\t" \
167         "pslldq $4, %%xmm4\n\t" \
168         "pxor %%xmm4, %%xmm1\n\t" \
169         "pxor %%xmm2, %%xmm1\n\t" \
170         "pshufd $0xff, %%xmm1, %%xmm2\n\t" \
171         "movdqu %%xmm3, %%xmm4\n\t" \
172         "pslldq $4, %%xmm4\n\t" \
173         "pxor %%xmm4, %%xmm3\n\t" \
174         "pxor %%xmm2, %%xmm3\n\t"
175
176       asm volatile ("movdqu (%[key]), %%xmm1\n\t"     /* xmm1 := key[0..15]   */
177                     "movq 16(%[key]), %%xmm3\n\t"     /* xmm3 := key[16..23]  */
178                     "movdqa %%xmm1, (%[ksch])\n\t"    /* ksch[0] := xmm1  */
179                     "movdqa %%xmm3, %%xmm5\n\t"
180
181                     AESKEYGENASSIST_xmm3_xmm2(0x01)
182                     AESKEY_EXPAND192
183                     "shufpd $0, %%xmm1, %%xmm5\n\t"
184                     "movdqa %%xmm5, 0x10(%[ksch])\n\t" /* ksch[1] := xmm5  */
185                     "movdqa %%xmm1, %%xmm6\n\t"
186                     "shufpd $1, %%xmm3, %%xmm6\n\t"
187                     "movdqa %%xmm6, 0x20(%[ksch])\n\t" /* ksch[2] := xmm6  */
188                     AESKEYGENASSIST_xmm3_xmm2(0x02)
189                     AESKEY_EXPAND192
190                     "movdqa %%xmm1, 0x30(%[ksch])\n\t" /* ksch[3] := xmm1  */
191                     "movdqa %%xmm3, %%xmm5\n\t"
192
193                     AESKEYGENASSIST_xmm3_xmm2(0x04)
194                     AESKEY_EXPAND192
195                     "shufpd $0, %%xmm1, %%xmm5\n\t"
196                     "movdqa %%xmm5, 0x40(%[ksch])\n\t" /* ksch[4] := xmm5  */
197                     "movdqa %%xmm1, %%xmm6\n\t"
198                     "shufpd $1, %%xmm3, %%xmm6\n\t"
199                     "movdqa %%xmm6, 0x50(%[ksch])\n\t" /* ksch[5] := xmm6  */
200                     AESKEYGENASSIST_xmm3_xmm2(0x08)
201                     AESKEY_EXPAND192
202                     "movdqa %%xmm1, 0x60(%[ksch])\n\t" /* ksch[6] := xmm1  */
203                     "movdqa %%xmm3, %%xmm5\n\t"
204
205                     AESKEYGENASSIST_xmm3_xmm2(0x10)
206                     AESKEY_EXPAND192
207                     "shufpd $0, %%xmm1, %%xmm5\n\t"
208                     "movdqa %%xmm5, 0x70(%[ksch])\n\t" /* ksch[7] := xmm5  */
209                     "movdqa %%xmm1, %%xmm6\n\t"
210                     "shufpd $1, %%xmm3, %%xmm6\n\t"
211                     "movdqa %%xmm6, 0x80(%[ksch])\n\t" /* ksch[8] := xmm6  */
212                     AESKEYGENASSIST_xmm3_xmm2(0x20)
213                     AESKEY_EXPAND192
214                     "movdqa %%xmm1, 0x90(%[ksch])\n\t" /* ksch[9] := xmm1  */
215                     "movdqa %%xmm3, %%xmm5\n\t"
216
217                     AESKEYGENASSIST_xmm3_xmm2(0x40)
218                     AESKEY_EXPAND192
219                     "shufpd $0, %%xmm1, %%xmm5\n\t"
220                     "movdqa %%xmm5, 0xa0(%[ksch])\n\t" /* ksch[10] := xmm5  */
221                     "movdqa %%xmm1, %%xmm6\n\t"
222                     "shufpd $1, %%xmm3, %%xmm6\n\t"
223                     "movdqa %%xmm6, 0xb0(%[ksch])\n\t" /* ksch[11] := xmm6  */
224                     AESKEYGENASSIST_xmm3_xmm2(0x80)
225                     AESKEY_EXPAND192
226                     "movdqa %%xmm1, 0xc0(%[ksch])\n\t" /* ksch[12] := xmm1  */
227                     :
228                     : [key] "r" (key), [ksch] "r" (ctx->keyschenc)
229                     : "cc", "memory" );
230 #undef AESKEYGENASSIST_xmm3_xmm2
231 #undef AESKEY_EXPAND192
232     }
233   else if (ctx->rounds > 12)
234     {
235       /* 256-bit key */
236 #define AESKEYGENASSIST_xmm1_xmm2(imm8) \
237         ".byte 0x66, 0x0f, 0x3a, 0xdf, 0xd1, " #imm8 " \n\t"
238 #define AESKEYGENASSIST_xmm3_xmm2(imm8) \
239         ".byte 0x66, 0x0f, 0x3a, 0xdf, 0xd3, " #imm8 " \n\t"
240 #define AESKEY_EXPAND256_A \
241         "pshufd $0xff, %%xmm2, %%xmm2\n\t" \
242         "movdqa %%xmm1, %%xmm4\n\t" \
243         "pslldq $4, %%xmm4\n\t" \
244         "pxor %%xmm4, %%xmm1\n\t" \
245         "pslldq $4, %%xmm4\n\t" \
246         "pxor %%xmm4, %%xmm1\n\t" \
247         "pslldq $4, %%xmm4\n\t" \
248         "pxor %%xmm4, %%xmm1\n\t" \
249         "pxor %%xmm2, %%xmm1\n\t"
250 #define AESKEY_EXPAND256_B \
251         "pshufd $0xaa, %%xmm2, %%xmm2\n\t" \
252         "movdqa %%xmm3, %%xmm4\n\t" \
253         "pslldq $4, %%xmm4\n\t" \
254         "pxor %%xmm4, %%xmm3\n\t" \
255         "pslldq $4, %%xmm4\n\t" \
256         "pxor %%xmm4, %%xmm3\n\t" \
257         "pslldq $4, %%xmm4\n\t" \
258         "pxor %%xmm4, %%xmm3\n\t" \
259         "pxor %%xmm2, %%xmm3\n\t"
260
261       asm volatile ("movdqu (%[key]), %%xmm1\n\t"     /* xmm1 := key[0..15]   */
262                     "movdqu 16(%[key]), %%xmm3\n\t"   /* xmm3 := key[16..31]  */
263                     "movdqa %%xmm1, (%[ksch])\n\t"     /* ksch[0] := xmm1  */
264                     "movdqa %%xmm3, 0x10(%[ksch])\n\t" /* ksch[1] := xmm3  */
265
266                     AESKEYGENASSIST_xmm3_xmm2(0x01)
267                     AESKEY_EXPAND256_A
268                     "movdqa %%xmm1, 0x20(%[ksch])\n\t" /* ksch[2] := xmm1  */
269                     AESKEYGENASSIST_xmm1_xmm2(0x00)
270                     AESKEY_EXPAND256_B
271                     "movdqa %%xmm3, 0x30(%[ksch])\n\t" /* ksch[3] := xmm3  */
272
273                     AESKEYGENASSIST_xmm3_xmm2(0x02)
274                     AESKEY_EXPAND256_A
275                     "movdqa %%xmm1, 0x40(%[ksch])\n\t" /* ksch[4] := xmm1  */
276                     AESKEYGENASSIST_xmm1_xmm2(0x00)
277                     AESKEY_EXPAND256_B
278                     "movdqa %%xmm3, 0x50(%[ksch])\n\t" /* ksch[5] := xmm3  */
279
280                     AESKEYGENASSIST_xmm3_xmm2(0x04)
281                     AESKEY_EXPAND256_A
282                     "movdqa %%xmm1, 0x60(%[ksch])\n\t" /* ksch[6] := xmm1  */
283                     AESKEYGENASSIST_xmm1_xmm2(0x00)
284                     AESKEY_EXPAND256_B
285                     "movdqa %%xmm3, 0x70(%[ksch])\n\t" /* ksch[7] := xmm3  */
286
287                     AESKEYGENASSIST_xmm3_xmm2(0x08)
288                     AESKEY_EXPAND256_A
289                     "movdqa %%xmm1, 0x80(%[ksch])\n\t" /* ksch[8] := xmm1  */
290                     AESKEYGENASSIST_xmm1_xmm2(0x00)
291                     AESKEY_EXPAND256_B
292                     "movdqa %%xmm3, 0x90(%[ksch])\n\t" /* ksch[9] := xmm3  */
293
294                     AESKEYGENASSIST_xmm3_xmm2(0x10)
295                     AESKEY_EXPAND256_A
296                     "movdqa %%xmm1, 0xa0(%[ksch])\n\t" /* ksch[10] := xmm1  */
297                     AESKEYGENASSIST_xmm1_xmm2(0x00)
298                     AESKEY_EXPAND256_B
299                     "movdqa %%xmm3, 0xb0(%[ksch])\n\t" /* ksch[11] := xmm3  */
300
301                     AESKEYGENASSIST_xmm3_xmm2(0x20)
302                     AESKEY_EXPAND256_A
303                     "movdqa %%xmm1, 0xc0(%[ksch])\n\t" /* ksch[12] := xmm1  */
304                     AESKEYGENASSIST_xmm1_xmm2(0x00)
305                     AESKEY_EXPAND256_B
306                     "movdqa %%xmm3, 0xd0(%[ksch])\n\t" /* ksch[13] := xmm3  */
307
308                     AESKEYGENASSIST_xmm3_xmm2(0x40)
309                     AESKEY_EXPAND256_A
310                     "movdqa %%xmm1, 0xe0(%[ksch])\n\t" /* ksch[14] := xmm1  */
311
312                     :
313                     : [key] "r" (key), [ksch] "r" (ctx->keyschenc)
314                     : "cc", "memory" );
315 #undef AESKEYGENASSIST_xmm1_xmm2
316 #undef AESKEYGENASSIST_xmm3_xmm2
317 #undef AESKEY_EXPAND256_A
318 #undef AESKEY_EXPAND256_B
319     }
320
321   aesni_cleanup();
322   aesni_cleanup_2_6();
323 }
324
325
326 /* Make a decryption key from an encryption key. */
327 void
328 _gcry_aes_aesni_prepare_decryption (RIJNDAEL_context *ctx)
329 {
330   /* The AES-NI decrypt instructions use the Equivalent Inverse
331      Cipher, thus we can't use the the standard decrypt key
332      preparation.  */
333   u128_t *ekey = (u128_t *)ctx->keyschenc;
334   u128_t *dkey = (u128_t *)ctx->keyschdec;
335   int rr;
336   int r;
337
338   aesni_prepare();
339
340 #define DO_AESNI_AESIMC() \
341   asm volatile ("movdqa %[ekey], %%xmm1\n\t" \
342                 /*"aesimc %%xmm1, %%xmm1\n\t"*/ \
343                 ".byte 0x66, 0x0f, 0x38, 0xdb, 0xc9\n\t" \
344                 "movdqa %%xmm1, %[dkey]" \
345                 : [dkey] "=m" (dkey[r]) \
346                 : [ekey] "m" (ekey[rr]) \
347                 : "memory")
348
349   dkey[0] = ekey[ctx->rounds];
350   r=1;
351   rr=ctx->rounds-1;
352   DO_AESNI_AESIMC(); r++; rr--; /* round 1 */
353   DO_AESNI_AESIMC(); r++; rr--; /* round 2 */
354   DO_AESNI_AESIMC(); r++; rr--; /* round 3 */
355   DO_AESNI_AESIMC(); r++; rr--; /* round 4 */
356   DO_AESNI_AESIMC(); r++; rr--; /* round 5 */
357   DO_AESNI_AESIMC(); r++; rr--; /* round 6 */
358   DO_AESNI_AESIMC(); r++; rr--; /* round 7 */
359   DO_AESNI_AESIMC(); r++; rr--; /* round 8 */
360   DO_AESNI_AESIMC(); r++; rr--; /* round 9 */
361   if (ctx->rounds > 10)
362     {
363       DO_AESNI_AESIMC(); r++; rr--; /* round 10 */
364       DO_AESNI_AESIMC(); r++; rr--; /* round 11 */
365       if (ctx->rounds > 12)
366         {
367           DO_AESNI_AESIMC(); r++; rr--; /* round 12 */
368           DO_AESNI_AESIMC(); r++; rr--; /* round 13 */
369         }
370     }
371
372   dkey[r] = ekey[0];
373
374 #undef DO_AESNI_AESIMC
375
376   aesni_cleanup();
377 }
378
379
380 /* Encrypt one block using the Intel AES-NI instructions.  Block is input
381  * and output through SSE register xmm0. */
382 static inline void
383 do_aesni_enc (const RIJNDAEL_context *ctx)
384 {
385 #define aesenc_xmm1_xmm0      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc1\n\t"
386 #define aesenclast_xmm1_xmm0  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc1\n\t"
387   asm volatile ("movdqa (%[key]), %%xmm1\n\t"    /* xmm1 := key[0] */
388                 "pxor   %%xmm1, %%xmm0\n\t"     /* xmm0 ^= key[0] */
389                 "movdqa 0x10(%[key]), %%xmm1\n\t"
390                 aesenc_xmm1_xmm0
391                 "movdqa 0x20(%[key]), %%xmm1\n\t"
392                 aesenc_xmm1_xmm0
393                 "movdqa 0x30(%[key]), %%xmm1\n\t"
394                 aesenc_xmm1_xmm0
395                 "movdqa 0x40(%[key]), %%xmm1\n\t"
396                 aesenc_xmm1_xmm0
397                 "movdqa 0x50(%[key]), %%xmm1\n\t"
398                 aesenc_xmm1_xmm0
399                 "movdqa 0x60(%[key]), %%xmm1\n\t"
400                 aesenc_xmm1_xmm0
401                 "movdqa 0x70(%[key]), %%xmm1\n\t"
402                 aesenc_xmm1_xmm0
403                 "movdqa 0x80(%[key]), %%xmm1\n\t"
404                 aesenc_xmm1_xmm0
405                 "movdqa 0x90(%[key]), %%xmm1\n\t"
406                 aesenc_xmm1_xmm0
407                 "movdqa 0xa0(%[key]), %%xmm1\n\t"
408                 "cmpl $10, %[rounds]\n\t"
409                 "jz .Lenclast%=\n\t"
410                 aesenc_xmm1_xmm0
411                 "movdqa 0xb0(%[key]), %%xmm1\n\t"
412                 aesenc_xmm1_xmm0
413                 "movdqa 0xc0(%[key]), %%xmm1\n\t"
414                 "cmpl $12, %[rounds]\n\t"
415                 "jz .Lenclast%=\n\t"
416                 aesenc_xmm1_xmm0
417                 "movdqa 0xd0(%[key]), %%xmm1\n\t"
418                 aesenc_xmm1_xmm0
419                 "movdqa 0xe0(%[key]), %%xmm1\n"
420
421                 ".Lenclast%=:\n\t"
422                 aesenclast_xmm1_xmm0
423                 "\n"
424                 :
425                 : [key] "r" (ctx->keyschenc),
426                   [rounds] "r" (ctx->rounds)
427                 : "cc", "memory");
428 #undef aesenc_xmm1_xmm0
429 #undef aesenclast_xmm1_xmm0
430 }
431
432
433 /* Decrypt one block using the Intel AES-NI instructions.  Block is input
434  * and output through SSE register xmm0. */
435 static inline void
436 do_aesni_dec (const RIJNDAEL_context *ctx)
437 {
438 #define aesdec_xmm1_xmm0      ".byte 0x66, 0x0f, 0x38, 0xde, 0xc1\n\t"
439 #define aesdeclast_xmm1_xmm0  ".byte 0x66, 0x0f, 0x38, 0xdf, 0xc1\n\t"
440   asm volatile ("movdqa (%[key]), %%xmm1\n\t"
441                 "pxor   %%xmm1, %%xmm0\n\t"     /* xmm0 ^= key[0] */
442                 "movdqa 0x10(%[key]), %%xmm1\n\t"
443                 aesdec_xmm1_xmm0
444                 "movdqa 0x20(%[key]), %%xmm1\n\t"
445                 aesdec_xmm1_xmm0
446                 "movdqa 0x30(%[key]), %%xmm1\n\t"
447                 aesdec_xmm1_xmm0
448                 "movdqa 0x40(%[key]), %%xmm1\n\t"
449                 aesdec_xmm1_xmm0
450                 "movdqa 0x50(%[key]), %%xmm1\n\t"
451                 aesdec_xmm1_xmm0
452                 "movdqa 0x60(%[key]), %%xmm1\n\t"
453                 aesdec_xmm1_xmm0
454                 "movdqa 0x70(%[key]), %%xmm1\n\t"
455                 aesdec_xmm1_xmm0
456                 "movdqa 0x80(%[key]), %%xmm1\n\t"
457                 aesdec_xmm1_xmm0
458                 "movdqa 0x90(%[key]), %%xmm1\n\t"
459                 aesdec_xmm1_xmm0
460                 "movdqa 0xa0(%[key]), %%xmm1\n\t"
461                 "cmpl $10, %[rounds]\n\t"
462                 "jz .Ldeclast%=\n\t"
463                 aesdec_xmm1_xmm0
464                 "movdqa 0xb0(%[key]), %%xmm1\n\t"
465                 aesdec_xmm1_xmm0
466                 "movdqa 0xc0(%[key]), %%xmm1\n\t"
467                 "cmpl $12, %[rounds]\n\t"
468                 "jz .Ldeclast%=\n\t"
469                 aesdec_xmm1_xmm0
470                 "movdqa 0xd0(%[key]), %%xmm1\n\t"
471                 aesdec_xmm1_xmm0
472                 "movdqa 0xe0(%[key]), %%xmm1\n"
473
474                 ".Ldeclast%=:\n\t"
475                 aesdeclast_xmm1_xmm0
476                 "\n"
477                 :
478                 : [key] "r" (ctx->keyschdec),
479                   [rounds] "r" (ctx->rounds)
480                 : "cc", "memory");
481 #undef aesdec_xmm1_xmm0
482 #undef aesdeclast_xmm1_xmm0
483 }
484
485
486 /* Encrypt four blocks using the Intel AES-NI instructions.  Blocks are input
487  * and output through SSE registers xmm1 to xmm4.  */
488 static inline void
489 do_aesni_enc_vec4 (const RIJNDAEL_context *ctx)
490 {
491 #define aesenc_xmm0_xmm1      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc8\n\t"
492 #define aesenc_xmm0_xmm2      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xd0\n\t"
493 #define aesenc_xmm0_xmm3      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xd8\n\t"
494 #define aesenc_xmm0_xmm4      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xe0\n\t"
495 #define aesenclast_xmm0_xmm1  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc8\n\t"
496 #define aesenclast_xmm0_xmm2  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xd0\n\t"
497 #define aesenclast_xmm0_xmm3  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xd8\n\t"
498 #define aesenclast_xmm0_xmm4  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xe0\n\t"
499   asm volatile ("movdqa (%[key]), %%xmm0\n\t"
500                 "pxor   %%xmm0, %%xmm1\n\t"     /* xmm1 ^= key[0] */
501                 "pxor   %%xmm0, %%xmm2\n\t"     /* xmm2 ^= key[0] */
502                 "pxor   %%xmm0, %%xmm3\n\t"     /* xmm3 ^= key[0] */
503                 "pxor   %%xmm0, %%xmm4\n\t"     /* xmm4 ^= key[0] */
504                 "movdqa 0x10(%[key]), %%xmm0\n\t"
505                 aesenc_xmm0_xmm1
506                 aesenc_xmm0_xmm2
507                 aesenc_xmm0_xmm3
508                 aesenc_xmm0_xmm4
509                 "movdqa 0x20(%[key]), %%xmm0\n\t"
510                 aesenc_xmm0_xmm1
511                 aesenc_xmm0_xmm2
512                 aesenc_xmm0_xmm3
513                 aesenc_xmm0_xmm4
514                 "movdqa 0x30(%[key]), %%xmm0\n\t"
515                 aesenc_xmm0_xmm1
516                 aesenc_xmm0_xmm2
517                 aesenc_xmm0_xmm3
518                 aesenc_xmm0_xmm4
519                 "movdqa 0x40(%[key]), %%xmm0\n\t"
520                 aesenc_xmm0_xmm1
521                 aesenc_xmm0_xmm2
522                 aesenc_xmm0_xmm3
523                 aesenc_xmm0_xmm4
524                 "movdqa 0x50(%[key]), %%xmm0\n\t"
525                 aesenc_xmm0_xmm1
526                 aesenc_xmm0_xmm2
527                 aesenc_xmm0_xmm3
528                 aesenc_xmm0_xmm4
529                 "movdqa 0x60(%[key]), %%xmm0\n\t"
530                 aesenc_xmm0_xmm1
531                 aesenc_xmm0_xmm2
532                 aesenc_xmm0_xmm3
533                 aesenc_xmm0_xmm4
534                 "movdqa 0x70(%[key]), %%xmm0\n\t"
535                 aesenc_xmm0_xmm1
536                 aesenc_xmm0_xmm2
537                 aesenc_xmm0_xmm3
538                 aesenc_xmm0_xmm4
539                 "movdqa 0x80(%[key]), %%xmm0\n\t"
540                 aesenc_xmm0_xmm1
541                 aesenc_xmm0_xmm2
542                 aesenc_xmm0_xmm3
543                 aesenc_xmm0_xmm4
544                 "movdqa 0x90(%[key]), %%xmm0\n\t"
545                 aesenc_xmm0_xmm1
546                 aesenc_xmm0_xmm2
547                 aesenc_xmm0_xmm3
548                 aesenc_xmm0_xmm4
549                 "movdqa 0xa0(%[key]), %%xmm0\n\t"
550                 "cmpl $10, %[rounds]\n\t"
551                 "jz .Ldeclast%=\n\t"
552                 aesenc_xmm0_xmm1
553                 aesenc_xmm0_xmm2
554                 aesenc_xmm0_xmm3
555                 aesenc_xmm0_xmm4
556                 "movdqa 0xb0(%[key]), %%xmm0\n\t"
557                 aesenc_xmm0_xmm1
558                 aesenc_xmm0_xmm2
559                 aesenc_xmm0_xmm3
560                 aesenc_xmm0_xmm4
561                 "movdqa 0xc0(%[key]), %%xmm0\n\t"
562                 "cmpl $12, %[rounds]\n\t"
563                 "jz .Ldeclast%=\n\t"
564                 aesenc_xmm0_xmm1
565                 aesenc_xmm0_xmm2
566                 aesenc_xmm0_xmm3
567                 aesenc_xmm0_xmm4
568                 "movdqa 0xd0(%[key]), %%xmm0\n\t"
569                 aesenc_xmm0_xmm1
570                 aesenc_xmm0_xmm2
571                 aesenc_xmm0_xmm3
572                 aesenc_xmm0_xmm4
573                 "movdqa 0xe0(%[key]), %%xmm0\n"
574
575                 ".Ldeclast%=:\n\t"
576                 aesenclast_xmm0_xmm1
577                 aesenclast_xmm0_xmm2
578                 aesenclast_xmm0_xmm3
579                 aesenclast_xmm0_xmm4
580                 : /* no output */
581                 : [key] "r" (ctx->keyschenc),
582                   [rounds] "r" (ctx->rounds)
583                 : "cc", "memory");
584 #undef aesenc_xmm0_xmm1
585 #undef aesenc_xmm0_xmm2
586 #undef aesenc_xmm0_xmm3
587 #undef aesenc_xmm0_xmm4
588 #undef aesenclast_xmm0_xmm1
589 #undef aesenclast_xmm0_xmm2
590 #undef aesenclast_xmm0_xmm3
591 #undef aesenclast_xmm0_xmm4
592 }
593
594
595 /* Decrypt four blocks using the Intel AES-NI instructions.  Blocks are input
596  * and output through SSE registers xmm1 to xmm4.  */
597 static inline void
598 do_aesni_dec_vec4 (const RIJNDAEL_context *ctx)
599 {
600 #define aesdec_xmm0_xmm1 ".byte 0x66, 0x0f, 0x38, 0xde, 0xc8\n\t"
601 #define aesdec_xmm0_xmm2 ".byte 0x66, 0x0f, 0x38, 0xde, 0xd0\n\t"
602 #define aesdec_xmm0_xmm3 ".byte 0x66, 0x0f, 0x38, 0xde, 0xd8\n\t"
603 #define aesdec_xmm0_xmm4 ".byte 0x66, 0x0f, 0x38, 0xde, 0xe0\n\t"
604 #define aesdeclast_xmm0_xmm1 ".byte 0x66, 0x0f, 0x38, 0xdf, 0xc8\n\t"
605 #define aesdeclast_xmm0_xmm2 ".byte 0x66, 0x0f, 0x38, 0xdf, 0xd0\n\t"
606 #define aesdeclast_xmm0_xmm3 ".byte 0x66, 0x0f, 0x38, 0xdf, 0xd8\n\t"
607 #define aesdeclast_xmm0_xmm4 ".byte 0x66, 0x0f, 0x38, 0xdf, 0xe0\n\t"
608   asm volatile ("movdqa (%[key]), %%xmm0\n\t"
609                 "pxor   %%xmm0, %%xmm1\n\t"     /* xmm1 ^= key[0] */
610                 "pxor   %%xmm0, %%xmm2\n\t"     /* xmm2 ^= key[0] */
611                 "pxor   %%xmm0, %%xmm3\n\t"     /* xmm3 ^= key[0] */
612                 "pxor   %%xmm0, %%xmm4\n\t"     /* xmm4 ^= key[0] */
613                 "movdqa 0x10(%[key]), %%xmm0\n\t"
614                 aesdec_xmm0_xmm1
615                 aesdec_xmm0_xmm2
616                 aesdec_xmm0_xmm3
617                 aesdec_xmm0_xmm4
618                 "movdqa 0x20(%[key]), %%xmm0\n\t"
619                 aesdec_xmm0_xmm1
620                 aesdec_xmm0_xmm2
621                 aesdec_xmm0_xmm3
622                 aesdec_xmm0_xmm4
623                 "movdqa 0x30(%[key]), %%xmm0\n\t"
624                 aesdec_xmm0_xmm1
625                 aesdec_xmm0_xmm2
626                 aesdec_xmm0_xmm3
627                 aesdec_xmm0_xmm4
628                 "movdqa 0x40(%[key]), %%xmm0\n\t"
629                 aesdec_xmm0_xmm1
630                 aesdec_xmm0_xmm2
631                 aesdec_xmm0_xmm3
632                 aesdec_xmm0_xmm4
633                 "movdqa 0x50(%[key]), %%xmm0\n\t"
634                 aesdec_xmm0_xmm1
635                 aesdec_xmm0_xmm2
636                 aesdec_xmm0_xmm3
637                 aesdec_xmm0_xmm4
638                 "movdqa 0x60(%[key]), %%xmm0\n\t"
639                 aesdec_xmm0_xmm1
640                 aesdec_xmm0_xmm2
641                 aesdec_xmm0_xmm3
642                 aesdec_xmm0_xmm4
643                 "movdqa 0x70(%[key]), %%xmm0\n\t"
644                 aesdec_xmm0_xmm1
645                 aesdec_xmm0_xmm2
646                 aesdec_xmm0_xmm3
647                 aesdec_xmm0_xmm4
648                 "movdqa 0x80(%[key]), %%xmm0\n\t"
649                 aesdec_xmm0_xmm1
650                 aesdec_xmm0_xmm2
651                 aesdec_xmm0_xmm3
652                 aesdec_xmm0_xmm4
653                 "movdqa 0x90(%[key]), %%xmm0\n\t"
654                 aesdec_xmm0_xmm1
655                 aesdec_xmm0_xmm2
656                 aesdec_xmm0_xmm3
657                 aesdec_xmm0_xmm4
658                 "movdqa 0xa0(%[key]), %%xmm0\n\t"
659                 "cmpl $10, %[rounds]\n\t"
660                 "jz .Ldeclast%=\n\t"
661                 aesdec_xmm0_xmm1
662                 aesdec_xmm0_xmm2
663                 aesdec_xmm0_xmm3
664                 aesdec_xmm0_xmm4
665                 "movdqa 0xb0(%[key]), %%xmm0\n\t"
666                 aesdec_xmm0_xmm1
667                 aesdec_xmm0_xmm2
668                 aesdec_xmm0_xmm3
669                 aesdec_xmm0_xmm4
670                 "movdqa 0xc0(%[key]), %%xmm0\n\t"
671                 "cmpl $12, %[rounds]\n\t"
672                 "jz .Ldeclast%=\n\t"
673                 aesdec_xmm0_xmm1
674                 aesdec_xmm0_xmm2
675                 aesdec_xmm0_xmm3
676                 aesdec_xmm0_xmm4
677                 "movdqa 0xd0(%[key]), %%xmm0\n\t"
678                 aesdec_xmm0_xmm1
679                 aesdec_xmm0_xmm2
680                 aesdec_xmm0_xmm3
681                 aesdec_xmm0_xmm4
682                 "movdqa 0xe0(%[key]), %%xmm0\n"
683
684                 ".Ldeclast%=:\n\t"
685                 aesdeclast_xmm0_xmm1
686                 aesdeclast_xmm0_xmm2
687                 aesdeclast_xmm0_xmm3
688                 aesdeclast_xmm0_xmm4
689                 : /* no output */
690                 : [key] "r" (ctx->keyschdec),
691                   [rounds] "r" (ctx->rounds)
692                 : "cc", "memory");
693 #undef aesdec_xmm0_xmm1
694 #undef aesdec_xmm0_xmm2
695 #undef aesdec_xmm0_xmm3
696 #undef aesdec_xmm0_xmm4
697 #undef aesdeclast_xmm0_xmm1
698 #undef aesdeclast_xmm0_xmm2
699 #undef aesdeclast_xmm0_xmm3
700 #undef aesdeclast_xmm0_xmm4
701 }
702
703
704 /* Perform a CTR encryption round using the counter CTR and the input
705    block A.  Write the result to the output block B and update CTR.
706    CTR needs to be a 16 byte aligned little-endian value.  */
707 static void
708 do_aesni_ctr (const RIJNDAEL_context *ctx,
709               unsigned char *ctr, unsigned char *b, const unsigned char *a)
710 {
711 #define aesenc_xmm1_xmm0      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc1\n\t"
712 #define aesenclast_xmm1_xmm0  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc1\n\t"
713
714   asm volatile ("movdqa %%xmm5, %%xmm0\n\t"     /* xmm0 := CTR (xmm5)  */
715                 "pcmpeqd %%xmm1, %%xmm1\n\t"
716                 "psrldq $8, %%xmm1\n\t"         /* xmm1 = -1 */
717
718                 "pshufb %%xmm6, %%xmm5\n\t"
719                 "psubq  %%xmm1, %%xmm5\n\t"     /* xmm5++ (big endian) */
720
721                 /* detect if 64-bit carry handling is needed */
722                 "cmpl   $0xffffffff, 8(%[ctr])\n\t"
723                 "jne    .Lno_carry%=\n\t"
724                 "cmpl   $0xffffffff, 12(%[ctr])\n\t"
725                 "jne    .Lno_carry%=\n\t"
726
727                 "pslldq $8, %%xmm1\n\t"         /* move lower 64-bit to high */
728                 "psubq   %%xmm1, %%xmm5\n\t"    /* add carry to upper 64bits */
729
730                 ".Lno_carry%=:\n\t"
731
732                 "pshufb %%xmm6, %%xmm5\n\t"
733                 "movdqa %%xmm5, (%[ctr])\n\t"   /* Update CTR (mem).       */
734
735                 "pxor (%[key]), %%xmm0\n\t"     /* xmm1 ^= key[0]    */
736                 "movdqa 0x10(%[key]), %%xmm1\n\t"
737                 aesenc_xmm1_xmm0
738                 "movdqa 0x20(%[key]), %%xmm1\n\t"
739                 aesenc_xmm1_xmm0
740                 "movdqa 0x30(%[key]), %%xmm1\n\t"
741                 aesenc_xmm1_xmm0
742                 "movdqa 0x40(%[key]), %%xmm1\n\t"
743                 aesenc_xmm1_xmm0
744                 "movdqa 0x50(%[key]), %%xmm1\n\t"
745                 aesenc_xmm1_xmm0
746                 "movdqa 0x60(%[key]), %%xmm1\n\t"
747                 aesenc_xmm1_xmm0
748                 "movdqa 0x70(%[key]), %%xmm1\n\t"
749                 aesenc_xmm1_xmm0
750                 "movdqa 0x80(%[key]), %%xmm1\n\t"
751                 aesenc_xmm1_xmm0
752                 "movdqa 0x90(%[key]), %%xmm1\n\t"
753                 aesenc_xmm1_xmm0
754                 "movdqa 0xa0(%[key]), %%xmm1\n\t"
755                 "cmpl $10, %[rounds]\n\t"
756                 "jz .Lenclast%=\n\t"
757                 aesenc_xmm1_xmm0
758                 "movdqa 0xb0(%[key]), %%xmm1\n\t"
759                 aesenc_xmm1_xmm0
760                 "movdqa 0xc0(%[key]), %%xmm1\n\t"
761                 "cmpl $12, %[rounds]\n\t"
762                 "jz .Lenclast%=\n\t"
763                 aesenc_xmm1_xmm0
764                 "movdqa 0xd0(%[key]), %%xmm1\n\t"
765                 aesenc_xmm1_xmm0
766                 "movdqa 0xe0(%[key]), %%xmm1\n"
767
768                 ".Lenclast%=:\n\t"
769                 aesenclast_xmm1_xmm0
770                 "movdqu %[src], %%xmm1\n\t"      /* xmm1 := input   */
771                 "pxor %%xmm1, %%xmm0\n\t"        /* EncCTR ^= input  */
772                 "movdqu %%xmm0, %[dst]"          /* Store EncCTR.    */
773
774                 : [dst] "=m" (*b)
775                 : [src] "m" (*a),
776                   [ctr] "r" (ctr),
777                   [key] "r" (ctx->keyschenc),
778                   [rounds] "g" (ctx->rounds)
779                 : "cc", "memory");
780 #undef aesenc_xmm1_xmm0
781 #undef aesenclast_xmm1_xmm0
782 }
783
784
785 /* Four blocks at a time variant of do_aesni_ctr.  */
786 static void
787 do_aesni_ctr_4 (const RIJNDAEL_context *ctx,
788                 unsigned char *ctr, unsigned char *b, const unsigned char *a)
789 {
790 #define aesenc_xmm1_xmm0      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc1\n\t"
791 #define aesenc_xmm1_xmm2      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xd1\n\t"
792 #define aesenc_xmm1_xmm3      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xd9\n\t"
793 #define aesenc_xmm1_xmm4      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xe1\n\t"
794 #define aesenclast_xmm1_xmm0  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc1\n\t"
795 #define aesenclast_xmm1_xmm2  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xd1\n\t"
796 #define aesenclast_xmm1_xmm3  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xd9\n\t"
797 #define aesenclast_xmm1_xmm4  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xe1\n\t"
798
799   /* Register usage:
800       esi   keyschedule
801       xmm0  CTR-0
802       xmm1  temp / round key
803       xmm2  CTR-1
804       xmm3  CTR-2
805       xmm4  CTR-3
806       xmm5  copy of *ctr
807       xmm6  endian swapping mask
808    */
809
810   asm volatile ("movdqa %%xmm5, %%xmm0\n\t"     /* xmm0, xmm2 := CTR (xmm5) */
811                 "movdqa %%xmm0, %%xmm2\n\t"
812                 "pcmpeqd %%xmm1, %%xmm1\n\t"
813                 "psrldq $8, %%xmm1\n\t"         /* xmm1 = -1 */
814
815                 "pshufb %%xmm6, %%xmm2\n\t"     /* xmm2 := le(xmm2) */
816                 "psubq  %%xmm1, %%xmm2\n\t"     /* xmm2++           */
817                 "movdqa %%xmm2, %%xmm3\n\t"     /* xmm3 := xmm2     */
818                 "psubq  %%xmm1, %%xmm3\n\t"     /* xmm3++           */
819                 "movdqa %%xmm3, %%xmm4\n\t"     /* xmm4 := xmm3     */
820                 "psubq  %%xmm1, %%xmm4\n\t"     /* xmm4++           */
821                 "movdqa %%xmm4, %%xmm5\n\t"     /* xmm5 := xmm4     */
822                 "psubq  %%xmm1, %%xmm5\n\t"     /* xmm5++           */
823
824                 /* detect if 64-bit carry handling is needed */
825                 "cmpl   $0xffffffff, 8(%[ctr])\n\t"
826                 "jne    .Lno_carry%=\n\t"
827                 "movl   12(%[ctr]), %%esi\n\t"
828                 "bswapl %%esi\n\t"
829                 "cmpl   $0xfffffffc, %%esi\n\t"
830                 "jb     .Lno_carry%=\n\t"       /* no carry */
831
832                 "pslldq $8, %%xmm1\n\t"         /* move lower 64-bit to high */
833                 "je     .Lcarry_xmm5%=\n\t"     /* esi == 0xfffffffc */
834                 "cmpl   $0xfffffffe, %%esi\n\t"
835                 "jb     .Lcarry_xmm4%=\n\t"     /* esi == 0xfffffffd */
836                 "je     .Lcarry_xmm3%=\n\t"     /* esi == 0xfffffffe */
837                 /* esi == 0xffffffff */
838
839                 "psubq   %%xmm1, %%xmm2\n\t"
840                 ".Lcarry_xmm3%=:\n\t"
841                 "psubq   %%xmm1, %%xmm3\n\t"
842                 ".Lcarry_xmm4%=:\n\t"
843                 "psubq   %%xmm1, %%xmm4\n\t"
844                 ".Lcarry_xmm5%=:\n\t"
845                 "psubq   %%xmm1, %%xmm5\n\t"
846
847                 ".Lno_carry%=:\n\t"
848                 "movdqa (%[key]), %%xmm1\n\t"   /* xmm1 := key[0]    */
849                 "movl %[rounds], %%esi\n\t"
850
851                 "pshufb %%xmm6, %%xmm2\n\t"     /* xmm2 := be(xmm2) */
852                 "pshufb %%xmm6, %%xmm3\n\t"     /* xmm3 := be(xmm3) */
853                 "pshufb %%xmm6, %%xmm4\n\t"     /* xmm4 := be(xmm4) */
854                 "pshufb %%xmm6, %%xmm5\n\t"     /* xmm5 := be(xmm5) */
855                 "movdqa %%xmm5, (%[ctr])\n\t"   /* Update CTR (mem).  */
856
857                 "pxor   %%xmm1, %%xmm0\n\t"     /* xmm0 ^= key[0]    */
858                 "pxor   %%xmm1, %%xmm2\n\t"     /* xmm2 ^= key[0]    */
859                 "pxor   %%xmm1, %%xmm3\n\t"     /* xmm3 ^= key[0]    */
860                 "pxor   %%xmm1, %%xmm4\n\t"     /* xmm4 ^= key[0]    */
861                 "movdqa 0x10(%[key]), %%xmm1\n\t"
862                 aesenc_xmm1_xmm0
863                 aesenc_xmm1_xmm2
864                 aesenc_xmm1_xmm3
865                 aesenc_xmm1_xmm4
866                 "movdqa 0x20(%[key]), %%xmm1\n\t"
867                 aesenc_xmm1_xmm0
868                 aesenc_xmm1_xmm2
869                 aesenc_xmm1_xmm3
870                 aesenc_xmm1_xmm4
871                 "movdqa 0x30(%[key]), %%xmm1\n\t"
872                 aesenc_xmm1_xmm0
873                 aesenc_xmm1_xmm2
874                 aesenc_xmm1_xmm3
875                 aesenc_xmm1_xmm4
876                 "movdqa 0x40(%[key]), %%xmm1\n\t"
877                 aesenc_xmm1_xmm0
878                 aesenc_xmm1_xmm2
879                 aesenc_xmm1_xmm3
880                 aesenc_xmm1_xmm4
881                 "movdqa 0x50(%[key]), %%xmm1\n\t"
882                 aesenc_xmm1_xmm0
883                 aesenc_xmm1_xmm2
884                 aesenc_xmm1_xmm3
885                 aesenc_xmm1_xmm4
886                 "movdqa 0x60(%[key]), %%xmm1\n\t"
887                 aesenc_xmm1_xmm0
888                 aesenc_xmm1_xmm2
889                 aesenc_xmm1_xmm3
890                 aesenc_xmm1_xmm4
891                 "movdqa 0x70(%[key]), %%xmm1\n\t"
892                 aesenc_xmm1_xmm0
893                 aesenc_xmm1_xmm2
894                 aesenc_xmm1_xmm3
895                 aesenc_xmm1_xmm4
896                 "movdqa 0x80(%[key]), %%xmm1\n\t"
897                 aesenc_xmm1_xmm0
898                 aesenc_xmm1_xmm2
899                 aesenc_xmm1_xmm3
900                 aesenc_xmm1_xmm4
901                 "movdqa 0x90(%[key]), %%xmm1\n\t"
902                 aesenc_xmm1_xmm0
903                 aesenc_xmm1_xmm2
904                 aesenc_xmm1_xmm3
905                 aesenc_xmm1_xmm4
906                 "movdqa 0xa0(%[key]), %%xmm1\n\t"
907                 "cmpl $10, %%esi\n\t"
908                 "jz .Lenclast%=\n\t"
909                 aesenc_xmm1_xmm0
910                 aesenc_xmm1_xmm2
911                 aesenc_xmm1_xmm3
912                 aesenc_xmm1_xmm4
913                 "movdqa 0xb0(%[key]), %%xmm1\n\t"
914                 aesenc_xmm1_xmm0
915                 aesenc_xmm1_xmm2
916                 aesenc_xmm1_xmm3
917                 aesenc_xmm1_xmm4
918                 "movdqa 0xc0(%[key]), %%xmm1\n\t"
919                 "cmpl $12, %%esi\n\t"
920                 "jz .Lenclast%=\n\t"
921                 aesenc_xmm1_xmm0
922                 aesenc_xmm1_xmm2
923                 aesenc_xmm1_xmm3
924                 aesenc_xmm1_xmm4
925                 "movdqa 0xd0(%[key]), %%xmm1\n\t"
926                 aesenc_xmm1_xmm0
927                 aesenc_xmm1_xmm2
928                 aesenc_xmm1_xmm3
929                 aesenc_xmm1_xmm4
930                 "movdqa 0xe0(%[key]), %%xmm1\n"
931
932                 ".Lenclast%=:\n\t"
933                 aesenclast_xmm1_xmm0
934                 aesenclast_xmm1_xmm2
935                 aesenclast_xmm1_xmm3
936                 aesenclast_xmm1_xmm4
937
938                 "movdqu (%[src]), %%xmm1\n\t"    /* Get block 1.      */
939                 "pxor %%xmm1, %%xmm0\n\t"        /* EncCTR-1 ^= input */
940                 "movdqu %%xmm0, (%[dst])\n\t"    /* Store block 1     */
941
942                 "movdqu 16(%[src]), %%xmm1\n\t"  /* Get block 2.      */
943                 "pxor %%xmm1, %%xmm2\n\t"        /* EncCTR-2 ^= input */
944                 "movdqu %%xmm2, 16(%[dst])\n\t"  /* Store block 2.    */
945
946                 "movdqu 32(%[src]), %%xmm1\n\t"  /* Get block 3.      */
947                 "pxor %%xmm1, %%xmm3\n\t"        /* EncCTR-3 ^= input */
948                 "movdqu %%xmm3, 32(%[dst])\n\t"  /* Store block 3.    */
949
950                 "movdqu 48(%[src]), %%xmm1\n\t"  /* Get block 4.      */
951                 "pxor %%xmm1, %%xmm4\n\t"        /* EncCTR-4 ^= input */
952                 "movdqu %%xmm4, 48(%[dst])"      /* Store block 4.   */
953
954                 :
955                 : [ctr] "r" (ctr),
956                   [src] "r" (a),
957                   [dst] "r" (b),
958                   [key] "r" (ctx->keyschenc),
959                   [rounds] "g" (ctx->rounds)
960                 : "%esi", "cc", "memory");
961 #undef aesenc_xmm1_xmm0
962 #undef aesenc_xmm1_xmm2
963 #undef aesenc_xmm1_xmm3
964 #undef aesenc_xmm1_xmm4
965 #undef aesenclast_xmm1_xmm0
966 #undef aesenclast_xmm1_xmm2
967 #undef aesenclast_xmm1_xmm3
968 #undef aesenclast_xmm1_xmm4
969 }
970
971
972 unsigned int
973 _gcry_aes_aesni_encrypt (const RIJNDAEL_context *ctx, unsigned char *dst,
974                          const unsigned char *src)
975 {
976   aesni_prepare ();
977   asm volatile ("movdqu %[src], %%xmm0\n\t"
978                 :
979                 : [src] "m" (*src)
980                 : "memory" );
981   do_aesni_enc (ctx);
982   asm volatile ("movdqu %%xmm0, %[dst]\n\t"
983                 : [dst] "=m" (*dst)
984                 :
985                 : "memory" );
986   aesni_cleanup ();
987   return 0;
988 }
989
990
991 void
992 _gcry_aes_aesni_cfb_enc (RIJNDAEL_context *ctx, unsigned char *outbuf,
993                          const unsigned char *inbuf, unsigned char *iv,
994                          size_t nblocks)
995 {
996   aesni_prepare ();
997
998   asm volatile ("movdqu %[iv], %%xmm0\n\t"
999                 : /* No output */
1000                 : [iv] "m" (*iv)
1001                 : "memory" );
1002
1003   for ( ;nblocks; nblocks-- )
1004     {
1005       do_aesni_enc (ctx);
1006
1007       asm volatile ("movdqu %[inbuf], %%xmm1\n\t"
1008                     "pxor %%xmm1, %%xmm0\n\t"
1009                     "movdqu %%xmm0, %[outbuf]\n\t"
1010                     : [outbuf] "=m" (*outbuf)
1011                     : [inbuf] "m" (*inbuf)
1012                     : "memory" );
1013
1014       outbuf += BLOCKSIZE;
1015       inbuf  += BLOCKSIZE;
1016     }
1017
1018   asm volatile ("movdqu %%xmm0, %[iv]\n\t"
1019                 : [iv] "=m" (*iv)
1020                 :
1021                 : "memory" );
1022
1023   aesni_cleanup ();
1024 }
1025
1026
1027 void
1028 _gcry_aes_aesni_cbc_enc (RIJNDAEL_context *ctx, unsigned char *outbuf,
1029                          const unsigned char *inbuf, unsigned char *iv,
1030                          size_t nblocks, int cbc_mac)
1031 {
1032   aesni_prepare_2_6_variable;
1033
1034   aesni_prepare ();
1035   aesni_prepare_2_6();
1036
1037   asm volatile ("movdqu %[iv], %%xmm5\n\t"
1038                 : /* No output */
1039                 : [iv] "m" (*iv)
1040                 : "memory" );
1041
1042   for ( ;nblocks; nblocks-- )
1043     {
1044       asm volatile ("movdqu %[inbuf], %%xmm0\n\t"
1045                     "pxor %%xmm5, %%xmm0\n\t"
1046                     : /* No output */
1047                     : [inbuf] "m" (*inbuf)
1048                     : "memory" );
1049
1050       do_aesni_enc (ctx);
1051
1052       asm volatile ("movdqa %%xmm0, %%xmm5\n\t"
1053                     "movdqu %%xmm0, %[outbuf]\n\t"
1054                     : [outbuf] "=m" (*outbuf)
1055                     :
1056                     : "memory" );
1057
1058       inbuf += BLOCKSIZE;
1059       if (!cbc_mac)
1060         outbuf += BLOCKSIZE;
1061     }
1062
1063   asm volatile ("movdqu %%xmm5, %[iv]\n\t"
1064                 : [iv] "=m" (*iv)
1065                 :
1066                 : "memory" );
1067
1068   aesni_cleanup ();
1069   aesni_cleanup_2_6 ();
1070 }
1071
1072
1073 void
1074 _gcry_aes_aesni_ctr_enc (RIJNDAEL_context *ctx, unsigned char *outbuf,
1075                          const unsigned char *inbuf, unsigned char *ctr,
1076                          size_t nblocks)
1077 {
1078   static const unsigned char be_mask[16] __attribute__ ((aligned (16))) =
1079     { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
1080   aesni_prepare_2_6_variable;
1081
1082   aesni_prepare ();
1083   aesni_prepare_2_6();
1084
1085   asm volatile ("movdqa %[mask], %%xmm6\n\t" /* Preload mask */
1086                 "movdqa %[ctr], %%xmm5\n\t"  /* Preload CTR */
1087                 : /* No output */
1088                 : [mask] "m" (*be_mask),
1089                   [ctr] "m" (*ctr)
1090                 : "memory");
1091
1092   for ( ;nblocks > 3 ; nblocks -= 4 )
1093     {
1094       do_aesni_ctr_4 (ctx, ctr, outbuf, inbuf);
1095       outbuf += 4*BLOCKSIZE;
1096       inbuf  += 4*BLOCKSIZE;
1097     }
1098   for ( ;nblocks; nblocks-- )
1099     {
1100       do_aesni_ctr (ctx, ctr, outbuf, inbuf);
1101       outbuf += BLOCKSIZE;
1102       inbuf  += BLOCKSIZE;
1103     }
1104   aesni_cleanup ();
1105   aesni_cleanup_2_6 ();
1106 }
1107
1108
1109 unsigned int
1110 _gcry_aes_aesni_decrypt (const RIJNDAEL_context *ctx, unsigned char *dst,
1111                          const unsigned char *src)
1112 {
1113   aesni_prepare ();
1114   asm volatile ("movdqu %[src], %%xmm0\n\t"
1115                 :
1116                 : [src] "m" (*src)
1117                 : "memory" );
1118   do_aesni_dec (ctx);
1119   asm volatile ("movdqu %%xmm0, %[dst]\n\t"
1120                 : [dst] "=m" (*dst)
1121                 :
1122                 : "memory" );
1123   aesni_cleanup ();
1124   return 0;
1125 }
1126
1127
1128 void
1129 _gcry_aes_aesni_cfb_dec (RIJNDAEL_context *ctx, unsigned char *outbuf,
1130                          const unsigned char *inbuf, unsigned char *iv,
1131                          size_t nblocks)
1132 {
1133   aesni_prepare_2_6_variable;
1134
1135   aesni_prepare ();
1136   aesni_prepare_2_6();
1137
1138   asm volatile ("movdqu %[iv], %%xmm6\n\t"
1139                 : /* No output */
1140                 : [iv] "m" (*iv)
1141                 : "memory" );
1142
1143   /* CFB decryption can be parallelized */
1144   for ( ;nblocks >= 4; nblocks -= 4)
1145     {
1146       asm volatile
1147         ("movdqu %%xmm6,         %%xmm1\n\t" /* load input blocks */
1148          "movdqu 0*16(%[inbuf]), %%xmm2\n\t"
1149          "movdqu 1*16(%[inbuf]), %%xmm3\n\t"
1150          "movdqu 2*16(%[inbuf]), %%xmm4\n\t"
1151
1152          "movdqu 3*16(%[inbuf]), %%xmm6\n\t" /* update IV */
1153          : /* No output */
1154          : [inbuf] "r" (inbuf)
1155          : "memory");
1156
1157       do_aesni_enc_vec4 (ctx);
1158
1159       asm volatile
1160         ("movdqu 0*16(%[inbuf]), %%xmm5\n\t"
1161          "pxor %%xmm5, %%xmm1\n\t"
1162          "movdqu %%xmm1, 0*16(%[outbuf])\n\t"
1163
1164          "movdqu 1*16(%[inbuf]), %%xmm5\n\t"
1165          "pxor %%xmm5, %%xmm2\n\t"
1166          "movdqu %%xmm2, 1*16(%[outbuf])\n\t"
1167
1168          "movdqu 2*16(%[inbuf]), %%xmm5\n\t"
1169          "pxor %%xmm5, %%xmm3\n\t"
1170          "movdqu %%xmm3, 2*16(%[outbuf])\n\t"
1171
1172          "movdqu 3*16(%[inbuf]), %%xmm5\n\t"
1173          "pxor %%xmm5, %%xmm4\n\t"
1174          "movdqu %%xmm4, 3*16(%[outbuf])\n\t"
1175
1176          : /* No output */
1177          : [inbuf] "r" (inbuf),
1178            [outbuf] "r" (outbuf)
1179          : "memory");
1180
1181       outbuf += 4*BLOCKSIZE;
1182       inbuf  += 4*BLOCKSIZE;
1183     }
1184
1185   asm volatile ("movdqu %%xmm6, %%xmm0\n\t" ::: "cc");
1186
1187   for ( ;nblocks; nblocks-- )
1188     {
1189       do_aesni_enc (ctx);
1190
1191       asm volatile ("movdqa %%xmm0, %%xmm6\n\t"
1192                     "movdqu %[inbuf], %%xmm0\n\t"
1193                     "pxor %%xmm0, %%xmm6\n\t"
1194                     "movdqu %%xmm6, %[outbuf]\n\t"
1195                     : [outbuf] "=m" (*outbuf)
1196                     : [inbuf] "m" (*inbuf)
1197                     : "memory" );
1198
1199       outbuf += BLOCKSIZE;
1200       inbuf  += BLOCKSIZE;
1201     }
1202
1203   asm volatile ("movdqu %%xmm0, %[iv]\n\t"
1204                 : [iv] "=m" (*iv)
1205                 :
1206                 : "memory" );
1207
1208   aesni_cleanup ();
1209   aesni_cleanup_2_6 ();
1210 }
1211
1212
1213 void
1214 _gcry_aes_aesni_cbc_dec (RIJNDAEL_context *ctx, unsigned char *outbuf,
1215                          const unsigned char *inbuf, unsigned char *iv,
1216                          size_t nblocks)
1217 {
1218   aesni_prepare_2_6_variable;
1219
1220   aesni_prepare ();
1221   aesni_prepare_2_6();
1222
1223   asm volatile
1224     ("movdqu %[iv], %%xmm5\n\t" /* use xmm5 as fast IV storage */
1225      : /* No output */
1226      : [iv] "m" (*iv)
1227      : "memory");
1228
1229   for ( ;nblocks > 3 ; nblocks -= 4 )
1230     {
1231       asm volatile
1232         ("movdqu 0*16(%[inbuf]), %%xmm1\n\t"    /* load input blocks */
1233          "movdqu 1*16(%[inbuf]), %%xmm2\n\t"
1234          "movdqu 2*16(%[inbuf]), %%xmm3\n\t"
1235          "movdqu 3*16(%[inbuf]), %%xmm4\n\t"
1236          : /* No output */
1237          : [inbuf] "r" (inbuf)
1238          : "memory");
1239
1240       do_aesni_dec_vec4 (ctx);
1241
1242       asm volatile
1243         ("pxor %%xmm5, %%xmm1\n\t"              /* xor IV with output */
1244          "movdqu 0*16(%[inbuf]), %%xmm5\n\t"    /* load new IV */
1245          "movdqu %%xmm1, 0*16(%[outbuf])\n\t"
1246
1247          "pxor %%xmm5, %%xmm2\n\t"              /* xor IV with output */
1248          "movdqu 1*16(%[inbuf]), %%xmm5\n\t"    /* load new IV */
1249          "movdqu %%xmm2, 1*16(%[outbuf])\n\t"
1250
1251          "pxor %%xmm5, %%xmm3\n\t"              /* xor IV with output */
1252          "movdqu 2*16(%[inbuf]), %%xmm5\n\t"    /* load new IV */
1253          "movdqu %%xmm3, 2*16(%[outbuf])\n\t"
1254
1255          "pxor %%xmm5, %%xmm4\n\t"              /* xor IV with output */
1256          "movdqu 3*16(%[inbuf]), %%xmm5\n\t"    /* load new IV */
1257          "movdqu %%xmm4, 3*16(%[outbuf])\n\t"
1258
1259          : /* No output */
1260          : [inbuf] "r" (inbuf),
1261            [outbuf] "r" (outbuf)
1262          : "memory");
1263
1264       outbuf += 4*BLOCKSIZE;
1265       inbuf  += 4*BLOCKSIZE;
1266     }
1267
1268   for ( ;nblocks; nblocks-- )
1269     {
1270       asm volatile
1271         ("movdqu %[inbuf], %%xmm0\n\t"
1272          "movdqa %%xmm0, %%xmm2\n\t"    /* use xmm2 as savebuf */
1273          : /* No output */
1274          : [inbuf] "m" (*inbuf)
1275          : "memory");
1276
1277       /* uses only xmm0 and xmm1 */
1278       do_aesni_dec (ctx);
1279
1280       asm volatile
1281         ("pxor %%xmm5, %%xmm0\n\t"      /* xor IV with output */
1282          "movdqu %%xmm0, %[outbuf]\n\t"
1283          "movdqu %%xmm2, %%xmm5\n\t"    /* store savebuf as new IV */
1284          : [outbuf] "=m" (*outbuf)
1285          :
1286          : "memory");
1287
1288       outbuf += BLOCKSIZE;
1289       inbuf  += BLOCKSIZE;
1290     }
1291
1292   asm volatile
1293     ("movdqu %%xmm5, %[iv]\n\t" /* store IV */
1294      : /* No output */
1295      : [iv] "m" (*iv)
1296      : "memory");
1297
1298   aesni_cleanup ();
1299   aesni_cleanup_2_6 ();
1300 }
1301
1302
1303 static inline const unsigned char *
1304 get_l (gcry_cipher_hd_t c, unsigned char *l_tmp, u64 i, unsigned char *iv,
1305        unsigned char *ctr)
1306 {
1307   const unsigned char *l;
1308   unsigned int ntz;
1309
1310   if (i & 0xffffffffU)
1311     {
1312       asm ("rep;bsf %k[low], %k[ntz]\n\t"
1313            : [ntz] "=r" (ntz)
1314            : [low] "r" (i & 0xffffffffU)
1315            : "cc");
1316     }
1317   else
1318     {
1319       if (OCB_L_TABLE_SIZE < 32)
1320         {
1321           ntz = 32;
1322         }
1323       else if (i)
1324         {
1325           asm ("rep;bsf %k[high], %k[ntz]\n\t"
1326                : [ntz] "=r" (ntz)
1327                : [high] "r" (i >> 32)
1328                : "cc");
1329           ntz += 32;
1330         }
1331       else
1332         {
1333           ntz = 64;
1334         }
1335     }
1336
1337   if (ntz < OCB_L_TABLE_SIZE)
1338     {
1339       l = c->u_mode.ocb.L[ntz];
1340     }
1341   else
1342     {
1343       /* Store Offset & Checksum before calling external function */
1344       asm volatile ("movdqu %%xmm5, %[iv]\n\t"
1345                     "movdqu %%xmm6, %[ctr]\n\t"
1346                     : [iv] "=m" (*iv),
1347                       [ctr] "=m" (*ctr)
1348                     :
1349                     : "memory" );
1350
1351       l = _gcry_cipher_ocb_get_l (c, l_tmp, i);
1352
1353       /* Restore Offset & Checksum */
1354       asm volatile ("movdqu %[iv], %%xmm5\n\t"
1355                     "movdqu %[ctr], %%xmm6\n\t"
1356                     : /* No output */
1357                     : [iv] "m" (*iv),
1358                       [ctr] "m" (*ctr)
1359                     : "memory" );
1360     }
1361
1362   return l;
1363 }
1364
1365
1366 static void
1367 aesni_ocb_enc (gcry_cipher_hd_t c, void *outbuf_arg,
1368                const void *inbuf_arg, size_t nblocks)
1369 {
1370   union { unsigned char x1[16] ATTR_ALIGNED_16; u32 x32[4]; } l_tmp;
1371   RIJNDAEL_context *ctx = (void *)&c->context.c;
1372   unsigned char *outbuf = outbuf_arg;
1373   const unsigned char *inbuf = inbuf_arg;
1374   u64 n = c->u_mode.ocb.data_nblocks;
1375   aesni_prepare_2_6_variable;
1376
1377   aesni_prepare ();
1378   aesni_prepare_2_6 ();
1379
1380   /* Preload Offset and Checksum */
1381   asm volatile ("movdqu %[iv], %%xmm5\n\t"
1382                 "movdqu %[ctr], %%xmm6\n\t"
1383                 : /* No output */
1384                 : [iv] "m" (*c->u_iv.iv),
1385                   [ctr] "m" (*c->u_ctr.ctr)
1386                 : "memory" );
1387
1388   for ( ;nblocks > 3 ; nblocks -= 4 )
1389     {
1390       const unsigned char *l[4];
1391
1392       /* l_tmp will be used only every 65536-th block. */
1393       l[0] = get_l(c, l_tmp.x1, ++n, c->u_iv.iv, c->u_ctr.ctr);
1394       l[1] = get_l(c, l_tmp.x1, ++n, c->u_iv.iv, c->u_ctr.ctr);
1395       l[2] = get_l(c, l_tmp.x1, ++n, c->u_iv.iv, c->u_ctr.ctr);
1396       l[3] = get_l(c, l_tmp.x1, ++n, c->u_iv.iv, c->u_ctr.ctr);
1397
1398       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
1399       /* Checksum_i = Checksum_{i-1} xor P_i  */
1400       /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
1401       asm volatile ("movdqu %[l0],     %%xmm0\n\t"
1402                     "movdqu %[inbuf0], %%xmm1\n\t"
1403                     "pxor   %%xmm0,    %%xmm5\n\t"
1404                     "pxor   %%xmm1,    %%xmm6\n\t"
1405                     "pxor   %%xmm5,    %%xmm1\n\t"
1406                     "movdqu %%xmm5,    %[outbuf0]\n\t"
1407                     : [outbuf0] "=m" (*(outbuf + 0 * BLOCKSIZE))
1408                     : [l0] "m" (*l[0]),
1409                       [inbuf0] "m" (*(inbuf + 0 * BLOCKSIZE))
1410                     : "memory" );
1411       asm volatile ("movdqu %[l1],     %%xmm0\n\t"
1412                     "movdqu %[inbuf1], %%xmm2\n\t"
1413                     "pxor   %%xmm0,    %%xmm5\n\t"
1414                     "pxor   %%xmm2,    %%xmm6\n\t"
1415                     "pxor   %%xmm5,    %%xmm2\n\t"
1416                     "movdqu %%xmm5,    %[outbuf1]\n\t"
1417                     : [outbuf1] "=m" (*(outbuf + 1 * BLOCKSIZE))
1418                     : [l1] "m" (*l[1]),
1419                       [inbuf1] "m" (*(inbuf + 1 * BLOCKSIZE))
1420                     : "memory" );
1421       asm volatile ("movdqu %[l2],     %%xmm0\n\t"
1422                     "movdqu %[inbuf2], %%xmm3\n\t"
1423                     "pxor   %%xmm0,    %%xmm5\n\t"
1424                     "pxor   %%xmm3,    %%xmm6\n\t"
1425                     "pxor   %%xmm5,    %%xmm3\n\t"
1426                     "movdqu %%xmm5,    %[outbuf2]\n\t"
1427                     : [outbuf2] "=m" (*(outbuf + 2 * BLOCKSIZE))
1428                     : [l2] "m" (*l[2]),
1429                       [inbuf2] "m" (*(inbuf + 2 * BLOCKSIZE))
1430                     : "memory" );
1431       asm volatile ("movdqu %[l3],     %%xmm0\n\t"
1432                     "movdqu %[inbuf3], %%xmm4\n\t"
1433                     "pxor   %%xmm0,    %%xmm5\n\t"
1434                     "pxor   %%xmm4,    %%xmm6\n\t"
1435                     "pxor   %%xmm5,    %%xmm4\n\t"
1436                     :
1437                     : [l3] "m" (*l[3]),
1438                       [inbuf3] "m" (*(inbuf + 3 * BLOCKSIZE))
1439                     : "memory" );
1440
1441       do_aesni_enc_vec4 (ctx);
1442
1443       asm volatile ("movdqu %[outbuf0],%%xmm0\n\t"
1444                     "pxor   %%xmm0,    %%xmm1\n\t"
1445                     "movdqu %%xmm1,    %[outbuf0]\n\t"
1446                     "movdqu %[outbuf1],%%xmm0\n\t"
1447                     "pxor   %%xmm0,    %%xmm2\n\t"
1448                     "movdqu %%xmm2,    %[outbuf1]\n\t"
1449                     "movdqu %[outbuf2],%%xmm0\n\t"
1450                     "pxor   %%xmm0,    %%xmm3\n\t"
1451                     "movdqu %%xmm3,    %[outbuf2]\n\t"
1452                     "pxor   %%xmm5,    %%xmm4\n\t"
1453                     "movdqu %%xmm4,    %[outbuf3]\n\t"
1454                     : [outbuf0] "+m" (*(outbuf + 0 * BLOCKSIZE)),
1455                       [outbuf1] "+m" (*(outbuf + 1 * BLOCKSIZE)),
1456                       [outbuf2] "+m" (*(outbuf + 2 * BLOCKSIZE)),
1457                       [outbuf3] "=m" (*(outbuf + 3 * BLOCKSIZE))
1458                     :
1459                     : "memory" );
1460
1461       outbuf += 4*BLOCKSIZE;
1462       inbuf  += 4*BLOCKSIZE;
1463     }
1464   for ( ;nblocks; nblocks-- )
1465     {
1466       const unsigned char *l;
1467
1468       l = get_l(c, l_tmp.x1, ++n, c->u_iv.iv, c->u_ctr.ctr);
1469
1470       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
1471       /* Checksum_i = Checksum_{i-1} xor P_i  */
1472       /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
1473       asm volatile ("movdqu %[l],     %%xmm1\n\t"
1474                     "movdqu %[inbuf], %%xmm0\n\t"
1475                     "pxor   %%xmm1,   %%xmm5\n\t"
1476                     "pxor   %%xmm0,   %%xmm6\n\t"
1477                     "pxor   %%xmm5,   %%xmm0\n\t"
1478                     :
1479                     : [l] "m" (*l),
1480                       [inbuf] "m" (*inbuf)
1481                     : "memory" );
1482
1483       do_aesni_enc (ctx);
1484
1485       asm volatile ("pxor   %%xmm5, %%xmm0\n\t"
1486                     "movdqu %%xmm0, %[outbuf]\n\t"
1487                     : [outbuf] "=m" (*outbuf)
1488                     :
1489                     : "memory" );
1490
1491       inbuf += BLOCKSIZE;
1492       outbuf += BLOCKSIZE;
1493     }
1494
1495   c->u_mode.ocb.data_nblocks = n;
1496   asm volatile ("movdqu %%xmm5, %[iv]\n\t"
1497                 "movdqu %%xmm6, %[ctr]\n\t"
1498                 : [iv] "=m" (*c->u_iv.iv),
1499                   [ctr] "=m" (*c->u_ctr.ctr)
1500                 :
1501                 : "memory" );
1502
1503   aesni_cleanup ();
1504   aesni_cleanup_2_6 ();
1505
1506   wipememory(&l_tmp, sizeof(l_tmp));
1507 }
1508
1509
1510 static void
1511 aesni_ocb_dec (gcry_cipher_hd_t c, void *outbuf_arg,
1512                const void *inbuf_arg, size_t nblocks)
1513 {
1514   union { unsigned char x1[16] ATTR_ALIGNED_16; u32 x32[4]; } l_tmp;
1515   RIJNDAEL_context *ctx = (void *)&c->context.c;
1516   unsigned char *outbuf = outbuf_arg;
1517   const unsigned char *inbuf = inbuf_arg;
1518   u64 n = c->u_mode.ocb.data_nblocks;
1519   aesni_prepare_2_6_variable;
1520
1521   aesni_prepare ();
1522   aesni_prepare_2_6 ();
1523
1524   /* Preload Offset and Checksum */
1525   asm volatile ("movdqu %[iv], %%xmm5\n\t"
1526                 "movdqu %[ctr], %%xmm6\n\t"
1527                 : /* No output */
1528                 : [iv] "m" (*c->u_iv.iv),
1529                   [ctr] "m" (*c->u_ctr.ctr)
1530                 : "memory" );
1531
1532   for ( ;nblocks > 3 ; nblocks -= 4 )
1533     {
1534       const unsigned char *l[4];
1535
1536       /* l_tmp will be used only every 65536-th block. */
1537       l[0] = get_l(c, l_tmp.x1, ++n, c->u_iv.iv, c->u_ctr.ctr);
1538       l[1] = get_l(c, l_tmp.x1, ++n, c->u_iv.iv, c->u_ctr.ctr);
1539       l[2] = get_l(c, l_tmp.x1, ++n, c->u_iv.iv, c->u_ctr.ctr);
1540       l[3] = get_l(c, l_tmp.x1, ++n, c->u_iv.iv, c->u_ctr.ctr);
1541
1542       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
1543       /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i)  */
1544       /* Checksum_i = Checksum_{i-1} xor P_i  */
1545       asm volatile ("movdqu %[l0],     %%xmm0\n\t"
1546                     "movdqu %[inbuf0], %%xmm1\n\t"
1547                     "pxor   %%xmm0,    %%xmm5\n\t"
1548                     "pxor   %%xmm5,    %%xmm1\n\t"
1549                     "movdqu %%xmm5,    %[outbuf0]\n\t"
1550                     : [outbuf0] "=m" (*(outbuf + 0 * BLOCKSIZE))
1551                     : [l0] "m" (*l[0]),
1552                       [inbuf0] "m" (*(inbuf + 0 * BLOCKSIZE))
1553                     : "memory" );
1554       asm volatile ("movdqu %[l1],     %%xmm0\n\t"
1555                     "movdqu %[inbuf1], %%xmm2\n\t"
1556                     "pxor   %%xmm0,    %%xmm5\n\t"
1557                     "pxor   %%xmm5,    %%xmm2\n\t"
1558                     "movdqu %%xmm5,    %[outbuf1]\n\t"
1559                     : [outbuf1] "=m" (*(outbuf + 1 * BLOCKSIZE))
1560                     : [l1] "m" (*l[1]),
1561                       [inbuf1] "m" (*(inbuf + 1 * BLOCKSIZE))
1562                     : "memory" );
1563       asm volatile ("movdqu %[l2],     %%xmm0\n\t"
1564                     "movdqu %[inbuf2], %%xmm3\n\t"
1565                     "pxor   %%xmm0,    %%xmm5\n\t"
1566                     "pxor   %%xmm5,    %%xmm3\n\t"
1567                     "movdqu %%xmm5,    %[outbuf2]\n\t"
1568                     : [outbuf2] "=m" (*(outbuf + 2 * BLOCKSIZE))
1569                     : [l2] "m" (*l[2]),
1570                       [inbuf2] "m" (*(inbuf + 2 * BLOCKSIZE))
1571                     : "memory" );
1572       asm volatile ("movdqu %[l3],     %%xmm0\n\t"
1573                     "movdqu %[inbuf3], %%xmm4\n\t"
1574                     "pxor   %%xmm0,    %%xmm5\n\t"
1575                     "pxor   %%xmm5,    %%xmm4\n\t"
1576                     :
1577                     : [l3] "m" (*l[3]),
1578                       [inbuf3] "m" (*(inbuf + 3 * BLOCKSIZE))
1579                     : "memory" );
1580
1581       do_aesni_dec_vec4 (ctx);
1582
1583       asm volatile ("movdqu %[outbuf0],%%xmm0\n\t"
1584                     "pxor   %%xmm0,    %%xmm1\n\t"
1585                     "movdqu %%xmm1,    %[outbuf0]\n\t"
1586                     "movdqu %[outbuf1],%%xmm0\n\t"
1587                     "pxor   %%xmm0,    %%xmm2\n\t"
1588                     "movdqu %%xmm2,    %[outbuf1]\n\t"
1589                     "movdqu %[outbuf2],%%xmm0\n\t"
1590                     "pxor   %%xmm0,    %%xmm3\n\t"
1591                     "movdqu %%xmm3,    %[outbuf2]\n\t"
1592                     "pxor   %%xmm5,    %%xmm4\n\t"
1593                     "movdqu %%xmm4,    %[outbuf3]\n\t"
1594                     "pxor   %%xmm1,    %%xmm6\n\t"
1595                     "pxor   %%xmm2,    %%xmm6\n\t"
1596                     "pxor   %%xmm3,    %%xmm6\n\t"
1597                     "pxor   %%xmm4,    %%xmm6\n\t"
1598                     : [outbuf0] "+m" (*(outbuf + 0 * BLOCKSIZE)),
1599                       [outbuf1] "+m" (*(outbuf + 1 * BLOCKSIZE)),
1600                       [outbuf2] "+m" (*(outbuf + 2 * BLOCKSIZE)),
1601                       [outbuf3] "=m" (*(outbuf + 3 * BLOCKSIZE))
1602                     :
1603                     : "memory" );
1604
1605       outbuf += 4*BLOCKSIZE;
1606       inbuf  += 4*BLOCKSIZE;
1607     }
1608   for ( ;nblocks; nblocks-- )
1609     {
1610       const unsigned char *l;
1611
1612       l = get_l(c, l_tmp.x1, ++n, c->u_iv.iv, c->u_ctr.ctr);
1613
1614       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
1615       /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i)  */
1616       /* Checksum_i = Checksum_{i-1} xor P_i  */
1617       asm volatile ("movdqu %[l],     %%xmm1\n\t"
1618                     "movdqu %[inbuf], %%xmm0\n\t"
1619                     "pxor   %%xmm1,   %%xmm5\n\t"
1620                     "pxor   %%xmm5,   %%xmm0\n\t"
1621                     :
1622                     : [l] "m" (*l),
1623                       [inbuf] "m" (*inbuf)
1624                     : "memory" );
1625
1626       do_aesni_dec (ctx);
1627
1628       asm volatile ("pxor   %%xmm5, %%xmm0\n\t"
1629                     "pxor   %%xmm0, %%xmm6\n\t"
1630                     "movdqu %%xmm0, %[outbuf]\n\t"
1631                     : [outbuf] "=m" (*outbuf)
1632                     :
1633                     : "memory" );
1634
1635       inbuf += BLOCKSIZE;
1636       outbuf += BLOCKSIZE;
1637     }
1638
1639   c->u_mode.ocb.data_nblocks = n;
1640   asm volatile ("movdqu %%xmm5, %[iv]\n\t"
1641                 "movdqu %%xmm6, %[ctr]\n\t"
1642                 : [iv] "=m" (*c->u_iv.iv),
1643                   [ctr] "=m" (*c->u_ctr.ctr)
1644                 :
1645                 : "memory" );
1646
1647   aesni_cleanup ();
1648   aesni_cleanup_2_6 ();
1649
1650   wipememory(&l_tmp, sizeof(l_tmp));
1651 }
1652
1653
1654 void
1655 _gcry_aes_aesni_ocb_crypt(gcry_cipher_hd_t c, void *outbuf_arg,
1656                           const void *inbuf_arg, size_t nblocks, int encrypt)
1657 {
1658   if (encrypt)
1659     aesni_ocb_enc(c, outbuf_arg, inbuf_arg, nblocks);
1660   else
1661     aesni_ocb_dec(c, outbuf_arg, inbuf_arg, nblocks);
1662 }
1663
1664
1665 void
1666 _gcry_aes_aesni_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
1667                           size_t nblocks)
1668 {
1669   union { unsigned char x1[16] ATTR_ALIGNED_16; u32 x32[4]; } l_tmp;
1670   RIJNDAEL_context *ctx = (void *)&c->context.c;
1671   const unsigned char *abuf = abuf_arg;
1672   u64 n = c->u_mode.ocb.aad_nblocks;
1673   aesni_prepare_2_6_variable;
1674
1675   aesni_prepare ();
1676   aesni_prepare_2_6 ();
1677
1678   /* Preload Offset and Sum */
1679   asm volatile ("movdqu %[iv], %%xmm5\n\t"
1680                 "movdqu %[ctr], %%xmm6\n\t"
1681                 : /* No output */
1682                 : [iv] "m" (*c->u_mode.ocb.aad_offset),
1683                   [ctr] "m" (*c->u_mode.ocb.aad_sum)
1684                 : "memory" );
1685
1686   for ( ;nblocks > 3 ; nblocks -= 4 )
1687     {
1688       const unsigned char *l[4];
1689
1690       /* l_tmp will be used only every 65536-th block. */
1691       l[0] = get_l(c, l_tmp.x1, ++n, c->u_mode.ocb.aad_offset,
1692                    c->u_mode.ocb.aad_sum);
1693       l[1] = get_l(c, l_tmp.x1, ++n, c->u_mode.ocb.aad_offset,
1694                    c->u_mode.ocb.aad_sum);
1695       l[2] = get_l(c, l_tmp.x1, ++n, c->u_mode.ocb.aad_offset,
1696                    c->u_mode.ocb.aad_sum);
1697       l[3] = get_l(c, l_tmp.x1, ++n, c->u_mode.ocb.aad_offset,
1698                    c->u_mode.ocb.aad_sum);
1699
1700       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
1701       /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i)  */
1702       asm volatile ("movdqu %[l0],     %%xmm0\n\t"
1703                     "movdqu %[abuf0],  %%xmm1\n\t"
1704                     "pxor   %%xmm0,    %%xmm5\n\t"
1705                     "pxor   %%xmm5,    %%xmm1\n\t"
1706                     :
1707                     : [l0] "m" (*l[0]),
1708                       [abuf0] "m" (*(abuf + 0 * BLOCKSIZE))
1709                     : "memory" );
1710       asm volatile ("movdqu %[l1],     %%xmm0\n\t"
1711                     "movdqu %[abuf1],  %%xmm2\n\t"
1712                     "pxor   %%xmm0,    %%xmm5\n\t"
1713                     "pxor   %%xmm5,    %%xmm2\n\t"
1714                     :
1715                     : [l1] "m" (*l[1]),
1716                       [abuf1] "m" (*(abuf + 1 * BLOCKSIZE))
1717                     : "memory" );
1718       asm volatile ("movdqu %[l2],     %%xmm0\n\t"
1719                     "movdqu %[abuf2],  %%xmm3\n\t"
1720                     "pxor   %%xmm0,    %%xmm5\n\t"
1721                     "pxor   %%xmm5,    %%xmm3\n\t"
1722                     :
1723                     : [l2] "m" (*l[2]),
1724                       [abuf2] "m" (*(abuf + 2 * BLOCKSIZE))
1725                     : "memory" );
1726       asm volatile ("movdqu %[l3],     %%xmm0\n\t"
1727                     "movdqu %[abuf3],  %%xmm4\n\t"
1728                     "pxor   %%xmm0,    %%xmm5\n\t"
1729                     "pxor   %%xmm5,    %%xmm4\n\t"
1730                     :
1731                     : [l3] "m" (*l[3]),
1732                       [abuf3] "m" (*(abuf + 3 * BLOCKSIZE))
1733                     : "memory" );
1734
1735       do_aesni_enc_vec4 (ctx);
1736
1737       asm volatile ("pxor   %%xmm1,   %%xmm6\n\t"
1738                     "pxor   %%xmm2,   %%xmm6\n\t"
1739                     "pxor   %%xmm3,   %%xmm6\n\t"
1740                     "pxor   %%xmm4,   %%xmm6\n\t"
1741                     :
1742                     :
1743                     : "memory" );
1744
1745       abuf += 4*BLOCKSIZE;
1746     }
1747   for ( ;nblocks; nblocks-- )
1748     {
1749       const unsigned char *l;
1750
1751       l = get_l(c, l_tmp.x1, ++n, c->u_mode.ocb.aad_offset,
1752                 c->u_mode.ocb.aad_sum);
1753
1754       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
1755       /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i)  */
1756       asm volatile ("movdqu %[l],     %%xmm1\n\t"
1757                     "movdqu %[abuf],  %%xmm0\n\t"
1758                     "pxor   %%xmm1,   %%xmm5\n\t"
1759                     "pxor   %%xmm5,   %%xmm0\n\t"
1760                     :
1761                     : [l] "m" (*l),
1762                       [abuf] "m" (*abuf)
1763                     : "memory" );
1764
1765       do_aesni_enc (ctx);
1766
1767       asm volatile ("pxor   %%xmm0,   %%xmm6\n\t"
1768                     :
1769                     :
1770                     : "memory" );
1771
1772       abuf += BLOCKSIZE;
1773     }
1774
1775   c->u_mode.ocb.aad_nblocks = n;
1776   asm volatile ("movdqu %%xmm5, %[iv]\n\t"
1777                 "movdqu %%xmm6, %[ctr]\n\t"
1778                 : [iv] "=m" (*c->u_mode.ocb.aad_offset),
1779                   [ctr] "=m" (*c->u_mode.ocb.aad_sum)
1780                 :
1781                 : "memory" );
1782
1783   aesni_cleanup ();
1784   aesni_cleanup_2_6 ();
1785
1786   wipememory(&l_tmp, sizeof(l_tmp));
1787 }
1788
1789
1790 #endif /* USE_AESNI */