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