97e0ad0a444ef47be4b07aef359ca668a9ed9400
[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   static const byte bige_addb_const[4][16] __attribute__ ((aligned (16))) =
791     {
792       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
793       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 },
794       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3 },
795       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4 }
796     };
797 #define aesenc_xmm1_xmm0      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc1\n\t"
798 #define aesenc_xmm1_xmm2      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xd1\n\t"
799 #define aesenc_xmm1_xmm3      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xd9\n\t"
800 #define aesenc_xmm1_xmm4      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xe1\n\t"
801 #define aesenclast_xmm1_xmm0  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc1\n\t"
802 #define aesenclast_xmm1_xmm2  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xd1\n\t"
803 #define aesenclast_xmm1_xmm3  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xd9\n\t"
804 #define aesenclast_xmm1_xmm4  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xe1\n\t"
805
806   /* Register usage:
807       esi   keyschedule
808       xmm0  CTR-0
809       xmm1  temp / round key
810       xmm2  CTR-1
811       xmm3  CTR-2
812       xmm4  CTR-3
813       xmm5  copy of *ctr
814       xmm6  endian swapping mask
815    */
816
817   asm volatile (/* detect if 8-bit carry handling is needed */
818                 "cmpb   $0xfb, 15(%[ctr])\n\t"
819                 "ja     .Ladd32bit%=\n\t"
820
821                 "movdqa %%xmm5, %%xmm0\n\t"     /* xmm0 := CTR (xmm5) */
822                 "movdqa %[addb_1], %%xmm2\n\t"  /* xmm2 := be(1) */
823                 "movdqa %[addb_2], %%xmm3\n\t"  /* xmm3 := be(2) */
824                 "movdqa %[addb_3], %%xmm4\n\t"  /* xmm4 := be(3) */
825                 "movdqa %[addb_4], %%xmm5\n\t"  /* xmm5 := be(4) */
826                 "paddb  %%xmm0, %%xmm2\n\t"     /* xmm2 := be(1) + CTR (xmm0) */
827                 "paddb  %%xmm0, %%xmm3\n\t"     /* xmm3 := be(2) + CTR (xmm0) */
828                 "paddb  %%xmm0, %%xmm4\n\t"     /* xmm4 := be(3) + CTR (xmm0) */
829                 "paddb  %%xmm0, %%xmm5\n\t"     /* xmm5 := be(4) + CTR (xmm0) */
830                 "movdqa (%[key]), %%xmm1\n\t"   /* xmm1 := key[0] */
831                 "movl   %[rounds], %%esi\n\t"
832                 "jmp    .Lstore_ctr%=\n\t"
833
834                 ".Ladd32bit%=:\n\t"
835                 "movdqa %%xmm5, %%xmm0\n\t"     /* xmm0, xmm2 := CTR (xmm5) */
836                 "movdqa %%xmm0, %%xmm2\n\t"
837                 "pcmpeqd %%xmm1, %%xmm1\n\t"
838                 "psrldq $8, %%xmm1\n\t"         /* xmm1 = -1 */
839
840                 "pshufb %%xmm6, %%xmm2\n\t"     /* xmm2 := le(xmm2) */
841                 "psubq  %%xmm1, %%xmm2\n\t"     /* xmm2++           */
842                 "movdqa %%xmm2, %%xmm3\n\t"     /* xmm3 := xmm2     */
843                 "psubq  %%xmm1, %%xmm3\n\t"     /* xmm3++           */
844                 "movdqa %%xmm3, %%xmm4\n\t"     /* xmm4 := xmm3     */
845                 "psubq  %%xmm1, %%xmm4\n\t"     /* xmm4++           */
846                 "movdqa %%xmm4, %%xmm5\n\t"     /* xmm5 := xmm4     */
847                 "psubq  %%xmm1, %%xmm5\n\t"     /* xmm5++           */
848
849                 /* detect if 64-bit carry handling is needed */
850                 "cmpl   $0xffffffff, 8(%[ctr])\n\t"
851                 "jne    .Lno_carry%=\n\t"
852                 "movl   12(%[ctr]), %%esi\n\t"
853                 "bswapl %%esi\n\t"
854                 "cmpl   $0xfffffffc, %%esi\n\t"
855                 "jb     .Lno_carry%=\n\t"       /* no carry */
856
857                 "pslldq $8, %%xmm1\n\t"         /* move lower 64-bit to high */
858                 "je     .Lcarry_xmm5%=\n\t"     /* esi == 0xfffffffc */
859                 "cmpl   $0xfffffffe, %%esi\n\t"
860                 "jb     .Lcarry_xmm4%=\n\t"     /* esi == 0xfffffffd */
861                 "je     .Lcarry_xmm3%=\n\t"     /* esi == 0xfffffffe */
862                 /* esi == 0xffffffff */
863
864                 "psubq   %%xmm1, %%xmm2\n\t"
865                 ".Lcarry_xmm3%=:\n\t"
866                 "psubq   %%xmm1, %%xmm3\n\t"
867                 ".Lcarry_xmm4%=:\n\t"
868                 "psubq   %%xmm1, %%xmm4\n\t"
869                 ".Lcarry_xmm5%=:\n\t"
870                 "psubq   %%xmm1, %%xmm5\n\t"
871
872                 ".Lno_carry%=:\n\t"
873                 "movdqa (%[key]), %%xmm1\n\t"   /* xmm1 := key[0]    */
874                 "movl %[rounds], %%esi\n\t"
875
876                 "pshufb %%xmm6, %%xmm2\n\t"     /* xmm2 := be(xmm2) */
877                 "pshufb %%xmm6, %%xmm3\n\t"     /* xmm3 := be(xmm3) */
878                 "pshufb %%xmm6, %%xmm4\n\t"     /* xmm4 := be(xmm4) */
879                 "pshufb %%xmm6, %%xmm5\n\t"     /* xmm5 := be(xmm5) */
880
881                 ".Lstore_ctr%=:\n\t"
882                 "movdqa %%xmm5, (%[ctr])\n\t"   /* Update CTR (mem).  */
883
884                 "pxor   %%xmm1, %%xmm0\n\t"     /* xmm0 ^= key[0]    */
885                 "pxor   %%xmm1, %%xmm2\n\t"     /* xmm2 ^= key[0]    */
886                 "pxor   %%xmm1, %%xmm3\n\t"     /* xmm3 ^= key[0]    */
887                 "pxor   %%xmm1, %%xmm4\n\t"     /* xmm4 ^= key[0]    */
888                 "movdqa 0x10(%[key]), %%xmm1\n\t"
889                 aesenc_xmm1_xmm0
890                 aesenc_xmm1_xmm2
891                 aesenc_xmm1_xmm3
892                 aesenc_xmm1_xmm4
893                 "movdqa 0x20(%[key]), %%xmm1\n\t"
894                 aesenc_xmm1_xmm0
895                 aesenc_xmm1_xmm2
896                 aesenc_xmm1_xmm3
897                 aesenc_xmm1_xmm4
898                 "movdqa 0x30(%[key]), %%xmm1\n\t"
899                 aesenc_xmm1_xmm0
900                 aesenc_xmm1_xmm2
901                 aesenc_xmm1_xmm3
902                 aesenc_xmm1_xmm4
903                 "movdqa 0x40(%[key]), %%xmm1\n\t"
904                 aesenc_xmm1_xmm0
905                 aesenc_xmm1_xmm2
906                 aesenc_xmm1_xmm3
907                 aesenc_xmm1_xmm4
908                 "movdqa 0x50(%[key]), %%xmm1\n\t"
909                 aesenc_xmm1_xmm0
910                 aesenc_xmm1_xmm2
911                 aesenc_xmm1_xmm3
912                 aesenc_xmm1_xmm4
913                 "movdqa 0x60(%[key]), %%xmm1\n\t"
914                 aesenc_xmm1_xmm0
915                 aesenc_xmm1_xmm2
916                 aesenc_xmm1_xmm3
917                 aesenc_xmm1_xmm4
918                 "movdqa 0x70(%[key]), %%xmm1\n\t"
919                 aesenc_xmm1_xmm0
920                 aesenc_xmm1_xmm2
921                 aesenc_xmm1_xmm3
922                 aesenc_xmm1_xmm4
923                 "movdqa 0x80(%[key]), %%xmm1\n\t"
924                 aesenc_xmm1_xmm0
925                 aesenc_xmm1_xmm2
926                 aesenc_xmm1_xmm3
927                 aesenc_xmm1_xmm4
928                 "movdqa 0x90(%[key]), %%xmm1\n\t"
929                 aesenc_xmm1_xmm0
930                 aesenc_xmm1_xmm2
931                 aesenc_xmm1_xmm3
932                 aesenc_xmm1_xmm4
933                 "movdqa 0xa0(%[key]), %%xmm1\n\t"
934                 "cmpl $10, %%esi\n\t"
935                 "jz .Lenclast%=\n\t"
936                 aesenc_xmm1_xmm0
937                 aesenc_xmm1_xmm2
938                 aesenc_xmm1_xmm3
939                 aesenc_xmm1_xmm4
940                 "movdqa 0xb0(%[key]), %%xmm1\n\t"
941                 aesenc_xmm1_xmm0
942                 aesenc_xmm1_xmm2
943                 aesenc_xmm1_xmm3
944                 aesenc_xmm1_xmm4
945                 "movdqa 0xc0(%[key]), %%xmm1\n\t"
946                 "cmpl $12, %%esi\n\t"
947                 "jz .Lenclast%=\n\t"
948                 aesenc_xmm1_xmm0
949                 aesenc_xmm1_xmm2
950                 aesenc_xmm1_xmm3
951                 aesenc_xmm1_xmm4
952                 "movdqa 0xd0(%[key]), %%xmm1\n\t"
953                 aesenc_xmm1_xmm0
954                 aesenc_xmm1_xmm2
955                 aesenc_xmm1_xmm3
956                 aesenc_xmm1_xmm4
957                 "movdqa 0xe0(%[key]), %%xmm1\n"
958
959                 ".Lenclast%=:\n\t"
960                 aesenclast_xmm1_xmm0
961                 aesenclast_xmm1_xmm2
962                 aesenclast_xmm1_xmm3
963                 aesenclast_xmm1_xmm4
964                 :
965                 : [ctr] "r" (ctr),
966                   [key] "r" (ctx->keyschenc),
967                   [rounds] "g" (ctx->rounds),
968                   [addb_1] "m" (bige_addb_const[0][0]),
969                   [addb_2] "m" (bige_addb_const[1][0]),
970                   [addb_3] "m" (bige_addb_const[2][0]),
971                   [addb_4] "m" (bige_addb_const[3][0])
972                 : "%esi", "cc", "memory");
973
974   asm volatile ("movdqu (%[src]), %%xmm1\n\t"    /* Get block 1.      */
975                 "pxor %%xmm1, %%xmm0\n\t"        /* EncCTR-1 ^= input */
976                 "movdqu %%xmm0, (%[dst])\n\t"    /* Store block 1     */
977
978                 "movdqu 16(%[src]), %%xmm1\n\t"  /* Get block 2.      */
979                 "pxor %%xmm1, %%xmm2\n\t"        /* EncCTR-2 ^= input */
980                 "movdqu %%xmm2, 16(%[dst])\n\t"  /* Store block 2.    */
981
982                 "movdqu 32(%[src]), %%xmm1\n\t"  /* Get block 3.      */
983                 "pxor %%xmm1, %%xmm3\n\t"        /* EncCTR-3 ^= input */
984                 "movdqu %%xmm3, 32(%[dst])\n\t"  /* Store block 3.    */
985
986                 "movdqu 48(%[src]), %%xmm1\n\t"  /* Get block 4.      */
987                 "pxor %%xmm1, %%xmm4\n\t"        /* EncCTR-4 ^= input */
988                 "movdqu %%xmm4, 48(%[dst])"      /* Store block 4.   */
989                 :
990                 : [src] "r" (a),
991                   [dst] "r" (b)
992                 : "memory");
993 #undef aesenc_xmm1_xmm0
994 #undef aesenc_xmm1_xmm2
995 #undef aesenc_xmm1_xmm3
996 #undef aesenc_xmm1_xmm4
997 #undef aesenclast_xmm1_xmm0
998 #undef aesenclast_xmm1_xmm2
999 #undef aesenclast_xmm1_xmm3
1000 #undef aesenclast_xmm1_xmm4
1001 }
1002
1003
1004 unsigned int
1005 _gcry_aes_aesni_encrypt (const RIJNDAEL_context *ctx, unsigned char *dst,
1006                          const unsigned char *src)
1007 {
1008   aesni_prepare ();
1009   asm volatile ("movdqu %[src], %%xmm0\n\t"
1010                 :
1011                 : [src] "m" (*src)
1012                 : "memory" );
1013   do_aesni_enc (ctx);
1014   asm volatile ("movdqu %%xmm0, %[dst]\n\t"
1015                 : [dst] "=m" (*dst)
1016                 :
1017                 : "memory" );
1018   aesni_cleanup ();
1019   return 0;
1020 }
1021
1022
1023 void
1024 _gcry_aes_aesni_cfb_enc (RIJNDAEL_context *ctx, unsigned char *outbuf,
1025                          const unsigned char *inbuf, unsigned char *iv,
1026                          size_t nblocks)
1027 {
1028   aesni_prepare ();
1029
1030   asm volatile ("movdqu %[iv], %%xmm0\n\t"
1031                 : /* No output */
1032                 : [iv] "m" (*iv)
1033                 : "memory" );
1034
1035   for ( ;nblocks; nblocks-- )
1036     {
1037       do_aesni_enc (ctx);
1038
1039       asm volatile ("movdqu %[inbuf], %%xmm1\n\t"
1040                     "pxor %%xmm1, %%xmm0\n\t"
1041                     "movdqu %%xmm0, %[outbuf]\n\t"
1042                     : [outbuf] "=m" (*outbuf)
1043                     : [inbuf] "m" (*inbuf)
1044                     : "memory" );
1045
1046       outbuf += BLOCKSIZE;
1047       inbuf  += BLOCKSIZE;
1048     }
1049
1050   asm volatile ("movdqu %%xmm0, %[iv]\n\t"
1051                 : [iv] "=m" (*iv)
1052                 :
1053                 : "memory" );
1054
1055   aesni_cleanup ();
1056 }
1057
1058
1059 void
1060 _gcry_aes_aesni_cbc_enc (RIJNDAEL_context *ctx, unsigned char *outbuf,
1061                          const unsigned char *inbuf, unsigned char *iv,
1062                          size_t nblocks, int cbc_mac)
1063 {
1064   aesni_prepare_2_6_variable;
1065
1066   aesni_prepare ();
1067   aesni_prepare_2_6();
1068
1069   asm volatile ("movdqu %[iv], %%xmm5\n\t"
1070                 : /* No output */
1071                 : [iv] "m" (*iv)
1072                 : "memory" );
1073
1074   for ( ;nblocks; nblocks-- )
1075     {
1076       asm volatile ("movdqu %[inbuf], %%xmm0\n\t"
1077                     "pxor %%xmm5, %%xmm0\n\t"
1078                     : /* No output */
1079                     : [inbuf] "m" (*inbuf)
1080                     : "memory" );
1081
1082       do_aesni_enc (ctx);
1083
1084       asm volatile ("movdqa %%xmm0, %%xmm5\n\t"
1085                     "movdqu %%xmm0, %[outbuf]\n\t"
1086                     : [outbuf] "=m" (*outbuf)
1087                     :
1088                     : "memory" );
1089
1090       inbuf += BLOCKSIZE;
1091       if (!cbc_mac)
1092         outbuf += BLOCKSIZE;
1093     }
1094
1095   asm volatile ("movdqu %%xmm5, %[iv]\n\t"
1096                 : [iv] "=m" (*iv)
1097                 :
1098                 : "memory" );
1099
1100   aesni_cleanup ();
1101   aesni_cleanup_2_6 ();
1102 }
1103
1104
1105 void
1106 _gcry_aes_aesni_ctr_enc (RIJNDAEL_context *ctx, unsigned char *outbuf,
1107                          const unsigned char *inbuf, unsigned char *ctr,
1108                          size_t nblocks)
1109 {
1110   static const unsigned char be_mask[16] __attribute__ ((aligned (16))) =
1111     { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
1112   aesni_prepare_2_6_variable;
1113
1114   aesni_prepare ();
1115   aesni_prepare_2_6();
1116
1117   asm volatile ("movdqa %[mask], %%xmm6\n\t" /* Preload mask */
1118                 "movdqa %[ctr], %%xmm5\n\t"  /* Preload CTR */
1119                 : /* No output */
1120                 : [mask] "m" (*be_mask),
1121                   [ctr] "m" (*ctr)
1122                 : "memory");
1123
1124   for ( ;nblocks > 3 ; nblocks -= 4 )
1125     {
1126       do_aesni_ctr_4 (ctx, ctr, outbuf, inbuf);
1127       outbuf += 4*BLOCKSIZE;
1128       inbuf  += 4*BLOCKSIZE;
1129     }
1130   for ( ;nblocks; nblocks-- )
1131     {
1132       do_aesni_ctr (ctx, ctr, outbuf, inbuf);
1133       outbuf += BLOCKSIZE;
1134       inbuf  += BLOCKSIZE;
1135     }
1136   aesni_cleanup ();
1137   aesni_cleanup_2_6 ();
1138 }
1139
1140
1141 unsigned int
1142 _gcry_aes_aesni_decrypt (const RIJNDAEL_context *ctx, unsigned char *dst,
1143                          const unsigned char *src)
1144 {
1145   aesni_prepare ();
1146   asm volatile ("movdqu %[src], %%xmm0\n\t"
1147                 :
1148                 : [src] "m" (*src)
1149                 : "memory" );
1150   do_aesni_dec (ctx);
1151   asm volatile ("movdqu %%xmm0, %[dst]\n\t"
1152                 : [dst] "=m" (*dst)
1153                 :
1154                 : "memory" );
1155   aesni_cleanup ();
1156   return 0;
1157 }
1158
1159
1160 void
1161 _gcry_aes_aesni_cfb_dec (RIJNDAEL_context *ctx, unsigned char *outbuf,
1162                          const unsigned char *inbuf, unsigned char *iv,
1163                          size_t nblocks)
1164 {
1165   aesni_prepare_2_6_variable;
1166
1167   aesni_prepare ();
1168   aesni_prepare_2_6();
1169
1170   asm volatile ("movdqu %[iv], %%xmm6\n\t"
1171                 : /* No output */
1172                 : [iv] "m" (*iv)
1173                 : "memory" );
1174
1175   /* CFB decryption can be parallelized */
1176   for ( ;nblocks >= 4; nblocks -= 4)
1177     {
1178       asm volatile
1179         ("movdqu %%xmm6,         %%xmm1\n\t" /* load input blocks */
1180          "movdqu 0*16(%[inbuf]), %%xmm2\n\t"
1181          "movdqu 1*16(%[inbuf]), %%xmm3\n\t"
1182          "movdqu 2*16(%[inbuf]), %%xmm4\n\t"
1183
1184          "movdqu 3*16(%[inbuf]), %%xmm6\n\t" /* update IV */
1185          : /* No output */
1186          : [inbuf] "r" (inbuf)
1187          : "memory");
1188
1189       do_aesni_enc_vec4 (ctx);
1190
1191       asm volatile
1192         ("movdqu 0*16(%[inbuf]), %%xmm5\n\t"
1193          "pxor %%xmm5, %%xmm1\n\t"
1194          "movdqu %%xmm1, 0*16(%[outbuf])\n\t"
1195
1196          "movdqu 1*16(%[inbuf]), %%xmm5\n\t"
1197          "pxor %%xmm5, %%xmm2\n\t"
1198          "movdqu %%xmm2, 1*16(%[outbuf])\n\t"
1199
1200          "movdqu 2*16(%[inbuf]), %%xmm5\n\t"
1201          "pxor %%xmm5, %%xmm3\n\t"
1202          "movdqu %%xmm3, 2*16(%[outbuf])\n\t"
1203
1204          "movdqu 3*16(%[inbuf]), %%xmm5\n\t"
1205          "pxor %%xmm5, %%xmm4\n\t"
1206          "movdqu %%xmm4, 3*16(%[outbuf])\n\t"
1207
1208          : /* No output */
1209          : [inbuf] "r" (inbuf),
1210            [outbuf] "r" (outbuf)
1211          : "memory");
1212
1213       outbuf += 4*BLOCKSIZE;
1214       inbuf  += 4*BLOCKSIZE;
1215     }
1216
1217   asm volatile ("movdqu %%xmm6, %%xmm0\n\t" ::: "cc");
1218
1219   for ( ;nblocks; nblocks-- )
1220     {
1221       do_aesni_enc (ctx);
1222
1223       asm volatile ("movdqa %%xmm0, %%xmm6\n\t"
1224                     "movdqu %[inbuf], %%xmm0\n\t"
1225                     "pxor %%xmm0, %%xmm6\n\t"
1226                     "movdqu %%xmm6, %[outbuf]\n\t"
1227                     : [outbuf] "=m" (*outbuf)
1228                     : [inbuf] "m" (*inbuf)
1229                     : "memory" );
1230
1231       outbuf += BLOCKSIZE;
1232       inbuf  += BLOCKSIZE;
1233     }
1234
1235   asm volatile ("movdqu %%xmm0, %[iv]\n\t"
1236                 : [iv] "=m" (*iv)
1237                 :
1238                 : "memory" );
1239
1240   aesni_cleanup ();
1241   aesni_cleanup_2_6 ();
1242 }
1243
1244
1245 void
1246 _gcry_aes_aesni_cbc_dec (RIJNDAEL_context *ctx, unsigned char *outbuf,
1247                          const unsigned char *inbuf, unsigned char *iv,
1248                          size_t nblocks)
1249 {
1250   aesni_prepare_2_6_variable;
1251
1252   aesni_prepare ();
1253   aesni_prepare_2_6();
1254
1255   asm volatile
1256     ("movdqu %[iv], %%xmm5\n\t" /* use xmm5 as fast IV storage */
1257      : /* No output */
1258      : [iv] "m" (*iv)
1259      : "memory");
1260
1261   for ( ;nblocks > 3 ; nblocks -= 4 )
1262     {
1263       asm volatile
1264         ("movdqu 0*16(%[inbuf]), %%xmm1\n\t"    /* load input blocks */
1265          "movdqu 1*16(%[inbuf]), %%xmm2\n\t"
1266          "movdqu 2*16(%[inbuf]), %%xmm3\n\t"
1267          "movdqu 3*16(%[inbuf]), %%xmm4\n\t"
1268          : /* No output */
1269          : [inbuf] "r" (inbuf)
1270          : "memory");
1271
1272       do_aesni_dec_vec4 (ctx);
1273
1274       asm volatile
1275         ("pxor %%xmm5, %%xmm1\n\t"              /* xor IV with output */
1276          "movdqu 0*16(%[inbuf]), %%xmm5\n\t"    /* load new IV */
1277          "movdqu %%xmm1, 0*16(%[outbuf])\n\t"
1278
1279          "pxor %%xmm5, %%xmm2\n\t"              /* xor IV with output */
1280          "movdqu 1*16(%[inbuf]), %%xmm5\n\t"    /* load new IV */
1281          "movdqu %%xmm2, 1*16(%[outbuf])\n\t"
1282
1283          "pxor %%xmm5, %%xmm3\n\t"              /* xor IV with output */
1284          "movdqu 2*16(%[inbuf]), %%xmm5\n\t"    /* load new IV */
1285          "movdqu %%xmm3, 2*16(%[outbuf])\n\t"
1286
1287          "pxor %%xmm5, %%xmm4\n\t"              /* xor IV with output */
1288          "movdqu 3*16(%[inbuf]), %%xmm5\n\t"    /* load new IV */
1289          "movdqu %%xmm4, 3*16(%[outbuf])\n\t"
1290
1291          : /* No output */
1292          : [inbuf] "r" (inbuf),
1293            [outbuf] "r" (outbuf)
1294          : "memory");
1295
1296       outbuf += 4*BLOCKSIZE;
1297       inbuf  += 4*BLOCKSIZE;
1298     }
1299
1300   for ( ;nblocks; nblocks-- )
1301     {
1302       asm volatile
1303         ("movdqu %[inbuf], %%xmm0\n\t"
1304          "movdqa %%xmm0, %%xmm2\n\t"    /* use xmm2 as savebuf */
1305          : /* No output */
1306          : [inbuf] "m" (*inbuf)
1307          : "memory");
1308
1309       /* uses only xmm0 and xmm1 */
1310       do_aesni_dec (ctx);
1311
1312       asm volatile
1313         ("pxor %%xmm5, %%xmm0\n\t"      /* xor IV with output */
1314          "movdqu %%xmm0, %[outbuf]\n\t"
1315          "movdqu %%xmm2, %%xmm5\n\t"    /* store savebuf as new IV */
1316          : [outbuf] "=m" (*outbuf)
1317          :
1318          : "memory");
1319
1320       outbuf += BLOCKSIZE;
1321       inbuf  += BLOCKSIZE;
1322     }
1323
1324   asm volatile
1325     ("movdqu %%xmm5, %[iv]\n\t" /* store IV */
1326      : /* No output */
1327      : [iv] "m" (*iv)
1328      : "memory");
1329
1330   aesni_cleanup ();
1331   aesni_cleanup_2_6 ();
1332 }
1333
1334
1335 static inline const unsigned char *
1336 get_l (gcry_cipher_hd_t c, unsigned char *l_tmp, u64 i, unsigned char *iv,
1337        unsigned char *ctr)
1338 {
1339   const unsigned char *l;
1340   unsigned int ntz;
1341
1342   if (i & 0xffffffffU)
1343     {
1344       asm ("rep;bsf %k[low], %k[ntz]\n\t"
1345            : [ntz] "=r" (ntz)
1346            : [low] "r" (i & 0xffffffffU)
1347            : "cc");
1348     }
1349   else
1350     {
1351       if (OCB_L_TABLE_SIZE < 32)
1352         {
1353           ntz = 32;
1354         }
1355       else if (i)
1356         {
1357           asm ("rep;bsf %k[high], %k[ntz]\n\t"
1358                : [ntz] "=r" (ntz)
1359                : [high] "r" (i >> 32)
1360                : "cc");
1361           ntz += 32;
1362         }
1363       else
1364         {
1365           ntz = 64;
1366         }
1367     }
1368
1369   if (ntz < OCB_L_TABLE_SIZE)
1370     {
1371       l = c->u_mode.ocb.L[ntz];
1372     }
1373   else
1374     {
1375       /* Store Offset & Checksum before calling external function */
1376       asm volatile ("movdqu %%xmm5, %[iv]\n\t"
1377                     "movdqu %%xmm6, %[ctr]\n\t"
1378                     : [iv] "=m" (*iv),
1379                       [ctr] "=m" (*ctr)
1380                     :
1381                     : "memory" );
1382
1383       l = _gcry_cipher_ocb_get_l (c, l_tmp, i);
1384
1385       /* Restore Offset & Checksum */
1386       asm volatile ("movdqu %[iv], %%xmm5\n\t"
1387                     "movdqu %[ctr], %%xmm6\n\t"
1388                     : /* No output */
1389                     : [iv] "m" (*iv),
1390                       [ctr] "m" (*ctr)
1391                     : "memory" );
1392     }
1393
1394   return l;
1395 }
1396
1397
1398 static void
1399 aesni_ocb_enc (gcry_cipher_hd_t c, void *outbuf_arg,
1400                const void *inbuf_arg, size_t nblocks)
1401 {
1402   union { unsigned char x1[16] ATTR_ALIGNED_16; u32 x32[4]; } l_tmp;
1403   RIJNDAEL_context *ctx = (void *)&c->context.c;
1404   unsigned char *outbuf = outbuf_arg;
1405   const unsigned char *inbuf = inbuf_arg;
1406   u64 n = c->u_mode.ocb.data_nblocks;
1407   const unsigned char *l;
1408   aesni_prepare_2_6_variable;
1409
1410   aesni_prepare ();
1411   aesni_prepare_2_6 ();
1412
1413   /* Preload Offset and Checksum */
1414   asm volatile ("movdqu %[iv], %%xmm5\n\t"
1415                 "movdqu %[ctr], %%xmm6\n\t"
1416                 : /* No output */
1417                 : [iv] "m" (*c->u_iv.iv),
1418                   [ctr] "m" (*c->u_ctr.ctr)
1419                 : "memory" );
1420
1421
1422   for ( ;nblocks && n % 4; nblocks-- )
1423     {
1424       l = get_l(c, l_tmp.x1, ++n, c->u_iv.iv, c->u_ctr.ctr);
1425
1426       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
1427       /* Checksum_i = Checksum_{i-1} xor P_i  */
1428       /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
1429       asm volatile ("movdqu %[l],     %%xmm1\n\t"
1430                     "movdqu %[inbuf], %%xmm0\n\t"
1431                     "pxor   %%xmm1,   %%xmm5\n\t"
1432                     "pxor   %%xmm0,   %%xmm6\n\t"
1433                     "pxor   %%xmm5,   %%xmm0\n\t"
1434                     :
1435                     : [l] "m" (*l),
1436                       [inbuf] "m" (*inbuf)
1437                     : "memory" );
1438
1439       do_aesni_enc (ctx);
1440
1441       asm volatile ("pxor   %%xmm5, %%xmm0\n\t"
1442                     "movdqu %%xmm0, %[outbuf]\n\t"
1443                     : [outbuf] "=m" (*outbuf)
1444                     :
1445                     : "memory" );
1446
1447       inbuf += BLOCKSIZE;
1448       outbuf += BLOCKSIZE;
1449     }
1450
1451   for ( ;nblocks > 3 ; nblocks -= 4 )
1452     {
1453       /* l_tmp will be used only every 65536-th block. */
1454       n += 4;
1455       l = get_l(c, l_tmp.x1, n, c->u_iv.iv, c->u_ctr.ctr);
1456
1457       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
1458       /* Checksum_i = Checksum_{i-1} xor P_i  */
1459       /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
1460       asm volatile ("movdqu %[l0],     %%xmm0\n\t"
1461                     "movdqu %[inbuf0], %%xmm1\n\t"
1462                     "pxor   %%xmm0,    %%xmm5\n\t"
1463                     "pxor   %%xmm1,    %%xmm6\n\t"
1464                     "pxor   %%xmm5,    %%xmm1\n\t"
1465                     "movdqu %%xmm5,    %[outbuf0]\n\t"
1466                     : [outbuf0] "=m" (*(outbuf + 0 * BLOCKSIZE))
1467                     : [l0] "m" (*c->u_mode.ocb.L[0]),
1468                       [inbuf0] "m" (*(inbuf + 0 * BLOCKSIZE))
1469                     : "memory" );
1470       asm volatile ("movdqu %[l1],     %%xmm0\n\t"
1471                     "movdqu %[inbuf1], %%xmm2\n\t"
1472                     "pxor   %%xmm0,    %%xmm5\n\t"
1473                     "pxor   %%xmm2,    %%xmm6\n\t"
1474                     "pxor   %%xmm5,    %%xmm2\n\t"
1475                     "movdqu %%xmm5,    %[outbuf1]\n\t"
1476                     : [outbuf1] "=m" (*(outbuf + 1 * BLOCKSIZE))
1477                     : [l1] "m" (*c->u_mode.ocb.L[1]),
1478                       [inbuf1] "m" (*(inbuf + 1 * BLOCKSIZE))
1479                     : "memory" );
1480       asm volatile ("movdqu %[l2],     %%xmm0\n\t"
1481                     "movdqu %[inbuf2], %%xmm3\n\t"
1482                     "pxor   %%xmm0,    %%xmm5\n\t"
1483                     "pxor   %%xmm3,    %%xmm6\n\t"
1484                     "pxor   %%xmm5,    %%xmm3\n\t"
1485                     "movdqu %%xmm5,    %[outbuf2]\n\t"
1486                     : [outbuf2] "=m" (*(outbuf + 2 * BLOCKSIZE))
1487                     : [l2] "m" (*c->u_mode.ocb.L[0]),
1488                       [inbuf2] "m" (*(inbuf + 2 * BLOCKSIZE))
1489                     : "memory" );
1490       asm volatile ("movdqu %[l3],     %%xmm0\n\t"
1491                     "movdqu %[inbuf3], %%xmm4\n\t"
1492                     "pxor   %%xmm0,    %%xmm5\n\t"
1493                     "pxor   %%xmm4,    %%xmm6\n\t"
1494                     "pxor   %%xmm5,    %%xmm4\n\t"
1495                     :
1496                     : [l3] "m" (*l),
1497                       [inbuf3] "m" (*(inbuf + 3 * BLOCKSIZE))
1498                     : "memory" );
1499
1500       do_aesni_enc_vec4 (ctx);
1501
1502       asm volatile ("movdqu %[outbuf0],%%xmm0\n\t"
1503                     "pxor   %%xmm0,    %%xmm1\n\t"
1504                     "movdqu %%xmm1,    %[outbuf0]\n\t"
1505                     "movdqu %[outbuf1],%%xmm0\n\t"
1506                     "pxor   %%xmm0,    %%xmm2\n\t"
1507                     "movdqu %%xmm2,    %[outbuf1]\n\t"
1508                     "movdqu %[outbuf2],%%xmm0\n\t"
1509                     "pxor   %%xmm0,    %%xmm3\n\t"
1510                     "movdqu %%xmm3,    %[outbuf2]\n\t"
1511                     "pxor   %%xmm5,    %%xmm4\n\t"
1512                     "movdqu %%xmm4,    %[outbuf3]\n\t"
1513                     : [outbuf0] "+m" (*(outbuf + 0 * BLOCKSIZE)),
1514                       [outbuf1] "+m" (*(outbuf + 1 * BLOCKSIZE)),
1515                       [outbuf2] "+m" (*(outbuf + 2 * BLOCKSIZE)),
1516                       [outbuf3] "=m" (*(outbuf + 3 * BLOCKSIZE))
1517                     :
1518                     : "memory" );
1519
1520       outbuf += 4*BLOCKSIZE;
1521       inbuf  += 4*BLOCKSIZE;
1522     }
1523
1524   for ( ;nblocks; nblocks-- )
1525     {
1526       l = get_l(c, l_tmp.x1, ++n, c->u_iv.iv, c->u_ctr.ctr);
1527
1528       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
1529       /* Checksum_i = Checksum_{i-1} xor P_i  */
1530       /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
1531       asm volatile ("movdqu %[l],     %%xmm1\n\t"
1532                     "movdqu %[inbuf], %%xmm0\n\t"
1533                     "pxor   %%xmm1,   %%xmm5\n\t"
1534                     "pxor   %%xmm0,   %%xmm6\n\t"
1535                     "pxor   %%xmm5,   %%xmm0\n\t"
1536                     :
1537                     : [l] "m" (*l),
1538                       [inbuf] "m" (*inbuf)
1539                     : "memory" );
1540
1541       do_aesni_enc (ctx);
1542
1543       asm volatile ("pxor   %%xmm5, %%xmm0\n\t"
1544                     "movdqu %%xmm0, %[outbuf]\n\t"
1545                     : [outbuf] "=m" (*outbuf)
1546                     :
1547                     : "memory" );
1548
1549       inbuf += BLOCKSIZE;
1550       outbuf += BLOCKSIZE;
1551     }
1552
1553   c->u_mode.ocb.data_nblocks = n;
1554   asm volatile ("movdqu %%xmm5, %[iv]\n\t"
1555                 "movdqu %%xmm6, %[ctr]\n\t"
1556                 : [iv] "=m" (*c->u_iv.iv),
1557                   [ctr] "=m" (*c->u_ctr.ctr)
1558                 :
1559                 : "memory" );
1560
1561   aesni_cleanup ();
1562   aesni_cleanup_2_6 ();
1563
1564   wipememory(&l_tmp, sizeof(l_tmp));
1565 }
1566
1567
1568 static void
1569 aesni_ocb_dec (gcry_cipher_hd_t c, void *outbuf_arg,
1570                const void *inbuf_arg, size_t nblocks)
1571 {
1572   union { unsigned char x1[16] ATTR_ALIGNED_16; u32 x32[4]; } l_tmp;
1573   RIJNDAEL_context *ctx = (void *)&c->context.c;
1574   unsigned char *outbuf = outbuf_arg;
1575   const unsigned char *inbuf = inbuf_arg;
1576   u64 n = c->u_mode.ocb.data_nblocks;
1577   const unsigned char *l;
1578   aesni_prepare_2_6_variable;
1579
1580   aesni_prepare ();
1581   aesni_prepare_2_6 ();
1582
1583   /* Preload Offset and Checksum */
1584   asm volatile ("movdqu %[iv], %%xmm5\n\t"
1585                 "movdqu %[ctr], %%xmm6\n\t"
1586                 : /* No output */
1587                 : [iv] "m" (*c->u_iv.iv),
1588                   [ctr] "m" (*c->u_ctr.ctr)
1589                 : "memory" );
1590
1591   for ( ;nblocks && n % 4; nblocks-- )
1592     {
1593       l = get_l(c, l_tmp.x1, ++n, c->u_iv.iv, c->u_ctr.ctr);
1594
1595       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
1596       /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i)  */
1597       /* Checksum_i = Checksum_{i-1} xor P_i  */
1598       asm volatile ("movdqu %[l],     %%xmm1\n\t"
1599                     "movdqu %[inbuf], %%xmm0\n\t"
1600                     "pxor   %%xmm1,   %%xmm5\n\t"
1601                     "pxor   %%xmm5,   %%xmm0\n\t"
1602                     :
1603                     : [l] "m" (*l),
1604                       [inbuf] "m" (*inbuf)
1605                     : "memory" );
1606
1607       do_aesni_dec (ctx);
1608
1609       asm volatile ("pxor   %%xmm5, %%xmm0\n\t"
1610                     "pxor   %%xmm0, %%xmm6\n\t"
1611                     "movdqu %%xmm0, %[outbuf]\n\t"
1612                     : [outbuf] "=m" (*outbuf)
1613                     :
1614                     : "memory" );
1615
1616       inbuf += BLOCKSIZE;
1617       outbuf += BLOCKSIZE;
1618     }
1619
1620   for ( ;nblocks > 3 ; nblocks -= 4 )
1621     {
1622       /* l_tmp will be used only every 65536-th block. */
1623       n += 4;
1624       l = get_l(c, l_tmp.x1, n, c->u_iv.iv, c->u_ctr.ctr);
1625
1626       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
1627       /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i)  */
1628       /* Checksum_i = Checksum_{i-1} xor P_i  */
1629       asm volatile ("movdqu %[l0],     %%xmm0\n\t"
1630                     "movdqu %[inbuf0], %%xmm1\n\t"
1631                     "pxor   %%xmm0,    %%xmm5\n\t"
1632                     "pxor   %%xmm5,    %%xmm1\n\t"
1633                     "movdqu %%xmm5,    %[outbuf0]\n\t"
1634                     : [outbuf0] "=m" (*(outbuf + 0 * BLOCKSIZE))
1635                     : [l0] "m" (*c->u_mode.ocb.L[0]),
1636                       [inbuf0] "m" (*(inbuf + 0 * BLOCKSIZE))
1637                     : "memory" );
1638       asm volatile ("movdqu %[l1],     %%xmm0\n\t"
1639                     "movdqu %[inbuf1], %%xmm2\n\t"
1640                     "pxor   %%xmm0,    %%xmm5\n\t"
1641                     "pxor   %%xmm5,    %%xmm2\n\t"
1642                     "movdqu %%xmm5,    %[outbuf1]\n\t"
1643                     : [outbuf1] "=m" (*(outbuf + 1 * BLOCKSIZE))
1644                     : [l1] "m" (*c->u_mode.ocb.L[1]),
1645                       [inbuf1] "m" (*(inbuf + 1 * BLOCKSIZE))
1646                     : "memory" );
1647       asm volatile ("movdqu %[l2],     %%xmm0\n\t"
1648                     "movdqu %[inbuf2], %%xmm3\n\t"
1649                     "pxor   %%xmm0,    %%xmm5\n\t"
1650                     "pxor   %%xmm5,    %%xmm3\n\t"
1651                     "movdqu %%xmm5,    %[outbuf2]\n\t"
1652                     : [outbuf2] "=m" (*(outbuf + 2 * BLOCKSIZE))
1653                     : [l2] "m" (*c->u_mode.ocb.L[0]),
1654                       [inbuf2] "m" (*(inbuf + 2 * BLOCKSIZE))
1655                     : "memory" );
1656       asm volatile ("movdqu %[l3],     %%xmm0\n\t"
1657                     "movdqu %[inbuf3], %%xmm4\n\t"
1658                     "pxor   %%xmm0,    %%xmm5\n\t"
1659                     "pxor   %%xmm5,    %%xmm4\n\t"
1660                     :
1661                     : [l3] "m" (*l),
1662                       [inbuf3] "m" (*(inbuf + 3 * BLOCKSIZE))
1663                     : "memory" );
1664
1665       do_aesni_dec_vec4 (ctx);
1666
1667       asm volatile ("movdqu %[outbuf0],%%xmm0\n\t"
1668                     "pxor   %%xmm0,    %%xmm1\n\t"
1669                     "movdqu %%xmm1,    %[outbuf0]\n\t"
1670                     "movdqu %[outbuf1],%%xmm0\n\t"
1671                     "pxor   %%xmm0,    %%xmm2\n\t"
1672                     "movdqu %%xmm2,    %[outbuf1]\n\t"
1673                     "movdqu %[outbuf2],%%xmm0\n\t"
1674                     "pxor   %%xmm0,    %%xmm3\n\t"
1675                     "movdqu %%xmm3,    %[outbuf2]\n\t"
1676                     "pxor   %%xmm5,    %%xmm4\n\t"
1677                     "movdqu %%xmm4,    %[outbuf3]\n\t"
1678                     "pxor   %%xmm1,    %%xmm6\n\t"
1679                     "pxor   %%xmm2,    %%xmm6\n\t"
1680                     "pxor   %%xmm3,    %%xmm6\n\t"
1681                     "pxor   %%xmm4,    %%xmm6\n\t"
1682                     : [outbuf0] "+m" (*(outbuf + 0 * BLOCKSIZE)),
1683                       [outbuf1] "+m" (*(outbuf + 1 * BLOCKSIZE)),
1684                       [outbuf2] "+m" (*(outbuf + 2 * BLOCKSIZE)),
1685                       [outbuf3] "=m" (*(outbuf + 3 * BLOCKSIZE))
1686                     :
1687                     : "memory" );
1688
1689       outbuf += 4*BLOCKSIZE;
1690       inbuf  += 4*BLOCKSIZE;
1691     }
1692
1693   for ( ;nblocks; nblocks-- )
1694     {
1695       l = get_l(c, l_tmp.x1, ++n, c->u_iv.iv, c->u_ctr.ctr);
1696
1697       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
1698       /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i)  */
1699       /* Checksum_i = Checksum_{i-1} xor P_i  */
1700       asm volatile ("movdqu %[l],     %%xmm1\n\t"
1701                     "movdqu %[inbuf], %%xmm0\n\t"
1702                     "pxor   %%xmm1,   %%xmm5\n\t"
1703                     "pxor   %%xmm5,   %%xmm0\n\t"
1704                     :
1705                     : [l] "m" (*l),
1706                       [inbuf] "m" (*inbuf)
1707                     : "memory" );
1708
1709       do_aesni_dec (ctx);
1710
1711       asm volatile ("pxor   %%xmm5, %%xmm0\n\t"
1712                     "pxor   %%xmm0, %%xmm6\n\t"
1713                     "movdqu %%xmm0, %[outbuf]\n\t"
1714                     : [outbuf] "=m" (*outbuf)
1715                     :
1716                     : "memory" );
1717
1718       inbuf += BLOCKSIZE;
1719       outbuf += BLOCKSIZE;
1720     }
1721
1722   c->u_mode.ocb.data_nblocks = n;
1723   asm volatile ("movdqu %%xmm5, %[iv]\n\t"
1724                 "movdqu %%xmm6, %[ctr]\n\t"
1725                 : [iv] "=m" (*c->u_iv.iv),
1726                   [ctr] "=m" (*c->u_ctr.ctr)
1727                 :
1728                 : "memory" );
1729
1730   aesni_cleanup ();
1731   aesni_cleanup_2_6 ();
1732
1733   wipememory(&l_tmp, sizeof(l_tmp));
1734 }
1735
1736
1737 void
1738 _gcry_aes_aesni_ocb_crypt(gcry_cipher_hd_t c, void *outbuf_arg,
1739                           const void *inbuf_arg, size_t nblocks, int encrypt)
1740 {
1741   if (encrypt)
1742     aesni_ocb_enc(c, outbuf_arg, inbuf_arg, nblocks);
1743   else
1744     aesni_ocb_dec(c, outbuf_arg, inbuf_arg, nblocks);
1745 }
1746
1747
1748 void
1749 _gcry_aes_aesni_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
1750                           size_t nblocks)
1751 {
1752   union { unsigned char x1[16] ATTR_ALIGNED_16; u32 x32[4]; } l_tmp;
1753   RIJNDAEL_context *ctx = (void *)&c->context.c;
1754   const unsigned char *abuf = abuf_arg;
1755   u64 n = c->u_mode.ocb.aad_nblocks;
1756   const unsigned char *l;
1757   aesni_prepare_2_6_variable;
1758
1759   aesni_prepare ();
1760   aesni_prepare_2_6 ();
1761
1762   /* Preload Offset and Sum */
1763   asm volatile ("movdqu %[iv], %%xmm5\n\t"
1764                 "movdqu %[ctr], %%xmm6\n\t"
1765                 : /* No output */
1766                 : [iv] "m" (*c->u_mode.ocb.aad_offset),
1767                   [ctr] "m" (*c->u_mode.ocb.aad_sum)
1768                 : "memory" );
1769
1770   for ( ;nblocks && n % 4; nblocks-- )
1771     {
1772       l = get_l(c, l_tmp.x1, ++n, c->u_mode.ocb.aad_offset,
1773                 c->u_mode.ocb.aad_sum);
1774
1775       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
1776       /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i)  */
1777       asm volatile ("movdqu %[l],     %%xmm1\n\t"
1778                     "movdqu %[abuf],  %%xmm0\n\t"
1779                     "pxor   %%xmm1,   %%xmm5\n\t"
1780                     "pxor   %%xmm5,   %%xmm0\n\t"
1781                     :
1782                     : [l] "m" (*l),
1783                       [abuf] "m" (*abuf)
1784                     : "memory" );
1785
1786       do_aesni_enc (ctx);
1787
1788       asm volatile ("pxor   %%xmm0,   %%xmm6\n\t"
1789                     :
1790                     :
1791                     : "memory" );
1792
1793       abuf += BLOCKSIZE;
1794     }
1795
1796   for ( ;nblocks > 3 ; nblocks -= 4 )
1797     {
1798       /* l_tmp will be used only every 65536-th block. */
1799       n += 4;
1800       l = get_l(c, l_tmp.x1, n, c->u_mode.ocb.aad_offset,
1801                 c->u_mode.ocb.aad_sum);
1802
1803       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
1804       /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i)  */
1805       asm volatile ("movdqu %[l0],     %%xmm0\n\t"
1806                     "movdqu %[abuf0],  %%xmm1\n\t"
1807                     "pxor   %%xmm0,    %%xmm5\n\t"
1808                     "pxor   %%xmm5,    %%xmm1\n\t"
1809                     :
1810                     : [l0] "m" (*c->u_mode.ocb.L[0]),
1811                       [abuf0] "m" (*(abuf + 0 * BLOCKSIZE))
1812                     : "memory" );
1813       asm volatile ("movdqu %[l1],     %%xmm0\n\t"
1814                     "movdqu %[abuf1],  %%xmm2\n\t"
1815                     "pxor   %%xmm0,    %%xmm5\n\t"
1816                     "pxor   %%xmm5,    %%xmm2\n\t"
1817                     :
1818                     : [l1] "m" (*c->u_mode.ocb.L[1]),
1819                       [abuf1] "m" (*(abuf + 1 * BLOCKSIZE))
1820                     : "memory" );
1821       asm volatile ("movdqu %[l2],     %%xmm0\n\t"
1822                     "movdqu %[abuf2],  %%xmm3\n\t"
1823                     "pxor   %%xmm0,    %%xmm5\n\t"
1824                     "pxor   %%xmm5,    %%xmm3\n\t"
1825                     :
1826                     : [l2] "m" (*c->u_mode.ocb.L[0]),
1827                       [abuf2] "m" (*(abuf + 2 * BLOCKSIZE))
1828                     : "memory" );
1829       asm volatile ("movdqu %[l3],     %%xmm0\n\t"
1830                     "movdqu %[abuf3],  %%xmm4\n\t"
1831                     "pxor   %%xmm0,    %%xmm5\n\t"
1832                     "pxor   %%xmm5,    %%xmm4\n\t"
1833                     :
1834                     : [l3] "m" (*l),
1835                       [abuf3] "m" (*(abuf + 3 * BLOCKSIZE))
1836                     : "memory" );
1837
1838       do_aesni_enc_vec4 (ctx);
1839
1840       asm volatile ("pxor   %%xmm1,   %%xmm6\n\t"
1841                     "pxor   %%xmm2,   %%xmm6\n\t"
1842                     "pxor   %%xmm3,   %%xmm6\n\t"
1843                     "pxor   %%xmm4,   %%xmm6\n\t"
1844                     :
1845                     :
1846                     : "memory" );
1847
1848       abuf += 4*BLOCKSIZE;
1849     }
1850
1851   for ( ;nblocks; nblocks-- )
1852     {
1853       l = get_l(c, l_tmp.x1, ++n, c->u_mode.ocb.aad_offset,
1854                 c->u_mode.ocb.aad_sum);
1855
1856       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
1857       /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i)  */
1858       asm volatile ("movdqu %[l],     %%xmm1\n\t"
1859                     "movdqu %[abuf],  %%xmm0\n\t"
1860                     "pxor   %%xmm1,   %%xmm5\n\t"
1861                     "pxor   %%xmm5,   %%xmm0\n\t"
1862                     :
1863                     : [l] "m" (*l),
1864                       [abuf] "m" (*abuf)
1865                     : "memory" );
1866
1867       do_aesni_enc (ctx);
1868
1869       asm volatile ("pxor   %%xmm0,   %%xmm6\n\t"
1870                     :
1871                     :
1872                     : "memory" );
1873
1874       abuf += BLOCKSIZE;
1875     }
1876
1877   c->u_mode.ocb.aad_nblocks = n;
1878   asm volatile ("movdqu %%xmm5, %[iv]\n\t"
1879                 "movdqu %%xmm6, %[ctr]\n\t"
1880                 : [iv] "=m" (*c->u_mode.ocb.aad_offset),
1881                   [ctr] "=m" (*c->u_mode.ocb.aad_sum)
1882                 :
1883                 : "memory" );
1884
1885   aesni_cleanup ();
1886   aesni_cleanup_2_6 ();
1887
1888   wipememory(&l_tmp, sizeof(l_tmp));
1889 }
1890
1891
1892 #endif /* USE_AESNI */