First take on using AES-NI instructions
authorWerner Koch <wk@gnupg.org>
Sun, 13 Feb 2011 16:48:37 +0000 (17:48 +0100)
committerWerner Koch <wk@gnupg.org>
Sun, 13 Feb 2011 16:48:37 +0000 (17:48 +0100)
This first naive use of the new Intel AES-NI instructions boosts the
performance of AES on CPUs supporting this by 3 to 5 times.

Results from running
  ./benchmark --cipher-repetitions 10 --large-buffers  cipher aes
on a
  cpu family      : 6
  model           : 37
  model name      : Intel(R) Core(TM) i5 CPU         660  @ 3.33GHz
  stepping        : 2
  cpu MHz         : 3325.494
  cache size      : 4096 KB
  cpu cores       : 2

yields this:

    ECB/Stream         CBC             CFB             OFB             CTR
--------------- --------------- --------------- --------------- ---------------
  130ms   110ms   110ms   100ms   110ms   110ms   160ms   150ms   170ms   170ms
   40ms    40ms    20ms    30ms    30ms    20ms    70ms    70ms    80ms    80ms

The first line is with runtime switched off AES-NI instructions (don't
set use_aesni in do_setkey), the second with enabled AES-NI.  By
fixing the alignment, I hope to squeeze out a little more even with
this naive implementation.

ChangeLog
NEWS
README
cipher/ChangeLog
cipher/cipher.c
cipher/rijndael.c
configure.ac
src/ChangeLog

index 03461e4..f192d20 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2011-02-11  Werner Koch  <wk@g10code.com>
+
+       * configure.ac: Add option --disbale-aesni-support.
+       (ENABLE_AESNI_SUPPORT): New macro.
+
 2011-02-04  Werner Koch  <wk@g10code.com>
 
        * autogen.sh: Install the git pre-commit if not yet done.
diff --git a/NEWS b/NEWS
index 7dbb54a..9848432 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -27,6 +27,8 @@ Noteworthy changes in version 1.5.x (unreleased)
 
  * gcry_mpi_cmp applied to opaque values has a defined semantic now.
 
+ * Uses the Intel AES-NI instructions if available.
+
  * Interface changes relative to the 1.4.2 release:
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  GCRY_CIPHER_MODE_AESWRAP   NEW.
diff --git a/README b/README
index 514464a..6fe1cfb 100644 (file)
--- a/README
+++ b/README
                      available.  Try this if you get problems with
                      assembler code.
 
+     --disable-aesni-support
+                     Disable support for the AES-NI instructions of
+                     newer Intel CPUs.  The default is to use AES-NI
+                     if available.  Try this if you get problems with
+                     assembler code.
+
      --disable-O-flag-munging
                      Some code is too complex for some compilers while
                      in higher optimization modes, thus the compiler
index 02dac02..670491d 100644 (file)
@@ -1,3 +1,16 @@
+2011-02-13  Werner Koch  <wk@g10code.com>
+
+       * rijndael.c (USE_AESNI): New.  Define for ia32 and gcc >= 4.
+       (m128i_t) [USE_AESNI]: New.
+       (RIJNDAEL_context) [USE_AESNI]: Add field use_aesni.
+       (do_setkey): Set USE_AESNI for all key lengths.
+       (prepare_decryption) [USE_AESNI]: Use aesimc instn if requested.
+       (do_aesni_enc_aligned, do_aesni_dec_aligned)
+       (do_aesni) [USE_AESNI]: New.
+       (rijndael_encrypt, _gcry_aes_cfb_enc, _gcry_aes_cbc_enc)
+       (rijndael_decrypt, _gcry_aes_cfb_dec)
+       (_gcry_aes_cbc_dec) [USE_AESNI]: Use do_aesni.
+
 2011-02-01  Werner Koch  <wk@g10code.com>
 
        * pubkey.c (gcry_pk_get_curve): New.
index af91b81..9e5bca5 100644 (file)
@@ -137,13 +137,14 @@ static int default_ciphers_registered;
   while (0)
 
 
-/* A VIA processor with the Padlock engine requires an alignment of
-   most data on a 16 byte boundary.  Because we trick out the compiler
-   while allocating the context, the align attribute as used in
-   rijndael.c does not work on its own.  Thus we need to make sure
-   that the entire context structure is a aligned on that boundary.
-   We achieve this by defining a new type and use that instead of our
-   usual alignment type.  */
+/* A VIA processor with the Padlock engine as well as the Intel AES_NI
+   instructions require an alignment of most data on a 16 byte
+   boundary.  Because we trick out the compiler while allocating the
+   context, the align attribute as used in rijndael.c does not work on
+   its own.  Thus we need to make sure that the entire context
+   structure is a aligned on that boundary.  We achieve this by
+   defining a new type and use that instead of our usual alignment
+   type.  */
 typedef union
 {
   PROPERLY_ALIGNED_TYPE foo;
index 2b19e09..bebe163 100644 (file)
@@ -1,6 +1,6 @@
 /* Rijndael (AES) for GnuPG
  * Copyright (C) 2000, 2001, 2002, 2003, 2007,
- *               2008 Free Software Foundation, Inc.
+ *               2008, 2011 Free Software Foundation, Inc.
  *
  * This file is part of Libgcrypt.
  *
  *
  */
 
+/* FIXME:
+
+   Most important:
+   For AES-NI we should use a prepare and depreparse function which
+   can take care of clearing registers we used for sensitive stuff
+   etc.  Need to read the Intel ABI specs to see how to handel SSE
+   registers.
+
+   Furuture stuff:
+
+   - Do the AES-NI code all in asm to avoid extra register loads and
+     unloads.
+
+   - Make use of aligned move instructions.  This requires that we
+     align the keyschedule filed in the context.
+
+   - Use AESKEYGENASSIST.
+
+   - Make better use of the CPU pipelines.
+*/
+
 #include <config.h>
 #include <stdio.h>
 #include <stdlib.h>
 #undef USE_PADLOCK
 #ifdef ENABLE_PADLOCK_SUPPORT
 # if defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 && defined (__GNUC__)
-# define USE_PADLOCK
+#  define USE_PADLOCK 1
 # endif
 #endif /*ENABLE_PADLOCK_SUPPORT*/
 
-
-/* USE_AESNI inidicates whether to compile with Intel AES-NI code.  */
+/* USE_AESNI inidicates whether to compile with Intel AES-NI code.  We
+   need the vector-size attribute which seems to be available since
+   gcc 3.  However, to be on the safe side we require at least gcc 4.  */
 #undef USE_AESNI
 #ifdef ENABLE_AESNI_SUPPORT
-# if defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 && defined (__GNUC__)
-#  define USE_AESNI
+# if defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 && __GNUC__ >= 4
+#  define USE_AESNI 1
 # endif
 #endif /* ENABLE_AESNI_SUPPORT */
 
+#ifdef USE_AESNI
+  typedef int m128i_t __attribute__ ((__vector_size__ (16)));
+#endif /*USE_AESNI*/
 
 static const char *selftest(void);
 
@@ -80,7 +105,10 @@ typedef struct
   int use_padlock;          /* Padlock shall be used.  */
   /* The key as passed to the padlock engine.  */
   unsigned char padlock_key[16] __attribute__ ((aligned (16)));
-#endif
+#endif /*USE_PADLOCK*/
+#ifdef USE_AESNI
+  int use_aesni;           /* AES-NI shall be used.  */
+#endif /*USE_AESNI*/
   union
   {
     PROPERLY_ALIGNED_TYPE dummy;
@@ -143,28 +171,58 @@ do_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen)
 #ifdef USE_PADLOCK
   ctx->use_padlock = 0;
 #endif
+#ifdef USE_AESNI
+  ctx->use_aesni = 0;
+#endif
 
   if( keylen == 128/8 )
     {
       ROUNDS = 10;
       KC = 4;
+
+      if (0)
+        ;
 #ifdef USE_PADLOCK
-      if ((_gcry_get_hw_features () & HWF_PADLOCK_AES))
+      else if ((_gcry_get_hw_features () & HWF_PADLOCK_AES))
         {
           ctx->use_padlock = 1;
           memcpy (ctx->padlock_key, key, keylen);
         }
 #endif
+#ifdef USE_AESNI
+      else if ((_gcry_get_hw_features () & HWF_INTEL_AESNI))
+        {
+          ctx->use_aesni = 1;
+        }
+#endif
     }
   else if ( keylen == 192/8 )
     {
       ROUNDS = 12;
       KC = 6;
+
+      if (0)
+        ;
+#ifdef USE_AESNI
+      else if ((_gcry_get_hw_features () & HWF_INTEL_AESNI))
+        {
+          ctx->use_aesni = 1;
+        }
+#endif
     }
   else if ( keylen == 256/8 )
     {
       ROUNDS = 14;
       KC = 8;
+
+      if (0)
+        ;
+#ifdef USE_AESNI
+      else if ((_gcry_get_hw_features () & HWF_INTEL_AESNI))
+        {
+          ctx->use_aesni = 1;
+        }
+#endif
     }
   else
     return GPG_ERR_INV_KEYLEN;
@@ -278,44 +336,71 @@ static void
 prepare_decryption( RIJNDAEL_context *ctx )
 {
   int r;
-  union
-  {
-    PROPERLY_ALIGNED_TYPE dummy;
-    byte *w;
-  } w;
-#define w w.w
 
-  for (r=0; r < MAXROUNDS+1; r++ )
+#ifdef USE_AESNI
+  if (ctx->use_aesni)
     {
-      *((u32*)ctx->keySched2[r][0]) = *((u32*)ctx->keySched[r][0]);
-      *((u32*)ctx->keySched2[r][1]) = *((u32*)ctx->keySched[r][1]);
-      *((u32*)ctx->keySched2[r][2]) = *((u32*)ctx->keySched[r][2]);
-      *((u32*)ctx->keySched2[r][3]) = *((u32*)ctx->keySched[r][3]);
+      /* The AES-NI decrypt instructions use the Equivalent Inverse
+         Cipher, thus we can't use the the standard decrypt key
+         preparation.  */
+        m128i_t *ekey = (m128i_t*)ctx->keySched;
+        m128i_t *dkey = (m128i_t*)ctx->keySched2;
+        int rr;
+
+        dkey[0] = ekey[ctx->ROUNDS];
+        for (r=1, rr=ctx->ROUNDS-1; r < ctx->ROUNDS; r++, rr--)
+          {
+            asm volatile
+              ("movdqu %[ekey], %%xmm1\n\t"
+               /*"aesimc %%xmm1, %%xmm1\n\t"*/
+               ".byte 0x66, 0x0f, 0x38, 0xdb, 0xc9\n\t"
+               "movdqu %%xmm1, %[dkey]"
+               : [dkey] "=m" (dkey[r])
+               : [ekey] "m" (ekey[rr]) );
+          }
+        dkey[r] = ekey[0];
     }
-#define W (ctx->keySched2)
-  for (r = 1; r < ctx->ROUNDS; r++)
+  else
+#endif /*USE_AESNI*/
     {
-      w = W[r][0];
-      *((u32*)w) = *((u32*)U1[w[0]]) ^ *((u32*)U2[w[1]])
-        ^ *((u32*)U3[w[2]]) ^ *((u32*)U4[w[3]]);
+      union
+      {
+        PROPERLY_ALIGNED_TYPE dummy;
+        byte *w;
+      } w;
+#define w w.w
 
-      w = W[r][1];
-      *((u32*)w) = *((u32*)U1[w[0]]) ^ *((u32*)U2[w[1]])
-        ^ *((u32*)U3[w[2]]) ^ *((u32*)U4[w[3]]);
+      for (r=0; r < MAXROUNDS+1; r++ )
+        {
+          *((u32*)ctx->keySched2[r][0]) = *((u32*)ctx->keySched[r][0]);
+          *((u32*)ctx->keySched2[r][1]) = *((u32*)ctx->keySched[r][1]);
+          *((u32*)ctx->keySched2[r][2]) = *((u32*)ctx->keySched[r][2]);
+          *((u32*)ctx->keySched2[r][3]) = *((u32*)ctx->keySched[r][3]);
+        }
+#define W (ctx->keySched2)
+      for (r = 1; r < ctx->ROUNDS; r++)
+        {
+          w = W[r][0];
+          *((u32*)w) = *((u32*)U1[w[0]]) ^ *((u32*)U2[w[1]])
+            ^ *((u32*)U3[w[2]]) ^ *((u32*)U4[w[3]]);
 
-      w = W[r][2];
-      *((u32*)w) = *((u32*)U1[w[0]]) ^ *((u32*)U2[w[1]])
-        ^ *((u32*)U3[w[2]]) ^ *((u32*)U4[w[3]]);
+          w = W[r][1];
+          *((u32*)w) = *((u32*)U1[w[0]]) ^ *((u32*)U2[w[1]])
+            ^ *((u32*)U3[w[2]]) ^ *((u32*)U4[w[3]]);
 
-      w = W[r][3];
-      *((u32*)w) = *((u32*)U1[w[0]]) ^ *((u32*)U2[w[1]])
+          w = W[r][2];
+          *((u32*)w) = *((u32*)U1[w[0]]) ^ *((u32*)U2[w[1]])
         ^ *((u32*)U3[w[2]]) ^ *((u32*)U4[w[3]]);
-    }
+
+          w = W[r][3];
+          *((u32*)w) = *((u32*)U1[w[0]]) ^ *((u32*)U2[w[1]])
+            ^ *((u32*)U3[w[2]]) ^ *((u32*)U4[w[3]]);
+        }
 #undef W
 #undef w
+    }
 }
 
-
 \f
 /* Encrypt one block.  A and B need to be aligned on a 4 byte
    boundary.  A and B may be the same. */
@@ -473,19 +558,130 @@ do_padlock (const RIJNDAEL_context *ctx, int decrypt_flag,
 #endif /*USE_PADLOCK*/
 
 
+/* Encrypt one block using the Intel AES-NI instructions.  A and B may
+   be the same; then need to be properly aligned to 16 bytes.
+
+   Our problem here is that gcc does not allow the "x" constraint for
+   SSE registers in asm unless you compile with -msse.  The common
+   wisdom is to use a separate file for SSE instructions and build it
+   separately.  This would require a lot of extra build system stuff,
+   similar to what we do in mpi/ for the asm stuff.  What we do
+   instead is to use standard registers and a bit more of plain asm
+   which copies the data and key stuff to the SSE registers and later
+   back.  If we decide to implement some block modes with parallelized
+   aES instructions, it might indeed be better to use plain asm ala
+   mpi/.  */
+#ifdef USE_AESNI
+static void
+do_aesni_enc_aligned (const RIJNDAEL_context *ctx,
+                      unsigned char *b, const unsigned char *a)
+{
+  int r;
+  m128i_t *key;
+
+  key = (m128i_t*)ctx->keySched;
+
+  asm volatile ("movdqu %[src], %%xmm0\n\t" /* xmm0 := *a     */
+                "movdqu %[key], %%xmm1\n\t"
+                "pxor   %%xmm1, %%xmm0"     /* xmm0 ^= key[0] */
+                : : [src] "m" (*a), [key] "m" (*key));
+
+  key++;
+  for (r = 1; r < ctx->ROUNDS; r++)
+    {
+      asm volatile ("movdqu %[key], %%xmm1\n\t"
+                    /*"aesenc %%xmm1, %%xmm0"*/
+                    ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc1"
+                    : : [key] "m" (*key) );
+      key++;
+    }
+  asm volatile ("movdqu %[key], %%xmm1\n\t"
+                /*"aesenclast %%xmm1, %%xmm0"*/
+                ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc1"
+                : : [key] "m" (*key) );
+
+  asm volatile ("movdqu %%xmm0, %[dst]"
+                : [dst] "=m" (*b));
+}
+
+static void
+do_aesni_dec_aligned (const RIJNDAEL_context *ctx,
+                      unsigned char *b, const unsigned char *a)
+{
+  int r;
+  m128i_t *key;
+
+  key = (m128i_t*)ctx->keySched2;
+
+  asm volatile ("movdqu %[src], %%xmm0\n\t" /* xmm0 := *a     */
+                "movdqu %[key], %%xmm1\n\t"
+                "pxor   %%xmm1, %%xmm0"     /* xmm0 ^= key[0] */
+                : : [src] "m" (*a), [key] "m" (key[0]));
+
+  for (r = 1; r < ctx->ROUNDS; r++)
+    {
+      asm volatile ("movdqu %[key], %%xmm1\n\t"
+                    /*"aesdec %%xmm1, %%xmm0"*/
+                    ".byte 0x66, 0x0f, 0x38, 0xde, 0xc1"
+                    : : [key] "m" (key[r]) );
+    }
+  asm volatile ("movdqu %[key], %%xmm1\n\t"
+                /*"aesdeclast %%xmm1, %%xmm0"*/
+                ".byte 0x66, 0x0f, 0x38, 0xdf, 0xc1"
+                : : [key] "m" (key[r]) );
+
+  asm volatile ("movdqu %%xmm0, %[dst]"
+                : [dst] "=m" (*b));
+}
+
+static void
+do_aesni (RIJNDAEL_context *ctx, int decrypt_flag,
+          unsigned char *bx, const unsigned char *ax)
+{
+  /* BX and AX are not necessary correctly aligned.  Thus we need to
+     copy them here. */
+  unsigned char a[16] __attribute__ ((aligned (16)));
+  unsigned char b[16] __attribute__ ((aligned (16)));
+
+  memcpy (a, ax, 16);
+  if (decrypt_flag)
+    {
+      if ( !ctx->decryption_prepared )
+        {
+          prepare_decryption ( ctx );
+          ctx->decryption_prepared = 1;
+        }
+      do_aesni_dec_aligned (ctx, b, a);
+    }
+  else
+    do_aesni_enc_aligned (ctx, b, a);
+  memcpy (bx, b, 16);
+}
+#endif /*USE_AESNI*/
+
+
 static void
 rijndael_encrypt (void *context, byte *b, const byte *a)
 {
   RIJNDAEL_context *ctx = context;
 
+  if (0)
+    ;
 #ifdef USE_PADLOCK
-  if (ctx->use_padlock)
+  else if (ctx->use_padlock)
     {
       do_padlock (ctx, 0, b, a);
       _gcry_burn_stack (48 + 15 /* possible padding for alignment */);
     }
-  else
 #endif /*USE_PADLOCK*/
+#ifdef USE_AESNI
+  else if (ctx->use_aesni)
+    {
+      do_aesni (ctx, 0, b, a);
+      _gcry_burn_stack (48 + 15 /* possible padding for alignment */);
+    }
+#endif /*USE_AESNI*/
+  else
     {
       do_encrypt (ctx, b, a);
       _gcry_burn_stack (48 + 2*sizeof(int));
@@ -508,8 +704,10 @@ _gcry_aes_cfb_enc (void *context, unsigned char *iv,
   unsigned char *ivp;
   int i;
 
+  if (0)
+    ;
 #ifdef USE_PADLOCK
-  if (ctx->use_padlock)
+  else if (ctx->use_padlock)
     {
       /* Fixme: Let Padlock do the CFBing.  */
       for ( ;nblocks; nblocks-- )
@@ -521,8 +719,21 @@ _gcry_aes_cfb_enc (void *context, unsigned char *iv,
             *outbuf++ = (*ivp++ ^= *inbuf++);
         }
     }
+#endif /*USE_PADLOCK*/
+#ifdef USE_AESNI
+  else if (ctx->use_aesni)
+    {
+      for ( ;nblocks; nblocks-- )
+        {
+          /* Encrypt the IV. */
+          do_aesni_enc_aligned (ctx, iv, iv);
+          /* XOR the input with the IV and store input into IV.  */
+          for (ivp=iv,i=0; i < BLOCKSIZE; i++ )
+            *outbuf++ = (*ivp++ ^= *inbuf++);
+        }
+    }
+#endif /*USE_AESNI*/
   else
-#endif /* USE_PADLOCK*/
     {
       for ( ;nblocks; nblocks-- )
         {
@@ -558,11 +769,17 @@ _gcry_aes_cbc_enc (void *context, unsigned char *iv,
       for (ivp=iv, i=0; i < BLOCKSIZE; i++ )
         outbuf[i] = inbuf[i] ^ *ivp++;
 
+      if (0)
+        ;
 #ifdef USE_PADLOCK
-      if (ctx->use_padlock)
+      else if (ctx->use_padlock)
         do_padlock (ctx, 0, outbuf, outbuf);
-      else
 #endif /*USE_PADLOCK*/
+#ifdef USE_AESNI
+      else if (ctx->use_aesni)
+        do_aesni (ctx, 0, outbuf, outbuf);
+#endif /*USE_AESNI*/
+      else
         do_encrypt (ctx, outbuf, outbuf );
 
       memcpy (iv, outbuf, BLOCKSIZE);
@@ -706,14 +923,23 @@ rijndael_decrypt (void *context, byte *b, const byte *a)
 {
   RIJNDAEL_context *ctx = context;
 
+  if (0)
+    ;
 #ifdef USE_PADLOCK
-  if (ctx->use_padlock)
+  else if (ctx->use_padlock)
     {
       do_padlock (ctx, 1, b, a);
       _gcry_burn_stack (48 + 2*sizeof(int) /* FIXME */);
     }
-  else
 #endif /*USE_PADLOCK*/
+#ifdef USE_AESNI
+  else if (ctx->use_aesni)
+    {
+      do_aesni (ctx, 1, b, a);
+      _gcry_burn_stack (48 + 2*sizeof(int) /* FIXME */);
+    }
+#endif /*USE_AESNI*/
+  else
     {
       do_decrypt (ctx, b, a);
       _gcry_burn_stack (48+2*sizeof(int));
@@ -737,8 +963,10 @@ _gcry_aes_cfb_dec (void *context, unsigned char *iv,
   unsigned char temp;
   int i;
 
+  if (0)
+    ;
 #ifdef USE_PADLOCK
-  if (ctx->use_padlock)
+  else if (ctx->use_padlock)
     {
       /* Fixme:  Let Padlock do the CFBing.  */
       for ( ;nblocks; nblocks-- )
@@ -752,8 +980,23 @@ _gcry_aes_cfb_dec (void *context, unsigned char *iv,
             }
         }
     }
-  else
 #endif /*USE_PADLOCK*/
+#ifdef USE_AESNI
+  else if (ctx->use_aesni)
+    {
+      for ( ;nblocks; nblocks-- )
+        {
+          do_aesni_enc_aligned (ctx, iv, iv);
+          for (ivp=iv,i=0; i < BLOCKSIZE; i++ )
+            {
+              temp = *inbuf++;
+              *outbuf++ = *ivp ^ temp;
+              *ivp++ = temp;
+            }
+        }
+    }
+#endif /*USE_AESNI*/
+  else
     {
       for ( ;nblocks; nblocks-- )
         {
@@ -793,11 +1036,17 @@ _gcry_aes_cbc_dec (void *context, unsigned char *iv,
          OUTBUF.  */
       memcpy (savebuf, inbuf, BLOCKSIZE);
 
+      if (0)
+        ;
 #ifdef USE_PADLOCK
-      if (ctx->use_padlock)
+      else if (ctx->use_padlock)
         do_padlock (ctx, 1, outbuf, inbuf);
-      else
 #endif /*USE_PADLOCK*/
+#ifdef USE_AESNI
+      else if (ctx->use_aesni)
+        do_aesni (ctx, 1, outbuf, inbuf);
+#endif /*USE_AESNI*/
+      else
         do_decrypt (ctx, outbuf, inbuf);
 
       for (ivp=iv, i=0; i < BLOCKSIZE; i++ )
@@ -837,6 +1086,22 @@ selftest_basic_128 (void)
       0x67,0x43,0xC3,0xD1,0x51,0x9A,0xB4,0xF2,
       0xCD,0x9A,0x78,0xAB,0x09,0xA5,0x11,0xBD
     };
+  /* /\* Test vectors from fips-197, appendix C.  *\/ */
+  /* static const unsigned char plaintext_128[16] = */
+  /*   { */
+  /*     0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77, */
+  /*     0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff */
+  /*   }; */
+  /* static const unsigned char key_128[16] = */
+  /*   { */
+  /*     0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, */
+  /*     0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f */
+  /*   }; */
+  /* static const unsigned char ciphertext_128[16] = */
+  /*   { */
+  /*     0x69,0xc4,0xe0,0xd8,0x6a,0x7b,0x04,0x30, */
+  /*     0xd8,0xcd,0xb7,0x80,0x70,0xb4,0xc5,0x5a */
+  /*   }; */
 
   rijndael_setkey (&ctx, key_128, sizeof (key_128));
   rijndael_encrypt (&ctx, scratch, plaintext_128);
index c6bff37..64692b6 100644 (file)
@@ -33,7 +33,7 @@ m4_define([svn_revision], m4_esyscmd([printf "%d" $(svn info 2>/dev/null \
           | sed -n '/^Revision:/ s/[^0-9]//gp'|head -1)]))
 m4_define([git_revision], m4_esyscmd([git branch -v 2>/dev/null \
           | awk '/^\* / {printf "%s",$3}']))
-AC_INIT([libgcrypt], 
+AC_INIT([libgcrypt],
         [my_version[]m4_if(my_issvn,[yes],
         [m4_if(git_revision,[],[-svn[]svn_revision],[-git[]git_revision])])],
         [bug-libgcrypt@gnupg.org])
@@ -90,7 +90,7 @@ AH_BOTTOM([
 # endif
 #endif /*DISABLED_ENDIAN_CHECK*/
 
-/* We basically use the original Camellia source.  Make sure the symbols 
+/* We basically use the original Camellia source.  Make sure the symbols
    properly prefixed.  */
 #define CAMELLIA_EXT_SYM_PREFIX _gcry_
 
@@ -186,7 +186,7 @@ case "${host}" in
     *-*-mingw32*)
       ac_cv_have_dev_random=no
       have_w32_system=yes
-      case "${host}" in 
+      case "${host}" in
         *-mingw32ce*)
             have_w32ce_system=yes
             available_random_modules="w32ce"
@@ -200,7 +200,7 @@ case "${host}" in
       AC_DEFINE(HAVE_DRIVE_LETTERS,1,
                 [defined if we must run on a stupid file system])
       AC_DEFINE(HAVE_DOSISH_SYSTEM,1,
-                [defined if we run on some of the PCDOS like systems 
+                [defined if we run on some of the PCDOS like systems
                  (DOS, Windoze. OS/2) with special properties like
                   no file modes])
       ;;
@@ -331,7 +331,7 @@ else
 fi
 
 # If not specified otherwise, all available algorithms will be
-# included.  
+# included.
 default_ciphers="$available_ciphers"
 default_pubkey_ciphers="$available_pubkey_ciphers"
 default_digests="$available_digests"
@@ -503,6 +503,18 @@ if test x"$padlocksupport" = xyes ; then
             [Enable support for the PadLock engine.])
 fi
 
+# Implementation of the --disable-aesni-support switch.
+AC_MSG_CHECKING([whether AESNI support is requested])
+AC_ARG_ENABLE(aesni-support,
+              AC_HELP_STRING([--disable-aesni-support],
+                 [Disable support for the Intel AES-NI instructions]),
+             aesnisupport=$enableval,aesnisupport=yes)
+AC_MSG_RESULT($aesnisupport)
+if test x"$aesnisupport" = xyes ; then
+  AC_DEFINE(ENABLE_AESNI_SUPPORT, 1,
+            [Enable support for Intel AES-NI instructions.])
+fi
+
 # Implementation of the --disable-O-flag-munging switch.
 AC_MSG_CHECKING([whether a -O flag munging is requested])
 AC_ARG_ENABLE([O-flag-munging],
@@ -518,7 +530,7 @@ AM_CONDITIONAL(ENABLE_O_FLAG_MUNGING, test "$enable_o_flag_munging" = "yes")
 AC_DEFINE_UNQUOTED(PRINTABLE_OS_NAME, "$PRINTABLE_OS_NAME",
                    [A human readable text with the name of the OS])
 
-# For some systems we know that we have ld_version scripts.  
+# For some systems we know that we have ld_version scripts.
 # Use it then as default.
 have_ld_version_script=no
 case "${host}" in
@@ -560,7 +572,7 @@ AC_DEFINE(GPG_ERR_SOURCE_DEFAULT, GPG_ERR_SOURCE_GCRYPT,
           [The default error source for libgcrypt.])
 
 #
-# Check whether the GNU Pth library is available.  We require this 
+# Check whether the GNU Pth library is available.  We require this
 # to build the optional gcryptrnd program.
 #
 AC_ARG_WITH(pth-prefix,
@@ -578,12 +590,12 @@ if test "$use_random_daemon" = "yes"; then
 *** To build the Libgcrypt's random number daemon
 *** we need the support of the GNU Portable Threads Library.
 *** Download it from ftp://ftp.gnu.org/gnu/pth/
-*** On a Debian GNU/Linux system you might want to try 
+*** On a Debian GNU/Linux system you might want to try
 ***   apt-get install libpth-dev
 ***]])
   else
     GNUPG_PTH_VERSION_CHECK([1.3.7])
-    if test $have_pth = yes; then      
+    if test $have_pth = yes; then
        PTH_CFLAGS=`$PTH_CONFIG --cflags`
        PTH_LIBS=`$PTH_CONFIG --ldflags`
        PTH_LIBS="$PTH_LIBS `$PTH_CONFIG --libs --all`"
@@ -650,8 +662,8 @@ case "${host}" in
     fi
 esac
 AC_SUBST(FALLBACK_SOCKLEN_T)
-            
-#            
+
+#
 # Check for ELF visibility support.
 #
 AC_CACHE_CHECK(whether the visibility attribute is supported,
@@ -661,15 +673,15 @@ AC_CACHE_CHECK(whether the visibility attribute is supported,
           [[int foo __attribute__ ((visibility ("hidden"))) = 1;
             int bar __attribute__ ((visibility ("protected"))) = 1;
           ]])])
-        
+
         if ${CC-cc} -Werror -S conftest.c -o conftest.s \
                   1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ; then
             if grep '\.hidden.*foo' conftest.s >/dev/null 2>&1 ; then
                 if grep '\.protected.*bar' conftest.s >/dev/null 2>&1; then
                     gcry_cv_visibility_attribute=yes
                 fi
-            fi  
-        fi  
+            fi
+        fi
        ])
 if test "$gcry_cv_visibility_attribute" = "yes"; then
     AC_CACHE_CHECK(for broken visibility attribute,
@@ -681,7 +693,7 @@ if test "$gcry_cv_visibility_attribute" = "yes"; then
                             __attribute__ ((visibility ("hidden")));
             int bar (int x) { return x; }
           ]])])
-                  
+
         if ${CC-cc} -Werror -S conftest.c -o conftest.s \
                   1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ; then
            if grep '\.hidden@<:@       _@:>@foo' conftest.s >/dev/null 2>&1;
@@ -727,7 +739,7 @@ fi
 if test "$gcry_cv_visibility_attribute" = "yes" \
    && test "$gcry_cv_broken_visibility_attribute" != "yes" \
    && test "$gcry_cv_broken_alias_attribute" != "yes" \
-   && test "$gcry_cv_gcc_has_f_visibility" = "yes"  
+   && test "$gcry_cv_gcc_has_f_visibility" = "yes"
  then
    AC_DEFINE(GCRY_USE_VISIBILITY, 1,
                [Define to use the GNU C visibility attribute.])
@@ -837,7 +849,7 @@ if test "$random" = "default"; then
           # Build everything, allow to select at runtime.
           random_modules="$auto_random_modules"
           ;;
-        esac    
+        esac
     fi
 else
     if test "$random" = "auto"; then
@@ -914,7 +926,7 @@ if test "$GCC" = yes; then
         CFLAGS="$CFLAGS -Wcast-align -Wshadow -Wstrict-prototypes"
         CFLAGS="$CFLAGS -Wformat -Wno-format-y2k -Wformat-security"
 
-        # If -Wno-missing-field-initializers is supported we can enable a 
+        # If -Wno-missing-field-initializers is supported we can enable a
         # a bunch of really useful warnings.
         AC_MSG_CHECKING([if gcc supports -Wno-missing-field-initializers])
         _gcc_cflags_save=$CFLAGS
@@ -982,7 +994,7 @@ DATADIRNAME=$DATADIRNAME
 # selected ciphers, pubkey-ciphers, digests and random modules.
 
 LIST_MEMBER(arcfour, $enabled_ciphers)
-if test "$found" = "1"; then 
+if test "$found" = "1"; then
    GCRYPT_CIPHERS="$GCRYPT_CIPHERS arcfour.lo"
    AC_DEFINE(USE_ARCFOUR, 1, [Defined if this module should be included])
 fi
@@ -1134,14 +1146,14 @@ fi
 LIST_MEMBER(w32, $random_modules)
 if test "$found" = "1" ; then
    GCRYPT_RANDOM="$GCRYPT_RANDOM rndw32.lo"
-   AC_DEFINE(USE_RNDW32, 1, 
+   AC_DEFINE(USE_RNDW32, 1,
              [Defined if the Windows specific RNG should be used.])
 fi
 
 LIST_MEMBER(w32ce, $random_modules)
 if test "$found" = "1" ; then
    GCRYPT_RANDOM="$GCRYPT_RANDOM rndw32ce.lo"
-   AC_DEFINE(USE_RNDW32CE, 1, 
+   AC_DEFINE(USE_RNDW32CE, 1,
              [Defined if the WindowsCE specific RNG should be used.])
 fi
 
@@ -1157,13 +1169,13 @@ AC_SUBST(LIBGCRYPT_DIGESTS, $enabled_digests)
 # For printing the configuration we need a colon separated list of
 # algorithm names.
 tmp=`echo "$enabled_ciphers" | tr ' ' : `
-AC_DEFINE_UNQUOTED(LIBGCRYPT_CIPHERS, "$tmp", 
+AC_DEFINE_UNQUOTED(LIBGCRYPT_CIPHERS, "$tmp",
                    [List of available cipher algorithms])
 tmp=`echo "$enabled_pubkey_ciphers" | tr ' ' : `
-AC_DEFINE_UNQUOTED(LIBGCRYPT_PUBKEY_CIPHERS, "$tmp", 
+AC_DEFINE_UNQUOTED(LIBGCRYPT_PUBKEY_CIPHERS, "$tmp",
                    [List of available public key cipher algorithms])
 tmp=`echo "$enabled_digests" | tr ' ' : `
-AC_DEFINE_UNQUOTED(LIBGCRYPT_DIGESTS, "$tmp", 
+AC_DEFINE_UNQUOTED(LIBGCRYPT_DIGESTS, "$tmp",
                    [List of available digest algorithms])
 
 
@@ -1171,7 +1183,7 @@ AC_DEFINE_UNQUOTED(LIBGCRYPT_DIGESTS, "$tmp",
 # Generate extended version information for W32.
 if test "$have_w32_system" = yes; then
    BUILD_TIMESTAMP=`date --iso-8601=minutes`
-   changequote(,)dnl 
+   changequote(,)dnl
    BUILD_FILEVERSION=`echo "$VERSION" | sed 's/\([0-9.]*\).*/\1./;s/\./,/g'`
    changequote([,])dnl
    BUILD_FILEVERSION="${BUILD_FILEVERSION}${BUILD_REVISION}"
@@ -1179,7 +1191,7 @@ fi
 AC_SUBST(BUILD_REVISION)
 AC_SUBST(BUILD_TIMESTAMP)
 AC_SUBST(BUILD_FILEVERSION)
-AC_DEFINE_UNQUOTED(BUILD_REVISION, "$BUILD_REVISION", 
+AC_DEFINE_UNQUOTED(BUILD_REVISION, "$BUILD_REVISION",
                    [Subversion revision used to build this package])
 
 
@@ -1209,7 +1221,7 @@ AC_OUTPUT
 # Give some feedback
 echo "
         Libgcrypt v${VERSION} has been configured as follows:
-        
+
         Platform:                  $PRINTABLE_OS_NAME ($host)
         Enabled cipher algorithms: $enabled_ciphers
         Enabled digest algorithms: $enabled_digests
@@ -1220,19 +1232,19 @@ echo "
 
 if test "$print_egd_notice" = "yes"; then
 cat <<G10EOF
-  
+
    The performance of the Unix random gatherer module (rndunix) is not
    very good and it does not keep the entropy pool over multiple
    invocations of Libgcrypt base applications.  The suggested way to
    overcome this problem is to use the
-  
+
                  Entropy Gathering Daemon (EGD)
-  
+
    which provides a entropy source for the whole system.  It is written
    in Perl and available at the GnuPG FTP servers.  To enable EGD you
    should rerun configure with the option "--enable-static-rnd=egd".
    For more information consult the GnuPG webpages:
-  
+
              http://www.gnupg.org/download.html#egd
 
 G10EOF
@@ -1244,4 +1256,3 @@ if test -n "$gpl"; then
   echo "included.  These parts are licensed under the GPL and thus the"
   echo "use of this library has to comply with the conditions of the GPL."
 fi
-
index eb804a2..b150b40 100644 (file)
@@ -1,6 +1,7 @@
 2011-02-11  Werner Koch  <wk@g10code.com>
 
        * g10lib.h (HWF_INTEL_AES): Rename to HWF_INTEL_AESNI.
+       * hwfeatures.c (detect_ia32_gnuc): Fix setting of this flag.
 
 2011-02-01  Werner Koch  <wk@g10code.com>