]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
fixes in acceleration detection.
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Mon, 11 Apr 2011 14:26:35 +0000 (16:26 +0200)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Mon, 11 Apr 2011 18:37:42 +0000 (20:37 +0200)
Added Intel's library code for AES-NI acceleration.

16 files changed:
.gitignore
configure.ac
lib/accelerated/Makefile.am
lib/accelerated/accelerated.c
lib/accelerated/aes-x86.c [deleted file]
lib/accelerated/intel/Makefile.am [new file with mode: 0644]
lib/accelerated/intel/aes-x86.c [new file with mode: 0644]
lib/accelerated/intel/aes-x86.h [moved from lib/accelerated/aes-x86.h with 100% similarity]
lib/accelerated/intel/asm/x64_do_rdtsc.s [new file with mode: 0755]
lib/accelerated/intel/asm/x64_iaesx64.s [new file with mode: 0755]
lib/accelerated/intel/asm/x86_do_rdtsc.s [new file with mode: 0755]
lib/accelerated/intel/asm/x86_iaesx86.s [new file with mode: 0755]
lib/accelerated/intel/iaes_asm_interface.h [new file with mode: 0755]
lib/accelerated/intel/iaesni.h [new file with mode: 0755]
lib/accelerated/intel/license.txt [new file with mode: 0755]
m4/gcc.m4

index c1aac5b08062949b57392f9061bf97b7fcd6003c..42008a71d0030e99e0f49455a5423a6333cc5c41 100644 (file)
@@ -449,3 +449,5 @@ gl/tests/test-vasprintf
 gl/tests/test-vsnprintf
 lib/accelerated/libaccelerated.la
 gl/time.h
+lib/accelerated/intel/libintel.la
+doc/cyclo/cyclo-gnutls.html
index fcbf5485004c4212ebb6c5f668ac128b13ddaa8a..f6b28b236a0ea21970e2fd4d40fc2febeddf0891 100644 (file)
@@ -90,6 +90,7 @@ AC_CHECK_TYPES(uint,,, [
 # include <sys/types.h>
 ])
 
+
 AC_ARG_ENABLE(hardware-acceleration,
   AS_HELP_STRING([--disable-hardware-acceleration], [unconditionally disable hardware acceleration]),
     use_accel=$enableval, use_accel=yes)
@@ -99,9 +100,18 @@ if test "$use_accel" != "no"; then
 case $host_cpu in
   i?86 | x86_64 | amd64)
     GCC_FLAG_ADD([-maes -mpclmul],[X86])
-
-    if test "x$X86" = "xyes";then
-      hw_accel="x86"
+    AC_CHECK_PROGS(YASM, yasm)
+
+    if test "x$YASM" != "x";then
+      if test "x$X86" = "xyes";then
+        if test "$host_cpu" = "x86_64" -o "$host_cpu" = "amd64";then
+          hw_accel="x86-64"
+        else
+          hw_accel="x86"
+        fi
+      fi
+    else
+      AC_MSG_WARN([[yasm assembler not found. Disabling AES-NI compilation.]])
     fi
   ;;
   *)
@@ -110,7 +120,8 @@ esac
 
 fi
 
-AM_CONDITIONAL(TRY_X86_OPTIMIZATIONS, test "$X86" = "yes")
+AM_CONDITIONAL(TRY_X86_OPTIMIZATIONS, test x"$hw_accel" = x"x86" -o x"$hw_accel" = x"x86-64")
+AM_CONDITIONAL(ASM_X86_64, test x"$hw_accel" = x"x86-64")
 AM_CONDITIONAL(HAVE_GCC_GNU89_INLINE_OPTION, test "$gnu89_inline" = "yes"])
 AM_CONDITIONAL(HAVE_GCC, test "$GCC" = "yes")
 
@@ -399,6 +410,7 @@ AC_CONFIG_FILES([
   lib/nettle/Makefile
   tests/suite/Makefile
   lib/accelerated/Makefile
+  lib/accelerated/intel/Makefile
 ])
 
 AC_OUTPUT
index bfe9a168c175fafd29fc56d976a2ba8551c617bb..0e760640d3729ba0e3c2299004d906f1f8f103c3 100644 (file)
 # MA 02110-1301, USA
 
 AM_CFLAGS = $(WERROR_CFLAGS) $(WSTACK_CFLAGS) $(WARN_CFLAGS)
+SUBDIRS = 
 AM_CPPFLAGS = \
        -I$(srcdir)/../../gl            \
        -I$(srcdir)/../includes         \
        -I$(builddir)/../includes       \
        -I$(srcdir)/..
 
+if ENABLE_MINITASN1
+AM_CPPFLAGS += -I$(srcdir)/../minitasn1
+endif
+
 noinst_LTLIBRARIES = libaccelerated.la
 
 EXTRA_DIST = x86.h aes-x86.h accelerated.h
 libaccelerated_la_SOURCES = accelerated.c
+libaccelerated_la_LIBADD =
 
 if TRY_X86_OPTIMIZATIONS
+SUBDIRS += intel
 AM_CFLAGS += -DTRY_X86_OPTIMIZATIONS
-libaccelerated_la_SOURCES += aes-x86.c
+libaccelerated_la_LIBADD += intel/libintel.la
 endif
-
index 91e7040fb01163d8c9ea82a4296ec3b187cebfb9..a25c57bd5f2424e6db59ab237806b2b1587f65d8 100644 (file)
@@ -1,6 +1,6 @@
 #include <accelerated.h>
 #ifdef TRY_X86_OPTIMIZATIONS
-# include <aes-x86.h>
+# include <intel/aes-x86.h>
 #endif
 
 void _gnutls_register_accel_crypto(void)
diff --git a/lib/accelerated/aes-x86.c b/lib/accelerated/aes-x86.c
deleted file mode 100644 (file)
index 1b705ed..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright (C) 2011, Free Software Foundation
- *
- * Author: Nikos Mavrogiannopoulos
- *
- * This file is part of GnuTLS.
- *
- * The GnuTLS is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA
- *
- * The following code is an implementation of the AES-128-CBC cipher
- * using intel's AES instruction set. It is based on Intel reference
- * code.
- */
-
-#include <gnutls_errors.h>
-#include <gnutls_int.h>
-#include <gnutls/crypto.h>
-#include <gnutls_errors.h>
-#include <wmmintrin.h>
-#include <aes-x86.h>
-#include <x86.h>
-
-struct aes_ctx {
-       uint8_t iv[16];
-       uint8_t key[16*10];
-       size_t keysize;
-};
-
-static int
-aes_cipher_init (gnutls_cipher_algorithm_t algorithm, void **_ctx)
-{
-  struct aes_ctx *ctx;
-  
-  if (algorithm != GNUTLS_CIPHER_AES_128_CBC)
-    return GNUTLS_E_INVALID_REQUEST;
-
-  *_ctx = gnutls_calloc (1, sizeof (struct aes_ctx));
-  if (*_ctx == NULL)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_MEMORY_ERROR;
-    }
-
-  ctx = *_ctx;
-
-  return 0;
-}
-
-inline static __m128i aes128_assist (__m128i temp1, __m128i temp2)
-{
-__m128i temp3;
-       temp2 = _mm_shuffle_epi32 (temp2 ,0xff);
-       temp3 = _mm_slli_si128 (temp1, 0x4);
-       temp1 = _mm_xor_si128 (temp1, temp3);
-       temp3 = _mm_slli_si128 (temp3, 0x4);
-       temp1 = _mm_xor_si128 (temp1, temp3);
-       temp3 = _mm_slli_si128 (temp3, 0x4);
-       temp1 = _mm_xor_si128 (temp1, temp3);
-       temp1 = _mm_xor_si128 (temp1, temp2);
-
-       return temp1;
-}
-
-static int
-aes_cipher_setkey (void *_ctx, const void *userkey, size_t keysize)
-{
-struct aes_ctx *ctx = _ctx;
-__m128i temp1, temp2;
-__m128i *Key_Schedule = (__m128i*)ctx->key;
-
-       temp1 = _mm_loadu_si128((__m128i*)userkey);
-       Key_Schedule[0] = temp1;
-       temp2 = _mm_aeskeygenassist_si128 (temp1 ,0x1);
-       temp1 = aes128_assist(temp1, temp2);
-       Key_Schedule[1] = temp1;
-       temp2 = _mm_aeskeygenassist_si128 (temp1,0x2);
-       temp1 = aes128_assist(temp1, temp2);
-       Key_Schedule[2] = temp1;
-       temp2 = _mm_aeskeygenassist_si128 (temp1,0x4);
-       temp1 = aes128_assist(temp1, temp2);
-       Key_Schedule[3] = temp1;
-       temp2 = _mm_aeskeygenassist_si128 (temp1,0x8);
-       temp1 = aes128_assist(temp1, temp2);
-       Key_Schedule[4] = temp1;
-       temp2 = _mm_aeskeygenassist_si128 (temp1,0x10);
-       temp1 = aes128_assist(temp1, temp2);
-       Key_Schedule[5] = temp1;
-       temp2 = _mm_aeskeygenassist_si128 (temp1,0x20);
-       temp1 = aes128_assist(temp1, temp2);
-       Key_Schedule[6] = temp1;
-       temp2 = _mm_aeskeygenassist_si128 (temp1,0x40);
-       temp1 = aes128_assist(temp1, temp2);
-       Key_Schedule[7] = temp1;
-       temp2 = _mm_aeskeygenassist_si128 (temp1,0x80);
-       temp1 = aes128_assist(temp1, temp2);
-       Key_Schedule[8] = temp1;
-       temp2 = _mm_aeskeygenassist_si128 (temp1,0x1b);
-       temp1 = aes128_assist(temp1, temp2);
-       Key_Schedule[9] = temp1;
-       temp2 = _mm_aeskeygenassist_si128 (temp1,0x36);
-       temp1 = aes128_assist(temp1, temp2);
-       Key_Schedule[10] = temp1;
-
-       ctx->keysize = keysize;
-
-       return 0;
-}
-
-static int
-aes_setiv (void *_ctx, const void *iv, size_t iv_size)
-{
-  struct aes_ctx *ctx = _ctx;
-
-  memcpy (ctx->iv, iv, 16);
-
-  return 0;
-}
-
-#define AES_128_ROUNDS 10
-
-static int
-aes_encrypt (void *_ctx, const void *plain, size_t plainsize,
-                   void *encr, size_t length)
-{
-struct aes_ctx *ctx = _ctx;
-__m128i feedback,data;
-int i,j;
-
-       feedback=_mm_loadu_si128 ((__m128i*)ctx->iv);
-       for(i=0; i < length; i++) {
-               data = _mm_loadu_si128 (&((__m128i*)plain)[i]);
-               feedback = _mm_xor_si128 (data,feedback);
-               feedback = _mm_xor_si128 (feedback,((__m128i*)ctx->key)[0]);
-    
-               for(j=1; j <AES_128_ROUNDS; j++)
-                       feedback = _mm_aesenc_si128 (feedback,((__m128i*)ctx->key)[j]);
-
-               feedback = _mm_aesenclast_si128 (feedback,((__m128i*)ctx->key)[j]);
-               _mm_storeu_si128 (&((__m128i*)encr)[i],feedback);
-       }
-
-  return 0;
-}
-
-static int
-aes_decrypt (void *_ctx, const void *encr, size_t encrsize,
-                   void *plain, size_t length)
-{
-struct aes_ctx *ctx = _ctx;
-__m128i data,feedback,last_in;
-int i,j;
-
-       feedback=_mm_loadu_si128 ((__m128i*)ctx->iv);
-
-       for(i=0; i < length; i++) {
-               last_in=_mm_loadu_si128 (&((__m128i*)encr)[i]);
-               data = _mm_xor_si128 (last_in,((__m128i*)ctx->key)[0]);
-    
-               for(j=1; j <AES_128_ROUNDS; j++)
-                       data = _mm_aesdec_si128 (data,((__m128i*)ctx->key)[j]);
-
-               data = _mm_aesdeclast_si128 (data,((__m128i*)ctx->key)[j]);
-               data = _mm_xor_si128 (data,feedback);
-               _mm_storeu_si128 (&((__m128i*)plain)[i],data);
-               feedback=last_in;
-       }
-
-       return 0;
-}
-
-static void
-aes_deinit (void *_ctx)
-{
-  gnutls_free (_ctx);
-}
-
-static const gnutls_crypto_cipher_st cipher_struct = {
-  .init = aes_cipher_init,
-  .setkey = aes_cipher_setkey,
-  .setiv = aes_setiv,
-  .encrypt = aes_encrypt,
-  .decrypt = aes_decrypt,
-  .deinit = aes_deinit,
-};
-
-static unsigned check_optimized_aes(void)
-{
-unsigned int a,b,c,d;
-  cpuid(1, a,b,c,d);
-  
-  return (c & 0x2000000);
-}
-
-void
-register_x86_crypto (void)
-{
-int ret;
-       if (check_optimized_aes()) {
-               fprintf(stderr, "Intel AES accelerator was detected\n");
-               ret = gnutls_crypto_single_cipher_register (GNUTLS_CIPHER_AES_128_CBC, 90, &cipher_struct);
-               if (ret < 0)
-               {
-                 gnutls_assert ();
-               }
-       }
-
-       return;
-}
diff --git a/lib/accelerated/intel/Makefile.am b/lib/accelerated/intel/Makefile.am
new file mode 100644 (file)
index 0000000..51dea2f
--- /dev/null
@@ -0,0 +1,60 @@
+## Process this file with automake to produce Makefile.in
+# Copyright (C) 2011 Free Software
+# Foundation, Inc.
+#
+# Author: Nikos Mavrogiannopoulos
+#
+# This file is part of GNUTLS.
+#
+# The GNUTLS library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public License
+# as published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+#
+# The GNUTLS library is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNUTLS library; if not, write to the Free
+# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA
+
+AM_CFLAGS = $(WERROR_CFLAGS) $(WSTACK_CFLAGS) $(WARN_CFLAGS)
+AM_CPPFLAGS = \
+       -I$(srcdir)/../../../gl         \
+       -I$(srcdir)/../../includes      \
+       -I$(srcdir)/../../ \
+       -I$(srcdir)/../
+
+if ENABLE_MINITASN1
+AM_CPPFLAGS += -I$(srcdir)/../minitasn1
+endif
+
+noinst_LTLIBRARIES = libintel.la
+
+EXTRA_DIST = aes-x86.h
+libintel_la_SOURCES = aes-x86.c
+libintel_la_LIBADD =
+
+YASM_OPTS = -D__linux__
+
+x64_do_rdtsc.o: asm/x64_do_rdtsc.s
+       $(YASM) $(YASM_OPTS) -f elf64 $^ -o $@
+
+x64_iaesx64.o: asm/x64_iaesx64.s
+       $(YASM) $(YASM_OPTS) -f elf64 $^ -o $@
+
+x86_do_rdtsc.o: asm/x86_do_rdtsc.s
+       $(YASM) $(YASM_OPTS) -f elf32 $^ -o $@
+
+x86_iaesx86.o: asm/x86_iaesx86.s
+       $(YASM) $(YASM_OPTS) -f elf32 $^ -o $@
+
+if ASM_X86_64
+libintel_la_LIBADD += x64_do_rdtsc.o x64_iaesx64.o
+else
+libintel_la_LIBADD += x86_do_rdtsc.o x86_iaesx86.o
+endif
+
diff --git a/lib/accelerated/intel/aes-x86.c b/lib/accelerated/intel/aes-x86.c
new file mode 100644 (file)
index 0000000..55ee6ff
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2011, Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ * The following code is an implementation of the AES-128-CBC cipher
+ * using intel's AES instruction set. It is based on Intel reference
+ * code.
+ */
+
+#include <gnutls_errors.h>
+#include <gnutls_int.h>
+#include <gnutls/crypto.h>
+#include <gnutls_errors.h>
+#include <aes-x86.h>
+#include <x86.h>
+#include "iaesni.h"
+#include "iaes_asm_interface.h"
+
+#ifdef __GNUC__
+# define ALIGN16 __attribute__ ((aligned (16))) 
+#else
+# define ALIGN16
+#endif
+
+typedef void (*enc_func)(sAesData*);
+
+struct aes_ctx {
+       uint8_t iv[16];
+       uint8_t ALIGN16 expanded_key[16*16];
+       uint8_t ALIGN16 expanded_key_dec[16*16];
+       enc_func enc;
+       enc_func dec;
+       size_t keysize;
+};
+
+static int
+aes_cipher_init (gnutls_cipher_algorithm_t algorithm, void **_ctx)
+{
+  struct aes_ctx *ctx;
+  
+  /* we use key size to distinguish */
+  if (algorithm != GNUTLS_CIPHER_AES_128_CBC && algorithm != GNUTLS_CIPHER_AES_192_CBC 
+    && algorithm != GNUTLS_CIPHER_AES_256_CBC)
+    return GNUTLS_E_INVALID_REQUEST;
+
+  *_ctx = gnutls_calloc (1, sizeof (struct aes_ctx));
+  if (*_ctx == NULL)
+    {
+      gnutls_assert ();
+      return GNUTLS_E_MEMORY_ERROR;
+    }
+
+  ctx = *_ctx;
+
+  return 0;
+}
+
+static int
+aes_cipher_setkey (void *_ctx, const void *userkey, size_t keysize)
+{
+struct aes_ctx *ctx = _ctx;
+
+  if (keysize == 128/8)
+    {
+      iEncExpandKey128((void*)userkey, ctx->expanded_key);
+      iDecExpandKey128((void*)userkey, ctx->expanded_key_dec);
+      ctx->enc = iEnc128_CBC;
+      ctx->dec = iDec128_CBC;
+    }
+  else if (keysize == 192/8)
+    {
+      iEncExpandKey192((void*)userkey, ctx->expanded_key);
+      iDecExpandKey192((void*)userkey, ctx->expanded_key_dec);
+      ctx->enc = iEnc192_CBC;
+      ctx->dec = iDec192_CBC;
+    }
+  else if (keysize == 256/8)
+    {
+      iEncExpandKey256((void*)userkey, ctx->expanded_key);
+      iDecExpandKey256((void*)userkey, ctx->expanded_key_dec);
+      ctx->enc = iEnc256_CBC;
+      ctx->dec = iDec256_CBC;
+    }
+
+  ctx->keysize = keysize;
+
+  return 0;
+}
+
+static int
+aes_setiv (void *_ctx, const void *iv, size_t iv_size)
+{
+  struct aes_ctx *ctx = _ctx;
+
+  memcpy (ctx->iv, iv, 16);
+
+  return 0;
+}
+
+static int
+aes_encrypt (void *_ctx, const void *plain, size_t plainsize,
+                   void *encr, size_t length)
+{
+struct aes_ctx *ctx = _ctx;
+sAesData aesData;
+
+  aesData.in_block = (void*)plain;
+  aesData.out_block = encr;
+  aesData.expanded_key = ctx->expanded_key;
+  aesData.num_blocks = length % 16;
+
+  ctx->enc(&aesData);
+
+  return 0;
+}
+
+static int
+aes_decrypt (void *_ctx, const void *encr, size_t encrsize,
+                   void *plain, size_t length)
+{
+struct aes_ctx *ctx = _ctx;
+sAesData aesData;
+
+  aesData.in_block = (void*)encr;
+  aesData.out_block = plain;
+  aesData.expanded_key = ctx->expanded_key;
+  aesData.num_blocks = length % 16;
+
+  ctx->dec(&aesData);
+
+  return 0;
+}
+
+static void
+aes_deinit (void *_ctx)
+{
+  gnutls_free (_ctx);
+}
+
+static const gnutls_crypto_cipher_st cipher_struct = {
+  .init = aes_cipher_init,
+  .setkey = aes_cipher_setkey,
+  .setiv = aes_setiv,
+  .encrypt = aes_encrypt,
+  .decrypt = aes_decrypt,
+  .deinit = aes_deinit,
+};
+
+static unsigned check_optimized_aes(void)
+{
+unsigned int a,b,c,d;
+  cpuid(1, a,b,c,d);
+  
+  return (c & 0x2000000);
+}
+
+void
+register_x86_crypto (void)
+{
+int ret;
+       if (check_optimized_aes()) {
+               fprintf(stderr, "Intel AES accelerator was detected\n");
+               ret = gnutls_crypto_single_cipher_register (GNUTLS_CIPHER_AES_128_CBC, 90, &cipher_struct);
+               if (ret < 0)
+               {
+                 gnutls_assert ();
+               }
+
+               ret = gnutls_crypto_single_cipher_register (GNUTLS_CIPHER_AES_192_CBC, 90, &cipher_struct);
+               if (ret < 0)
+               {
+                 gnutls_assert ();
+               }
+
+               ret = gnutls_crypto_single_cipher_register (GNUTLS_CIPHER_AES_256_CBC, 90, &cipher_struct);
+               if (ret < 0)
+               {
+                 gnutls_assert ();
+               }
+       }
+
+       return;
+}
diff --git a/lib/accelerated/intel/asm/x64_do_rdtsc.s b/lib/accelerated/intel/asm/x64_do_rdtsc.s
new file mode 100755 (executable)
index 0000000..74435c7
--- /dev/null
@@ -0,0 +1,37 @@
+[bits 64]\r
+[CPU intelnop]\r
+\r
+; Copyright (c) 2010, Intel Corporation\r
+; All rights reserved.\r
+; \r
+; Redistribution and use in source and binary forms, with or without \r
+; modification, are permitted provided that the following conditions are met:\r
+; \r
+;     * Redistributions of source code must retain the above copyright notice, \r
+;       this list of conditions and the following disclaimer.\r
+;     * Redistributions in binary form must reproduce the above copyright notice, \r
+;       this list of conditions and the following disclaimer in the documentation \r
+;       and/or other materials provided with the distribution.\r
+;     * Neither the name of Intel Corporation nor the names of its contributors \r
+;       may be used to endorse or promote products derived from this software \r
+;       without specific prior written permission.\r
+; \r
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND \r
+; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED \r
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. \r
+; IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, \r
+; INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, \r
+; BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, \r
+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF \r
+; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE \r
+; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \r
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+\r
+align 16\r
+global do_rdtsc\r
+do_rdtsc:\r
+\r
+       rdtsc\r
+       shl rdx, 32\r
+       or  rax, rdx\r
+       ret     0\r
diff --git a/lib/accelerated/intel/asm/x64_iaesx64.s b/lib/accelerated/intel/asm/x64_iaesx64.s
new file mode 100755 (executable)
index 0000000..433d177
--- /dev/null
@@ -0,0 +1,2054 @@
+[bits 64]\r
+[CPU intelnop]\r
+\r
+; Copyright (c) 2010, Intel Corporation\r
+; All rights reserved.\r
+; \r
+; Redistribution and use in source and binary forms, with or without \r
+; modification, are permitted provided that the following conditions are met:\r
+; \r
+;     * Redistributions of source code must retain the above copyright notice, \r
+;       this list of conditions and the following disclaimer.\r
+;     * Redistributions in binary form must reproduce the above copyright notice, \r
+;       this list of conditions and the following disclaimer in the documentation \r
+;       and/or other materials provided with the distribution.\r
+;     * Neither the name of Intel Corporation nor the names of its contributors \r
+;       may be used to endorse or promote products derived from this software \r
+;       without specific prior written permission.\r
+; \r
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND \r
+; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED \r
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. \r
+; IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, \r
+; INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, \r
+; BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, \r
+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF \r
+; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE \r
+; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \r
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+\r
+%macro linux_setup 0\r
+%ifdef __linux__\r
+       mov rcx, rdi\r
+       mov rdx, rsi\r
+%endif\r
+%endmacro\r
+\r
+%macro inversekey 1\r
+       movdqu  xmm1,%1\r
+       aesimc  xmm0,xmm1\r
+       movdqu  %1,xmm0\r
+%endmacro\r
+\r
+%macro aesdeclast1 1\r
+       aesdeclast      xmm0,%1\r
+%endmacro\r
+\r
+%macro aesenclast1 1\r
+       aesenclast      xmm0,%1\r
+%endmacro\r
+\r
+%macro aesdec1 1\r
+       aesdec  xmm0,%1\r
+%endmacro\r
+\r
+%macro aesenc1 1\r
+       aesenc  xmm0,%1\r
+%endmacro\r
+\r
+\r
+%macro aesdeclast1_u 1\r
+       movdqu xmm4,%1\r
+       aesdeclast      xmm0,xmm4\r
+%endmacro\r
+\r
+%macro aesenclast1_u 1\r
+       movdqu xmm4,%1\r
+       aesenclast      xmm0,xmm4\r
+%endmacro\r
+\r
+%macro aesdec1_u 1\r
+       movdqu xmm4,%1\r
+       aesdec  xmm0,xmm4\r
+%endmacro\r
+\r
+%macro aesenc1_u 1\r
+       movdqu xmm4,%1\r
+       aesenc  xmm0,xmm4\r
+%endmacro\r
\r
+%macro aesdec4 1\r
+       movdqa  xmm4,%1\r
+\r
+       aesdec  xmm0,xmm4\r
+       aesdec  xmm1,xmm4\r
+       aesdec  xmm2,xmm4\r
+       aesdec  xmm3,xmm4\r
+\r
+%endmacro\r
+\r
+%macro aesdeclast4 1\r
+       movdqa  xmm4,%1\r
+\r
+       aesdeclast      xmm0,xmm4\r
+       aesdeclast      xmm1,xmm4\r
+       aesdeclast      xmm2,xmm4\r
+       aesdeclast      xmm3,xmm4\r
+\r
+%endmacro\r
+\r
+\r
+%macro aesenc4 1\r
+       movdqa  xmm4,%1\r
+\r
+       aesenc  xmm0,xmm4\r
+       aesenc  xmm1,xmm4\r
+       aesenc  xmm2,xmm4\r
+       aesenc  xmm3,xmm4\r
+\r
+%endmacro\r
+\r
+%macro aesenclast4 1\r
+       movdqa  xmm4,%1\r
+\r
+       aesenclast      xmm0,xmm4\r
+       aesenclast      xmm1,xmm4\r
+       aesenclast      xmm2,xmm4\r
+       aesenclast      xmm3,xmm4\r
+\r
+%endmacro\r
+\r
+\r
+%macro load_and_inc4 1\r
+       movdqa  xmm4,%1\r
+       movdqa  xmm0,xmm5\r
+       movdqa  xmm1,xmm5\r
+       paddq   xmm1,[counter_add_one wrt rip]\r
+       movdqa  xmm2,xmm5\r
+       paddq   xmm2,[counter_add_two wrt rip]\r
+       movdqa  xmm3,xmm5\r
+       paddq   xmm3,[counter_add_three wrt rip]\r
+       pxor    xmm0,xmm4\r
+       paddq   xmm5,[counter_add_four wrt rip]\r
+       pxor    xmm1,xmm4\r
+       pxor    xmm2,xmm4\r
+       pxor    xmm3,xmm4\r
+%endmacro\r
+\r
+%macro xor_with_input4 1\r
+       movdqu xmm4,[%1]\r
+       pxor xmm0,xmm4\r
+       movdqu xmm4,[%1+16]\r
+       pxor xmm1,xmm4\r
+       movdqu xmm4,[%1+32]\r
+       pxor xmm2,xmm4\r
+       movdqu xmm4,[%1+48]\r
+       pxor xmm3,xmm4\r
+%endmacro\r
+\r
+\r
+\r
+%macro load_and_xor4 2\r
+       movdqa  xmm4,%2\r
+       movdqu  xmm0,[%1 + 0*16]\r
+       pxor    xmm0,xmm4\r
+       movdqu  xmm1,[%1 + 1*16]\r
+       pxor    xmm1,xmm4\r
+       movdqu  xmm2,[%1 + 2*16]\r
+       pxor    xmm2,xmm4\r
+       movdqu  xmm3,[%1 + 3*16]\r
+       pxor    xmm3,xmm4\r
+%endmacro\r
+\r
+%macro store4 1\r
+       movdqu [%1 + 0*16],xmm0\r
+       movdqu [%1 + 1*16],xmm1\r
+       movdqu [%1 + 2*16],xmm2\r
+       movdqu [%1 + 3*16],xmm3\r
+%endmacro\r
+\r
+%macro copy_round_keys 3\r
+       movdqu xmm4,[%2 + ((%3)*16)]\r
+       movdqa [%1 + ((%3)*16)],xmm4\r
+%endmacro\r
+\r
+\r
+%macro key_expansion_1_192 1\r
+               ;; Assumes the xmm3 includes all zeros at this point. \r
+        pshufd xmm2, xmm2, 11111111b        \r
+        shufps xmm3, xmm1, 00010000b        \r
+        pxor xmm1, xmm3        \r
+        shufps xmm3, xmm1, 10001100b\r
+        pxor xmm1, xmm3        \r
+               pxor xmm1, xmm2         \r
+               movdqu [rdx+%1], xmm1                   \r
+%endmacro\r
+\r
+; Calculate w10 and w11 using calculated w9 and known w4-w5\r
+%macro key_expansion_2_192 1                           \r
+               movdqa xmm5, xmm4\r
+               pslldq xmm5, 4\r
+               shufps xmm6, xmm1, 11110000b\r
+               pxor xmm6, xmm5\r
+               pxor xmm4, xmm6\r
+               pshufd xmm7, xmm4, 00001110b \r
+               movdqu [rdx+%1], xmm7\r
+%endmacro\r
+\r
+\r
+section .data\r
+align 16\r
+shuffle_mask:\r
+DD 0FFFFFFFFh\r
+DD 03020100h\r
+DD 07060504h\r
+DD 0B0A0908h\r
+\r
+\r
+align 16\r
+counter_add_one:\r
+DD 1\r
+DD 0\r
+DD 0\r
+DD 0\r
+\r
+counter_add_two:\r
+DD 2\r
+DD 0\r
+DD 0\r
+DD 0\r
+\r
+counter_add_three:\r
+DD 3\r
+DD 0\r
+DD 0\r
+DD 0\r
+\r
+counter_add_four:\r
+DD 4\r
+DD 0\r
+DD 0\r
+DD 0\r
+\r
+\r
+\r
+section .text\r
+\r
+align 16\r
+key_expansion256:\r
+\r
+    pshufd xmm2, xmm2, 011111111b\r
+\r
+    movdqa xmm4, xmm1\r
+    pshufb xmm4, xmm5\r
+    pxor xmm1, xmm4\r
+    pshufb xmm4, xmm5\r
+    pxor xmm1, xmm4\r
+    pshufb xmm4, xmm5\r
+    pxor xmm1, xmm4\r
+    pxor xmm1, xmm2\r
+\r
+    movdqu [rdx], xmm1\r
+    add rdx, 0x10\r
+    \r
+    aeskeygenassist xmm4, xmm1, 0\r
+    pshufd xmm2, xmm4, 010101010b\r
+\r
+    movdqa xmm4, xmm3\r
+    pshufb xmm4, xmm5\r
+    pxor xmm3, xmm4\r
+    pshufb xmm4, xmm5\r
+    pxor xmm3, xmm4\r
+    pshufb xmm4, xmm5\r
+    pxor xmm3, xmm4\r
+    pxor xmm3, xmm2\r
+\r
+    movdqu [rdx], xmm3\r
+    add rdx, 0x10\r
+\r
+    ret\r
+\r
+\r
+\r
+align 16\r
+key_expansion128: \r
+    pshufd xmm2, xmm2, 0xFF;\r
+    movdqa xmm3, xmm1\r
+    pshufb xmm3, xmm5\r
+    pxor xmm1, xmm3\r
+    pshufb xmm3, xmm5\r
+    pxor xmm1, xmm3\r
+    pshufb xmm3, xmm5\r
+    pxor xmm1, xmm3\r
+    pxor xmm1, xmm2\r
+\r
+    ; storing the result in the key schedule array\r
+    movdqu [rdx], xmm1\r
+    add rdx, 0x10                    \r
+    ret\r
+\r
+\r
+\r
+\r
+\r
+\r
+align 16\r
+global iEncExpandKey128\r
+iEncExpandKey128:\r
+\r
+               linux_setup\r
+\r
+        movdqu xmm1, [rcx]    ; loading the key\r
+\r
+        movdqu [rdx], xmm1\r
+\r
+        movdqa xmm5, [shuffle_mask wrt rip]\r
+\r
+        add rdx,16\r
+\r
+        aeskeygenassist xmm2, xmm1, 0x1     ; Generating round key 1\r
+        call key_expansion128\r
+        aeskeygenassist xmm2, xmm1, 0x2     ; Generating round key 2\r
+        call key_expansion128\r
+        aeskeygenassist xmm2, xmm1, 0x4     ; Generating round key 3\r
+        call key_expansion128\r
+        aeskeygenassist xmm2, xmm1, 0x8     ; Generating round key 4\r
+        call key_expansion128\r
+        aeskeygenassist xmm2, xmm1, 0x10    ; Generating round key 5\r
+        call key_expansion128\r
+        aeskeygenassist xmm2, xmm1, 0x20    ; Generating round key 6\r
+        call key_expansion128\r
+        aeskeygenassist xmm2, xmm1, 0x40    ; Generating round key 7\r
+        call key_expansion128\r
+        aeskeygenassist xmm2, xmm1, 0x80    ; Generating round key 8\r
+        call key_expansion128\r
+        aeskeygenassist xmm2, xmm1, 0x1b    ; Generating round key 9\r
+        call key_expansion128\r
+        aeskeygenassist xmm2, xmm1, 0x36    ; Generating round key 10\r
+        call key_expansion128\r
+\r
+               ret \r
+\r
+\r
+\r
+align 16\r
+global iEncExpandKey192\r
+iEncExpandKey192:\r
+\r
+               linux_setup\r
+               sub rsp,64+8\r
+               movdqa  [rsp],xmm6\r
+               movdqa  [rsp+16],xmm7\r
+\r
+\r
+        movq xmm7, [rcx+16]    ; loading the AES key\r
+        movq [rdx+16], xmm7  ; Storing key in memory where all key expansion \r
+        pshufd xmm4, xmm7, 01001111b\r
+        movdqu xmm1, [rcx]     ; loading the AES key\r
+        movdqu [rdx], xmm1  ; Storing key in memory where all key expansion \r
+                       \r
+        pxor xmm3, xmm3                ; Set xmm3 to be all zeros. Required for the key_expansion. \r
+        pxor xmm6, xmm6                ; Set xmm3 to be all zeros. Required for the key_expansion. \r
+\r
+        aeskeygenassist xmm2, xmm4, 0x1     ; Complete round key 1 and generate round key 2 \r
+        key_expansion_1_192 24\r
+               key_expansion_2_192 40                          \r
+\r
+        aeskeygenassist xmm2, xmm4, 0x2     ; Generate round key 3 and part of round key 4\r
+        key_expansion_1_192 48\r
+               key_expansion_2_192 64                          \r
+\r
+        aeskeygenassist xmm2, xmm4, 0x4     ; Complete round key 4 and generate round key 5\r
+        key_expansion_1_192 72\r
+               key_expansion_2_192 88\r
+               \r
+        aeskeygenassist xmm2, xmm4, 0x8     ; Generate round key 6 and part of round key 7\r
+        key_expansion_1_192 96\r
+               key_expansion_2_192 112\r
+               \r
+        aeskeygenassist xmm2, xmm4, 0x10     ; Complete round key 7 and generate round key 8 \r
+        key_expansion_1_192 120\r
+               key_expansion_2_192 136                         \r
+\r
+        aeskeygenassist xmm2, xmm4, 0x20     ; Generate round key 9 and part of round key 10\r
+        key_expansion_1_192 144\r
+               key_expansion_2_192 160                         \r
+\r
+        aeskeygenassist xmm2, xmm4, 0x40     ; Complete round key 10 and generate round key 11\r
+        key_expansion_1_192 168\r
+               key_expansion_2_192 184                         \r
+\r
+        aeskeygenassist xmm2, xmm4, 0x80     ; Generate round key 12\r
+        key_expansion_1_192 192\r
+\r
+\r
+               movdqa  xmm6,[rsp]\r
+               movdqa  xmm7,[rsp+16]\r
+               add rsp,64+8\r
+\r
+               ret \r
+\r
+\r
+\r
+\r
+align 16\r
+global iDecExpandKey128\r
+iDecExpandKey128:\r
+\r
+       linux_setup\r
+       push rcx\r
+       push rdx\r
+       sub rsp,16+8\r
+\r
+       call iEncExpandKey128\r
+\r
+       add rsp,16+8\r
+       pop rdx\r
+       pop rcx\r
+\r
+       inversekey [rdx + 1*16]\r
+       inversekey [rdx + 2*16]\r
+       inversekey [rdx + 3*16]\r
+       inversekey [rdx + 4*16]\r
+       inversekey [rdx + 5*16]\r
+       inversekey [rdx + 6*16]\r
+       inversekey [rdx + 7*16]\r
+       inversekey [rdx + 8*16]\r
+       inversekey [rdx + 9*16]\r
+\r
+       ret\r
+\r
+\r
+align 16\r
+global iDecExpandKey192\r
+iDecExpandKey192:\r
+\r
+       linux_setup\r
+       push rcx\r
+       push rdx\r
+       sub rsp,16+8\r
+\r
+       call iEncExpandKey192\r
+\r
+       add rsp,16+8\r
+       pop rdx\r
+       pop rcx\r
+\r
+       \r
+       inversekey [rdx + 1*16]\r
+       inversekey [rdx + 2*16]\r
+       inversekey [rdx + 3*16]\r
+       inversekey [rdx + 4*16]\r
+       inversekey [rdx + 5*16]\r
+       inversekey [rdx + 6*16]\r
+       inversekey [rdx + 7*16]\r
+       inversekey [rdx + 8*16]\r
+       inversekey [rdx + 9*16]\r
+       inversekey [rdx + 10*16]\r
+       inversekey [rdx + 11*16]\r
+\r
+       ret\r
+\r
+\r
+\r
+align 16\r
+global iDecExpandKey256\r
+iDecExpandKey256:\r
+\r
+       linux_setup\r
+       push rcx\r
+       push rdx\r
+       sub rsp,16+8\r
+\r
+       call iEncExpandKey256\r
+\r
+       add rsp,16+8\r
+       pop rdx\r
+       pop rcx\r
+\r
+       inversekey [rdx + 1*16]\r
+       inversekey [rdx + 2*16]\r
+       inversekey [rdx + 3*16]\r
+       inversekey [rdx + 4*16]\r
+       inversekey [rdx + 5*16]\r
+       inversekey [rdx + 6*16]\r
+       inversekey [rdx + 7*16]\r
+       inversekey [rdx + 8*16]\r
+       inversekey [rdx + 9*16]\r
+       inversekey [rdx + 10*16]\r
+       inversekey [rdx + 11*16]\r
+       inversekey [rdx + 12*16]\r
+       inversekey [rdx + 13*16]\r
+\r
+       ret\r
+       \r
+\r
+       \r
+       \r
+align 16\r
+global iEncExpandKey256\r
+iEncExpandKey256:\r
+\r
+       linux_setup\r
+\r
+    movdqu xmm1, [rcx]    ; loading the key\r
+    movdqu xmm3, [rcx+16]\r
+    movdqu [rdx], xmm1  ; Storing key in memory where all key schedule will be stored\r
+    movdqu [rdx+16], xmm3 \r
+    \r
+    add rdx,32\r
+\r
+    movdqa xmm5, [shuffle_mask wrt rip]  ; this mask is used by key_expansion\r
+\r
+    aeskeygenassist xmm2, xmm3, 0x1     ; \r
+    call key_expansion256\r
+    aeskeygenassist xmm2, xmm3, 0x2     ; \r
+    call key_expansion256\r
+    aeskeygenassist xmm2, xmm3, 0x4     ; \r
+    call key_expansion256\r
+    aeskeygenassist xmm2, xmm3, 0x8     ; \r
+    call key_expansion256\r
+    aeskeygenassist xmm2, xmm3, 0x10    ; \r
+    call key_expansion256\r
+    aeskeygenassist xmm2, xmm3, 0x20    ; \r
+    call key_expansion256\r
+    aeskeygenassist xmm2, xmm3, 0x40    ; \r
+;    call key_expansion256 \r
+\r
+    pshufd xmm2, xmm2, 011111111b\r
+\r
+    movdqa xmm4, xmm1\r
+    pshufb xmm4, xmm5\r
+    pxor xmm1, xmm4\r
+    pshufb xmm4, xmm5\r
+    pxor xmm1, xmm4\r
+    pshufb xmm4, xmm5\r
+    pxor xmm1, xmm4\r
+    pxor xmm1, xmm2\r
+\r
+    movdqu [rdx], xmm1\r
+\r
+\r
+       ret \r
+       \r
+       \r
+       \r
+\r
+\r
+\r
+align 16\r
+global iDec128\r
+iDec128:\r
+\r
+       linux_setup\r
+       sub rsp,16*16+8\r
+\r
+\r
+       mov eax,[rcx+32] ; numblocks\r
+       mov rdx,[rcx]\r
+       mov r8,[rcx+8]\r
+       mov rcx,[rcx+16]\r
+       \r
+       sub r8,rdx\r
+\r
+       test eax,eax\r
+       jz end_dec128\r
+\r
+       cmp eax,4\r
+       jl      lp128decsingle\r
+\r
+       test    rcx,0xf\r
+       jz              lp128decfour\r
+       \r
+       copy_round_keys rsp,rcx,0\r
+       copy_round_keys rsp,rcx,1\r
+       copy_round_keys rsp,rcx,2\r
+       copy_round_keys rsp,rcx,3\r
+       copy_round_keys rsp,rcx,4\r
+       copy_round_keys rsp,rcx,5\r
+       copy_round_keys rsp,rcx,6\r
+       copy_round_keys rsp,rcx,7\r
+       copy_round_keys rsp,rcx,8\r
+       copy_round_keys rsp,rcx,9\r
+       copy_round_keys rsp,rcx,10\r
+       mov rcx,rsp     \r
+       \r
+       \r
+\r
+align 16\r
+lp128decfour:\r
+       \r
+       test eax,eax\r
+       jz end_dec128\r
+\r
+       cmp eax,4\r
+       jl      lp128decsingle\r
+\r
+       load_and_xor4 rdx, [rcx+10*16]\r
+       add rdx,16*4\r
+       aesdec4 [rcx+9*16]\r
+       aesdec4 [rcx+8*16]\r
+       aesdec4 [rcx+7*16]\r
+       aesdec4 [rcx+6*16]\r
+       aesdec4 [rcx+5*16]\r
+       aesdec4 [rcx+4*16]\r
+       aesdec4 [rcx+3*16]\r
+       aesdec4 [rcx+2*16]\r
+       aesdec4 [rcx+1*16]\r
+       aesdeclast4 [rcx+0*16]\r
+       \r
+       sub eax,4\r
+       store4 r8+rdx-(16*4)\r
+       jmp lp128decfour\r
+\r
+\r
+       align 16\r
+lp128decsingle:\r
+\r
+       movdqu xmm0, [rdx]\r
+       movdqu xmm4,[rcx+10*16]\r
+       pxor xmm0, xmm4\r
+       aesdec1_u [rcx+9*16]\r
+       aesdec1_u [rcx+8*16]\r
+       aesdec1_u [rcx+7*16]\r
+       aesdec1_u [rcx+6*16]\r
+       aesdec1_u [rcx+5*16]\r
+       aesdec1_u [rcx+4*16]\r
+       aesdec1_u [rcx+3*16]\r
+       aesdec1_u [rcx+2*16]\r
+       aesdec1_u [rcx+1*16]\r
+       aesdeclast1_u [rcx+0*16]\r
+\r
+       add rdx, 16\r
+       movdqu  [r8 + rdx - 16], xmm0\r
+       dec eax\r
+       jnz lp128decsingle\r
+\r
+end_dec128:\r
+\r
+       add rsp,16*16+8\r
+       ret\r
+\r
+\r
+align 16\r
+global iDec128_CBC\r
+iDec128_CBC:\r
+       \r
+       linux_setup\r
+       sub rsp,16*16+8\r
+\r
+       mov r9,rcx\r
+       mov rax,[rcx+24]\r
+       movdqu  xmm5,[rax]\r
+       \r
+       mov eax,[rcx+32] ; numblocks\r
+       mov rdx,[rcx]\r
+       mov r8,[rcx+8]\r
+       mov rcx,[rcx+16]\r
+       \r
+       \r
+       sub r8,rdx\r
+\r
+\r
+       test eax,eax\r
+       jz end_dec128_CBC\r
+\r
+       cmp eax,4\r
+       jl      lp128decsingle_CBC\r
+\r
+       test    rcx,0xf\r
+       jz              lp128decfour_CBC\r
+       \r
+       copy_round_keys rsp,rcx,0\r
+       copy_round_keys rsp,rcx,1\r
+       copy_round_keys rsp,rcx,2\r
+       copy_round_keys rsp,rcx,3\r
+       copy_round_keys rsp,rcx,4\r
+       copy_round_keys rsp,rcx,5\r
+       copy_round_keys rsp,rcx,6\r
+       copy_round_keys rsp,rcx,7\r
+       copy_round_keys rsp,rcx,8\r
+       copy_round_keys rsp,rcx,9\r
+       copy_round_keys rsp,rcx,10\r
+       mov rcx,rsp     \r
+\r
+\r
+align 16\r
+lp128decfour_CBC:\r
+       \r
+       test eax,eax\r
+       jz end_dec128_CBC\r
+\r
+       cmp eax,4\r
+       jl      lp128decsingle_CBC\r
+\r
+       load_and_xor4 rdx, [rcx+10*16]\r
+       add rdx,16*4\r
+       aesdec4 [rcx+9*16]\r
+       aesdec4 [rcx+8*16]\r
+       aesdec4 [rcx+7*16]\r
+       aesdec4 [rcx+6*16]\r
+       aesdec4 [rcx+5*16]\r
+       aesdec4 [rcx+4*16]\r
+       aesdec4 [rcx+3*16]\r
+       aesdec4 [rcx+2*16]\r
+       aesdec4 [rcx+1*16]\r
+       aesdeclast4 [rcx+0*16]\r
+\r
+       pxor    xmm0,xmm5\r
+       movdqu  xmm4,[rdx - 16*4 + 0*16]\r
+       pxor    xmm1,xmm4\r
+       movdqu  xmm4,[rdx - 16*4 + 1*16]\r
+       pxor    xmm2,xmm4\r
+       movdqu  xmm4,[rdx - 16*4 + 2*16]\r
+       pxor    xmm3,xmm4\r
+       movdqu  xmm5,[rdx - 16*4 + 3*16]\r
+       \r
+       sub eax,4\r
+       store4 r8+rdx-(16*4)\r
+       jmp lp128decfour_CBC\r
+\r
+\r
+       align 16\r
+lp128decsingle_CBC:\r
+\r
+       movdqu xmm0, [rdx]\r
+       movdqa  xmm1,xmm0\r
+       movdqu xmm4,[rcx+10*16]\r
+       pxor xmm0, xmm4\r
+       aesdec1_u [rcx+9*16]\r
+       aesdec1_u [rcx+8*16]\r
+       aesdec1_u [rcx+7*16]\r
+       aesdec1_u [rcx+6*16]\r
+       aesdec1_u [rcx+5*16]\r
+       aesdec1_u [rcx+4*16]\r
+       aesdec1_u [rcx+3*16]\r
+       aesdec1_u [rcx+2*16]\r
+       aesdec1_u [rcx+1*16]\r
+       aesdeclast1_u [rcx+0*16]\r
+\r
+       pxor    xmm0,xmm5\r
+       movdqa  xmm5,xmm1\r
+       add rdx, 16\r
+       movdqu  [r8 + rdx - 16], xmm0\r
+       dec eax\r
+       jnz lp128decsingle_CBC\r
+\r
+end_dec128_CBC:\r
+\r
+       mov        r9,[r9+24]\r
+       movdqu [r9],xmm5\r
+       add rsp,16*16+8\r
+       ret\r
+\r
+\r
+align 16\r
+global iDec192_CBC\r
+iDec192_CBC:\r
+\r
+       linux_setup\r
+       sub rsp,16*16+8\r
+\r
+       mov r9,rcx\r
+       mov rax,[rcx+24]\r
+       movdqu  xmm5,[rax]\r
+       \r
+       mov eax,[rcx+32] ; numblocks\r
+       mov rdx,[rcx]\r
+       mov r8,[rcx+8]\r
+       mov rcx,[rcx+16]\r
+       \r
+       \r
+       sub r8,rdx\r
+\r
+       test eax,eax\r
+       jz end_dec192_CBC\r
+\r
+       cmp eax,4\r
+       jl      lp192decsingle_CBC\r
+\r
+       test    rcx,0xf\r
+       jz              lp192decfour_CBC\r
+       \r
+       copy_round_keys rsp,rcx,0\r
+       copy_round_keys rsp,rcx,1\r
+       copy_round_keys rsp,rcx,2\r
+       copy_round_keys rsp,rcx,3\r
+       copy_round_keys rsp,rcx,4\r
+       copy_round_keys rsp,rcx,5\r
+       copy_round_keys rsp,rcx,6\r
+       copy_round_keys rsp,rcx,7\r
+       copy_round_keys rsp,rcx,8\r
+       copy_round_keys rsp,rcx,9\r
+       copy_round_keys rsp,rcx,10\r
+       copy_round_keys rsp,rcx,11\r
+       copy_round_keys rsp,rcx,12\r
+       mov rcx,rsp     \r
+\r
+\r
+align 16\r
+lp192decfour_CBC:\r
+       \r
+       test eax,eax\r
+       jz end_dec192_CBC\r
+\r
+       cmp eax,4\r
+       jl      lp192decsingle_CBC\r
+\r
+       load_and_xor4 rdx, [rcx+12*16]\r
+       add rdx,16*4\r
+       aesdec4 [rcx+11*16]\r
+       aesdec4 [rcx+10*16]\r
+       aesdec4 [rcx+9*16]\r
+       aesdec4 [rcx+8*16]\r
+       aesdec4 [rcx+7*16]\r
+       aesdec4 [rcx+6*16]\r
+       aesdec4 [rcx+5*16]\r
+       aesdec4 [rcx+4*16]\r
+       aesdec4 [rcx+3*16]\r
+       aesdec4 [rcx+2*16]\r
+       aesdec4 [rcx+1*16]\r
+       aesdeclast4 [rcx+0*16]\r
+\r
+       pxor    xmm0,xmm5\r
+       movdqu  xmm4,[rdx - 16*4 + 0*16]\r
+       pxor    xmm1,xmm4\r
+       movdqu  xmm4,[rdx - 16*4 + 1*16]\r
+       pxor    xmm2,xmm4\r
+       movdqu  xmm4,[rdx - 16*4 + 2*16]\r
+       pxor    xmm3,xmm4\r
+       movdqu  xmm5,[rdx - 16*4 + 3*16]\r
+       \r
+       sub eax,4\r
+       store4 r8+rdx-(16*4)\r
+       jmp lp192decfour_CBC\r
+\r
+\r
+       align 16\r
+lp192decsingle_CBC:\r
+\r
+       movdqu xmm0, [rdx]\r
+       movdqu xmm4,[rcx+12*16]\r
+       movdqa  xmm1,xmm0\r
+       pxor xmm0, xmm4\r
+       aesdec1_u [rcx+11*16]\r
+       aesdec1_u [rcx+10*16]\r
+       aesdec1_u [rcx+9*16]\r
+       aesdec1_u [rcx+8*16]\r
+       aesdec1_u [rcx+7*16]\r
+       aesdec1_u [rcx+6*16]\r
+       aesdec1_u [rcx+5*16]\r
+       aesdec1_u [rcx+4*16]\r
+       aesdec1_u [rcx+3*16]\r
+       aesdec1_u [rcx+2*16]\r
+       aesdec1_u [rcx+1*16]\r
+       aesdeclast1_u [rcx+0*16]\r
+\r
+       pxor    xmm0,xmm5\r
+       movdqa  xmm5,xmm1\r
+       add rdx, 16\r
+       movdqu  [r8 + rdx - 16], xmm0\r
+       dec eax\r
+       jnz lp192decsingle_CBC\r
+\r
+end_dec192_CBC:\r
+\r
+       mov        r9,[r9+24]\r
+       movdqu [r9],xmm5\r
+       add rsp,16*16+8\r
+       ret\r
+\r
+\r
+\r
+\r
+align 16\r
+global iDec256_CBC\r
+iDec256_CBC:\r
+\r
+       linux_setup\r
+       sub rsp,16*16+8\r
+\r
+       mov r9,rcx\r
+       mov rax,[rcx+24]\r
+       movdqu  xmm5,[rax]\r
+       \r
+       mov eax,[rcx+32] ; numblocks\r
+       mov rdx,[rcx]\r
+       mov r8,[rcx+8]\r
+       mov rcx,[rcx+16]\r
+       \r
+       \r
+       sub r8,rdx\r
+\r
+       test eax,eax\r
+       jz end_dec256_CBC\r
+\r
+       cmp eax,4\r
+       jl      lp256decsingle_CBC\r
+\r
+       test    rcx,0xf\r
+       jz              lp256decfour_CBC\r
+       \r
+       copy_round_keys rsp,rcx,0\r
+       copy_round_keys rsp,rcx,1\r
+       copy_round_keys rsp,rcx,2\r
+       copy_round_keys rsp,rcx,3\r
+       copy_round_keys rsp,rcx,4\r
+       copy_round_keys rsp,rcx,5\r
+       copy_round_keys rsp,rcx,6\r
+       copy_round_keys rsp,rcx,7\r
+       copy_round_keys rsp,rcx,8\r
+       copy_round_keys rsp,rcx,9\r
+       copy_round_keys rsp,rcx,10\r
+       copy_round_keys rsp,rcx,11\r
+       copy_round_keys rsp,rcx,12\r
+       copy_round_keys rsp,rcx,13\r
+       copy_round_keys rsp,rcx,14\r
+       mov rcx,rsp     \r
+\r
+align 16\r
+lp256decfour_CBC:\r
+       \r
+       test eax,eax\r
+       jz end_dec256_CBC\r
+\r
+       cmp eax,4\r
+       jl      lp256decsingle_CBC\r
+\r
+       load_and_xor4 rdx, [rcx+14*16]\r
+       add rdx,16*4\r
+       aesdec4 [rcx+13*16]\r
+       aesdec4 [rcx+12*16]\r
+       aesdec4 [rcx+11*16]\r
+       aesdec4 [rcx+10*16]\r
+       aesdec4 [rcx+9*16]\r
+       aesdec4 [rcx+8*16]\r
+       aesdec4 [rcx+7*16]\r
+       aesdec4 [rcx+6*16]\r
+       aesdec4 [rcx+5*16]\r
+       aesdec4 [rcx+4*16]\r
+       aesdec4 [rcx+3*16]\r
+       aesdec4 [rcx+2*16]\r
+       aesdec4 [rcx+1*16]\r
+       aesdeclast4 [rcx+0*16]\r
+\r
+       pxor    xmm0,xmm5\r
+       movdqu  xmm4,[rdx - 16*4 + 0*16]\r
+       pxor    xmm1,xmm4\r
+       movdqu  xmm4,[rdx - 16*4 + 1*16]\r
+       pxor    xmm2,xmm4\r
+       movdqu  xmm4,[rdx - 16*4 + 2*16]\r
+       pxor    xmm3,xmm4\r
+       movdqu  xmm5,[rdx - 16*4 + 3*16]\r
+       \r
+       sub eax,4\r
+       store4 r8+rdx-(16*4)\r
+       jmp lp256decfour_CBC\r
+\r
+\r
+       align 16\r
+lp256decsingle_CBC:\r
+\r
+       movdqu xmm0, [rdx]\r
+       movdqu xmm4,[rcx+14*16]\r
+       movdqa  xmm1,xmm0\r
+       pxor xmm0, xmm4\r
+       aesdec1_u [rcx+13*16]\r
+       aesdec1_u [rcx+12*16]\r
+       aesdec1_u [rcx+11*16]\r
+       aesdec1_u [rcx+10*16]\r
+       aesdec1_u [rcx+9*16]\r
+       aesdec1_u [rcx+8*16]\r
+       aesdec1_u [rcx+7*16]\r
+       aesdec1_u [rcx+6*16]\r
+       aesdec1_u [rcx+5*16]\r
+       aesdec1_u [rcx+4*16]\r
+       aesdec1_u [rcx+3*16]\r
+       aesdec1_u [rcx+2*16]\r
+       aesdec1_u [rcx+1*16]\r
+       aesdeclast1_u [rcx+0*16]\r
+\r
+       pxor    xmm0,xmm5\r
+       movdqa  xmm5,xmm1\r
+       add rdx, 16\r
+       movdqu  [r8 + rdx - 16], xmm0\r
+       dec eax\r
+       jnz lp256decsingle_CBC\r
+\r
+end_dec256_CBC:\r
+\r
+       mov        r9,[r9+24]\r
+       movdqu [r9],xmm5\r
+       add rsp,16*16+8\r
+       ret\r
+\r
+\r
+\r
+\r
+\r
+align 16\r
+global iDec192\r
+iDec192:\r
+\r
+       linux_setup\r
+       sub rsp,16*16+8\r
+\r
+       mov eax,[rcx+32] ; numblocks\r
+       mov rdx,[rcx]\r
+       mov r8,[rcx+8]\r
+       mov rcx,[rcx+16]\r
+       \r
+       sub r8,rdx\r
+       \r
+       test eax,eax\r
+       jz end_dec192\r
+\r
+       cmp eax,4\r
+       jl      lp192decsingle\r
+       \r
+       test    rcx,0xf\r
+       jz              lp192decfour\r
+       \r
+       copy_round_keys rsp,rcx,0\r
+       copy_round_keys rsp,rcx,1\r
+       copy_round_keys rsp,rcx,2\r
+       copy_round_keys rsp,rcx,3\r
+       copy_round_keys rsp,rcx,4\r
+       copy_round_keys rsp,rcx,5\r
+       copy_round_keys rsp,rcx,6\r
+       copy_round_keys rsp,rcx,7\r
+       copy_round_keys rsp,rcx,8\r
+       copy_round_keys rsp,rcx,9\r
+       copy_round_keys rsp,rcx,10\r
+       copy_round_keys rsp,rcx,11\r
+       copy_round_keys rsp,rcx,12\r
+       mov rcx,rsp     \r
+\r
+align 16\r
+lp192decfour:\r
+       \r
+       test eax,eax\r
+       jz end_dec192\r
+\r
+       cmp eax,4\r
+       jl      lp192decsingle\r
+\r
+       load_and_xor4 rdx, [rcx+12*16]\r
+       add rdx,16*4\r
+       aesdec4 [rcx+11*16]\r
+       aesdec4 [rcx+10*16]\r
+       aesdec4 [rcx+9*16]\r
+       aesdec4 [rcx+8*16]\r
+       aesdec4 [rcx+7*16]\r
+       aesdec4 [rcx+6*16]\r
+       aesdec4 [rcx+5*16]\r
+       aesdec4 [rcx+4*16]\r
+       aesdec4 [rcx+3*16]\r
+       aesdec4 [rcx+2*16]\r
+       aesdec4 [rcx+1*16]\r
+       aesdeclast4 [rcx+0*16]\r
+       \r
+       sub eax,4\r
+       store4 r8+rdx-(16*4)\r
+       jmp lp192decfour\r
+\r
+\r
+       align 16\r
+lp192decsingle:\r
+\r
+       movdqu xmm0, [rdx]\r
+       movdqu xmm4,[rcx+12*16]\r
+       pxor xmm0, xmm4\r
+       aesdec1_u [rcx+11*16]\r
+       aesdec1_u [rcx+10*16]\r
+       aesdec1_u [rcx+9*16]\r
+       aesdec1_u [rcx+8*16]\r
+       aesdec1_u [rcx+7*16]\r
+       aesdec1_u [rcx+6*16]\r
+       aesdec1_u [rcx+5*16]\r
+       aesdec1_u [rcx+4*16]\r
+       aesdec1_u [rcx+3*16]\r
+       aesdec1_u [rcx+2*16]\r
+       aesdec1_u [rcx+1*16]\r
+       aesdeclast1_u [rcx+0*16]\r
+\r
+       add rdx, 16\r
+       movdqu  [r8 + rdx - 16], xmm0\r
+       dec eax\r
+       jnz lp192decsingle\r
+\r
+end_dec192:\r
+\r
+       add rsp,16*16+8\r
+       ret\r
+\r
+\r
+\r
+\r
+align 16\r
+global iDec256\r
+iDec256:\r
+\r
+       linux_setup\r
+       sub rsp,16*16+8\r
+       \r
+       mov eax,[rcx+32] ; numblocks\r
+       mov rdx,[rcx]\r
+       mov r8,[rcx+8]\r
+       mov rcx,[rcx+16]\r
+       \r
+       sub r8,rdx\r
+\r
+\r
+       test eax,eax\r
+       jz end_dec256\r
+       \r
+       cmp eax,4\r
+       jl lp256dec\r
+\r
+       test    rcx,0xf\r
+       jz              lp256dec4\r
+       \r
+       copy_round_keys rsp,rcx,0\r
+       copy_round_keys rsp,rcx,1\r
+       copy_round_keys rsp,rcx,2\r
+       copy_round_keys rsp,rcx,3\r
+       copy_round_keys rsp,rcx,4\r
+       copy_round_keys rsp,rcx,5\r
+       copy_round_keys rsp,rcx,6\r
+       copy_round_keys rsp,rcx,7\r
+       copy_round_keys rsp,rcx,8\r
+       copy_round_keys rsp,rcx,9\r
+       copy_round_keys rsp,rcx,10\r
+       copy_round_keys rsp,rcx,11\r
+       copy_round_keys rsp,rcx,12\r
+       copy_round_keys rsp,rcx,13\r
+       copy_round_keys rsp,rcx,14\r
+       mov rcx,rsp     \r
+\r
+       \r
+       align 16\r
+lp256dec4:     \r
+       test eax,eax\r
+       jz end_dec256\r
+       \r
+       cmp eax,4\r
+       jl lp256dec\r
+       \r
+       load_and_xor4 rdx,[rcx+14*16]\r
+       add rdx, 4*16\r
+       aesdec4 [rcx+13*16]\r
+       aesdec4 [rcx+12*16]\r
+       aesdec4 [rcx+11*16]\r
+       aesdec4 [rcx+10*16]\r
+       aesdec4 [rcx+9*16]\r
+       aesdec4 [rcx+8*16]\r
+       aesdec4 [rcx+7*16]\r
+       aesdec4 [rcx+6*16]\r
+       aesdec4 [rcx+5*16]\r
+       aesdec4 [rcx+4*16]\r
+       aesdec4 [rcx+3*16]\r
+       aesdec4 [rcx+2*16]\r
+       aesdec4 [rcx+1*16]\r
+       aesdeclast4 [rcx+0*16]\r
+\r
+       store4 r8+rdx-16*4\r
+       sub eax,4\r
+       jmp lp256dec4   \r
+       \r
+       align 16\r
+lp256dec:\r
+\r
+       movdqu xmm0, [rdx]\r
+       movdqu xmm4,[rcx+14*16]\r
+       add rdx, 16\r
+       pxor xmm0, xmm4                    ; Round 0 (only xor)\r
+       aesdec1_u [rcx+13*16]\r
+       aesdec1_u [rcx+12*16]\r
+       aesdec1_u [rcx+11*16]\r
+       aesdec1_u [rcx+10*16]\r
+       aesdec1_u [rcx+9*16]\r
+       aesdec1_u [rcx+8*16]\r
+       aesdec1_u [rcx+7*16]\r
+       aesdec1_u [rcx+6*16]\r
+       aesdec1_u [rcx+5*16]\r
+       aesdec1_u [rcx+4*16]\r
+       aesdec1_u [rcx+3*16]\r
+       aesdec1_u [rcx+2*16]\r
+       aesdec1_u [rcx+1*16]\r
+       aesdeclast1_u [rcx+0*16]\r
+\r
+               ; Store output encrypted data into CIPHERTEXT array\r
+       movdqu  [r8+rdx-16], xmm0\r
+       dec eax\r
+       jnz lp256dec\r
+\r
+end_dec256:\r
+       \r
+       add rsp,16*16+8\r
+       ret\r
+\r
+\r
+\r
+\r
+\r
+\r
+align 16\r
+global iEnc128\r
+iEnc128:\r
+\r
+       linux_setup\r
+       sub rsp,16*16+8\r
+       \r
+       mov eax,[rcx+32] ; numblocks\r
+       mov rdx,[rcx]\r
+       mov r8,[rcx+8]\r
+       mov rcx,[rcx+16]\r
+       \r
+       sub r8,rdx\r
+\r
+\r
+       test eax,eax\r
+       jz end_enc128\r
+       \r
+       cmp eax,4\r
+       jl lp128encsingle\r
+\r
+       test    rcx,0xf\r
+       jz              lpenc128four\r
+       \r
+       copy_round_keys rsp,rcx,0\r
+       copy_round_keys rsp,rcx,1\r
+       copy_round_keys rsp,rcx,2\r
+       copy_round_keys rsp,rcx,3\r
+       copy_round_keys rsp,rcx,4\r
+       copy_round_keys rsp,rcx,5\r
+       copy_round_keys rsp,rcx,6\r
+       copy_round_keys rsp,rcx,7\r
+       copy_round_keys rsp,rcx,8\r
+       copy_round_keys rsp,rcx,9\r
+       copy_round_keys rsp,rcx,10\r
+       mov rcx,rsp     \r
+\r
+\r
+       align 16        \r
+       \r
+lpenc128four:\r
+       \r
+       test eax,eax\r
+       jz end_enc128\r
+       \r
+       cmp eax,4\r
+       jl lp128encsingle\r
+\r
+       load_and_xor4 rdx,[rcx+0*16]\r
+       add rdx,4*16\r
+       aesenc4 [rcx+1*16]\r
+       aesenc4 [rcx+2*16]\r
+       aesenc4 [rcx+3*16]\r
+       aesenc4 [rcx+4*16]\r
+       aesenc4 [rcx+5*16]\r
+       aesenc4 [rcx+6*16]\r
+       aesenc4 [rcx+7*16]\r
+       aesenc4 [rcx+8*16]\r
+       aesenc4 [rcx+9*16]\r
+       aesenclast4     [rcx+10*16]\r
+       \r
+       store4 r8+rdx-16*4\r
+       sub eax,4\r
+       jmp lpenc128four\r
+       \r
+       align 16\r
+lp128encsingle:\r
+\r
+       movdqu xmm0, [rdx]\r
+       movdqu xmm4,[rcx+0*16]\r
+       add rdx, 16\r
+       pxor xmm0, xmm4\r
+       aesenc1_u [rcx+1*16]\r
+       aesenc1_u [rcx+2*16]\r
+       aesenc1_u [rcx+3*16]\r
+       aesenc1_u [rcx+4*16]     \r
+       aesenc1_u [rcx+5*16]\r
+       aesenc1_u [rcx+6*16]\r
+       aesenc1_u [rcx+7*16]\r
+       aesenc1_u [rcx+8*16]\r
+       aesenc1_u [rcx+9*16]\r
+       aesenclast1_u [rcx+10*16]\r
+\r
+               ; Store output encrypted data into CIPHERTEXT array\r
+       movdqu  [r8+rdx-16], xmm0\r
+       dec eax\r
+       jnz lp128encsingle\r
+\r
+end_enc128:\r
+\r
+       add rsp,16*16+8\r
+       ret\r
+\r
+\r
+align 16\r
+global iEnc128_CTR\r
+iEnc128_CTR:\r
+\r
+       linux_setup\r
+\r
+       mov r9,rcx\r
+       mov rax,[rcx+24]\r
+       movdqu xmm5,[rax]\r
+\r
+\r
+       sub rsp,16*16+8\r
+       \r
+       mov eax,[rcx+32] ; numblocks\r
+       mov rdx,[rcx]\r
+       mov r8,[rcx+8]\r
+       mov rcx,[rcx+16]\r
+       \r
+       sub r8,rdx\r
+\r
+\r
+       test eax,eax\r
+       jz end_encctr128\r
+       \r
+       cmp eax,4\r
+       jl lp128encctrsingle\r
+\r
+       test    rcx,0xf\r
+       jz              lpencctr128four\r
+       \r
+       copy_round_keys rsp,rcx,0\r
+       copy_round_keys rsp,rcx,1\r
+       copy_round_keys rsp,rcx,2\r
+       copy_round_keys rsp,rcx,3\r
+       copy_round_keys rsp,rcx,4\r
+       copy_round_keys rsp,rcx,5\r
+       copy_round_keys rsp,rcx,6\r
+       copy_round_keys rsp,rcx,7\r
+       copy_round_keys rsp,rcx,8\r
+       copy_round_keys rsp,rcx,9\r
+       copy_round_keys rsp,rcx,10\r
+       mov rcx,rsp     \r
+\r
+\r
+       align 16        \r
+       \r
+lpencctr128four:\r
+       \r
+       test eax,eax\r
+       jz end_encctr128\r
+       \r
+       cmp eax,4\r
+       jl lp128encctrsingle\r
+\r
+       load_and_inc4 [rcx+0*16]\r
+       add rdx,4*16\r
+       aesenc4 [rcx+1*16]\r
+       aesenc4 [rcx+2*16]\r
+       aesenc4 [rcx+3*16]\r
+       aesenc4 [rcx+4*16]\r
+       aesenc4 [rcx+5*16]\r
+       aesenc4 [rcx+6*16]\r
+       aesenc4 [rcx+7*16]\r
+       aesenc4 [rcx+8*16]\r
+       aesenc4 [rcx+9*16]\r
+       aesenclast4     [rcx+10*16]\r
+       xor_with_input4 rdx-(4*16)\r
+       \r
+       store4 r8+rdx-16*4\r
+       sub eax,4\r
+       jmp lpencctr128four\r
+       \r
+       align 16\r
+lp128encctrsingle:\r
+\r
+       movdqa xmm0,xmm5\r
+       paddq   xmm5,[counter_add_one wrt rip]\r
+       add rdx, 16\r
+       movdqu xmm4,[rcx+0*16]\r
+       pxor xmm0, xmm4\r
+       aesenc1_u [rcx+1*16]\r
+       aesenc1_u [rcx+2*16]\r
+       aesenc1_u [rcx+3*16]\r
+       aesenc1_u [rcx+4*16]     \r
+       aesenc1_u [rcx+5*16]\r
+       aesenc1_u [rcx+6*16]\r
+       aesenc1_u [rcx+7*16]\r
+       aesenc1_u [rcx+8*16]\r
+       aesenc1_u [rcx+9*16]\r
+       aesenclast1_u [rcx+10*16]\r
+       movdqu xmm4, [rdx-16]\r
+       pxor  xmm0,xmm4\r
+\r
+               ; Store output encrypted data into CIPHERTEXT array\r
+       movdqu  [r8+rdx-16], xmm0\r
+       dec eax\r
+       jnz lp128encctrsingle\r
+\r
+end_encctr128:\r
+\r
+       mov        r9,[r9+24]\r
+       movdqu [r9],xmm5\r
+       add rsp,16*16+8\r
+       ret\r
+\r
+\r
+\r
+align 16\r
+global iEnc192_CTR\r
+iEnc192_CTR:\r
+\r
+       linux_setup\r
+\r
+       mov r9,rcx\r
+       mov rax,[rcx+24]\r
+       movdqu xmm5,[rax]\r
+\r
+\r
+       sub rsp,16*16+8\r
+       \r
+       mov eax,[rcx+32] ; numblocks\r
+       mov rdx,[rcx]\r
+       mov r8,[rcx+8]\r
+       mov rcx,[rcx+16]\r
+       \r
+       sub r8,rdx\r
+\r
+\r
+       test eax,eax\r
+       jz end_encctr192\r
+       \r
+       cmp eax,4\r
+       jl lp192encctrsingle\r
+\r
+       test    rcx,0xf\r
+       jz              lpencctr192four\r
+       \r
+       copy_round_keys rsp,rcx,0\r
+       copy_round_keys rsp,rcx,1\r
+       copy_round_keys rsp,rcx,2\r
+       copy_round_keys rsp,rcx,3\r
+       copy_round_keys rsp,rcx,4\r
+       copy_round_keys rsp,rcx,5\r
+       copy_round_keys rsp,rcx,6\r
+       copy_round_keys rsp,rcx,7\r
+       copy_round_keys rsp,rcx,8\r
+       copy_round_keys rsp,rcx,9\r
+       copy_round_keys rsp,rcx,10\r
+       copy_round_keys rsp,rcx,11\r
+       copy_round_keys rsp,rcx,12\r
+       mov rcx,rsp     \r
+\r
+\r
+       align 16        \r
+       \r
+lpencctr192four:\r
+       \r
+       test eax,eax\r
+       jz end_encctr192\r
+       \r
+       cmp eax,4\r
+       jl lp192encctrsingle\r
+\r
+       load_and_inc4 [rcx+0*16]\r
+       add rdx,4*16\r
+       aesenc4 [rcx+1*16]\r
+       aesenc4 [rcx+2*16]\r
+       aesenc4 [rcx+3*16]\r
+       aesenc4 [rcx+4*16]\r
+       aesenc4 [rcx+5*16]\r
+       aesenc4 [rcx+6*16]\r
+       aesenc4 [rcx+7*16]\r
+       aesenc4 [rcx+8*16]\r
+       aesenc4 [rcx+9*16]\r
+       aesenc4 [rcx+10*16]\r
+       aesenc4 [rcx+11*16]\r
+       aesenclast4     [rcx+12*16]\r
+       xor_with_input4 rdx-(4*16)\r
+       \r
+       store4 r8+rdx-16*4\r
+       sub eax,4\r
+       jmp lpencctr192four\r
+       \r
+       align 16\r
+lp192encctrsingle:\r
+\r
+       movdqa xmm5,xmm0\r
+       movdqu xmm4,[rcx+0*16]\r
+       paddq   xmm5,[counter_add_one wrt rip]\r
+       add rdx, 16\r
+       pxor xmm0, xmm4\r
+       aesenc1_u [rcx+1*16]\r
+       aesenc1_u [rcx+2*16]\r
+       aesenc1_u [rcx+3*16]\r
+       aesenc1_u [rcx+4*16]     \r
+       aesenc1_u [rcx+5*16]\r
+       aesenc1_u [rcx+6*16]\r
+       aesenc1_u [rcx+7*16]\r
+       aesenc1_u [rcx+8*16]\r
+       aesenc1_u [rcx+9*16]\r
+       aesenc1_u [rcx+10*16]\r
+       aesenc1_u [rcx+11*16]\r
+       aesenclast1_u [rcx+12*16]\r
+       movdqu xmm4, [rdx]\r
+       pxor  xmm0,xmm4\r
+\r
+               ; Store output encrypted data into CIPHERTEXT array\r
+       movdqu  [r8+rdx-16], xmm0\r
+       dec eax\r
+       jnz lp192encctrsingle\r
+\r
+end_encctr192:\r
+\r
+       mov        r9,[r9+24]\r
+       movdqu [r9],xmm5\r
+       add rsp,16*16+8\r
+       ret\r
+\r
+\r
+align 16\r
+global iEnc256_CTR\r
+iEnc256_CTR:\r
+\r
+       linux_setup\r
+\r
+       mov r9,rcx\r
+       mov rax,[rcx+24]\r
+       movdqu xmm5,[rax]\r
+\r
+\r
+       sub rsp,16*16+8\r
+       \r
+       mov eax,[rcx+32] ; numblocks\r
+       mov rdx,[rcx]\r
+       mov r8,[rcx+8]\r
+       mov rcx,[rcx+16]\r
+       \r
+       sub r8,rdx\r
+\r
+\r
+       test eax,eax\r
+       jz end_encctr256\r
+       \r
+       cmp eax,4\r
+       jl lp256encctrsingle\r
+\r
+       test    rcx,0xf\r
+       jz              lpencctr256four\r
+       \r
+       copy_round_keys rsp,rcx,0\r
+       copy_round_keys rsp,rcx,1\r
+       copy_round_keys rsp,rcx,2\r
+       copy_round_keys rsp,rcx,3\r
+       copy_round_keys rsp,rcx,4\r
+       copy_round_keys rsp,rcx,5\r
+       copy_round_keys rsp,rcx,6\r
+       copy_round_keys rsp,rcx,7\r
+       copy_round_keys rsp,rcx,8\r
+       copy_round_keys rsp,rcx,9\r
+       copy_round_keys rsp,rcx,10\r
+       copy_round_keys rsp,rcx,11\r
+       copy_round_keys rsp,rcx,12\r
+       copy_round_keys rsp,rcx,13\r
+       copy_round_keys rsp,rcx,14\r
+       mov rcx,rsp     \r
+\r
+\r
+       align 16        \r
+       \r
+lpencctr256four:\r
+       \r
+       test eax,eax\r
+       jz end_encctr256\r
+       \r
+       cmp eax,4\r
+       jl lp256encctrsingle\r
+\r
+       load_and_inc4 [rcx+0*16]\r
+       add rdx,4*16\r
+       aesenc4 [rcx+1*16]\r
+       aesenc4 [rcx+2*16]\r
+       aesenc4 [rcx+3*16]\r
+       aesenc4 [rcx+4*16]\r
+       aesenc4 [rcx+5*16]\r
+       aesenc4 [rcx+6*16]\r
+       aesenc4 [rcx+7*16]\r
+       aesenc4 [rcx+8*16]\r
+       aesenc4 [rcx+9*16]\r
+       aesenc4 [rcx+10*16]\r
+       aesenc4 [rcx+11*16]\r
+       aesenc4 [rcx+12*16]\r
+       aesenc4 [rcx+13*16]\r
+       aesenclast4     [rcx+14*16]\r
+       xor_with_input4 rdx-(4*16)\r
+       \r
+       store4 r8+rdx-16*4\r
+       sub eax,4\r
+       jmp lpencctr256four\r
+       \r
+       align 16\r
+lp256encctrsingle:\r
+\r
+       movdqa xmm5,xmm0\r
+       movdqu xmm4,[rcx+0*16]\r
+       paddq   xmm5,[counter_add_one wrt rip]\r
+       add rdx, 16\r
+       pxor xmm0, xmm4\r
+       aesenc1_u [rcx+1*16]\r
+       aesenc1_u [rcx+2*16]\r
+       aesenc1_u [rcx+3*16]\r
+       aesenc1_u [rcx+4*16]     \r
+       aesenc1_u [rcx+5*16]\r
+       aesenc1_u [rcx+6*16]\r
+       aesenc1_u [rcx+7*16]\r
+       aesenc1_u [rcx+8*16]\r
+       aesenc1_u [rcx+9*16]\r
+       aesenc1_u [rcx+10*16]\r
+       aesenc1_u [rcx+11*16]\r
+       aesenc1_u [rcx+12*16]\r
+       aesenc1_u [rcx+13*16]\r
+       aesenclast1_u [rcx+14*16]\r
+       movdqu xmm4, [rdx]\r
+       pxor  xmm0,xmm4\r
+\r
+               ; Store output encrypted data into CIPHERTEXT array\r
+       movdqu  [r8+rdx-16], xmm0\r
+       dec eax\r
+       jnz lp256encctrsingle\r
+\r
+end_encctr256:\r
+\r
+       mov        r9,[r9+24]\r
+       movdqu [r9],xmm5\r
+       add rsp,16*16+8\r
+       ret\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+align 16\r
+global iEnc128_CBC\r
+iEnc128_CBC:\r
+\r
+       linux_setup\r
+       sub rsp,16*16+8\r
+       \r
+       mov r9,rcx\r
+       mov rax,[rcx+24]\r
+       movdqu xmm1,[rax]\r
+       \r
+       mov eax,[rcx+32] ; numblocks\r
+       mov rdx,[rcx]\r
+       mov r8,[rcx+8]\r
+       mov rcx,[rcx+16]\r
+       \r
+       sub r8,rdx\r
+\r
+\r
+       test    rcx,0xf\r
+       jz              lp128encsingle_CBC\r
+       \r
+       copy_round_keys rsp,rcx,0\r
+       copy_round_keys rsp,rcx,1\r
+       copy_round_keys rsp,rcx,2\r
+       copy_round_keys rsp,rcx,3\r
+       copy_round_keys rsp,rcx,4\r
+       copy_round_keys rsp,rcx,5\r
+       copy_round_keys rsp,rcx,6\r
+       copy_round_keys rsp,rcx,7\r
+       copy_round_keys rsp,rcx,8\r
+       copy_round_keys rsp,rcx,9\r
+       copy_round_keys rsp,rcx,10\r
+       mov rcx,rsp     \r
+\r
+\r
+       align 16        \r
+       \r
+lp128encsingle_CBC:\r
+\r
+       movdqu xmm0, [rdx]\r
+       movdqu xmm4,[rcx+0*16]\r
+       add rdx, 16\r
+       pxor xmm0, xmm1\r
+       pxor xmm0, xmm4\r
+       aesenc1 [rcx+1*16]\r
+       aesenc1 [rcx+2*16]\r
+       aesenc1 [rcx+3*16]\r
+       aesenc1 [rcx+4*16]     \r
+       aesenc1 [rcx+5*16]\r
+       aesenc1 [rcx+6*16]\r
+       aesenc1 [rcx+7*16]\r
+       aesenc1 [rcx+8*16]\r
+       aesenc1 [rcx+9*16]\r
+       aesenclast1 [rcx+10*16]\r
+       movdqa xmm1,xmm0\r
+\r
+               ; Store output encrypted data into CIPHERTEXT array\r
+       movdqu  [r8+rdx-16], xmm0\r
+       dec eax\r
+       jnz lp128encsingle_CBC\r
+\r
+       mov        r9,[r9+24]\r
+       movdqu [r9],xmm1\r
+       add rsp,16*16+8\r
+       ret\r
+\r
+\r
+align 16\r
+global iEnc192_CBC\r
+iEnc192_CBC:\r
+\r
+       linux_setup\r
+       sub rsp,16*16+8\r
+       mov r9,rcx\r
+       mov rax,[rcx+24]\r
+       movdqu xmm1,[rax]\r
+       \r
+       mov eax,[rcx+32] ; numblocks\r
+       mov rdx,[rcx]\r
+       mov r8,[rcx+8]\r
+       mov rcx,[rcx+16]\r
+       \r
+       sub r8,rdx\r
+\r
+       test    rcx,0xf\r
+       jz              lp192encsingle_CBC\r
+       \r
+       copy_round_keys rsp,rcx,0\r
+       copy_round_keys rsp,rcx,1\r
+       copy_round_keys rsp,rcx,2\r
+       copy_round_keys rsp,rcx,3\r
+       copy_round_keys rsp,rcx,4\r
+       copy_round_keys rsp,rcx,5\r
+       copy_round_keys rsp,rcx,6\r
+       copy_round_keys rsp,rcx,7\r
+       copy_round_keys rsp,rcx,8\r
+       copy_round_keys rsp,rcx,9\r
+       copy_round_keys rsp,rcx,10\r
+       copy_round_keys rsp,rcx,11\r
+       copy_round_keys rsp,rcx,12\r
+       mov rcx,rsp     \r
+\r
+\r
+\r
+       align 16        \r
+       \r
+lp192encsingle_CBC:\r
+\r
+       movdqu xmm0, [rdx]\r
+       movdqu xmm4, [rcx+0*16]\r
+       add rdx, 16\r
+       pxor xmm0, xmm1\r
+       pxor xmm0, xmm4\r
+       aesenc1 [rcx+1*16]\r
+       aesenc1 [rcx+2*16]\r
+       aesenc1 [rcx+3*16]\r
+       aesenc1 [rcx+4*16]     \r
+       aesenc1 [rcx+5*16]\r
+       aesenc1 [rcx+6*16]\r
+       aesenc1 [rcx+7*16]\r
+       aesenc1 [rcx+8*16]\r
+       aesenc1 [rcx+9*16]\r
+       aesenc1 [rcx+10*16]\r
+       aesenc1 [rcx+11*16]\r
+       aesenclast1 [rcx+12*16]\r
+       movdqa xmm1,xmm0\r
+\r
+               ; Store output encrypted data into CIPHERTEXT array\r
+       movdqu  [r8+rdx-16], xmm0\r
+       dec eax\r
+       jnz lp192encsingle_CBC\r
+\r
+       mov        r9,[r9+24]\r
+       movdqu [r9],xmm1\r
+\r
+       add rsp,16*16+8\r
+       ret\r
+\r
+\r
+align 16\r
+global iEnc256_CBC\r
+iEnc256_CBC:\r
+\r
+       linux_setup\r
+       sub rsp,16*16+8\r
+       \r
+       mov r9,rcx\r
+       mov rax,[rcx+24]\r
+       movdqu xmm1,[rax]\r
+       \r
+       mov eax,[rcx+32] ; numblocks\r
+       mov rdx,[rcx]\r
+       mov r8,[rcx+8]\r
+       mov rcx,[rcx+16]\r
+       \r
+       sub r8,rdx\r
+\r
+       test    rcx,0xf\r
+       jz              lp256encsingle_CBC\r
+       \r
+       copy_round_keys rsp,rcx,0\r
+       copy_round_keys rsp,rcx,1\r
+       copy_round_keys rsp,rcx,2\r
+       copy_round_keys rsp,rcx,3\r
+       copy_round_keys rsp,rcx,4\r
+       copy_round_keys rsp,rcx,5\r
+       copy_round_keys rsp,rcx,6\r
+       copy_round_keys rsp,rcx,7\r
+       copy_round_keys rsp,rcx,8\r
+       copy_round_keys rsp,rcx,9\r
+       copy_round_keys rsp,rcx,10\r
+       copy_round_keys rsp,rcx,11\r
+       copy_round_keys rsp,rcx,12\r
+       copy_round_keys rsp,rcx,13\r
+       copy_round_keys rsp,rcx,14\r
+       mov rcx,rsp     \r
+\r
+       align 16        \r
+       \r
+lp256encsingle_CBC:\r
+\r
+       movdqu xmm0, [rdx]\r
+       movdqu xmm4, [rcx+0*16]\r
+       add rdx, 16\r
+       pxor xmm0, xmm1\r
+       pxor xmm0, xmm4\r
+       aesenc1 [rcx+1*16]\r
+       aesenc1 [rcx+2*16]\r
+       aesenc1 [rcx+3*16]\r
+       aesenc1 [rcx+4*16]     \r
+       aesenc1 [rcx+5*16]\r
+       aesenc1 [rcx+6*16]\r
+       aesenc1 [rcx+7*16]\r
+       aesenc1 [rcx+8*16]\r
+       aesenc1 [rcx+9*16]\r
+       aesenc1 [rcx+10*16]\r
+       aesenc1 [rcx+11*16]\r
+       aesenc1 [rcx+12*16]\r
+       aesenc1 [rcx+13*16]\r
+       aesenclast1 [rcx+14*16]\r
+       movdqa xmm1,xmm0\r
+\r
+               ; Store output encrypted data into CIPHERTEXT array\r
+       movdqu  [r8+rdx-16], xmm0\r
+       dec eax\r
+       jnz lp256encsingle_CBC\r
+\r
+       mov        r9,[r9+24]\r
+       movdqu [r9],xmm1\r
+       add rsp,16*16+8\r
+       ret\r
+\r
+\r
+\r
+\r
+align 16\r
+global iEnc192\r
+iEnc192:\r
+\r
+       linux_setup\r
+       sub rsp,16*16+8\r
+       \r
+       mov eax,[rcx+32] ; numblocks\r
+       mov rdx,[rcx]\r
+       mov r8,[rcx+8]\r
+       mov rcx,[rcx+16]\r
+       \r
+       sub r8,rdx\r
+\r
+       test eax,eax\r
+       jz end_enc192\r
+       \r
+       cmp eax,4\r
+       jl lp192encsingle\r
+\r
+       test    rcx,0xf\r
+       jz              lpenc192four\r
+       \r
+       copy_round_keys rsp,rcx,0\r
+       copy_round_keys rsp,rcx,1\r
+       copy_round_keys rsp,rcx,2\r
+       copy_round_keys rsp,rcx,3\r
+       copy_round_keys rsp,rcx,4\r
+       copy_round_keys rsp,rcx,5\r
+       copy_round_keys rsp,rcx,6\r
+       copy_round_keys rsp,rcx,7\r
+       copy_round_keys rsp,rcx,8\r
+       copy_round_keys rsp,rcx,9\r
+       copy_round_keys rsp,rcx,10\r
+       copy_round_keys rsp,rcx,11\r
+       copy_round_keys rsp,rcx,12\r
+       mov rcx,rsp     \r
+\r
+\r
+       align 16        \r
+       \r
+lpenc192four:\r
+       \r
+       test eax,eax\r
+       jz end_enc192\r
+       \r
+       cmp eax,4\r
+       jl lp192encsingle\r
+\r
+       load_and_xor4 rdx,[rcx+0*16]\r
+       add rdx,4*16\r
+       aesenc4 [rcx+1*16]\r
+       aesenc4 [rcx+2*16]\r
+       aesenc4 [rcx+3*16]\r
+       aesenc4 [rcx+4*16]\r
+       aesenc4 [rcx+5*16]\r
+       aesenc4 [rcx+6*16]\r
+       aesenc4 [rcx+7*16]\r
+       aesenc4 [rcx+8*16]\r
+       aesenc4 [rcx+9*16]\r
+       aesenc4 [rcx+10*16]\r
+       aesenc4 [rcx+11*16]\r
+       aesenclast4     [rcx+12*16]\r
+       \r
+       store4 r8+rdx-16*4\r
+       sub eax,4\r
+       jmp lpenc192four\r
+       \r
+       align 16\r
+lp192encsingle:\r
+\r
+       movdqu xmm0, [rdx]\r
+       movdqu xmm4, [rcx+0*16]\r
+       add rdx, 16\r
+       pxor xmm0, xmm4\r
+       aesenc1_u [rcx+1*16]\r
+       aesenc1_u [rcx+2*16]\r
+       aesenc1_u [rcx+3*16]\r
+       aesenc1_u [rcx+4*16]     \r
+       aesenc1_u [rcx+5*16]\r
+       aesenc1_u [rcx+6*16]\r
+       aesenc1_u [rcx+7*16]\r
+       aesenc1_u [rcx+8*16]\r
+       aesenc1_u [rcx+9*16]\r
+       aesenc1_u [rcx+10*16]\r
+       aesenc1_u [rcx+11*16]\r
+       aesenclast1_u [rcx+12*16]\r
+\r
+               ; Store output encrypted data into CIPHERTEXT array\r
+       movdqu  [r8+rdx-16], xmm0\r
+       dec eax\r
+       jnz lp192encsingle\r
+\r
+end_enc192:\r
+\r
+       add rsp,16*16+8\r
+       ret\r
+\r
+\r
+\r
+\r
+\r
+\r
+align 16\r
+global iEnc256\r
+iEnc256:\r
+\r
+       linux_setup\r
+       sub rsp,16*16+8\r
+       \r
+       mov eax,[rcx+32] ; numblocks\r
+       mov rdx,[rcx]\r
+       mov r8,[rcx+8]\r
+       mov rcx,[rcx+16]\r
+\r
+       sub r8,rdx      \r
+\r
+\r
+       test eax,eax\r
+       jz end_enc256\r
+\r
+       cmp eax,4\r
+       jl lp256enc\r
+\r
+       test    rcx,0xf\r
+       jz              lp256enc4\r
+       \r
+       copy_round_keys rsp,rcx,0\r
+       copy_round_keys rsp,rcx,1\r
+       copy_round_keys rsp,rcx,2\r
+       copy_round_keys rsp,rcx,3\r
+       copy_round_keys rsp,rcx,4\r
+       copy_round_keys rsp,rcx,5\r
+       copy_round_keys rsp,rcx,6\r
+       copy_round_keys rsp,rcx,7\r
+       copy_round_keys rsp,rcx,8\r
+       copy_round_keys rsp,rcx,9\r
+       copy_round_keys rsp,rcx,10\r
+       copy_round_keys rsp,rcx,11\r
+       copy_round_keys rsp,rcx,12\r
+       copy_round_keys rsp,rcx,13\r
+       copy_round_keys rsp,rcx,14\r
+       mov rcx,rsp     \r
+\r
+\r
+       align 16\r
+       \r
+lp256enc4:\r
+       test eax,eax\r
+       jz end_enc256\r
+\r
+       cmp eax,4\r
+       jl lp256enc\r
+\r
+\r
+       load_and_xor4 rdx,[rcx+0*16]\r
+       add rdx, 16*4\r
+       aesenc4 [rcx+1*16]\r
+       aesenc4 [rcx+2*16]\r
+       aesenc4 [rcx+3*16]\r
+       aesenc4 [rcx+4*16]\r
+       aesenc4 [rcx+5*16]\r
+       aesenc4 [rcx+6*16]\r
+       aesenc4 [rcx+7*16]\r
+       aesenc4 [rcx+8*16]\r
+       aesenc4 [rcx+9*16]\r
+       aesenc4 [rcx+10*16]\r
+       aesenc4 [rcx+11*16]\r
+       aesenc4 [rcx+12*16]\r
+       aesenc4 [rcx+13*16]\r
+       aesenclast4 [rcx+14*16]\r
+\r
+       store4  r8+rdx-16*4\r
+       sub eax,4\r
+       jmp lp256enc4\r
+       \r
+       align 16\r
+lp256enc:\r
+\r
+       movdqu xmm0, [rdx]\r
+       movdqu xmm4, [rcx+0*16]\r
+       add rdx, 16\r
+       pxor xmm0, xmm4\r
+       aesenc1_u [rcx+1*16]\r
+       aesenc1_u [rcx+2*16]\r
+       aesenc1_u [rcx+3*16]\r
+       aesenc1_u [rcx+4*16]\r
+       aesenc1_u [rcx+5*16]\r
+       aesenc1_u [rcx+6*16]\r
+       aesenc1_u [rcx+7*16]\r
+       aesenc1_u [rcx+8*16]\r
+       aesenc1_u [rcx+9*16]\r
+       aesenc1_u [rcx+10*16]\r
+       aesenc1_u [rcx+11*16]\r
+       aesenc1_u [rcx+12*16]\r
+       aesenc1_u [rcx+13*16]\r
+       aesenclast1_u [rcx+14*16]\r
+\r
+               ; Store output encrypted data into CIPHERTEXT array\r
+       movdqu  [r8+rdx-16], xmm0\r
+       dec eax\r
+       jnz lp256enc\r
+\r
+end_enc256:\r
+\r
+       add rsp,16*16+8\r
+       ret\r
diff --git a/lib/accelerated/intel/asm/x86_do_rdtsc.s b/lib/accelerated/intel/asm/x86_do_rdtsc.s
new file mode 100755 (executable)
index 0000000..ba4f410
--- /dev/null
@@ -0,0 +1,35 @@
+[bits 32]\r
+[CPU intelnop]\r
+\r
+; Copyright (c) 2010, Intel Corporation\r
+; All rights reserved.\r
+; \r
+; Redistribution and use in source and binary forms, with or without \r
+; modification, are permitted provided that the following conditions are met:\r
+; \r
+;     * Redistributions of source code must retain the above copyright notice, \r
+;       this list of conditions and the following disclaimer.\r
+;     * Redistributions in binary form must reproduce the above copyright notice, \r
+;       this list of conditions and the following disclaimer in the documentation \r
+;       and/or other materials provided with the distribution.\r
+;     * Neither the name of Intel Corporation nor the names of its contributors \r
+;       may be used to endorse or promote products derived from this software \r
+;       without specific prior written permission.\r
+; \r
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND \r
+; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED \r
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. \r
+; IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, \r
+; INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, \r
+; BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, \r
+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF \r
+; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE \r
+; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \r
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+\r
+align 16\r
+global _do_rdtsc\r
+_do_rdtsc:\r
+\r
+       rdtsc\r
+       ret\r
diff --git a/lib/accelerated/intel/asm/x86_iaesx86.s b/lib/accelerated/intel/asm/x86_iaesx86.s
new file mode 100755 (executable)
index 0000000..16fda3b
--- /dev/null
@@ -0,0 +1,2183 @@
+[bits 32]\r
+[CPU intelnop]\r
+\r
+; Copyright (c) 2010, Intel Corporation\r
+; All rights reserved.\r
+; \r
+; Redistribution and use in source and binary forms, with or without \r
+; modification, are permitted provided that the following conditions are met:\r
+; \r
+;     * Redistributions of source code must retain the above copyright notice, \r
+;       this list of conditions and the following disclaimer.\r
+;     * Redistributions in binary form must reproduce the above copyright notice, \r
+;       this list of conditions and the following disclaimer in the documentation \r
+;       and/or other materials provided with the distribution.\r
+;     * Neither the name of Intel Corporation nor the names of its contributors \r
+;       may be used to endorse or promote products derived from this software \r
+;       without specific prior written permission.\r
+; \r
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND \r
+; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED \r
+; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. \r
+; IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, \r
+; INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, \r
+; BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, \r
+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF \r
+; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE \r
+; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \r
+; ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+\r
+\r
+%macro inversekey 1\r
+       movdqu  xmm1,%1\r
+       aesimc  xmm0,xmm1\r
+       movdqu  %1,xmm0\r
+%endmacro\r
+\r
+\r
+%macro aesdec4 1\r
+       movdqa  xmm4,%1\r
+\r
+       aesdec  xmm0,xmm4\r
+       aesdec  xmm1,xmm4\r
+       aesdec  xmm2,xmm4\r
+       aesdec  xmm3,xmm4\r
+\r
+%endmacro\r
+\r
+\r
+%macro aesdeclast4 1\r
+       movdqa  xmm4,%1\r
+\r
+       aesdeclast      xmm0,xmm4\r
+       aesdeclast      xmm1,xmm4\r
+       aesdeclast      xmm2,xmm4\r
+       aesdeclast      xmm3,xmm4\r
+\r
+%endmacro\r
+\r
+\r
+%macro aesenc4 1\r
+       movdqa  xmm4,%1\r
+\r
+       aesenc  xmm0,xmm4\r
+       aesenc  xmm1,xmm4\r
+       aesenc  xmm2,xmm4\r
+       aesenc  xmm3,xmm4\r
+\r
+%endmacro\r
+\r
+%macro aesenclast4 1\r
+       movdqa  xmm4,%1\r
+\r
+       aesenclast      xmm0,xmm4\r
+       aesenclast      xmm1,xmm4\r
+       aesenclast      xmm2,xmm4\r
+       aesenclast      xmm3,xmm4\r
+\r
+%endmacro\r
+\r
+\r
+%macro aesdeclast1 1\r
+       aesdeclast      xmm0,%1\r
+%endmacro\r
+\r
+%macro aesenclast1 1\r
+       aesenclast      xmm0,%1\r
+%endmacro\r
+\r
+%macro aesdec1 1\r
+       aesdec  xmm0,%1\r
+%endmacro\r
+\r
+;abab\r
+%macro aesenc1 1\r
+       aesenc  xmm0,%1\r
+%endmacro\r
+\r
+\r
+%macro aesdeclast1_u 1\r
+       movdqu xmm4,%1\r
+       aesdeclast      xmm0,xmm4\r
+%endmacro\r
+\r
+%macro aesenclast1_u 1\r
+       movdqu xmm4,%1\r
+       aesenclast      xmm0,xmm4\r
+%endmacro\r
+\r
+%macro aesdec1_u 1\r
+       movdqu xmm4,%1\r
+       aesdec  xmm0,xmm4\r
+%endmacro\r
+\r
+%macro aesenc1_u 1\r
+       movdqu xmm4,%1\r
+       aesenc  xmm0,xmm4\r
+%endmacro\r
+\r
+\r
+%macro load_and_xor4 2\r
+       movdqa  xmm4,%2\r
+       movdqu  xmm0,[%1 + 0*16]\r
+       pxor    xmm0,xmm4\r
+       movdqu  xmm1,[%1 + 1*16]\r
+       pxor    xmm1,xmm4\r
+       movdqu  xmm2,[%1 + 2*16]\r
+       pxor    xmm2,xmm4\r
+       movdqu  xmm3,[%1 + 3*16]\r
+       pxor    xmm3,xmm4\r
+%endmacro\r
+\r
+\r
+%macro load_and_inc4 1\r
+       movdqa  xmm4,%1\r
+       movdqa  xmm0,xmm5\r
+       movdqa  xmm1,xmm5\r
+       paddq   xmm1,[counter_add_one]\r
+       movdqa  xmm2,xmm5\r
+       paddq   xmm2,[counter_add_two]\r
+       movdqa  xmm3,xmm5\r
+       paddq   xmm3,[counter_add_three]\r
+       pxor    xmm0,xmm4\r
+       paddq   xmm5,[counter_add_four]\r
+       pxor    xmm1,xmm4\r
+       pxor    xmm2,xmm4\r
+       pxor    xmm3,xmm4\r
+%endmacro\r
+\r
+%macro xor_with_input4 1\r
+       movdqu xmm4,[%1]\r
+       pxor xmm0,xmm4\r
+       movdqu xmm4,[%1+16]\r
+       pxor xmm1,xmm4\r
+       movdqu xmm4,[%1+32]\r
+       pxor xmm2,xmm4\r
+       movdqu xmm4,[%1+48]\r
+       pxor xmm3,xmm4\r
+%endmacro\r
+\r
+%macro store4 1\r
+       movdqu [%1 + 0*16],xmm0\r
+       movdqu [%1 + 1*16],xmm1\r
+       movdqu [%1 + 2*16],xmm2\r
+       movdqu [%1 + 3*16],xmm3\r
+%endmacro\r
+\r
+\r
+%macro copy_round_keys 3\r
+       movdqu xmm4,[%2 + ((%3)*16)]\r
+       movdqa [%1 + ((%3)*16)],xmm4\r
+%endmacro\r
+\r
+;abab\r
+%macro copy_round_keyx 3\r
+       movdqu xmm4,[%2 + ((%3)*16)]\r
+       movdqa %1,xmm4\r
+%endmacro\r
+\r
+\r
+\r
+%macro key_expansion_1_192 1\r
+               ;; Assumes the xmm3 includes all zeros at this point. \r
+        pshufd xmm2, xmm2, 11111111b        \r
+        shufps xmm3, xmm1, 00010000b        \r
+        pxor xmm1, xmm3        \r
+        shufps xmm3, xmm1, 10001100b\r
+        pxor xmm1, xmm3        \r
+               pxor xmm1, xmm2         \r
+               movdqu [edx+%1], xmm1                   \r
+%endmacro\r
+\r
+; Calculate w10 and w11 using calculated w9 and known w4-w5\r
+%macro key_expansion_2_192 1                           \r
+               movdqa xmm5, xmm4\r
+               pslldq xmm5, 4\r
+               shufps xmm6, xmm1, 11110000b\r
+               pxor xmm6, xmm5\r
+               pxor xmm4, xmm6\r
+               pshufd xmm7, xmm4, 00001110b \r
+               movdqu [edx+%1], xmm7\r
+%endmacro\r
+\r
+\r
+\r
+\r
+\r
+section .data\r
+align 16\r
+shuffle_mask:\r
+DD 0FFFFFFFFh\r
+DD 03020100h\r
+DD 07060504h\r
+DD 0B0A0908h\r
+\r
+align 16\r
+counter_add_one:\r
+DD 1\r
+DD 0\r
+DD 0\r
+DD 0\r
+\r
+counter_add_two:\r
+DD 2\r
+DD 0\r
+DD 0\r
+DD 0\r
+\r
+counter_add_three:\r
+DD 3\r
+DD 0\r
+DD 0\r
+DD 0\r
+\r
+counter_add_four:\r
+DD 4\r
+DD 0\r
+DD 0\r
+DD 0\r
+\r
+\r
+section .text\r
+\r
+\r
+\r
+align 16\r
+key_expansion256:\r
+\r
+    pshufd xmm2, xmm2, 011111111b\r
+\r
+    movdqu xmm4, xmm1\r
+    pshufb xmm4, xmm5\r
+    pxor xmm1, xmm4\r
+    pshufb xmm4, xmm5\r
+    pxor xmm1, xmm4\r
+    pshufb xmm4, xmm5\r
+    pxor xmm1, xmm4\r
+    pxor xmm1, xmm2\r
+\r
+    movdqu [edx], xmm1\r
+    add edx, 0x10\r
+    \r
+    aeskeygenassist xmm4, xmm1, 0\r
+    pshufd xmm2, xmm4, 010101010b\r
+\r
+    movdqu xmm4, xmm3\r
+    pshufb xmm4, xmm5\r
+    pxor xmm3, xmm4\r
+    pshufb xmm4, xmm5\r
+    pxor xmm3, xmm4\r
+    pshufb xmm4, xmm5\r
+    pxor xmm3, xmm4\r
+    pxor xmm3, xmm2\r
+\r
+    movdqu [edx], xmm3\r
+    add edx, 0x10\r
+\r
+    ret\r
+\r
+\r
+\r
+align 16\r
+key_expansion128: \r
+    pshufd xmm2, xmm2, 0xFF;\r
+    movdqu xmm3, xmm1\r
+    pshufb xmm3, xmm5\r
+    pxor xmm1, xmm3\r
+    pshufb xmm3, xmm5\r
+    pxor xmm1, xmm3\r
+    pshufb xmm3, xmm5\r
+    pxor xmm1, xmm3\r
+    pxor xmm1, xmm2\r
+\r
+    ; storing the result in the key schedule array\r
+    movdqu [edx], xmm1\r
+    add edx, 0x10                    \r
+    ret\r
+\r
+\r
+\r
+align 16\r
+global _iEncExpandKey128\r
+_iEncExpandKey128:\r
+\r
+       mov ecx,[esp-4+8]               ;input\r
+       mov edx,[esp-4+12]              ;ctx\r
+\r
+        movdqu xmm1, [ecx]    ; loading the key\r
+\r
+        movdqu [edx], xmm1\r
+\r
+        movdqa xmm5, [shuffle_mask]\r
+\r
+        add edx,16\r
+\r
+        aeskeygenassist xmm2, xmm1, 0x1     ; Generating round key 1\r
+        call key_expansion128\r
+        aeskeygenassist xmm2, xmm1, 0x2     ; Generating round key 2\r
+        call key_expansion128\r
+        aeskeygenassist xmm2, xmm1, 0x4     ; Generating round key 3\r
+        call key_expansion128\r
+        aeskeygenassist xmm2, xmm1, 0x8     ; Generating round key 4\r
+        call key_expansion128\r
+        aeskeygenassist xmm2, xmm1, 0x10    ; Generating round key 5\r
+        call key_expansion128\r
+        aeskeygenassist xmm2, xmm1, 0x20    ; Generating round key 6\r
+        call key_expansion128\r
+        aeskeygenassist xmm2, xmm1, 0x40    ; Generating round key 7\r
+        call key_expansion128\r
+        aeskeygenassist xmm2, xmm1, 0x80    ; Generating round key 8\r
+        call key_expansion128\r
+        aeskeygenassist xmm2, xmm1, 0x1b    ; Generating round key 9\r
+        call key_expansion128\r
+        aeskeygenassist xmm2, xmm1, 0x36    ; Generating round key 10\r
+        call key_expansion128\r
+\r
+       ret\r
+\r
+\r
+align 16\r
+global _iEncExpandKey192\r
+_iEncExpandKey192:\r
+\r
+       mov ecx,[esp-4+8]               ;input\r
+       mov edx,[esp-4+12]              ;ctx\r
+\r
+        movq xmm7, [ecx+16]    ; loading the AES key\r
+        movq [edx+16], xmm7  ; Storing key in memory where all key expansion \r
+        pshufd xmm4, xmm7, 01001111b\r
+        movdqu xmm1, [ecx]     ; loading the AES key\r
+        movdqu [edx], xmm1  ; Storing key in memory where all key expansion \r
+                       \r
+        pxor xmm3, xmm3                ; Set xmm3 to be all zeros. Required for the key_expansion. \r
+        pxor xmm6, xmm6                ; Set xmm3 to be all zeros. Required for the key_expansion. \r
+\r
+        aeskeygenassist xmm2, xmm4, 0x1     ; Complete round key 1 and generate round key 2 \r
+        key_expansion_1_192 24\r
+       key_expansion_2_192 40                          \r
+\r
+        aeskeygenassist xmm2, xmm4, 0x2     ; Generate round key 3 and part of round key 4\r
+        key_expansion_1_192 48\r
+       key_expansion_2_192 64                          \r
+\r
+        aeskeygenassist xmm2, xmm4, 0x4     ; Complete round key 4 and generate round key 5\r
+        key_expansion_1_192 72\r
+       key_expansion_2_192 88\r
+               \r
+        aeskeygenassist xmm2, xmm4, 0x8     ; Generate round key 6 and part of round key 7\r
+        key_expansion_1_192 96\r
+       key_expansion_2_192 112\r
+               \r
+        aeskeygenassist xmm2, xmm4, 0x10     ; Complete round key 7 and generate round key 8 \r
+        key_expansion_1_192 120\r
+       key_expansion_2_192 136                         \r
+\r
+        aeskeygenassist xmm2, xmm4, 0x20     ; Generate round key 9 and part of round key 10\r
+        key_expansion_1_192 144\r
+       key_expansion_2_192 160                         \r
+\r
+        aeskeygenassist xmm2, xmm4, 0x40     ; Complete round key 10 and generate round key 11\r
+        key_expansion_1_192 168\r
+       key_expansion_2_192 184                         \r
+\r
+        aeskeygenassist xmm2, xmm4, 0x80     ; Generate round key 12\r
+        key_expansion_1_192 192\r
+\r
+       ret\r
+\r
+\r
+\r
+\r
+\r
+\r
+align 16\r
+global _iDecExpandKey128\r
+_iDecExpandKey128:\r
+       push DWORD [esp+8]\r
+       push DWORD [esp+8]\r
+       \r
+       call _iEncExpandKey128\r
+       add esp,8\r
+\r
+       mov edx,[esp-4+12]              ;ctx\r
+       \r
+       inversekey      [edx + 1*16]\r
+       inversekey      [edx + 2*16]\r
+       inversekey      [edx + 3*16]\r
+       inversekey      [edx + 4*16]\r
+       inversekey      [edx + 5*16]\r
+       inversekey      [edx + 6*16]\r
+       inversekey      [edx + 7*16]\r
+       inversekey      [edx + 8*16]\r
+       inversekey      [edx + 9*16]\r
+\r
+       ret\r
+\r
+\r
+\r
+\r
+align 16\r
+global _iDecExpandKey192\r
+_iDecExpandKey192:\r
+       push DWORD [esp+8]\r
+       push DWORD [esp+8]\r
+       \r
+       call _iEncExpandKey192\r
+       add esp,8\r
+\r
+       mov edx,[esp-4+12]              ;ctx\r
+       \r
+       inversekey      [edx + 1*16]\r
+       inversekey      [edx + 2*16]\r
+       inversekey      [edx + 3*16]\r
+       inversekey      [edx + 4*16]\r
+       inversekey      [edx + 5*16]\r
+       inversekey      [edx + 6*16]\r
+       inversekey      [edx + 7*16]\r
+       inversekey      [edx + 8*16]\r
+       inversekey      [edx + 9*16]\r
+       inversekey      [edx + 10*16]\r
+       inversekey      [edx + 11*16]\r
+\r
+       ret\r
+\r
+\r
+\r
+\r
+align 16\r
+global _iDecExpandKey256\r
+_iDecExpandKey256:\r
+       push DWORD [esp+8]\r
+       push DWORD [esp+8]\r
+       \r
+       call _iEncExpandKey256\r
+       add esp, 8\r
+\r
+       mov edx, [esp-4+12]             ;expanded key\r
+       \r
+       inversekey      [edx + 1*16]\r
+       inversekey      [edx + 2*16]\r
+       inversekey      [edx + 3*16]\r
+       inversekey      [edx + 4*16]\r
+       inversekey      [edx + 5*16]\r
+       inversekey      [edx + 6*16]\r
+       inversekey      [edx + 7*16]\r
+       inversekey      [edx + 8*16]\r
+       inversekey      [edx + 9*16]\r
+       inversekey      [edx + 10*16]\r
+       inversekey      [edx + 11*16]\r
+       inversekey      [edx + 12*16]\r
+       inversekey      [edx + 13*16]\r
+\r
+       ret\r
+       \r
+\r
+       \r
+       \r
+align 16\r
+global _iEncExpandKey256\r
+_iEncExpandKey256:\r
+       mov ecx, [esp-4+8]              ;input\r
+       mov edx, [esp-4+12]             ;expanded key\r
+\r
+\r
+    movdqu xmm1, [ecx]    ; loading the key\r
+    movdqu xmm3, [ecx+16]\r
+    movdqu [edx], xmm1  ; Storing key in memory where all key schedule will be stored\r
+    movdqu [edx+16], xmm3 \r
+    \r
+    add edx,32\r
+\r
+    movdqa xmm5, [shuffle_mask]  ; this mask is used by key_expansion\r
+\r
+    aeskeygenassist xmm2, xmm3, 0x1     ; \r
+    call key_expansion256\r
+    aeskeygenassist xmm2, xmm3, 0x2     ; \r
+    call key_expansion256\r
+    aeskeygenassist xmm2, xmm3, 0x4     ; \r
+    call key_expansion256\r
+    aeskeygenassist xmm2, xmm3, 0x8     ; \r
+    call key_expansion256\r
+    aeskeygenassist xmm2, xmm3, 0x10    ; \r
+    call key_expansion256\r
+    aeskeygenassist xmm2, xmm3, 0x20    ; \r
+    call key_expansion256\r
+    aeskeygenassist xmm2, xmm3, 0x40    ; \r
+;    call key_expansion256 \r
+\r
+    pshufd xmm2, xmm2, 011111111b\r
+\r
+    movdqu xmm4, xmm1\r
+    pshufb xmm4, xmm5\r
+    pxor xmm1, xmm4\r
+    pshufb xmm4, xmm5\r
+    pxor xmm1, xmm4\r
+    pshufb xmm4, xmm5\r
+    pxor xmm1, xmm4\r
+    pxor xmm1, xmm2\r
+\r
+    movdqu [edx], xmm1\r
+\r
+\r
+       ret\r
+       \r
+       \r
+       \r
+       \r
+       \r
+\r
+align 16\r
+global _iDec128\r
+_iDec128:\r
+       mov ecx,[esp-4+8]\r
+       \r
+       push esi\r
+       push edi\r
+       push ebp\r
+       mov ebp,esp\r
+       \r
+       sub esp,16*16\r
+       and esp,0xfffffff0\r
+       \r
+       mov eax,[ecx+16] ; numblocks\r
+       mov esi,[ecx]\r
+       mov edi,[ecx+4]\r
+       mov ecx,[ecx+8]\r
+\r
+       sub edi,esi\r
+       \r
+       test eax,eax\r
+       jz end_dec128\r
+\r
+       cmp eax,4\r
+       jl      lp128decsingle\r
+\r
+       test    ecx,0xf\r
+       jz              lp128decfour\r
+       \r
+       copy_round_keys esp,ecx,0\r
+       copy_round_keys esp,ecx,1\r
+       copy_round_keys esp,ecx,2\r
+       copy_round_keys esp,ecx,3\r
+       copy_round_keys esp,ecx,4\r
+       copy_round_keys esp,ecx,5\r
+       copy_round_keys esp,ecx,6\r
+       copy_round_keys esp,ecx,7\r
+       copy_round_keys esp,ecx,8\r
+       copy_round_keys esp,ecx,9\r
+       copy_round_keys esp,ecx,10\r
+       mov ecx,esp     \r
+       \r
+\r
+align 16\r
+lp128decfour:\r
+       \r
+       test eax,eax\r
+       jz end_dec128\r
+\r
+       cmp eax,4\r
+       jl      lp128decsingle\r
+\r
+       load_and_xor4 esi, [ecx+10*16]\r
+       add esi,16*4\r
+       aesdec4 [ecx+9*16]\r
+       aesdec4 [ecx+8*16]\r
+       aesdec4 [ecx+7*16]\r
+       aesdec4 [ecx+6*16]\r
+       aesdec4 [ecx+5*16]\r
+       aesdec4 [ecx+4*16]\r
+       aesdec4 [ecx+3*16]\r
+       aesdec4 [ecx+2*16]\r
+       aesdec4 [ecx+1*16]\r
+       aesdeclast4 [ecx+0*16]\r
+       \r
+       sub eax,4\r
+       store4 esi+edi-(16*4)\r
+       jmp lp128decfour\r
+\r
+\r
+       align 16\r
+lp128decsingle:\r
+\r
+       movdqu xmm0, [esi]\r
+       movdqu xmm4,[ecx+10*16]\r
+       pxor xmm0, xmm4\r
+       aesdec1_u  [ecx+9*16]\r
+       aesdec1_u  [ecx+8*16]\r
+       aesdec1_u  [ecx+7*16]\r
+       aesdec1_u  [ecx+6*16]\r
+       aesdec1_u  [ecx+5*16]\r
+       aesdec1_u  [ecx+4*16]\r
+       aesdec1_u  [ecx+3*16]\r
+       aesdec1_u  [ecx+2*16]\r
+       aesdec1_u  [ecx+1*16]\r
+       aesdeclast1_u [ecx+0*16]\r
+\r
+       add esi, 16\r
+       movdqu  [edi+esi - 16], xmm0\r
+       dec eax\r
+       jnz lp128decsingle\r
+\r
+end_dec128:\r
+\r
+       mov esp,ebp\r
+       pop ebp\r
+       pop edi\r
+       pop esi\r
+       \r
+       ret\r
+\r
+\r
+\r
+align 16\r
+global _iDec128_CBC\r
+_iDec128_CBC:\r
+       mov ecx,[esp-4+8]\r
+       \r
+       push esi\r
+       push edi\r
+       push ebp\r
+       mov ebp,esp\r
+       sub esp,16*16\r
+       and esp,0xfffffff0\r
+       \r
+       mov eax,[ecx+12]\r
+       movdqu xmm5,[eax]       ;iv\r
+       \r
+       mov eax,[ecx+16] ; numblocks\r
+       mov esi,[ecx]\r
+       mov edi,[ecx+4]\r
+       mov ecx,[ecx+8]\r
+       \r
+       sub edi,esi\r
+\r
+       test eax,eax\r
+       jz end_dec128_CBC\r
+\r
+       cmp eax,4\r
+       jl      lp128decsingle_CBC\r
+\r
+       test    ecx,0xf\r
+       jz              lp128decfour_CBC\r
+       \r
+       copy_round_keys esp,ecx,0\r
+       copy_round_keys esp,ecx,1\r
+       copy_round_keys esp,ecx,2\r
+       copy_round_keys esp,ecx,3\r
+       copy_round_keys esp,ecx,4\r
+       copy_round_keys esp,ecx,5\r
+       copy_round_keys esp,ecx,6\r
+       copy_round_keys esp,ecx,7\r
+       copy_round_keys esp,ecx,8\r
+       copy_round_keys esp,ecx,9\r
+       copy_round_keys esp,ecx,10\r
+       mov ecx,esp     \r
+\r
+\r
+align 16\r
+lp128decfour_CBC:\r
+       \r
+       test eax,eax\r
+       jz end_dec128_CBC\r
+\r
+       cmp eax,4\r
+       jl      lp128decsingle_CBC\r
+\r
+       load_and_xor4 esi, [ecx+10*16]\r
+       add esi,16*4\r
+       aesdec4 [ecx+9*16]\r
+       aesdec4 [ecx+8*16]\r
+       aesdec4 [ecx+7*16]\r
+       aesdec4 [ecx+6*16]\r
+       aesdec4 [ecx+5*16]\r
+       aesdec4 [ecx+4*16]\r
+       aesdec4 [ecx+3*16]\r
+       aesdec4 [ecx+2*16]\r
+       aesdec4 [ecx+1*16]\r
+       aesdeclast4 [ecx+0*16]\r
+       \r
+       pxor    xmm0,xmm5\r
+       movdqu  xmm4,[esi- 16*4 + 0*16]\r
+       pxor    xmm1,xmm4\r
+       movdqu  xmm4,[esi- 16*4 + 1*16]\r
+       pxor    xmm2,xmm4\r
+       movdqu  xmm4,[esi- 16*4 + 2*16]\r
+       pxor    xmm3,xmm4\r
+       movdqu  xmm5,[esi- 16*4 + 3*16]\r
+       \r
+       sub eax,4\r
+       store4 esi+edi-(16*4)\r
+       jmp lp128decfour_CBC\r
+\r
+\r
+       align 16\r
+lp128decsingle_CBC:\r
+\r
+       movdqu xmm0, [esi]\r
+       movdqa xmm1,xmm0\r
+       movdqu xmm4,[ecx+10*16]\r
+       pxor xmm0, xmm4\r
+       aesdec1_u  [ecx+9*16]\r
+       aesdec1_u  [ecx+8*16]\r
+       aesdec1_u  [ecx+7*16]\r
+       aesdec1_u  [ecx+6*16]\r
+       aesdec1_u  [ecx+5*16]\r
+       aesdec1_u  [ecx+4*16]\r
+       aesdec1_u  [ecx+3*16]\r
+       aesdec1_u  [ecx+2*16]\r
+       aesdec1_u  [ecx+1*16]\r
+       aesdeclast1_u [ecx+0*16]\r
+       \r
+       pxor    xmm0,xmm5\r
+       movdqa  xmm5,xmm1\r
+       \r
+       add esi, 16\r
+       movdqu  [edi+esi - 16], xmm0\r
+       dec eax\r
+       jnz lp128decsingle_CBC\r
+\r
+end_dec128_CBC:\r
+\r
+       mov esp,ebp\r
+       pop ebp\r
+       pop edi\r
+       pop esi\r
+\r
+       mov ecx,[esp-4+8]   ; first arg\r
+       mov ecx,[ecx+12]\r
+       movdqu  [ecx],xmm5 ; store last iv for chaining\r
+       \r
+       ret\r
+\r
+\r
+\r
+\r
+\r
+\r
+align 16\r
+global _iDec192\r
+_iDec192:\r
+       mov ecx,[esp-4+8]\r
+       \r
+       push esi\r
+       push edi\r
+       push ebp\r
+       mov ebp,esp\r
+       \r
+       sub esp,16*16\r
+       and esp,0xfffffff0\r
+       \r
+       mov eax,[ecx+16] ; numblocks\r
+       mov esi,[ecx]\r
+       mov edi,[ecx+4]\r
+       mov ecx,[ecx+8]\r
+       \r
+       sub edi,esi\r
+\r
+       test eax,eax\r
+       jz end_dec192\r
+\r
+       cmp eax,4\r
+       jl      lp192decsingle\r
+\r
+       test    ecx,0xf\r
+       jz              lp192decfour\r
+       \r
+       copy_round_keys esp,ecx,0\r
+       copy_round_keys esp,ecx,1\r
+       copy_round_keys esp,ecx,2\r
+       copy_round_keys esp,ecx,3\r
+       copy_round_keys esp,ecx,4\r
+       copy_round_keys esp,ecx,5\r
+       copy_round_keys esp,ecx,6\r
+       copy_round_keys esp,ecx,7\r
+       copy_round_keys esp,ecx,8\r
+       copy_round_keys esp,ecx,9\r
+       copy_round_keys esp,ecx,10\r
+       copy_round_keys esp,ecx,11\r
+       copy_round_keys esp,ecx,12\r
+       mov ecx,esp     \r
+\r
+\r
+align 16\r
+lp192decfour:\r
+       \r
+       test eax,eax\r
+       jz end_dec192\r
+\r
+       cmp eax,4\r
+       jl      lp192decsingle\r
+\r
+       load_and_xor4 esi, [ecx+12*16]\r
+       add esi,16*4\r
+       aesdec4 [ecx+11*16]\r
+       aesdec4 [ecx+10*16]\r
+       aesdec4 [ecx+9*16]\r
+       aesdec4 [ecx+8*16]\r
+       aesdec4 [ecx+7*16]\r
+       aesdec4 [ecx+6*16]\r
+       aesdec4 [ecx+5*16]\r
+       aesdec4 [ecx+4*16]\r
+       aesdec4 [ecx+3*16]\r
+       aesdec4 [ecx+2*16]\r
+       aesdec4 [ecx+1*16]\r
+       aesdeclast4 [ecx+0*16]\r
+       \r
+       sub eax,4\r
+       store4 esi+edi-(16*4)\r
+       jmp lp192decfour\r
+\r
+\r
+       align 16\r
+lp192decsingle:\r
+\r
+       movdqu xmm0, [esi]\r
+       movdqu xmm4,[ecx+12*16]\r
+       pxor xmm0, xmm4\r
+       aesdec1_u [ecx+11*16]\r
+       aesdec1_u  [ecx+10*16]\r
+       aesdec1_u  [ecx+9*16]\r
+       aesdec1_u  [ecx+8*16]\r
+       aesdec1_u  [ecx+7*16]\r
+       aesdec1_u  [ecx+6*16]\r
+       aesdec1_u  [ecx+5*16]\r
+       aesdec1_u  [ecx+4*16]\r
+       aesdec1_u  [ecx+3*16]\r
+       aesdec1_u  [ecx+2*16]\r
+       aesdec1_u  [ecx+1*16]\r
+       aesdeclast1_u  [ecx+0*16]\r
+\r
+       add esi, 16\r
+       movdqu  [edi+esi - 16], xmm0\r
+       dec eax\r
+       jnz lp192decsingle\r
+\r
+end_dec192:\r
+\r
+\r
+       mov esp,ebp\r
+       pop ebp\r
+       pop edi\r
+       pop esi\r
+       \r
+       ret\r
+\r
+\r
+align 16\r
+global _iDec192_CBC\r
+_iDec192_CBC:\r
+       mov ecx,[esp-4+8]\r
+       \r
+       push esi\r
+       push edi\r
+       push ebp\r
+       mov ebp,esp\r
+       \r
+       sub esp,16*16\r
+       and esp,0xfffffff0\r
+\r
+       mov eax,[ecx+12]\r
+       movdqu xmm5,[eax]       ;iv\r
+       \r
+       mov eax,[ecx+16] ; numblocks\r
+       mov esi,[ecx]\r
+       mov edi,[ecx+4]\r
+       mov ecx,[ecx+8]\r
+       \r
+       sub edi,esi\r
+\r
+       test eax,eax\r
+       jz end_dec192_CBC\r
+\r
+       cmp eax,4\r
+       jl      lp192decsingle_CBC\r
+\r
+       test    ecx,0xf\r
+       jz              lp192decfour_CBC\r
+       \r
+       copy_round_keys esp,ecx,0\r
+       copy_round_keys esp,ecx,1\r
+       copy_round_keys esp,ecx,2\r
+       copy_round_keys esp,ecx,3\r
+       copy_round_keys esp,ecx,4\r
+       copy_round_keys esp,ecx,5\r
+       copy_round_keys esp,ecx,6\r
+       copy_round_keys esp,ecx,7\r
+       copy_round_keys esp,ecx,8\r
+       copy_round_keys esp,ecx,9\r
+       copy_round_keys esp,ecx,10\r
+       copy_round_keys esp,ecx,11\r
+       copy_round_keys esp,ecx,12\r
+       mov ecx,esp     \r
+\r
+align 16\r
+lp192decfour_CBC:\r
+       \r
+       test eax,eax\r
+       jz end_dec192_CBC\r
+\r
+       cmp eax,4\r
+       jl      lp192decsingle_CBC\r
+\r
+       load_and_xor4 esi, [ecx+12*16]\r
+       add esi,16*4\r
+       aesdec4 [ecx+11*16]\r
+       aesdec4 [ecx+10*16]\r
+       aesdec4 [ecx+9*16]\r
+       aesdec4 [ecx+8*16]\r
+       aesdec4 [ecx+7*16]\r
+       aesdec4 [ecx+6*16]\r
+       aesdec4 [ecx+5*16]\r
+       aesdec4 [ecx+4*16]\r
+       aesdec4 [ecx+3*16]\r
+       aesdec4 [ecx+2*16]\r
+       aesdec4 [ecx+1*16]\r
+       aesdeclast4 [ecx+0*16]\r
+       \r
+       pxor    xmm0,xmm5\r
+       movdqu  xmm4,[esi- 16*4 + 0*16]\r
+       pxor    xmm1,xmm4\r
+       movdqu  xmm4,[esi- 16*4 + 1*16]\r
+       pxor    xmm2,xmm4\r
+       movdqu  xmm4,[esi- 16*4 + 2*16]\r
+       pxor    xmm3,xmm4\r
+       movdqu  xmm5,[esi- 16*4 + 3*16]\r
+       \r
+       sub eax,4\r
+       store4 esi+edi-(16*4)\r
+       jmp lp192decfour_CBC\r
+\r
+\r
+       align 16\r
+lp192decsingle_CBC:\r
+\r
+       movdqu xmm0, [esi]\r
+       movdqu xmm4,[ecx+12*16]\r
+       movdqa xmm1,xmm0\r
+       pxor xmm0, xmm4\r
+       aesdec1_u [ecx+11*16]\r
+       aesdec1_u [ecx+10*16]\r
+       aesdec1_u [ecx+9*16]\r
+       aesdec1_u [ecx+8*16]\r
+       aesdec1_u [ecx+7*16]\r
+       aesdec1_u [ecx+6*16]\r
+       aesdec1_u [ecx+5*16]\r
+       aesdec1_u [ecx+4*16]\r
+       aesdec1_u [ecx+3*16]\r
+       aesdec1_u [ecx+2*16]\r
+       aesdec1_u [ecx+1*16]\r
+       aesdeclast1_u [ecx+0*16]\r
+       \r
+       pxor    xmm0,xmm5\r
+       movdqa  xmm5,xmm1\r
+       \r
+       add esi, 16\r
+       movdqu  [edi+esi - 16], xmm0\r
+       dec eax\r
+       jnz lp192decsingle_CBC\r
+\r
+end_dec192_CBC:\r
+\r
+\r
+       mov esp,ebp\r
+       pop ebp\r
+       pop edi\r
+       pop esi\r
+\r
+       mov ecx,[esp-4+8]\r
+       mov ecx,[ecx+12]\r
+       movdqu  [ecx],xmm5 ; store last iv for chaining\r
+       \r
+       ret\r
+\r
+\r
+\r
+\r
+\r
+align 16\r
+global _iDec256\r
+_iDec256:\r
+       mov ecx, [esp-4+8]\r
+       \r
+       push esi\r
+       push edi\r
+       push ebp\r
+       mov ebp,esp\r
+       \r
+       sub esp,16*16\r
+       and esp,0xfffffff0\r
+\r
+       mov eax,[ecx+16] ; numblocks\r
+       mov esi,[ecx]\r
+       mov edi,[ecx+4]\r
+       mov ecx,[ecx+8]\r
+       \r
+       sub edi,esi\r
+\r
+\r
+       test eax,eax\r
+       jz end_dec256\r
+       \r
+       cmp eax,4\r
+       jl lp256dec\r
+\r
+       test    ecx,0xf\r
+       jz      lp256dec4\r
+       \r
+       copy_round_keys esp,ecx,0\r
+       copy_round_keys esp,ecx,1\r
+       copy_round_keys esp,ecx,2\r
+       copy_round_keys esp,ecx,3\r
+       copy_round_keys esp,ecx,4\r
+       copy_round_keys esp,ecx,5\r
+       copy_round_keys esp,ecx,6\r
+       copy_round_keys esp,ecx,7\r
+       copy_round_keys esp,ecx,8\r
+       copy_round_keys esp,ecx,9\r
+       copy_round_keys esp,ecx,10\r
+       copy_round_keys esp,ecx,11\r
+       copy_round_keys esp,ecx,12\r
+       copy_round_keys esp,ecx,13\r
+       copy_round_keys esp,ecx,14\r
+       mov ecx,esp     \r
+       \r
+       align 16\r
+lp256dec4:\r
+       test eax,eax\r
+       jz end_dec256\r
+       \r
+       cmp eax,4\r
+       jl lp256dec\r
+       \r
+       load_and_xor4 esi,[ecx+14*16]\r
+       add esi, 4*16\r
+       aesdec4 [ecx+13*16]\r
+       aesdec4 [ecx+12*16]\r
+       aesdec4 [ecx+11*16]\r
+       aesdec4 [ecx+10*16]\r
+       aesdec4 [ecx+9*16]\r
+       aesdec4 [ecx+8*16]\r
+       aesdec4 [ecx+7*16]\r
+       aesdec4 [ecx+6*16]\r
+       aesdec4 [ecx+5*16]\r
+       aesdec4 [ecx+4*16]\r
+       aesdec4 [ecx+3*16]\r
+       aesdec4 [ecx+2*16]\r
+       aesdec4 [ecx+1*16]\r
+       aesdeclast4 [ecx+0*16]\r
+\r
+       store4 esi+edi-16*4\r
+       sub eax,4\r
+       jmp lp256dec4   \r
+       \r
+       align 16\r
+lp256dec:\r
+\r
+       movdqu xmm0, [esi]\r
+       movdqu xmm4,[ecx+14*16]\r
+       add esi, 16\r
+       pxor xmm0, xmm4                     ; Round 0 (only xor)\r
+       aesdec1_u  [ecx+13*16]\r
+       aesdec1_u  [ecx+12*16]\r
+       aesdec1_u  [ecx+11*16]\r
+       aesdec1_u  [ecx+10*16]\r
+       aesdec1_u  [ecx+9*16]\r
+       aesdec1_u  [ecx+8*16]\r
+       aesdec1_u  [ecx+7*16]\r
+       aesdec1_u  [ecx+6*16]\r
+       aesdec1_u  [ecx+5*16]\r
+       aesdec1_u  [ecx+4*16]\r
+       aesdec1_u  [ecx+3*16]\r
+       aesdec1_u  [ecx+2*16]\r
+       aesdec1_u  [ecx+1*16]\r
+       aesdeclast1_u  [ecx+0*16]\r
+\r
+               ; Store output encrypted data into CIPHERTEXT array\r
+       movdqu  [esi+edi-16], xmm0\r
+       dec eax\r
+       jnz lp256dec\r
+\r
+end_dec256:\r
+\r
+\r
+       mov esp,ebp\r
+       pop ebp\r
+       pop edi\r
+       pop esi\r
+       \r
+       ret\r
+\r
+\r
+\r
+\r
+align 16\r
+global _iDec256_CBC\r
+_iDec256_CBC:\r
+       mov ecx,[esp-4+8]\r
+       \r
+       push esi\r
+       push edi\r
+       push ebp\r
+       mov ebp,esp\r
+       \r
+       sub esp,16*16\r
+       and esp,0xfffffff0\r
+\r
+       mov eax,[ecx+12]\r
+       movdqu xmm5,[eax]       ;iv\r
+       \r
+       mov eax,[ecx+16] ; numblocks\r
+       mov esi,[ecx]\r
+       mov edi,[ecx+4]\r
+       mov ecx,[ecx+8]\r
+       \r
+       sub edi,esi\r
+\r
+       test eax,eax\r
+       jz end_dec256_CBC\r
+\r
+       cmp eax,4\r
+       jl      lp256decsingle_CBC\r
+\r
+       test    ecx,0xf\r
+       jz      lp256decfour_CBC\r
+       \r
+       copy_round_keys esp,ecx,0\r
+       copy_round_keys esp,ecx,1\r
+       copy_round_keys esp,ecx,2\r
+       copy_round_keys esp,ecx,3\r
+       copy_round_keys esp,ecx,4\r
+       copy_round_keys esp,ecx,5\r
+       copy_round_keys esp,ecx,6\r
+       copy_round_keys esp,ecx,7\r
+       copy_round_keys esp,ecx,8\r
+       copy_round_keys esp,ecx,9\r
+       copy_round_keys esp,ecx,10\r
+       copy_round_keys esp,ecx,11\r
+       copy_round_keys esp,ecx,12\r
+       copy_round_keys esp,ecx,13\r
+       copy_round_keys esp,ecx,14\r
+       mov ecx,esp     \r
+\r
+align 16\r
+lp256decfour_CBC:\r
+       \r
+       test eax,eax\r
+       jz end_dec256_CBC\r
+\r
+       cmp eax,4\r
+       jl      lp256decsingle_CBC\r
+\r
+       load_and_xor4 esi, [ecx+14*16]\r
+       add esi,16*4\r
+       aesdec4 [ecx+13*16]\r
+       aesdec4 [ecx+12*16]\r
+       aesdec4 [ecx+11*16]\r
+       aesdec4 [ecx+10*16]\r
+       aesdec4 [ecx+9*16]\r
+       aesdec4 [ecx+8*16]\r
+       aesdec4 [ecx+7*16]\r
+       aesdec4 [ecx+6*16]\r
+       aesdec4 [ecx+5*16]\r
+       aesdec4 [ecx+4*16]\r
+       aesdec4 [ecx+3*16]\r
+       aesdec4 [ecx+2*16]\r
+       aesdec4 [ecx+1*16]\r
+       aesdeclast4 [ecx+0*16]\r
+       \r
+       pxor    xmm0,xmm5\r
+       movdqu  xmm4,[esi- 16*4 + 0*16]\r
+       pxor    xmm1,xmm4\r
+       movdqu  xmm4,[esi- 16*4 + 1*16]\r
+       pxor    xmm2,xmm4\r
+       movdqu  xmm4,[esi- 16*4 + 2*16]\r
+       pxor    xmm3,xmm4\r
+       movdqu  xmm5,[esi- 16*4 + 3*16]\r
+       \r
+       sub eax,4\r
+       store4 esi+edi-(16*4)\r
+       jmp lp256decfour_CBC\r
+\r
+\r
+       align 16\r
+lp256decsingle_CBC:\r
+\r
+       movdqu xmm0, [esi]\r
+       movdqa xmm1,xmm0\r
+       movdqu xmm4, [ecx+14*16]\r
+       pxor xmm0, xmm4\r
+       aesdec1_u  [ecx+13*16]\r
+       aesdec1_u  [ecx+12*16]\r
+       aesdec1_u  [ecx+11*16]\r
+       aesdec1_u  [ecx+10*16]\r
+       aesdec1_u  [ecx+9*16]\r
+       aesdec1_u  [ecx+8*16]\r
+       aesdec1_u  [ecx+7*16]\r
+       aesdec1_u  [ecx+6*16]\r
+       aesdec1_u  [ecx+5*16]\r
+       aesdec1_u  [ecx+4*16]\r
+       aesdec1_u  [ecx+3*16]\r
+       aesdec1_u  [ecx+2*16]\r
+       aesdec1_u  [ecx+1*16]\r
+       aesdeclast1_u  [ecx+0*16]\r
+       \r
+       pxor    xmm0,xmm5\r
+       movdqa  xmm5,xmm1\r
+       \r
+       add esi, 16\r
+       movdqu  [edi+esi - 16], xmm0\r
+       dec eax\r
+       jnz lp256decsingle_CBC\r
+\r
+end_dec256_CBC:\r
+\r
+\r
+       mov esp,ebp\r
+       pop ebp\r
+       pop edi\r
+       pop esi\r
+\r
+       mov ecx,[esp-4+8]  ; first arg\r
+       mov ecx,[ecx+12]\r
+       movdqu  [ecx],xmm5 ; store last iv for chaining\r
+       \r
+       ret\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+align 16\r
+global _iEnc128\r
+_iEnc128:\r
+       mov ecx,[esp-4+8]\r
+       \r
+       push esi\r
+       push edi\r
+       push ebp\r
+       mov ebp,esp\r
+       \r
+       sub esp,16*16\r
+       and esp,0xfffffff0\r
+\r
+       mov eax,[ecx+16] ; numblocks\r
+       mov esi,[ecx]\r
+       mov edi,[ecx+4]\r
+       mov ecx,[ecx+8]\r
+       \r
+       sub edi,esi\r
+\r
+       test eax,eax\r
+       jz end_enc128\r
+       \r
+       cmp eax,4\r
+       jl lp128encsingle\r
+\r
+       test    ecx,0xf\r
+       jz              lpenc128four\r
+       \r
+       copy_round_keys esp,ecx,0\r
+       copy_round_keys esp,ecx,1\r
+       copy_round_keys esp,ecx,2\r
+       copy_round_keys esp,ecx,3\r
+       copy_round_keys esp,ecx,4\r
+       copy_round_keys esp,ecx,5\r
+       copy_round_keys esp,ecx,6\r
+       copy_round_keys esp,ecx,7\r
+       copy_round_keys esp,ecx,8\r
+       copy_round_keys esp,ecx,9\r
+       copy_round_keys esp,ecx,10\r
+       mov ecx,esp     \r
+\r
+\r
+       align 16        \r
+       \r
+lpenc128four:\r
+       \r
+       test eax,eax\r
+       jz end_enc128\r
+       \r
+       cmp eax,4\r
+       jl lp128encsingle\r
+\r
+       load_and_xor4 esi,[ecx+0*16]\r
+       add esi,4*16\r
+       aesenc4 [ecx+1*16]\r
+       aesenc4 [ecx+2*16]\r
+       aesenc4 [ecx+3*16]\r
+       aesenc4 [ecx+4*16]\r
+       aesenc4 [ecx+5*16]\r
+       aesenc4 [ecx+6*16]\r
+       aesenc4 [ecx+7*16]\r
+       aesenc4 [ecx+8*16]\r
+       aesenc4 [ecx+9*16]\r
+       aesenclast4     [ecx+10*16]\r
+       \r
+       store4 esi+edi-16*4\r
+       sub eax,4\r
+       jmp lpenc128four\r
+       \r
+       align 16\r
+lp128encsingle:\r
+\r
+       movdqu xmm0, [esi]\r
+       add esi, 16\r
+       movdqu xmm4,[ecx+0*16]\r
+       pxor xmm0, xmm4\r
+       aesenc1_u  [ecx+1*16]\r
+       aesenc1_u  [ecx+2*16]\r
+       aesenc1_u  [ecx+3*16]\r
+       aesenc1_u  [ecx+4*16]     \r
+       aesenc1_u  [ecx+5*16]\r
+       aesenc1_u  [ecx+6*16]\r
+       aesenc1_u  [ecx+7*16]\r
+       aesenc1_u  [ecx+8*16]\r
+       aesenc1_u  [ecx+9*16]\r
+       aesenclast1_u  [ecx+10*16]\r
+               ; Store output encrypted data into CIPHERTEXT array\r
+       movdqu  [esi+edi-16], xmm0\r
+       dec eax\r
+       jnz lp128encsingle\r
+\r
+end_enc128:\r
+\r
+\r
+       mov esp,ebp\r
+       pop ebp\r
+       pop edi\r
+       pop esi\r
+       \r
+       ret\r
+\r
+\r
+align 16\r
+global _iEnc128_CTR\r
+_iEnc128_CTR:\r
+       mov ecx,[esp-4+8]\r
+       \r
+       push esi\r
+       push edi\r
+       push ebp\r
+       mov ebp,esp\r
+       \r
+       sub esp,16*16\r
+       and esp,0xfffffff0\r
+\r
+       mov     eax,[ecx+12]\r
+       movdqu xmm5,[eax]       ;initial counter\r
+\r
+       mov eax,[ecx+16] ; numblocks\r
+       mov esi,[ecx]\r
+       mov edi,[ecx+4]\r
+       mov ecx,[ecx+8]\r
+       \r
+       sub edi,esi\r
+\r
+       test eax,eax\r
+       jz end_encctr128\r
+       \r
+       cmp eax,4\r
+       jl lp128encctrsingle\r
+\r
+       test    ecx,0xf\r
+       jz              lpencctr128four\r
+       \r
+       copy_round_keys esp,ecx,0\r
+       copy_round_keys esp,ecx,1\r
+       copy_round_keys esp,ecx,2\r
+       copy_round_keys esp,ecx,3\r
+       copy_round_keys esp,ecx,4\r
+       copy_round_keys esp,ecx,5\r
+       copy_round_keys esp,ecx,6\r
+       copy_round_keys esp,ecx,7\r
+       copy_round_keys esp,ecx,8\r
+       copy_round_keys esp,ecx,9\r
+       copy_round_keys esp,ecx,10\r
+       mov ecx,esp     \r
+\r
+\r
+       align 16        \r
+       \r
+lpencctr128four:\r
+       \r
+       test eax,eax\r
+       jz end_encctr128\r
+       \r
+       cmp eax,4\r
+       jl lp128encsingle\r
+\r
+       load_and_inc4 [ecx+0*16]\r
+       add esi,4*16\r
+       aesenc4 [ecx+1*16]\r
+       aesenc4 [ecx+2*16]\r
+       aesenc4 [ecx+3*16]\r
+       aesenc4 [ecx+4*16]\r
+       aesenc4 [ecx+5*16]\r
+       aesenc4 [ecx+6*16]\r
+       aesenc4 [ecx+7*16]\r
+       aesenc4 [ecx+8*16]\r
+       aesenc4 [ecx+9*16]\r
+       aesenclast4     [ecx+10*16]\r
+       xor_with_input4 esi-(4*16)\r
+       \r
+       store4 esi+edi-16*4\r
+       sub eax,4\r
+       jmp lpencctr128four\r
+       \r
+       align 16\r
+lp128encctrsingle:\r
+\r
+       movdqa  xmm0,xmm5\r
+       paddq   xmm5,[counter_add_one]\r
+       add esi, 16\r
+       movdqu xmm4,[ecx+0*16]\r
+       pxor xmm0, xmm4\r
+       aesenc1_u [ecx+1*16]\r
+       aesenc1_u [ecx+2*16]\r
+       aesenc1_u [ecx+3*16]\r
+       aesenc1_u [ecx+4*16]     \r
+       aesenc1_u [ecx+5*16]\r
+       aesenc1_u [ecx+6*16]\r
+       aesenc1_u [ecx+7*16]\r
+       aesenc1_u [ecx+8*16]\r
+       aesenc1_u [ecx+9*16]\r
+       aesenclast1_u [ecx+10*16]\r
+       movdqu xmm4, [esi-16]\r
+       pxor    xmm0,xmm4\r
+               ; Store output encrypted data into CIPHERTEXT array\r
+       movdqu  [esi+edi-16], xmm0\r
+       dec eax\r
+       jnz lp128encctrsingle\r
+\r
+end_encctr128:\r
+\r
+       mov esp,ebp\r
+       pop ebp\r
+       pop edi\r
+       pop esi\r
+\r
+       mov ecx,[esp-4+8]  ; first arg\r
+       mov ecx,[ecx+12]\r
+       movdqu  [ecx],xmm5 ; store last counter for chaining\r
+       \r
+       ret\r
+\r
+\r
+align 16\r
+global _iEnc192_CTR\r
+_iEnc192_CTR:\r
+       mov ecx,[esp-4+8]\r
+       \r
+       push esi\r
+       push edi\r
+       push ebp\r
+       mov ebp,esp\r
+       \r
+       sub esp,16*16\r
+       and esp,0xfffffff0\r
+\r
+       mov     eax,[ecx+12]\r
+       movdqu xmm5,[eax]       ;initial counter\r
+\r
+       mov eax,[ecx+16] ; numblocks\r
+       mov esi,[ecx]\r
+       mov edi,[ecx+4]\r
+       mov ecx,[ecx+8]\r
+       \r
+       sub edi,esi\r
+\r
+       test eax,eax\r
+       jz end_encctr192\r
+       \r
+       cmp eax,4\r
+       jl lp192encctrsingle\r
+\r
+       test    ecx,0xf\r
+       jz              lpencctr128four\r
+       \r
+       copy_round_keys esp,ecx,0\r
+       copy_round_keys esp,ecx,1\r
+       copy_round_keys esp,ecx,2\r
+       copy_round_keys esp,ecx,3\r
+       copy_round_keys esp,ecx,4\r
+       copy_round_keys esp,ecx,5\r
+       copy_round_keys esp,ecx,6\r
+       copy_round_keys esp,ecx,7\r
+       copy_round_keys esp,ecx,8\r
+       copy_round_keys esp,ecx,9\r
+       copy_round_keys esp,ecx,10\r
+       copy_round_keys esp,ecx,11\r
+       copy_round_keys esp,ecx,12\r
+       mov ecx,esp     \r
+\r
+\r
+       align 16        \r
+       \r
+lpencctr192four:\r
+       \r
+       test eax,eax\r
+       jz end_encctr192\r
+       \r
+       cmp eax,4\r
+       jl lp192encsingle\r
+\r
+       load_and_inc4 [ecx+0*16]\r
+       add esi,4*16\r
+       aesenc4 [ecx+1*16]\r
+       aesenc4 [ecx+2*16]\r
+       aesenc4 [ecx+3*16]\r
+       aesenc4 [ecx+4*16]\r
+       aesenc4 [ecx+5*16]\r
+       aesenc4 [ecx+6*16]\r
+       aesenc4 [ecx+7*16]\r
+       aesenc4 [ecx+8*16]\r
+       aesenc4 [ecx+9*16]\r
+       aesenc4 [ecx+10*16]\r
+       aesenc4 [ecx+11*16]\r
+       aesenclast4     [ecx+12*16]\r
+       xor_with_input4 esi-(4*16)\r
+       \r
+       store4 esi+edi-16*4\r
+       sub eax,4\r
+       jmp lpencctr192four\r
+       \r
+       align 16\r
+lp192encctrsingle:\r
+\r
+       movdqa  xmm0,xmm5\r
+       paddq   xmm5,[counter_add_one]\r
+       add esi, 16\r
+       movdqu xmm4,[ecx+0*16]\r
+       pxor xmm0, xmm4\r
+       aesenc1_u  [ecx+1*16]\r
+       aesenc1_u  [ecx+2*16]\r
+       aesenc1_u  [ecx+3*16]\r
+       aesenc1_u  [ecx+4*16]     \r
+       aesenc1_u  [ecx+5*16]\r
+       aesenc1_u  [ecx+6*16]\r
+       aesenc1_u  [ecx+7*16]\r
+       aesenc1_u  [ecx+8*16]\r
+       aesenc1_u  [ecx+9*16]\r
+       aesenc1_u  [ecx+10*16]\r
+       aesenc1_u  [ecx+11*16]\r
+       aesenclast1_u  [ecx+12*16]\r
+       movdqu xmm4, [esi-16]\r
+       pxor    xmm0,xmm4\r
+               ; Store output encrypted data into CIPHERTEXT array\r
+       movdqu  [esi+edi-16], xmm0\r
+       dec eax\r
+       jnz lp192encctrsingle\r
+\r
+end_encctr192:\r
+\r
+       mov esp,ebp\r
+       pop ebp\r
+       pop edi\r
+       pop esi\r
+\r
+       mov ecx,[esp-4+8]  ; first arg\r
+       mov ecx,[ecx+12]\r
+       movdqu  [ecx],xmm5 ; store last counter for chaining\r
+       \r
+       ret\r
+\r
+\r
+align 16\r
+global _iEnc256_CTR\r
+_iEnc256_CTR:\r
+       mov ecx,[esp-4+8]\r
+       \r
+       push esi\r
+       push edi\r
+       push ebp\r
+       mov ebp,esp\r
+       \r
+       sub esp,16*16\r
+       and esp,0xfffffff0\r
+\r
+       mov     eax,[ecx+12]\r
+       movdqu xmm5,[eax]       ;initial counter\r
+\r
+       mov eax,[ecx+16] ; numblocks\r
+       mov esi,[ecx]\r
+       mov edi,[ecx+4]\r
+       mov ecx,[ecx+8]\r
+       \r
+       sub edi,esi\r
+\r
+       test eax,eax\r
+       jz end_encctr256\r
+       \r
+       cmp eax,4\r
+       jl lp256encctrsingle\r
+\r
+       test    ecx,0xf\r
+       jz              lpencctr128four\r
+       \r
+       copy_round_keys esp,ecx,0\r
+       copy_round_keys esp,ecx,1\r
+       copy_round_keys esp,ecx,2\r
+       copy_round_keys esp,ecx,3\r
+       copy_round_keys esp,ecx,4\r
+       copy_round_keys esp,ecx,5\r
+       copy_round_keys esp,ecx,6\r
+       copy_round_keys esp,ecx,7\r
+       copy_round_keys esp,ecx,8\r
+       copy_round_keys esp,ecx,9\r
+       copy_round_keys esp,ecx,10\r
+       copy_round_keys esp,ecx,11\r
+       copy_round_keys esp,ecx,12\r
+       copy_round_keys esp,ecx,13\r
+       copy_round_keys esp,ecx,14\r
+       mov ecx,esp     \r
+\r
+\r
+       align 16        \r
+       \r
+lpencctr256four:\r
+       \r
+       test eax,eax\r
+       jz end_encctr256\r
+       \r
+       cmp eax,4\r
+       jl lp256encctrsingle\r
+\r
+       load_and_inc4 [ecx+0*16]\r
+       add esi,4*16\r
+       aesenc4 [ecx+1*16]\r
+       aesenc4 [ecx+2*16]\r
+       aesenc4 [ecx+3*16]\r
+       aesenc4 [ecx+4*16]\r
+       aesenc4 [ecx+5*16]\r
+       aesenc4 [ecx+6*16]\r
+       aesenc4 [ecx+7*16]\r
+       aesenc4 [ecx+8*16]\r
+       aesenc4 [ecx+9*16]\r
+       aesenc4 [ecx+10*16]\r
+       aesenc4 [ecx+11*16]\r
+       aesenc4 [ecx+12*16]\r
+       aesenc4 [ecx+13*16]\r
+       aesenclast4     [ecx+14*16]\r
+       xor_with_input4 esi-(4*16)\r
+       \r
+       store4 esi+edi-16*4\r
+       sub eax,4\r
+       jmp lpencctr256four\r
+       \r
+       align 16\r
+       \r
+lp256encctrsingle:\r
+\r
+       movdqa  xmm0,xmm5\r
+       paddq   xmm5,[counter_add_one]\r
+       add esi, 16\r
+       movdqu xmm4,[ecx+0*16]\r
+       pxor xmm0, xmm4\r
+       aesenc1_u  [ecx+1*16]\r
+       aesenc1_u  [ecx+2*16]\r
+       aesenc1_u  [ecx+3*16]\r
+       aesenc1_u  [ecx+4*16]     \r
+       aesenc1_u  [ecx+5*16]\r
+       aesenc1_u  [ecx+6*16]\r
+       aesenc1_u  [ecx+7*16]\r
+       aesenc1_u  [ecx+8*16]\r
+       aesenc1_u  [ecx+9*16]\r
+       aesenc1_u  [ecx+10*16]\r
+       aesenc1_u  [ecx+11*16]\r
+       aesenc1_u  [ecx+12*16]\r
+       aesenc1_u  [ecx+13*16]\r
+       aesenclast1_u  [ecx+14*16]\r
+       movdqu xmm4, [esi-16]\r
+       pxor    xmm0,xmm4\r
+               ; Store output encrypted data into CIPHERTEXT array\r
+       movdqu  [esi+edi-16], xmm0\r
+       dec eax\r
+       jnz lp256encctrsingle\r
+\r
+end_encctr256:\r
+\r
+       mov esp,ebp\r
+       pop ebp\r
+       pop edi\r
+       pop esi\r
+\r
+       mov ecx,[esp-4+8]  ; first arg\r
+       mov ecx,[ecx+12]\r
+       movdqu  [ecx],xmm5 ; store last counter for chaining\r
+       \r
+       ret\r
+\r
+\r
+\r
+\r
+\r
+\r
+align 16\r
+global _iEnc128_CBC\r
+_iEnc128_CBC:\r
+       mov ecx,[esp-4+8]\r
+       \r
+       push esi\r
+       push edi\r
+       push ebp\r
+       mov ebp,esp\r
+       \r
+       sub esp,16*16\r
+       and esp,0xfffffff0\r
+\r
+       mov     eax,[ecx+12]\r
+       movdqu xmm1,[eax]       ;iv     \r
+       \r
+       mov eax,[ecx+16] ; numblocks\r
+       mov esi,[ecx]\r
+       mov edi,[ecx+4]\r
+       mov ecx,[ecx+8]\r
+       sub edi,esi\r
+\r
+       test    ecx,0xf\r
+       jz              lp128encsingle_CBC\r
+       \r
+       copy_round_keys esp,ecx,0\r
+       copy_round_keys esp,ecx,1\r
+       copy_round_keys esp,ecx,2\r
+       copy_round_keys esp,ecx,3\r
+       copy_round_keys esp,ecx,4\r
+       copy_round_keys esp,ecx,5\r
+       copy_round_keys esp,ecx,6\r
+       copy_round_keys esp,ecx,7\r
+       copy_round_keys esp,ecx,8\r
+       copy_round_keys esp,ecx,9\r
+       copy_round_keys esp,ecx,10\r
+       mov ecx,esp     \r
+\r
+       align 16        \r
+       \r
+lp128encsingle_CBC:\r
+\r
+       movdqu xmm0, [esi]\r
+       add esi, 16\r
+       pxor xmm0, xmm1\r
+       movdqu xmm4,[ecx+0*16]\r
+       pxor xmm0, xmm4\r
+       aesenc1  [ecx+1*16]\r
+       aesenc1  [ecx+2*16]\r
+       aesenc1  [ecx+3*16]\r
+       aesenc1  [ecx+4*16]     \r
+       aesenc1  [ecx+5*16]\r
+       aesenc1  [ecx+6*16]\r
+       aesenc1  [ecx+7*16]\r
+       aesenc1  [ecx+8*16]\r
+       aesenc1  [ecx+9*16]\r
+       aesenclast1  [ecx+10*16]\r
+               ; Store output encrypted data into CIPHERTEXT array\r
+       movdqu  [esi+edi-16], xmm0\r
+       movdqa xmm1,xmm0\r
+       dec eax\r
+       jnz lp128encsingle_CBC\r
+\r
+\r
+       mov esp,ebp\r
+       pop ebp\r
+       pop edi\r
+       pop esi\r
+       mov ecx,[esp-4+8]  ; first arg\r
+       mov ecx,[ecx+12]\r
+       movdqu  [ecx],xmm1 ; store last iv for chaining\r
+       \r
+       ret\r
+\r
+\r
+align 16\r
+global _iEnc192_CBC\r
+_iEnc192_CBC:\r
+       mov ecx,[esp-4+8]  ; first arg\r
+       \r
+       push esi\r
+       push edi\r
+       push ebp\r
+       mov ebp,esp\r
+       \r
+       sub esp,16*16\r
+       and esp,0xfffffff0\r
+\r
+       mov     eax,[ecx+12]\r
+       movdqu xmm1,[eax]       ;iv     \r
+       \r
+       mov eax,[ecx+16] ; numblocks\r
+       mov esi,[ecx]\r
+       mov edi,[ecx+4]\r
+       mov ecx,[ecx+8]\r
+       sub edi,esi\r
+\r
+       test    ecx,0xf\r
+       jz              lp192encsingle_CBC\r
+       \r
+       copy_round_keys esp,ecx,0\r
+       copy_round_keys esp,ecx,1\r
+       copy_round_keys esp,ecx,2\r
+       copy_round_keys esp,ecx,3\r
+       copy_round_keys esp,ecx,4\r
+       copy_round_keys esp,ecx,5\r
+       copy_round_keys esp,ecx,6\r
+       copy_round_keys esp,ecx,7\r
+       copy_round_keys esp,ecx,8\r
+       copy_round_keys esp,ecx,9\r
+       copy_round_keys esp,ecx,10\r
+       copy_round_keys esp,ecx,11\r
+       copy_round_keys esp,ecx,12\r
+       mov ecx,esp     \r
+\r
+       align 16        \r
+       \r
+lp192encsingle_CBC:\r
+\r
+       movdqu xmm0, [esi]\r
+       add esi, 16\r
+       pxor xmm0, xmm1\r
+       movdqu xmm4,[ecx+0*16]\r
+       pxor xmm0, xmm4\r
+       aesenc1  [ecx+1*16]\r
+       aesenc1  [ecx+2*16]\r
+       aesenc1  [ecx+3*16]\r
+       aesenc1  [ecx+4*16]     \r
+       aesenc1  [ecx+5*16]\r
+       aesenc1  [ecx+6*16]\r
+       aesenc1  [ecx+7*16]\r
+       aesenc1  [ecx+8*16]\r
+       aesenc1  [ecx+9*16]\r
+       aesenc1  [ecx+10*16]\r
+       aesenc1  [ecx+11*16]\r
+       aesenclast1  [ecx+12*16]\r
+               ; Store output encrypted data into CIPHERTEXT array\r
+       movdqu  [esi+edi-16], xmm0\r
+       movdqa xmm1,xmm0\r
+       dec eax\r
+       jnz lp192encsingle_CBC\r
+\r
+\r
+       mov esp,ebp\r
+       pop ebp\r
+       pop edi\r
+       pop esi\r
+       mov ecx,[esp-4+8]  ; first arg\r
+       mov ecx,[ecx+12]\r
+       movdqu  [ecx],xmm1 ; store last iv for chaining\r
+       \r
+       ret\r
+\r
+align 16\r
+global _iEnc256_CBC\r
+_iEnc256_CBC:\r
+       mov ecx,[esp-4+8]  ; first arg\r
+       \r
+       push esi\r
+       push edi\r
+       push ebp\r
+       mov ebp,esp\r
+       \r
+       sub esp,16*16\r
+       and esp,0xfffffff0\r
+\r
+       mov     eax,[ecx+12]\r
+       movdqu xmm1,[eax]       ;iv     \r
+       \r
+       mov eax,[ecx+16] ; numblocks\r
+       mov esi,[ecx]\r
+       mov edi,[ecx+4]\r
+       mov ecx,[ecx+8]\r
+       sub edi,esi\r
+\r
+       test    ecx,0xf\r
+       jz              lp256encsingle_CBC\r
+       \r
+       copy_round_keys esp,ecx,0\r
+       copy_round_keys esp,ecx,1\r
+       copy_round_keys esp,ecx,2\r
+       copy_round_keys esp,ecx,3\r
+       copy_round_keys esp,ecx,4\r
+       copy_round_keys esp,ecx,5\r
+       copy_round_keys esp,ecx,6\r
+       copy_round_keys esp,ecx,7\r
+       copy_round_keys esp,ecx,8\r
+       copy_round_keys esp,ecx,9\r
+       copy_round_keys esp,ecx,10\r
+       copy_round_keys esp,ecx,11\r
+       copy_round_keys esp,ecx,12\r
+       copy_round_keys esp,ecx,13\r
+       copy_round_keys esp,ecx,14\r
+       mov ecx,esp     \r
+\r
+       align 16        \r
+       \r
+lp256encsingle_CBC:\r
+\r
+;abab\r
+       movdqu xmm0, [esi]\r
+       add esi, 16\r
+       pxor xmm0, xmm1\r
+       movdqu xmm4,[ecx+0*16]\r
+       pxor xmm0, xmm4\r
+       aesenc1 [ecx+1*16]\r
+       aesenc1 [ecx+2*16]\r
+       aesenc1 [ecx+3*16]\r
+       aesenc1 [ecx+4*16]     \r
+       aesenc1 [ecx+5*16]\r
+       aesenc1 [ecx+6*16]\r
+       aesenc1 [ecx+7*16]\r
+       aesenc1 [ecx+8*16]\r
+       aesenc1 [ecx+9*16]\r
+       aesenc1 [ecx+10*16]\r
+       aesenc1 [ecx+11*16]\r
+       aesenc1 [ecx+12*16]\r
+       aesenc1 [ecx+13*16]\r
+       aesenclast1 [ecx+14*16]\r
+               ; Store output encrypted data into CIPHERTEXT array\r
+       movdqu  [esi+edi-16], xmm0\r
+       movdqa xmm1,xmm0\r
+       dec eax\r
+       jnz lp256encsingle_CBC\r
+\r
+\r
+       mov esp,ebp\r
+       pop ebp\r
+       pop edi\r
+       pop esi\r
+       mov ecx,[esp-4+8]\r
+       mov ecx,[ecx+12]\r
+       movdqu  [ecx],xmm1 ; store last iv for chaining\r
+       \r
+       ret\r
+\r
+\r
+\r
+\r
+\r
+align 16\r
+global _iEnc192\r
+_iEnc192:\r
+       mov ecx,[esp-4+8]\r
+       \r
+       push esi\r
+       push edi\r
+       push ebp\r
+       mov ebp,esp\r
+       \r
+       sub esp,16*16\r
+       and esp,0xfffffff0\r
+\r
+       mov eax,[ecx+16] ; numblocks\r
+       mov esi,[ecx]\r
+       mov edi,[ecx+4]\r
+       mov ecx,[ecx+8]\r
+       \r
+       sub edi,esi\r
+\r
+       test eax,eax\r
+       jz end_enc192\r
+       \r
+       cmp eax,4\r
+       jl lp192encsingle\r
+\r
+       test    ecx,0xf\r
+       jz              lpenc192four\r
+       \r
+       copy_round_keys esp,ecx,0\r
+       copy_round_keys esp,ecx,1\r
+       copy_round_keys esp,ecx,2\r
+       copy_round_keys esp,ecx,3\r
+       copy_round_keys esp,ecx,4\r
+       copy_round_keys esp,ecx,5\r
+       copy_round_keys esp,ecx,6\r
+       copy_round_keys esp,ecx,7\r
+       copy_round_keys esp,ecx,8\r
+       copy_round_keys esp,ecx,9\r
+       copy_round_keys esp,ecx,10\r
+       copy_round_keys esp,ecx,11\r
+       copy_round_keys esp,ecx,12\r
+       mov ecx,esp     \r
+\r
+       align 16        \r
+       \r
+lpenc192four:\r
+       \r
+       test eax,eax\r
+       jz end_enc192\r
+       \r
+       cmp eax,4\r
+       jl lp192encsingle\r
+\r
+       load_and_xor4 esi,[ecx+0*16]\r
+       add esi,4*16\r
+       aesenc4 [ecx+1*16]\r
+       aesenc4 [ecx+2*16]\r
+       aesenc4 [ecx+3*16]\r
+       aesenc4 [ecx+4*16]\r
+       aesenc4 [ecx+5*16]\r
+       aesenc4 [ecx+6*16]\r
+       aesenc4 [ecx+7*16]\r
+       aesenc4 [ecx+8*16]\r
+       aesenc4 [ecx+9*16]\r
+       aesenc4 [ecx+10*16]\r
+       aesenc4 [ecx+11*16]\r
+       aesenclast4     [ecx+12*16]\r
+       \r
+       store4 esi+edi-16*4\r
+       sub eax,4\r
+       jmp lpenc192four\r
+       \r
+       align 16\r
+lp192encsingle:\r
+\r
+       movdqu xmm0, [esi]\r
+       add esi, 16\r
+       movdqu xmm4,[ecx+0*16]\r
+       pxor xmm0, xmm4\r
+       aesenc1_u [ecx+1*16]\r
+       aesenc1_u [ecx+2*16]\r
+       aesenc1_u [ecx+3*16]\r
+       aesenc1_u [ecx+4*16]     \r
+       aesenc1_u [ecx+5*16]\r
+       aesenc1_u [ecx+6*16]\r
+       aesenc1_u [ecx+7*16]\r
+       aesenc1_u [ecx+8*16]\r
+       aesenc1_u [ecx+9*16]\r
+       aesenc1_u [ecx+10*16]\r
+       aesenc1_u [ecx+11*16]\r
+       aesenclast1_u [ecx+12*16]\r
+               ; Store output encrypted data into CIPHERTEXT array\r
+       movdqu  [esi+edi-16], xmm0\r
+       dec eax\r
+       jnz lp192encsingle\r
+\r
+end_enc192:\r
+\r
+\r
+       mov esp,ebp\r
+       pop ebp\r
+       pop edi\r
+       pop esi\r
+       \r
+       ret\r
+\r
+\r
+\r
+\r
+align 16\r
+global _iEnc256\r
+_iEnc256:\r
+       mov ecx,[esp-4+8]\r
+       \r
+       push esi\r
+       push edi\r
+       push ebp\r
+       mov ebp,esp\r
+       \r
+       sub esp,16*16\r
+       and esp,0xfffffff0\r
+\r
+       mov eax,[ecx+16] ; numblocks\r
+       mov esi,[ecx]\r
+       mov edi,[ecx+4]\r
+       mov ecx,[ecx+8]\r
+       \r
+       sub edi,esi     \r
+\r
+       test eax,eax\r
+       jz end_enc256\r
+\r
+       cmp eax,4\r
+       jl lp256enc\r
+\r
+       test    ecx,0xf\r
+       jz      lp256enc4\r
+       \r
+       copy_round_keys esp,ecx,0\r
+       copy_round_keys esp,ecx,1\r
+       copy_round_keys esp,ecx,2\r
+       copy_round_keys esp,ecx,3\r
+       copy_round_keys esp,ecx,4\r
+       copy_round_keys esp,ecx,5\r
+       copy_round_keys esp,ecx,6\r
+       copy_round_keys esp,ecx,7\r
+       copy_round_keys esp,ecx,8\r
+       copy_round_keys esp,ecx,9\r
+       copy_round_keys esp,ecx,10\r
+       copy_round_keys esp,ecx,11\r
+       copy_round_keys esp,ecx,12\r
+       copy_round_keys esp,ecx,13\r
+       copy_round_keys esp,ecx,14\r
+       mov ecx,esp     \r
+\r
+\r
+\r
+       align 16\r
+       \r
+lp256enc4:\r
+       test eax,eax\r
+       jz end_enc256\r
+\r
+       cmp eax,4\r
+       jl lp256enc\r
+\r
+\r
+       load_and_xor4 esi,[ecx+0*16]\r
+       add esi, 16*4\r
+       aesenc4 [ecx+1*16]\r
+       aesenc4 [ecx+2*16]\r
+       aesenc4 [ecx+3*16]\r
+       aesenc4 [ecx+4*16]\r
+       aesenc4 [ecx+5*16]\r
+       aesenc4 [ecx+6*16]\r
+       aesenc4 [ecx+7*16]\r
+       aesenc4 [ecx+8*16]\r
+       aesenc4 [ecx+9*16]\r
+       aesenc4 [ecx+10*16]\r
+       aesenc4 [ecx+11*16]\r
+       aesenc4 [ecx+12*16]\r
+       aesenc4 [ecx+13*16]\r
+       aesenclast4 [ecx+14*16]\r
+\r
+       store4  esi+edi-16*4\r
+       sub eax,4\r
+       jmp lp256enc4\r
+       \r
+       align 16\r
+lp256enc:\r
+\r
+       movdqu xmm0, [esi]\r
+       add esi, 16\r
+       movdqu xmm4,[ecx+0*16]\r
+       pxor xmm0, xmm4\r
+       aesenc1_u [ecx+1*16]\r
+       aesenc1_u [ecx+2*16]\r
+       aesenc1_u [ecx+3*16]\r
+       aesenc1_u [ecx+4*16]\r
+       aesenc1_u [ecx+5*16]\r
+       aesenc1_u [ecx+6*16]\r
+       aesenc1_u [ecx+7*16]\r
+       aesenc1_u [ecx+8*16]\r
+       aesenc1_u [ecx+9*16]\r
+       aesenc1_u [ecx+10*16]\r
+       aesenc1_u [ecx+11*16]\r
+       aesenc1_u [ecx+12*16]\r
+       aesenc1_u [ecx+13*16]\r
+       aesenclast1_u [ecx+14*16]\r
+\r
+               ; Store output encrypted data into CIPHERTEXT array\r
+       movdqu  [esi+edi-16], xmm0\r
+       dec eax\r
+       jnz lp256enc\r
+\r
+end_enc256:\r
+\r
+\r
+       mov esp,ebp\r
+       pop ebp\r
+       pop edi\r
+       pop esi\r
+       \r
+       ret\r
diff --git a/lib/accelerated/intel/iaes_asm_interface.h b/lib/accelerated/intel/iaes_asm_interface.h
new file mode 100755 (executable)
index 0000000..093d2a5
--- /dev/null
@@ -0,0 +1,126 @@
+/* \r
+ * Copyright (c) 2010, Intel Corporation\r
+ * All rights reserved.\r
+ * \r
+ * Redistribution and use in source and binary forms, with or without \r
+ * modification, are permitted provided that the following conditions are met:\r
+ * \r
+ *     * Redistributions of source code must retain the above copyright notice, \r
+ *       this list of conditions and the following disclaimer.\r
+ *     * Redistributions in binary form must reproduce the above copyright notice, \r
+ *       this list of conditions and the following disclaimer in the documentation \r
+ *       and/or other materials provided with the distribution.\r
+ *     * Neither the name of Intel Corporation nor the names of its contributors \r
+ *       may be used to endorse or promote products derived from this software \r
+ *       without specific prior written permission.\r
+ * \r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND \r
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED \r
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. \r
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, \r
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, \r
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, \r
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF \r
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE \r
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \r
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ * \r
+*/\r
+\r
+#ifndef _INTEL_AES_ASM_INTERFACE_H__\r
+#define _INTEL_AES_ASM_INTERFACE_H__\r
+\r
+\r
+#include "iaesni.h"\r
+\r
+\r
+\r
+//structure to pass aes processing data to asm level functions\r
+typedef struct _sAesData\r
+{\r
+       _AES_IN         UCHAR   *in_block;\r
+       _AES_OUT        UCHAR   *out_block;\r
+       _AES_IN         UCHAR   *expanded_key;          \r
+       _AES_INOUT      UCHAR   *iv;                                    // for CBC mode\r
+       _AES_IN         size_t  num_blocks;\r
+} sAesData;\r
+\r
+#if (__cplusplus)\r
+extern "C"\r
+{\r
+#endif\r
+#if 0\r
+#define MYSTDCALL __stdcall\r
+#else\r
+#define MYSTDCALL \r
+#endif\r
+\r
+#ifdef __linux__\r
+#ifndef __LP64__\r
+#define iEncExpandKey256 _iEncExpandKey256\r
+#define iEncExpandKey192 _iEncExpandKey192\r
+#define iEncExpandKey128 _iEncExpandKey128\r
+#define iDecExpandKey256 _iDecExpandKey256\r
+#define iDecExpandKey192 _iDecExpandKey192\r
+#define iDecExpandKey128 _iDecExpandKey128\r
+#define iEnc128 _iEnc128\r
+#define iDec128 _iDec128\r
+#define iEnc256 _iEnc256\r
+#define iDec256 _iDec256\r
+#define iEnc192 _iEnc192\r
+#define iDec192 _iDec192\r
+#define iEnc128_CBC _iEnc128_CBC\r
+#define iDec128_CBC _iDec128_CBC\r
+#define iEnc256_CBC _iEnc256_CBC\r
+#define iDec256_CBC _iDec256_CBC\r
+#define iEnc192_CBC _iEnc192_CBC\r
+#define iDec192_CBC _iDec192_CBC\r
+#define iEnc128_CTR _iEnc128_CTR\r
+#define iEnc192_CTR _iEnc192_CTR\r
+#define iEnc256_CTR _iEnc256_CTR\r
+#define do_rdtsc    _do_rdtsc\r
+#endif\r
+#endif\r
+       // prepearing the different key rounds, for enc/dec in asm\r
+       // expnaded key should be 16-byte aligned\r
+       // expanded key should have enough space to hold all key rounds (16 bytes per round) - 256 bytes would cover all cases (AES256 has 14 rounds + 1 xor)\r
+       void MYSTDCALL iEncExpandKey256(_AES_IN UCHAR *key, _AES_OUT UCHAR *expanded_key);\r
+       void MYSTDCALL iEncExpandKey192(_AES_IN UCHAR *key, _AES_OUT UCHAR *expanded_key);\r
+       void MYSTDCALL iEncExpandKey128(_AES_IN UCHAR *key, _AES_OUT UCHAR *expanded_key);\r
+\r
+       void MYSTDCALL iDecExpandKey256(UCHAR *key, _AES_OUT UCHAR *expanded_key);\r
+       void MYSTDCALL iDecExpandKey192(UCHAR *key, _AES_OUT UCHAR *expanded_key);\r
+       void MYSTDCALL iDecExpandKey128(UCHAR *key, _AES_OUT UCHAR *expanded_key);\r
+\r
+\r
+       //enc/dec asm functions\r
+       void MYSTDCALL iEnc128(sAesData *data);\r
+       void MYSTDCALL iDec128(sAesData *data);\r
+       void MYSTDCALL iEnc256(sAesData *data);\r
+       void MYSTDCALL iDec256(sAesData *data);\r
+       void MYSTDCALL iEnc192(sAesData *data);\r
+       void MYSTDCALL iDec192(sAesData *data);\r
+\r
+       void MYSTDCALL iEnc128_CBC(sAesData *data);\r
+       void MYSTDCALL iDec128_CBC(sAesData *data);\r
+       void MYSTDCALL iEnc256_CBC(sAesData *data);\r
+       void MYSTDCALL iDec256_CBC(sAesData *data);\r
+       void MYSTDCALL iEnc192_CBC(sAesData *data);\r
+       void MYSTDCALL iDec192_CBC(sAesData *data);\r
+\r
+\r
+       void MYSTDCALL iEnc128_CTR(sAesData *data);\r
+       void MYSTDCALL iEnc256_CTR(sAesData *data);\r
+       void MYSTDCALL iEnc192_CTR(sAesData *data);\r
+\r
+       // rdtsc function\r
+       unsigned long long do_rdtsc(void);\r
+\r
+\r
+#if (__cplusplus)\r
+}\r
+#endif\r
+\r
+\r
+#endif\r
+\r
diff --git a/lib/accelerated/intel/iaesni.h b/lib/accelerated/intel/iaesni.h
new file mode 100755 (executable)
index 0000000..b358faa
--- /dev/null
@@ -0,0 +1,147 @@
+/* \r
+ * Copyright (c) 2010, Intel Corporation\r
+ * All rights reserved.\r
+ * \r
+ * Redistribution and use in source and binary forms, with or without \r
+ * modification, are permitted provided that the following conditions are met:\r
+ * \r
+ *     * Redistributions of source code must retain the above copyright notice, \r
+ *       this list of conditions and the following disclaimer.\r
+ *     * Redistributions in binary form must reproduce the above copyright notice, \r
+ *       this list of conditions and the following disclaimer in the documentation \r
+ *       and/or other materials provided with the distribution.\r
+ *     * Neither the name of Intel Corporation nor the names of its contributors \r
+ *       may be used to endorse or promote products derived from this software \r
+ *       without specific prior written permission.\r
+ * \r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND \r
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED \r
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. \r
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, \r
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, \r
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, \r
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF \r
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE \r
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \r
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ * \r
+*/\r
+\r
+\r
+#ifndef _IAESNI_H__\r
+#define _IAESNI_H__\r
+\r
+#include <stdlib.h>\r
+\r
+#define AES_INSTRCTIONS_CPUID_BIT (1<<25)\r
+\r
+//indicates input param\r
+#define _AES_IN        \r
+\r
+//indicates output param\r
+#define _AES_OUT\r
+\r
+//indicates input/output param - based on context\r
+#define _AES_INOUT\r
+\r
+typedef unsigned char UCHAR;\r
+\r
+\r
+#ifndef bool\r
+#define bool BOOL\r
+#endif\r
+//test if the processor actually supports the above functions\r
+//executing one the functions below without processor support will cause UD fault\r
+//bool check_for_aes_instructions(void);\r
+#if (__cplusplus)\r
+extern "C" {\r
+#endif\r
+int check_for_aes_instructions(void);\r
+\r
+#define ROUND_KEYS_UNALIGNED_TESTING\r
+\r
+#ifdef __linux__\r
+\r
+#ifdef ROUND_KEYS_UNALIGNED_TESTING\r
+\r
+#define DEFINE_ROUND_KEYS \\r
+       UCHAR __attribute__ ((aligned (16))) _expandedKey[16*16];       \\r
+       UCHAR *expandedKey = _expandedKey + 4;  \\r
+\r
+\r
+#else\r
+\r
+\r
+\r
+#define DEFINE_ROUND_KEYS \\r
+       UCHAR __attribute__ ((aligned (16))) _expandedKey[16*16];       \\r
+       UCHAR *expandedKey = _expandedKey;      \\r
+\r
+#endif\r
+\r
+#else // if not __linux__\r
+\r
+#ifdef ROUND_KEYS_UNALIGNED_TESTING\r
+\r
+#define DEFINE_ROUND_KEYS \\r
+       __declspec(align(16)) UCHAR _expandedKey[16*16];        \\r
+       UCHAR *expandedKey = _expandedKey + 4;  \\r
+\r
+\r
+#else\r
+\r
+\r
+\r
+#define DEFINE_ROUND_KEYS \\r
+       __declspec(align(16)) UCHAR _expandedKey[16*16];        \\r
+       UCHAR *expandedKey = _expandedKey;      \\r
+\r
+\r
+#endif\r
+\r
+#endif\r
+\r
+\r
+\r
+// encryption functions\r
+// plainText is pointer to input stream\r
+// cipherText is pointer to buffer to be filled with encrypted (cipher text) data\r
+// key is pointer to enc key (sizes are 16 bytes for AES-128, 24 bytes for AES-192, 32 for AES-256)\r
+// numBlocks is number of 16 bytes blocks to process - note that encryption is done of full 16 byte blocks\r
+void intel_AES_enc128(_AES_IN UCHAR *plainText, _AES_OUT UCHAR *cipherText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks);\r
+void intel_AES_enc192(_AES_IN UCHAR *plainText, _AES_OUT UCHAR *cipherText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks);\r
+void intel_AES_enc256(_AES_IN UCHAR *plainText, _AES_OUT UCHAR *cipherText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks);\r
+\r
+\r
+void intel_AES_enc128_CBC(_AES_IN UCHAR *plainText, _AES_OUT UCHAR *cipherText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *iv);\r
+void intel_AES_enc192_CBC(_AES_IN UCHAR *plainText, _AES_OUT UCHAR *cipherText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *iv);\r
+void intel_AES_enc256_CBC(_AES_IN UCHAR *plainText, _AES_OUT UCHAR *cipherText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *iv);\r
+\r
+\r
+// encryption functions\r
+// cipherText is pointer to encrypted stream\r
+// plainText is pointer to buffer to be filled with original (plain text) data\r
+// key is pointer to enc key (sizes are 16 bytes for AES-128, 24 bytes for AES-192, 32 for AES-256)\r
+// numBlocks is number of 16 bytes blocks to process - note that decryption is done of full 16 byte blocks\r
+void intel_AES_dec128(_AES_IN UCHAR *cipherText, _AES_OUT UCHAR *plainText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks);\r
+void intel_AES_dec192(_AES_IN UCHAR *cipherText, _AES_OUT UCHAR *plainText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks);\r
+void intel_AES_dec256(_AES_IN UCHAR *cipherText, _AES_OUT UCHAR *plainText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks);\r
+\r
+void intel_AES_dec128_CBC(_AES_IN UCHAR *cipherText, _AES_OUT UCHAR *plainText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *iv);\r
+void intel_AES_dec192_CBC(_AES_IN UCHAR *cipherText, _AES_OUT UCHAR *plainText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *iv);\r
+void intel_AES_dec256_CBC(_AES_IN UCHAR *cipherText, _AES_OUT UCHAR *plainText, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *iv);\r
+\r
+void intel_AES_encdec128_CTR(_AES_IN UCHAR *input, _AES_OUT UCHAR *output, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *initial_counter);\r
+void intel_AES_encdec192_CTR(_AES_IN UCHAR *input, _AES_OUT UCHAR *output, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *initial_counter);\r
+void intel_AES_encdec256_CTR(_AES_IN UCHAR *input, _AES_OUT UCHAR *output, _AES_IN UCHAR *key, _AES_IN size_t numBlocks, _AES_IN UCHAR *initial_counter);\r
+\r
+\r
+#if (__cplusplus)\r
+}\r
+#endif\r
+\r
+\r
+#endif\r
+\r
+\r
+\r
diff --git a/lib/accelerated/intel/license.txt b/lib/accelerated/intel/license.txt
new file mode 100755 (executable)
index 0000000..a93c323
--- /dev/null
@@ -0,0 +1,34 @@
+/* intel_aes_lib source files come from Intel.\r
+ * Modified by Patrick Fay\r
+ *\r
+Copyright (c) 2010, Intel Corporation\r
+All rights reserved.\r
+\r
+Redistribution and use in source and binary forms, with or without \r
+modification, are permitted provided that the following conditions are met:\r
+\r
+    * Redistributions of source code must retain the above copyright notice, \r
+      this list of conditions and the following disclaimer.\r
+    * Redistributions in binary form must reproduce the above copyright notice, \r
+      this list of conditions and the following disclaimer in the documentation \r
+      and/or other materials provided with the distribution.\r
+    * Neither the name of Intel Corporation nor the names of its contributors \r
+      may be used to endorse or promote products derived from this software \r
+      without specific prior written permission.\r
+\r
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND \r
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED \r
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. \r
+IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, \r
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, \r
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, \r
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF \r
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE \r
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \r
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+\r
+ ---------------------------------------------------------------------------\r
+ Issue Date: Aug 6, 2010\r
+ */\r
+\r
+Other source code files use the license shown in the source code file.\r
index ad40adac7e2fd5021efab2c5abf19f9e9e67af5c..78ba57017a53e2b5a7694f5d24c9c62902a29dd2 100644 (file)
--- a/m4/gcc.m4
+++ b/m4/gcc.m4
@@ -15,7 +15,7 @@ AC_DEFUN([GCC_FLAG_ADD],
 AC_CACHE_CHECK([whether compiler handles $1], [GCC_FLAG], [
   save_CFLAGS="$CFLAGS"
   CFLAGS="${CFLAGS} $1"
-  AC_PREPROC_IFELSE([AC_LANG_PROGRAM([])],
+  AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],
                     [AS_VAR_SET([GCC_FLAG], [yes])],
                     [AS_VAR_SET([GCC_FLAG], [no])])
   CFLAGS="$save_CFLAGS"