diff --git a/ChangeLog b/ChangeLog
index 25ada286019eee36fc900ae7d45241cd76f6f6db..28141b54873d8ca7d58a30e517f76fbb58870e3e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2015-01-20  Niels Möller  <nisse@lysator.liu.se>
 
+	* fat-x86_64.c (get_x86_features): New function. Check
+	NETTLE_FAT_OVERRIDE environment variable.
+	(fat_init): Use it.
+
+	* fat-setup.h (secure_getenv) [!HAVE_SECURE_GETENV]: Dummy
+	definition, returning NULL.
+	(ENV_OVERRIDE): New constant.
+
 	* configure.ac: Check for secure_getenv function.
 
 2015-01-19  Niels Möller  <nisse@lysator.liu.se>
diff --git a/fat-setup.h b/fat-setup.h
index 70ff9b6ff0ace729dc62ec048eade3a0d4a319e8..f437b4ee06ae9e361cfb257d2d0bd442c7f979bf 100644
--- a/fat-setup.h
+++ b/fat-setup.h
@@ -70,7 +70,12 @@
 # endif
 #endif
 
+#if !HAVE_SECURE_GETENV
+#define secure_getenv(s) NULL
+#endif
+
 #define ENV_VERBOSE "NETTLE_FAT_VERBOSE"
+#define ENV_OVERRIDE "NETTLE_FAT_OVERRIDE"
 
 /* DECLARE_FAT_FUNC(name, ftype)
  *
diff --git a/fat-x86_64.c b/fat-x86_64.c
index 6aab97486a04dc11aded4e78a88a71b8cc8439cc..20be1c57f6a944c0baa7e0aaafde40c487681f38 100644
--- a/fat-x86_64.c
+++ b/fat-x86_64.c
@@ -29,6 +29,8 @@
    not, see http://www.gnu.org/licenses/.
 */
 
+#define _GNU_SOURCE
+
 #if HAVE_CONFIG_H
 # include "config.h"
 #endif
@@ -46,6 +48,61 @@
 
 void _nettle_cpuid (uint32_t input, uint32_t regs[4]);
 
+struct x86_features
+{
+  enum x86_vendor { X86_OTHER, X86_INTEL, X86_AMD } vendor;
+  int have_aesni;
+};
+
+#define SKIP(s, slen, literal, llen)				\
+  (((slen) >= (llen) && memcmp ((s), (literal), llen) == 0)	\
+   ? ((slen) -= (llen), (s) += (llen), 1) : 0)
+#define MATCH(s, slen, literal, llen)				\
+  ((slen) == (llen) && memcmp ((s), (literal), llen) == 0)
+
+static void
+get_x86_features (struct x86_features *features)
+{
+  const char *s;
+  features->vendor = X86_OTHER;
+  features->have_aesni = 0;
+
+  s = secure_getenv (ENV_OVERRIDE);
+  if (s)
+    for (;;)
+      {
+	const char *sep = strchr (s, ',');
+	size_t length = sep ? (size_t) (sep - s) : strlen(s);
+
+	if (SKIP (s, length, "vendor:", 7))
+	  {
+	    if (MATCH(s, length, "intel", 5))
+	      features->vendor = X86_INTEL;
+	    else if (MATCH(s, length, "amd", 3))
+	      features->vendor = X86_AMD;
+	    
+	  }
+	else if (MATCH (s, length, "aesni", 5))
+	  features->have_aesni = 1;
+	if (!sep)
+	  break;
+	s = sep + 1;	
+      }
+  else
+    {
+      uint32_t cpuid_data[4];
+      _nettle_cpuid (0, cpuid_data);
+      if (memcmp (cpuid_data + 1, "Genu" "ntel" "ineI", 12) == 0)
+	features->vendor = X86_INTEL;
+      else if (memcmp (cpuid_data + 1, "Auth" "cAMD" "enti", 12) == 0)
+	features->vendor = X86_AMD;
+
+      _nettle_cpuid (1, cpuid_data);
+      if (cpuid_data[2] & 0x02000000)
+	features->have_aesni = 1;      
+    }
+}
+
 DECLARE_FAT_FUNC(_nettle_aes_encrypt, aes_crypt_internal_func)
 DECLARE_FAT_FUNC_VAR(aes_encrypt, aes_crypt_internal_func, x86_64)
 DECLARE_FAT_FUNC_VAR(aes_encrypt, aes_crypt_internal_func, aesni)
@@ -66,7 +123,7 @@ static void CONSTRUCTOR
 fat_init (void)
 {
   static volatile int initialized = 0;
-  uint32_t cpuid_data[4];
+  struct x86_features features;
   int verbose;
   if (initialized)
     return;
@@ -76,39 +133,40 @@ fat_init (void)
   if (verbose)
     fprintf (stderr, "libnettle: fat library initialization.\n");
 
-  _nettle_cpuid (1, cpuid_data);
+  get_x86_features (&features);
   if (verbose)
-    fprintf (stderr, "libnettle: cpuid 1: %08x, %08x, %08x, %08x\n",
-	     cpuid_data[0], cpuid_data[1], cpuid_data[2], cpuid_data[3]);
-
-  if (cpuid_data[2] & 0x02000000)
+    {
+      const char * const vendor_names[3] =
+	{ "other", "intel", "amd" };
+      fprintf (stderr, "libnettle: cpu features: vendor:%s%s\n",
+	       vendor_names[features.vendor],
+	       features.have_aesni ? ",aesni" : "");
+    }
+  if (features.have_aesni)
     {
       if (verbose)
-	fprintf (stderr, "libnettle: aes instructions available.\n");
+	fprintf (stderr, "libnettle: using aes instructions.\n");
       _nettle_aes_encrypt_vec = _nettle_aes_encrypt_aesni;
       _nettle_aes_decrypt_vec = _nettle_aes_decrypt_aesni;
     }
   else
     {
       if (verbose)
-	fprintf (stderr, "libnettle: aes instructions not available.\n");
+	fprintf (stderr, "libnettle: not using aes instructions.\n");
       _nettle_aes_encrypt_vec = _nettle_aes_encrypt_x86_64;
       _nettle_aes_decrypt_vec = _nettle_aes_decrypt_x86_64;
     }
 
-  _nettle_cpuid (0, cpuid_data);
-  if (memcmp(&cpuid_data[1], "Genu", 4) == 0 &&
-      memcmp(&cpuid_data[3], "ineI", 4) == 0 &&
-      memcmp(&cpuid_data[2], "ntel", 4) == 0)
+  if (features.vendor == X86_INTEL)
     {
       if (verbose)
-	fprintf (stderr, "libnettle: intel SSE2 will be used for XOR.\n");
+	fprintf (stderr, "libnettle: intel SSE2 will be used for memxor.\n");
       nettle_memxor_vec = _nettle_memxor_sse2;
     }
   else
     {
       if (verbose)
-	fprintf (stderr, "libnettle: intel SSE2 will not be used for XOR.\n");
+	fprintf (stderr, "libnettle: intel SSE2 will not be used for memxor.\n");
       nettle_memxor_vec = _nettle_memxor_x86_64;
     }