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