Line data Source code
1 : /* SSSE3 vector permutation AES for Libgcrypt
2 : * Copyright (C) 2014-2017 Jussi Kivilinna <jussi.kivilinna@iki.fi>
3 : *
4 : * This file is part of Libgcrypt.
5 : *
6 : * Libgcrypt is free software; you can redistribute it and/or modify
7 : * it under the terms of the GNU Lesser General Public License as
8 : * published by the Free Software Foundation; either version 2.1 of
9 : * the License, or (at your option) any later version.
10 : *
11 : * Libgcrypt is distributed in the hope that it will be useful,
12 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : * GNU Lesser General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU Lesser General Public
17 : * License along with this program; if not, see <http://www.gnu.org/licenses/>.
18 : *
19 : *
20 : * The code is based on the public domain library libvpaes version 0.5
21 : * available at http://crypto.stanford.edu/vpaes/ and which carries
22 : * this notice:
23 : *
24 : * libvpaes: constant-time SSSE3 AES encryption and decryption.
25 : * version 0.5
26 : *
27 : * By Mike Hamburg, Stanford University, 2009. Public domain.
28 : * I wrote essentially all of this code. I did not write the test
29 : * vectors; they are the NIST known answer tests. I hereby release all
30 : * the code and documentation here that I wrote into the public domain.
31 : *
32 : * This is an implementation of AES following my paper,
33 : * "Accelerating AES with Vector Permute Instructions"
34 : * CHES 2009; http://shiftleft.org/papers/vector_aes/
35 : */
36 :
37 : #include <config.h>
38 : #include <stdio.h>
39 : #include <stdlib.h>
40 : #include <string.h> /* for memcmp() */
41 :
42 : #include "types.h" /* for byte and u32 typedefs */
43 : #include "g10lib.h"
44 : #include "cipher.h"
45 : #include "bufhelp.h"
46 : #include "cipher-selftest.h"
47 : #include "rijndael-internal.h"
48 : #include "./cipher-internal.h"
49 :
50 :
51 : #ifdef USE_SSSE3
52 :
53 :
54 : #if _GCRY_GCC_VERSION >= 40400 /* 4.4 */
55 : /* Prevent compiler from issuing SSE instructions between asm blocks. */
56 : # pragma GCC target("no-sse")
57 : #endif
58 :
59 :
60 : /* Assembly functions in rijndael-ssse3-amd64-asm.S. Note that these
61 : have custom calling convention and need to be called from assembly
62 : blocks, not directly. */
63 : extern void _gcry_aes_ssse3_enc_preload(void);
64 : extern void _gcry_aes_ssse3_dec_preload(void);
65 : extern void _gcry_aes_ssse3_schedule_core(void);
66 : extern void _gcry_aes_ssse3_encrypt_core(void);
67 : extern void _gcry_aes_ssse3_decrypt_core(void);
68 :
69 :
70 :
71 : /* Two macros to be called prior and after the use of SSSE3
72 : instructions. There should be no external function calls between
73 : the use of these macros. There purpose is to make sure that the
74 : SSE registers are cleared and won't reveal any information about
75 : the key or the data. */
76 : #ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
77 : # define SSSE3_STATE_SIZE (16 * 10)
78 : /* XMM6-XMM15 are callee-saved registers on WIN64. */
79 : # define vpaes_ssse3_prepare() \
80 : asm volatile ("movdqu %%xmm6, 0*16(%0)\n\t" \
81 : "movdqu %%xmm7, 1*16(%0)\n\t" \
82 : "movdqu %%xmm8, 2*16(%0)\n\t" \
83 : "movdqu %%xmm9, 3*16(%0)\n\t" \
84 : "movdqu %%xmm10, 4*16(%0)\n\t" \
85 : "movdqu %%xmm11, 5*16(%0)\n\t" \
86 : "movdqu %%xmm12, 6*16(%0)\n\t" \
87 : "movdqu %%xmm13, 7*16(%0)\n\t" \
88 : "movdqu %%xmm14, 8*16(%0)\n\t" \
89 : "movdqu %%xmm15, 9*16(%0)\n\t" \
90 : : \
91 : : "r" (ssse3_state) \
92 : : "memory" )
93 : # define vpaes_ssse3_cleanup() \
94 : asm volatile ("pxor %%xmm0, %%xmm0 \n\t" \
95 : "pxor %%xmm1, %%xmm1 \n\t" \
96 : "pxor %%xmm2, %%xmm2 \n\t" \
97 : "pxor %%xmm3, %%xmm3 \n\t" \
98 : "pxor %%xmm4, %%xmm4 \n\t" \
99 : "pxor %%xmm5, %%xmm5 \n\t" \
100 : "movdqu 0*16(%0), %%xmm6 \n\t" \
101 : "movdqu 1*16(%0), %%xmm7 \n\t" \
102 : "movdqu 2*16(%0), %%xmm8 \n\t" \
103 : "movdqu 3*16(%0), %%xmm9 \n\t" \
104 : "movdqu 4*16(%0), %%xmm10 \n\t" \
105 : "movdqu 5*16(%0), %%xmm11 \n\t" \
106 : "movdqu 6*16(%0), %%xmm12 \n\t" \
107 : "movdqu 7*16(%0), %%xmm13 \n\t" \
108 : "movdqu 8*16(%0), %%xmm14 \n\t" \
109 : "movdqu 9*16(%0), %%xmm15 \n\t" \
110 : : \
111 : : "r" (ssse3_state) \
112 : : "memory" )
113 : #else
114 : # define SSSE3_STATE_SIZE 1
115 : # define vpaes_ssse3_prepare() (void)ssse3_state
116 : # define vpaes_ssse3_cleanup() \
117 : asm volatile ("pxor %%xmm0, %%xmm0 \n\t" \
118 : "pxor %%xmm1, %%xmm1 \n\t" \
119 : "pxor %%xmm2, %%xmm2 \n\t" \
120 : "pxor %%xmm3, %%xmm3 \n\t" \
121 : "pxor %%xmm4, %%xmm4 \n\t" \
122 : "pxor %%xmm5, %%xmm5 \n\t" \
123 : "pxor %%xmm6, %%xmm6 \n\t" \
124 : "pxor %%xmm7, %%xmm7 \n\t" \
125 : "pxor %%xmm8, %%xmm8 \n\t" \
126 : ::: "memory" )
127 : #endif
128 :
129 : #define vpaes_ssse3_prepare_enc() \
130 : vpaes_ssse3_prepare(); \
131 : asm volatile ("callq *%q[core] \n\t" \
132 : : \
133 : : [core] "r" (_gcry_aes_ssse3_enc_preload) \
134 : : "rax", "cc", "memory" )
135 :
136 : #define vpaes_ssse3_prepare_dec() \
137 : vpaes_ssse3_prepare(); \
138 : asm volatile ("callq *%q[core] \n\t" \
139 : : \
140 : : [core] "r" (_gcry_aes_ssse3_dec_preload) \
141 : : "rax", "cc", "memory" )
142 :
143 :
144 :
145 : void
146 0 : _gcry_aes_ssse3_do_setkey (RIJNDAEL_context *ctx, const byte *key)
147 : {
148 0 : unsigned int keybits = (ctx->rounds - 10) * 32 + 128;
149 : byte ssse3_state[SSSE3_STATE_SIZE];
150 :
151 : vpaes_ssse3_prepare();
152 :
153 0 : asm volatile ("leaq %q[key], %%rdi" "\n\t"
154 : "movl %[bits], %%esi" "\n\t"
155 : "leaq %[buf], %%rdx" "\n\t"
156 : "movl %[dir], %%ecx" "\n\t"
157 : "movl %[rotoffs], %%r8d" "\n\t"
158 : "callq *%q[core]" "\n\t"
159 : :
160 : : [core] "r" (&_gcry_aes_ssse3_schedule_core),
161 : [key] "m" (*key),
162 : [bits] "g" (keybits),
163 : [buf] "m" (ctx->keyschenc32[0][0]),
164 : [dir] "g" (0),
165 : [rotoffs] "g" (48)
166 : : "r8", "r9", "r10", "r11", "rax", "rcx", "rdx", "rdi", "rsi",
167 : "cc", "memory");
168 :
169 : /* Save key for setting up decryption. */
170 0 : if (keybits > 192)
171 0 : asm volatile ("movdqu (%[src]), %%xmm0\n\t"
172 : "movdqu 16(%[src]), %%xmm1\n\t"
173 : "movdqu %%xmm0, (%[dst])\n\t"
174 : "movdqu %%xmm1, 16(%[dst])\n\t"
175 : : /* No output */
176 0 : : [dst] "r" (&ctx->keyschdec32[0][0]), [src] "r" (key)
177 : : "memory" );
178 0 : else if (keybits == 192)
179 0 : asm volatile ("movdqu (%[src]), %%xmm0\n\t"
180 : "movq 16(%[src]), %%xmm1\n\t"
181 : "movdqu %%xmm0, (%[dst])\n\t"
182 : "movq %%xmm1, 16(%[dst])\n\t"
183 : : /* No output */
184 0 : : [dst] "r" (&ctx->keyschdec32[0][0]), [src] "r" (key)
185 : : "memory" );
186 : else
187 0 : asm volatile ("movdqu (%[src]), %%xmm0\n\t"
188 : "movdqu %%xmm0, (%[dst])\n\t"
189 : : /* No output */
190 0 : : [dst] "r" (&ctx->keyschdec32[0][0]), [src] "r" (key)
191 : : "memory" );
192 :
193 0 : vpaes_ssse3_cleanup();
194 0 : }
195 :
196 :
197 : /* Make a decryption key from an encryption key. */
198 : void
199 0 : _gcry_aes_ssse3_prepare_decryption (RIJNDAEL_context *ctx)
200 : {
201 0 : unsigned int keybits = (ctx->rounds - 10) * 32 + 128;
202 : byte ssse3_state[SSSE3_STATE_SIZE];
203 :
204 : vpaes_ssse3_prepare();
205 :
206 0 : asm volatile ("leaq %q[key], %%rdi" "\n\t"
207 : "movl %[bits], %%esi" "\n\t"
208 : "leaq %[buf], %%rdx" "\n\t"
209 : "movl %[dir], %%ecx" "\n\t"
210 : "movl %[rotoffs], %%r8d" "\n\t"
211 : "callq *%q[core]" "\n\t"
212 : :
213 : : [core] "r" (_gcry_aes_ssse3_schedule_core),
214 : [key] "m" (ctx->keyschdec32[0][0]),
215 : [bits] "g" (keybits),
216 0 : [buf] "m" (ctx->keyschdec32[ctx->rounds][0]),
217 : [dir] "g" (1),
218 0 : [rotoffs] "g" ((keybits == 192) ? 0 : 32)
219 : : "r8", "r9", "r10", "r11", "rax", "rcx", "rdx", "rdi", "rsi",
220 : "cc", "memory");
221 :
222 0 : vpaes_ssse3_cleanup();
223 0 : }
224 :
225 :
226 : /* Encrypt one block using the Intel SSSE3 instructions. Block is input
227 : * and output through SSE register xmm0. */
228 : static inline void
229 0 : do_vpaes_ssse3_enc (const RIJNDAEL_context *ctx, unsigned int nrounds)
230 : {
231 0 : unsigned int middle_rounds = nrounds - 1;
232 0 : const void *keysched = ctx->keyschenc32;
233 :
234 0 : asm volatile ("callq *%q[core]" "\n\t"
235 : : "+a" (middle_rounds), "+d" (keysched)
236 : : [core] "r" (_gcry_aes_ssse3_encrypt_core)
237 : : "rcx", "rsi", "rdi", "cc", "memory");
238 0 : }
239 :
240 :
241 : /* Decrypt one block using the Intel SSSE3 instructions. Block is input
242 : * and output through SSE register xmm0. */
243 : static inline void
244 0 : do_vpaes_ssse3_dec (const RIJNDAEL_context *ctx, unsigned int nrounds)
245 : {
246 0 : unsigned int middle_rounds = nrounds - 1;
247 0 : const void *keysched = ctx->keyschdec32;
248 :
249 0 : asm volatile ("callq *%q[core]" "\n\t"
250 : : "+a" (middle_rounds), "+d" (keysched)
251 : : [core] "r" (_gcry_aes_ssse3_decrypt_core)
252 : : "rcx", "rsi", "cc", "memory");
253 0 : }
254 :
255 :
256 : unsigned int
257 0 : _gcry_aes_ssse3_encrypt (const RIJNDAEL_context *ctx, unsigned char *dst,
258 : const unsigned char *src)
259 : {
260 0 : unsigned int nrounds = ctx->rounds;
261 : byte ssse3_state[SSSE3_STATE_SIZE];
262 :
263 0 : vpaes_ssse3_prepare_enc ();
264 0 : asm volatile ("movdqu %[src], %%xmm0\n\t"
265 : :
266 : : [src] "m" (*src)
267 : : "memory" );
268 0 : do_vpaes_ssse3_enc (ctx, nrounds);
269 0 : asm volatile ("movdqu %%xmm0, %[dst]\n\t"
270 : : [dst] "=m" (*dst)
271 : :
272 : : "memory" );
273 0 : vpaes_ssse3_cleanup ();
274 0 : return 0;
275 : }
276 :
277 :
278 : void
279 0 : _gcry_aes_ssse3_cfb_enc (RIJNDAEL_context *ctx, unsigned char *outbuf,
280 : const unsigned char *inbuf, unsigned char *iv,
281 : size_t nblocks)
282 : {
283 0 : unsigned int nrounds = ctx->rounds;
284 : byte ssse3_state[SSSE3_STATE_SIZE];
285 :
286 0 : vpaes_ssse3_prepare_enc ();
287 :
288 0 : asm volatile ("movdqu %[iv], %%xmm0\n\t"
289 : : /* No output */
290 : : [iv] "m" (*iv)
291 : : "memory" );
292 :
293 0 : for ( ;nblocks; nblocks-- )
294 : {
295 0 : do_vpaes_ssse3_enc (ctx, nrounds);
296 :
297 0 : asm volatile ("movdqu %[inbuf], %%xmm1\n\t"
298 : "pxor %%xmm1, %%xmm0\n\t"
299 : "movdqu %%xmm0, %[outbuf]\n\t"
300 : : [outbuf] "=m" (*outbuf)
301 : : [inbuf] "m" (*inbuf)
302 : : "memory" );
303 :
304 0 : outbuf += BLOCKSIZE;
305 0 : inbuf += BLOCKSIZE;
306 : }
307 :
308 0 : asm volatile ("movdqu %%xmm0, %[iv]\n\t"
309 : : [iv] "=m" (*iv)
310 : :
311 : : "memory" );
312 :
313 0 : vpaes_ssse3_cleanup ();
314 0 : }
315 :
316 :
317 : void
318 0 : _gcry_aes_ssse3_cbc_enc (RIJNDAEL_context *ctx, unsigned char *outbuf,
319 : const unsigned char *inbuf, unsigned char *iv,
320 : size_t nblocks, int cbc_mac)
321 : {
322 0 : unsigned int nrounds = ctx->rounds;
323 : byte ssse3_state[SSSE3_STATE_SIZE];
324 :
325 0 : vpaes_ssse3_prepare_enc ();
326 :
327 0 : asm volatile ("movdqu %[iv], %%xmm7\n\t"
328 : : /* No output */
329 : : [iv] "m" (*iv)
330 : : "memory" );
331 :
332 0 : for ( ;nblocks; nblocks-- )
333 : {
334 0 : asm volatile ("movdqu %[inbuf], %%xmm0\n\t"
335 : "pxor %%xmm7, %%xmm0\n\t"
336 : : /* No output */
337 : : [inbuf] "m" (*inbuf)
338 : : "memory" );
339 :
340 0 : do_vpaes_ssse3_enc (ctx, nrounds);
341 :
342 0 : asm volatile ("movdqa %%xmm0, %%xmm7\n\t"
343 : "movdqu %%xmm0, %[outbuf]\n\t"
344 : : [outbuf] "=m" (*outbuf)
345 : :
346 : : "memory" );
347 :
348 0 : inbuf += BLOCKSIZE;
349 0 : if (!cbc_mac)
350 0 : outbuf += BLOCKSIZE;
351 : }
352 :
353 0 : asm volatile ("movdqu %%xmm7, %[iv]\n\t"
354 : : [iv] "=m" (*iv)
355 : :
356 : : "memory" );
357 :
358 0 : vpaes_ssse3_cleanup ();
359 0 : }
360 :
361 :
362 : void
363 0 : _gcry_aes_ssse3_ctr_enc (RIJNDAEL_context *ctx, unsigned char *outbuf,
364 : const unsigned char *inbuf, unsigned char *ctr,
365 : size_t nblocks)
366 : {
367 : static const unsigned char be_mask[16] __attribute__ ((aligned (16))) =
368 : { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
369 0 : unsigned int nrounds = ctx->rounds;
370 : byte ssse3_state[SSSE3_STATE_SIZE];
371 : u64 ctrlow;
372 :
373 0 : vpaes_ssse3_prepare_enc ();
374 :
375 0 : asm volatile ("movdqa %[mask], %%xmm6\n\t" /* Preload mask */
376 : "movdqa (%[ctr]), %%xmm7\n\t" /* Preload CTR */
377 : "movq 8(%[ctr]), %q[ctrlow]\n\t"
378 : "bswapq %q[ctrlow]\n\t"
379 : : [ctrlow] "=r" (ctrlow)
380 : : [mask] "m" (*be_mask),
381 : [ctr] "r" (ctr)
382 : : "memory", "cc");
383 :
384 0 : for ( ;nblocks; nblocks-- )
385 : {
386 0 : asm volatile ("movdqa %%xmm7, %%xmm0\n\t" /* xmm0 := CTR (xmm7) */
387 : "pcmpeqd %%xmm1, %%xmm1\n\t"
388 : "psrldq $8, %%xmm1\n\t" /* xmm1 = -1 */
389 :
390 : "pshufb %%xmm6, %%xmm7\n\t"
391 : "psubq %%xmm1, %%xmm7\n\t" /* xmm7++ (big endian) */
392 :
393 : /* detect if 64-bit carry handling is needed */
394 : "incq %q[ctrlow]\n\t"
395 : "jnz .Lno_carry%=\n\t"
396 :
397 : "pslldq $8, %%xmm1\n\t" /* move lower 64-bit to high */
398 : "psubq %%xmm1, %%xmm7\n\t" /* add carry to upper 64bits */
399 :
400 : ".Lno_carry%=:\n\t"
401 :
402 : "pshufb %%xmm6, %%xmm7\n\t"
403 : : [ctrlow] "+r" (ctrlow)
404 : :
405 : : "cc", "memory");
406 :
407 0 : do_vpaes_ssse3_enc (ctx, nrounds);
408 :
409 0 : asm volatile ("movdqu %[src], %%xmm1\n\t" /* xmm1 := input */
410 : "pxor %%xmm1, %%xmm0\n\t" /* EncCTR ^= input */
411 : "movdqu %%xmm0, %[dst]" /* Store EncCTR. */
412 : : [dst] "=m" (*outbuf)
413 : : [src] "m" (*inbuf)
414 : : "memory");
415 :
416 0 : outbuf += BLOCKSIZE;
417 0 : inbuf += BLOCKSIZE;
418 : }
419 :
420 0 : asm volatile ("movdqu %%xmm7, %[ctr]\n\t" /* Update CTR (mem). */
421 : : [ctr] "=m" (*ctr)
422 : :
423 : : "memory" );
424 :
425 0 : vpaes_ssse3_cleanup ();
426 0 : }
427 :
428 :
429 : unsigned int
430 0 : _gcry_aes_ssse3_decrypt (const RIJNDAEL_context *ctx, unsigned char *dst,
431 : const unsigned char *src)
432 : {
433 0 : unsigned int nrounds = ctx->rounds;
434 : byte ssse3_state[SSSE3_STATE_SIZE];
435 :
436 0 : vpaes_ssse3_prepare_dec ();
437 0 : asm volatile ("movdqu %[src], %%xmm0\n\t"
438 : :
439 : : [src] "m" (*src)
440 : : "memory" );
441 0 : do_vpaes_ssse3_dec (ctx, nrounds);
442 0 : asm volatile ("movdqu %%xmm0, %[dst]\n\t"
443 : : [dst] "=m" (*dst)
444 : :
445 : : "memory" );
446 0 : vpaes_ssse3_cleanup ();
447 0 : return 0;
448 : }
449 :
450 :
451 : void
452 0 : _gcry_aes_ssse3_cfb_dec (RIJNDAEL_context *ctx, unsigned char *outbuf,
453 : const unsigned char *inbuf, unsigned char *iv,
454 : size_t nblocks)
455 : {
456 0 : unsigned int nrounds = ctx->rounds;
457 : byte ssse3_state[SSSE3_STATE_SIZE];
458 :
459 0 : vpaes_ssse3_prepare_enc ();
460 :
461 0 : asm volatile ("movdqu %[iv], %%xmm0\n\t"
462 : : /* No output */
463 : : [iv] "m" (*iv)
464 : : "memory" );
465 :
466 0 : for ( ;nblocks; nblocks-- )
467 : {
468 0 : do_vpaes_ssse3_enc (ctx, nrounds);
469 :
470 0 : asm volatile ("movdqa %%xmm0, %%xmm6\n\t"
471 : "movdqu %[inbuf], %%xmm0\n\t"
472 : "pxor %%xmm0, %%xmm6\n\t"
473 : "movdqu %%xmm6, %[outbuf]\n\t"
474 : : [outbuf] "=m" (*outbuf)
475 : : [inbuf] "m" (*inbuf)
476 : : "memory" );
477 :
478 0 : outbuf += BLOCKSIZE;
479 0 : inbuf += BLOCKSIZE;
480 : }
481 :
482 0 : asm volatile ("movdqu %%xmm0, %[iv]\n\t"
483 : : [iv] "=m" (*iv)
484 : :
485 : : "memory" );
486 :
487 0 : vpaes_ssse3_cleanup ();
488 0 : }
489 :
490 :
491 : void
492 0 : _gcry_aes_ssse3_cbc_dec (RIJNDAEL_context *ctx, unsigned char *outbuf,
493 : const unsigned char *inbuf, unsigned char *iv,
494 : size_t nblocks)
495 : {
496 0 : unsigned int nrounds = ctx->rounds;
497 : byte ssse3_state[SSSE3_STATE_SIZE];
498 :
499 0 : vpaes_ssse3_prepare_dec ();
500 :
501 0 : asm volatile ("movdqu %[iv], %%xmm7\n\t" /* use xmm7 as fast IV storage */
502 : : /* No output */
503 : : [iv] "m" (*iv)
504 : : "memory");
505 :
506 0 : for ( ;nblocks; nblocks-- )
507 : {
508 0 : asm volatile ("movdqu %[inbuf], %%xmm0\n\t"
509 : "movdqa %%xmm0, %%xmm6\n\t" /* use xmm6 as savebuf */
510 : : /* No output */
511 : : [inbuf] "m" (*inbuf)
512 : : "memory");
513 :
514 0 : do_vpaes_ssse3_dec (ctx, nrounds);
515 :
516 0 : asm volatile ("pxor %%xmm7, %%xmm0\n\t" /* xor IV with output */
517 : "movdqu %%xmm0, %[outbuf]\n\t"
518 : "movdqu %%xmm6, %%xmm7\n\t" /* store savebuf as new IV */
519 : : [outbuf] "=m" (*outbuf)
520 : :
521 : : "memory");
522 :
523 0 : outbuf += BLOCKSIZE;
524 0 : inbuf += BLOCKSIZE;
525 : }
526 :
527 0 : asm volatile ("movdqu %%xmm7, %[iv]\n\t" /* store IV */
528 : : /* No output */
529 : : [iv] "m" (*iv)
530 : : "memory");
531 :
532 0 : vpaes_ssse3_cleanup ();
533 0 : }
534 :
535 :
536 : static void
537 0 : ssse3_ocb_enc (gcry_cipher_hd_t c, void *outbuf_arg,
538 : const void *inbuf_arg, size_t nblocks)
539 : {
540 0 : RIJNDAEL_context *ctx = (void *)&c->context.c;
541 0 : unsigned char *outbuf = outbuf_arg;
542 0 : const unsigned char *inbuf = inbuf_arg;
543 0 : u64 n = c->u_mode.ocb.data_nblocks;
544 0 : unsigned int nrounds = ctx->rounds;
545 : byte ssse3_state[SSSE3_STATE_SIZE];
546 :
547 0 : vpaes_ssse3_prepare_enc ();
548 :
549 : /* Preload Offset and Checksum */
550 0 : asm volatile ("movdqu %[iv], %%xmm7\n\t"
551 : "movdqu %[ctr], %%xmm6\n\t"
552 : : /* No output */
553 : : [iv] "m" (*c->u_iv.iv),
554 : [ctr] "m" (*c->u_ctr.ctr)
555 : : "memory" );
556 :
557 0 : for ( ;nblocks; nblocks-- )
558 : {
559 : const unsigned char *l;
560 :
561 0 : l = ocb_get_l(c, ++n);
562 :
563 : /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
564 : /* Checksum_i = Checksum_{i-1} xor P_i */
565 : /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) */
566 0 : asm volatile ("movdqu %[l], %%xmm1\n\t"
567 : "movdqu %[inbuf], %%xmm0\n\t"
568 : "pxor %%xmm1, %%xmm7\n\t"
569 : "pxor %%xmm0, %%xmm6\n\t"
570 : "pxor %%xmm7, %%xmm0\n\t"
571 : :
572 : : [l] "m" (*l),
573 : [inbuf] "m" (*inbuf)
574 : : "memory" );
575 :
576 0 : do_vpaes_ssse3_enc (ctx, nrounds);
577 :
578 0 : asm volatile ("pxor %%xmm7, %%xmm0\n\t"
579 : "movdqu %%xmm0, %[outbuf]\n\t"
580 : : [outbuf] "=m" (*outbuf)
581 : :
582 : : "memory" );
583 :
584 0 : inbuf += BLOCKSIZE;
585 0 : outbuf += BLOCKSIZE;
586 : }
587 :
588 0 : c->u_mode.ocb.data_nblocks = n;
589 0 : asm volatile ("movdqu %%xmm7, %[iv]\n\t"
590 : "movdqu %%xmm6, %[ctr]\n\t"
591 : : [iv] "=m" (*c->u_iv.iv),
592 : [ctr] "=m" (*c->u_ctr.ctr)
593 : :
594 : : "memory" );
595 :
596 0 : vpaes_ssse3_cleanup ();
597 0 : }
598 :
599 : static void
600 0 : ssse3_ocb_dec (gcry_cipher_hd_t c, void *outbuf_arg,
601 : const void *inbuf_arg, size_t nblocks)
602 : {
603 0 : RIJNDAEL_context *ctx = (void *)&c->context.c;
604 0 : unsigned char *outbuf = outbuf_arg;
605 0 : const unsigned char *inbuf = inbuf_arg;
606 0 : u64 n = c->u_mode.ocb.data_nblocks;
607 0 : unsigned int nrounds = ctx->rounds;
608 : byte ssse3_state[SSSE3_STATE_SIZE];
609 :
610 0 : vpaes_ssse3_prepare_dec ();
611 :
612 : /* Preload Offset and Checksum */
613 0 : asm volatile ("movdqu %[iv], %%xmm7\n\t"
614 : "movdqu %[ctr], %%xmm6\n\t"
615 : : /* No output */
616 : : [iv] "m" (*c->u_iv.iv),
617 : [ctr] "m" (*c->u_ctr.ctr)
618 : : "memory" );
619 :
620 0 : for ( ;nblocks; nblocks-- )
621 : {
622 : const unsigned char *l;
623 :
624 0 : l = ocb_get_l(c, ++n);
625 :
626 : /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
627 : /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i) */
628 : /* Checksum_i = Checksum_{i-1} xor P_i */
629 0 : asm volatile ("movdqu %[l], %%xmm1\n\t"
630 : "movdqu %[inbuf], %%xmm0\n\t"
631 : "pxor %%xmm1, %%xmm7\n\t"
632 : "pxor %%xmm7, %%xmm0\n\t"
633 : :
634 : : [l] "m" (*l),
635 : [inbuf] "m" (*inbuf)
636 : : "memory" );
637 :
638 0 : do_vpaes_ssse3_dec (ctx, nrounds);
639 :
640 0 : asm volatile ("pxor %%xmm7, %%xmm0\n\t"
641 : "pxor %%xmm0, %%xmm6\n\t"
642 : "movdqu %%xmm0, %[outbuf]\n\t"
643 : : [outbuf] "=m" (*outbuf)
644 : :
645 : : "memory" );
646 :
647 0 : inbuf += BLOCKSIZE;
648 0 : outbuf += BLOCKSIZE;
649 : }
650 :
651 0 : c->u_mode.ocb.data_nblocks = n;
652 0 : asm volatile ("movdqu %%xmm7, %[iv]\n\t"
653 : "movdqu %%xmm6, %[ctr]\n\t"
654 : : [iv] "=m" (*c->u_iv.iv),
655 : [ctr] "=m" (*c->u_ctr.ctr)
656 : :
657 : : "memory" );
658 :
659 0 : vpaes_ssse3_cleanup ();
660 0 : }
661 :
662 :
663 : void
664 0 : _gcry_aes_ssse3_ocb_crypt(gcry_cipher_hd_t c, void *outbuf_arg,
665 : const void *inbuf_arg, size_t nblocks, int encrypt)
666 : {
667 0 : if (encrypt)
668 0 : ssse3_ocb_enc(c, outbuf_arg, inbuf_arg, nblocks);
669 : else
670 0 : ssse3_ocb_dec(c, outbuf_arg, inbuf_arg, nblocks);
671 0 : }
672 :
673 :
674 : void
675 0 : _gcry_aes_ssse3_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
676 : size_t nblocks)
677 : {
678 0 : RIJNDAEL_context *ctx = (void *)&c->context.c;
679 0 : const unsigned char *abuf = abuf_arg;
680 0 : u64 n = c->u_mode.ocb.aad_nblocks;
681 0 : unsigned int nrounds = ctx->rounds;
682 : byte ssse3_state[SSSE3_STATE_SIZE];
683 :
684 0 : vpaes_ssse3_prepare_enc ();
685 :
686 : /* Preload Offset and Sum */
687 0 : asm volatile ("movdqu %[iv], %%xmm7\n\t"
688 : "movdqu %[ctr], %%xmm6\n\t"
689 : : /* No output */
690 : : [iv] "m" (*c->u_mode.ocb.aad_offset),
691 : [ctr] "m" (*c->u_mode.ocb.aad_sum)
692 : : "memory" );
693 :
694 0 : for ( ;nblocks; nblocks-- )
695 : {
696 : const unsigned char *l;
697 :
698 0 : l = ocb_get_l(c, ++n);
699 :
700 : /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
701 : /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i) */
702 0 : asm volatile ("movdqu %[l], %%xmm1\n\t"
703 : "movdqu %[abuf], %%xmm0\n\t"
704 : "pxor %%xmm1, %%xmm7\n\t"
705 : "pxor %%xmm7, %%xmm0\n\t"
706 : :
707 : : [l] "m" (*l),
708 : [abuf] "m" (*abuf)
709 : : "memory" );
710 :
711 0 : do_vpaes_ssse3_enc (ctx, nrounds);
712 :
713 0 : asm volatile ("pxor %%xmm0, %%xmm6\n\t"
714 : :
715 : :
716 : : "memory" );
717 :
718 0 : abuf += BLOCKSIZE;
719 : }
720 :
721 0 : c->u_mode.ocb.aad_nblocks = n;
722 0 : asm volatile ("movdqu %%xmm7, %[iv]\n\t"
723 : "movdqu %%xmm6, %[ctr]\n\t"
724 : : [iv] "=m" (*c->u_mode.ocb.aad_offset),
725 : [ctr] "=m" (*c->u_mode.ocb.aad_sum)
726 : :
727 : : "memory" );
728 :
729 0 : vpaes_ssse3_cleanup ();
730 0 : }
731 :
732 : #endif /* USE_SSSE3 */
|