LCOV - code coverage report
Current view: top level - cipher - rijndael-aesni.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 273 0.0 %
Date: 2016-12-15 12:59:22 Functions: 0 19 0.0 %

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

Generated by: LCOV version 1.12