diff --git a/ChangeLog b/ChangeLog
index ca7d0c1fce916769c9c06d0aea82bd0006f80925..965d894d26afcfab844c4db00a4a014e51ae7a0d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,98 @@
+2013-09-28  Niels Möller  <nisse@lysator.liu.se>
+
+	* Merge aes-reorg branch. Changes below,
+	dated 2013-05-17 - 2013-08-13.
+
+2013-08-13  Niels Möller  <nisse@lysator.liu.se>
+
+	* yarrow.h (struct yarrow256_ctx): Use aes256_ctx, not aes_ctx.
+	* yarrow256.c: Adapted to use new aes256 interface.
+
+2013-08-07  Niels Möller  <nisse@lysator.liu.se>
+
+	* umac.h (_UMAC_STATE): Use struct aes128_ctx, not aes_ctx.
+	* umac-set-key.c (umac_kdf, _umac_set_key): Use aes128 interface.
+	* umac32.c (umac32_digest): Likewise.
+	* umac64.c (umac64_digest): Likewise.
+	* umac96.c (umac96_digest): Likewise.
+	* umac128.c (umac128_digest): Likewise.
+
+2013-06-25  Niels Möller  <nisse@lysator.liu.se>
+
+	* aes-meta.c: Deleted file.
+
+	Analogous changes for new aes192 and aes256 interface.
+
+	* aes.h (struct aes128_ctx): New aes128 declarations.
+	* aes-decrypt.c (aes128_decrypt): New function.
+	* aes-encrypt.c (aes128_encrypt): New function.
+	* aes128-meta.c: New file.
+	* aes128-set-encrypt-key.c (aes128_set_encrypt_key): New file and
+	function.
+	* aes128-set-decrypt-key.c (aes128_set_decrypt_key)
+	(aes128_invert_key): New file and functions.
+	* Makefile.in (nettle_SOURCES): Added aes128-set-encrypt-key.c,
+	aes128-set-decrypt-key.c and aes128-meta.c.
+
+	* nettle-internal.c (nettle_unified_aes128): For testing the old
+	AES interface.
+	* testsuite/aes-test.c (test_cipher2): New function.
+	(test_main): Test both nettle_aes128 and nettle_unified_aes128.
+
+2013-05-22  Niels Möller  <nisse@lysator.liu.se>
+
+	* Makefile.in (nettle_SOURCES): Added aes-invert-internal.c and
+	aes-set-key-internal.c.
+
+	* aes.h (AES128_KEY_SIZE, _AES128_ROUNDS): New constants.
+	Similarly also for aes192 and aes256.
+
+	* aes-internal.h: Declare new functions.
+
+	* aes-set-key-internal.c (_aes_set_key): New file and funxtion
+	extracted from aes_set_encrypt_key.
+	* aes-set-encrypt-key.c (aes_set_encrypt_key): Use _aes_set_key.
+
+	* aes-invert-internal.c (_aes_invert): New file and function,
+	extracted from aes_invert_key.
+	* aes-set-decrypt-key.c (aes_invert_key): Use _aes_invert.
+
+	* arm/v6/aes-encrypt-internal.asm: Adapted to new interface.
+	Unfortunately, 4% slowdown on Cortex-A9, for unknown reason.
+	* arm/v6/aes-decrypt-internal.asm: Likewise.
+	* arm/aes-encrypt-internal.asm: Adapted to new interface.
+	* arm/aes-decrypt-internal.asm: Likewise.
+
+2013-05-21  Niels Möller  <nisse@lysator.liu.se>
+
+	* sparc32/aes-encrypt-internal.asm: Adapted to new interface.
+	* sparc32/aes-decrypt-internal.asm: Likewise.
+	* sparc64/aes-encrypt-internal.asm: Likewise.
+	* sparc64/aes-decrypt-internal.asm: Likewise.
+
+	* x86/aes-encrypt-internal.asm: Adapted to new interface.
+	* x86/aes-decrypt-internal.asm: Likewise.
+
+2013-05-20  Niels Möller  <nisse@lysator.liu.se>
+
+	* x86_64/aes-encrypt-internal.asm: Adapted to new interface.
+	* x86_64/aes-decrypt-internal.asm: Likewise.
+
+2013-05-17  Niels Möller  <nisse@lysator.liu.se>
+
+	* aes.h (struct aes_ctx): Renamed nrounds to rounds, and moved
+	first in the structure.
+	* aes-set-encrypt-key.c (aes_set_encrypt_key): Updated for renaming.
+	* aes-set-decrypt-key.c (aes_invert_key): Likewise.
+
+	* aes-encrypt-internal.c (_nettle_aes_encrypt): Take rounds and
+	subkeys as separate arguments, not a struct aes_ctx *. Updated
+	callers.
+	* aes-decrypt-internal.c (_nettle_aes_decrypt): Likewise.
+	* aes-internal.h: Updated prototypes.
+
+	* Start of aes-reorg changes.
+
 2013-09-28  Niels Möller  <nisse@lysator.liu.se>
 
 	* md4.h (struct md4_ctx): Use single uint64_t variable for block
diff --git a/Makefile.in b/Makefile.in
index 3e03f0b32c97a78dcba0d21d6b658e3e5618374f..253ccec361e55dd70a6c6224a85e56c4ca7f7c5a 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -64,7 +64,14 @@ all-here: $(TARGETS) $(DOCTARGETS)
 
 nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c \
 		 aes-encrypt-internal.c aes-encrypt.c aes-encrypt-table.c \
-		 aes-set-encrypt-key.c aes-set-decrypt-key.c aes-meta.c \
+		 aes-invert-internal.c aes-set-key-internal.c \
+		 aes-set-encrypt-key.c aes-set-decrypt-key.c \
+		 aes128-set-encrypt-key.c aes128-set-decrypt-key.c \
+		 aes128-meta.c \
+		 aes192-set-encrypt-key.c aes192-set-decrypt-key.c \
+		 aes192-meta.c \
+		 aes256-set-encrypt-key.c aes256-set-decrypt-key.c \
+		 aes256-meta.c \
 		 arcfour.c arcfour-crypt.c arcfour-meta.c \
 		 arctwo.c arctwo-meta.c gosthash94-meta.c \
 		 base16-encode.c base16-decode.c base16-meta.c \
diff --git a/aes-decrypt-internal.c b/aes-decrypt-internal.c
index af2891e9fc2582ebfd79465dba302cffae88e2e5..be73e680dd23a06e76b66be06b46f3ce028af093 100644
--- a/aes-decrypt-internal.c
+++ b/aes-decrypt-internal.c
@@ -5,7 +5,7 @@
 
 /* nettle, low-level cryptographics library
  *
- * Copyright (C) 2002 Niels Möller
+ * Copyright (C) 2002, 2013 Niels Möller
  *  
  * The nettle 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
@@ -33,7 +33,7 @@
 #include "macros.h"
 
 void
-_nettle_aes_decrypt(const struct aes_ctx *ctx,
+_nettle_aes_decrypt(unsigned rounds, const uint32_t *keys,
 		    const struct aes_table *T,
 		    size_t length, uint8_t *dst,
 		    const uint8_t *src)
@@ -42,22 +42,22 @@ _nettle_aes_decrypt(const struct aes_ctx *ctx,
     {
       uint32_t w0, w1, w2, w3;		/* working ciphertext */
       uint32_t t0, t1, t2, t3;
-      unsigned round;
+      unsigned i;
       
       /* Get clear text, using little-endian byte order.
        * Also XOR with the first subkey. */
 
-      w0 = LE_READ_UINT32(src)      ^ ctx->keys[0];
-      w1 = LE_READ_UINT32(src + 4)  ^ ctx->keys[1];
-      w2 = LE_READ_UINT32(src + 8)  ^ ctx->keys[2];
-      w3 = LE_READ_UINT32(src + 12) ^ ctx->keys[3];
+      w0 = LE_READ_UINT32(src)      ^ keys[0];
+      w1 = LE_READ_UINT32(src + 4)  ^ keys[1];
+      w2 = LE_READ_UINT32(src + 8)  ^ keys[2];
+      w3 = LE_READ_UINT32(src + 12) ^ keys[3];
 
-      for (round = 1; round < ctx->nrounds; round++)
+      for (i = 1; i < rounds; i++)
 	{
-	  t0 = AES_ROUND(T, w0, w3, w2, w1, ctx->keys[4*round]);
-	  t1 = AES_ROUND(T, w1, w0, w3, w2, ctx->keys[4*round + 1]);
-	  t2 = AES_ROUND(T, w2, w1, w0, w3, ctx->keys[4*round + 2]);
-	  t3 = AES_ROUND(T, w3, w2, w1, w0, ctx->keys[4*round + 3]);
+	  t0 = AES_ROUND(T, w0, w3, w2, w1, keys[4*i]);
+	  t1 = AES_ROUND(T, w1, w0, w3, w2, keys[4*i + 1]);
+	  t2 = AES_ROUND(T, w2, w1, w0, w3, keys[4*i + 2]);
+	  t3 = AES_ROUND(T, w3, w2, w1, w0, keys[4*i + 3]);
 
 	  /* We could unroll the loop twice, to avoid these
 	     assignments. If all eight variables fit in registers,
@@ -70,14 +70,14 @@ _nettle_aes_decrypt(const struct aes_ctx *ctx,
 
       /* Final round */
 
-      t0 = AES_FINAL_ROUND(T, w0, w3, w2, w1, ctx->keys[4*round]);
-      t1 = AES_FINAL_ROUND(T, w1, w0, w3, w2, ctx->keys[4*round + 1]);
-      t2 = AES_FINAL_ROUND(T, w2, w1, w0, w3, ctx->keys[4*round + 2]);
-      t3 = AES_FINAL_ROUND(T, w3, w2, w1, w0, ctx->keys[4*round + 3]);
+      t0 = AES_FINAL_ROUND(T, w0, w3, w2, w1, keys[4*i]);
+      t1 = AES_FINAL_ROUND(T, w1, w0, w3, w2, keys[4*i + 1]);
+      t2 = AES_FINAL_ROUND(T, w2, w1, w0, w3, keys[4*i + 2]);
+      t3 = AES_FINAL_ROUND(T, w3, w2, w1, w0, keys[4*i + 3]);
 
       LE_WRITE_UINT32(dst, t0);
-      LE_WRITE_UINT32(dst + 8, t2);
       LE_WRITE_UINT32(dst + 4, t1);
+      LE_WRITE_UINT32(dst + 8, t2);
       LE_WRITE_UINT32(dst + 12, t3);
     }
 }
diff --git a/aes-decrypt.c b/aes-decrypt.c
index 96862e4787018b6807926c2c364a65d6b00f7c03..d0fefc4f363b1bc447e6dc09be4f406ad1cc1a43 100644
--- a/aes-decrypt.c
+++ b/aes-decrypt.c
@@ -5,7 +5,7 @@
 
 /* nettle, low-level cryptographics library
  *
- * Copyright (C) 2002 Niels Möller
+ * Copyright (C) 2002, 2013 Niels Möller
  *  
  * The nettle 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
@@ -342,6 +342,36 @@ aes_decrypt(const struct aes_ctx *ctx,
 	    const uint8_t *src)
 {
   assert(!(length % AES_BLOCK_SIZE) );
-  _aes_decrypt(ctx, &_aes_decrypt_table,
+  _aes_decrypt(ctx->rounds, ctx->keys, &_aes_decrypt_table,
+	       length, dst, src);
+}
+
+void
+aes128_decrypt(const struct aes128_ctx *ctx,
+	       size_t length, uint8_t *dst,
+	       const uint8_t *src)
+{
+  assert(!(length % AES_BLOCK_SIZE) );
+  _aes_decrypt(_AES128_ROUNDS, ctx->keys, &_aes_decrypt_table,
+	       length, dst, src);
+}
+
+void
+aes192_decrypt(const struct aes192_ctx *ctx,
+	       size_t length, uint8_t *dst,
+	       const uint8_t *src)
+{
+  assert(!(length % AES_BLOCK_SIZE) );
+  _aes_decrypt(_AES192_ROUNDS, ctx->keys, &_aes_decrypt_table,
+	       length, dst, src);
+}
+
+void
+aes256_decrypt(const struct aes256_ctx *ctx,
+	       size_t length, uint8_t *dst,
+	       const uint8_t *src)
+{
+  assert(!(length % AES_BLOCK_SIZE) );
+  _aes_decrypt(_AES256_ROUNDS, ctx->keys, &_aes_decrypt_table,
 	       length, dst, src);
 }
diff --git a/aes-encrypt-internal.c b/aes-encrypt-internal.c
index cf9d82475328b96543e796fe9fcaeddc74595334..2f34f21e877219f596062442b16ebf89300cc35a 100644
--- a/aes-encrypt-internal.c
+++ b/aes-encrypt-internal.c
@@ -5,7 +5,7 @@
 
 /* nettle, low-level cryptographics library
  *
- * Copyright (C) 2002 Niels Möller
+ * Copyright (C) 2002, 2013 Niels Möller
  *  
  * The nettle 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
@@ -33,7 +33,7 @@
 #include "macros.h"
 
 void
-_nettle_aes_encrypt(const struct aes_ctx *ctx,
+_nettle_aes_encrypt(unsigned rounds, const uint32_t *keys,
 		    const struct aes_table *T,
 		    size_t length, uint8_t *dst,
 		    const uint8_t *src)
@@ -42,22 +42,22 @@ _nettle_aes_encrypt(const struct aes_ctx *ctx,
     {
       uint32_t w0, w1, w2, w3;		/* working ciphertext */
       uint32_t t0, t1, t2, t3;
-      unsigned round;
+      unsigned i;
       
       /* Get clear text, using little-endian byte order.
        * Also XOR with the first subkey. */
 
-      w0 = LE_READ_UINT32(src)      ^ ctx->keys[0];
-      w1 = LE_READ_UINT32(src + 4)  ^ ctx->keys[1];
-      w2 = LE_READ_UINT32(src + 8)  ^ ctx->keys[2];
-      w3 = LE_READ_UINT32(src + 12) ^ ctx->keys[3];
+      w0 = LE_READ_UINT32(src)      ^ keys[0];
+      w1 = LE_READ_UINT32(src + 4)  ^ keys[1];
+      w2 = LE_READ_UINT32(src + 8)  ^ keys[2];
+      w3 = LE_READ_UINT32(src + 12) ^ keys[3];
 
-      for (round = 1; round < ctx->nrounds; round++)
+      for (i = 1; i < rounds; i++)
 	{
-	  t0 = AES_ROUND(T, w0, w1, w2, w3, ctx->keys[4*round]);
-	  t1 = AES_ROUND(T, w1, w2, w3, w0, ctx->keys[4*round + 1]);
-	  t2 = AES_ROUND(T, w2, w3, w0, w1, ctx->keys[4*round + 2]);
-	  t3 = AES_ROUND(T, w3, w0, w1, w2, ctx->keys[4*round + 3]);
+	  t0 = AES_ROUND(T, w0, w1, w2, w3, keys[4*i]);
+	  t1 = AES_ROUND(T, w1, w2, w3, w0, keys[4*i + 1]);
+	  t2 = AES_ROUND(T, w2, w3, w0, w1, keys[4*i + 2]);
+	  t3 = AES_ROUND(T, w3, w0, w1, w2, keys[4*i + 3]);
 
 	  /* We could unroll the loop twice, to avoid these
 	     assignments. If all eight variables fit in registers,
@@ -70,14 +70,14 @@ _nettle_aes_encrypt(const struct aes_ctx *ctx,
 
       /* Final round */
 
-      t0 = AES_FINAL_ROUND(T, w0, w1, w2, w3, ctx->keys[4*round]);
-      t1 = AES_FINAL_ROUND(T, w1, w2, w3, w0, ctx->keys[4*round + 1]);
-      t2 = AES_FINAL_ROUND(T, w2, w3, w0, w1, ctx->keys[4*round + 2]);
-      t3 = AES_FINAL_ROUND(T, w3, w0, w1, w2, ctx->keys[4*round + 3]);
+      t0 = AES_FINAL_ROUND(T, w0, w1, w2, w3, keys[4*i]);
+      t1 = AES_FINAL_ROUND(T, w1, w2, w3, w0, keys[4*i + 1]);
+      t2 = AES_FINAL_ROUND(T, w2, w3, w0, w1, keys[4*i + 2]);
+      t3 = AES_FINAL_ROUND(T, w3, w0, w1, w2, keys[4*i + 3]);
 
       LE_WRITE_UINT32(dst, t0);
-      LE_WRITE_UINT32(dst + 8, t2);
       LE_WRITE_UINT32(dst + 4, t1);
+      LE_WRITE_UINT32(dst + 8, t2);
       LE_WRITE_UINT32(dst + 12, t3);
     }
 }
diff --git a/aes-encrypt.c b/aes-encrypt.c
index f28ac3197c2a9b7983eb7f379e1749e8f1ef191b..8d55ca18d32103878f139e13ad96c8e39c6dbae7 100644
--- a/aes-encrypt.c
+++ b/aes-encrypt.c
@@ -5,7 +5,7 @@
 
 /* nettle, low-level cryptographics library
  *
- * Copyright (C) 2002 Niels Möller
+ * Copyright (C) 2002, 2013 Niels Möller
  *  
  * The nettle 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
@@ -40,6 +40,36 @@ aes_encrypt(const struct aes_ctx *ctx,
 	    const uint8_t *src)
 {
   assert(!(length % AES_BLOCK_SIZE) );
-  _aes_encrypt(ctx, &_aes_encrypt_table,
+  _aes_encrypt(ctx->rounds, ctx->keys, &_aes_encrypt_table,
+	       length, dst, src);
+}
+
+void
+aes128_encrypt(const struct aes128_ctx *ctx,
+	       size_t length, uint8_t *dst,
+	       const uint8_t *src)
+{
+  assert(!(length % AES_BLOCK_SIZE) );
+  _aes_encrypt(_AES128_ROUNDS, ctx->keys, &_aes_encrypt_table,
+	       length, dst, src);
+}
+
+void
+aes192_encrypt(const struct aes192_ctx *ctx,
+	       size_t length, uint8_t *dst,
+	       const uint8_t *src)
+{
+  assert(!(length % AES_BLOCK_SIZE) );
+  _aes_encrypt(_AES192_ROUNDS, ctx->keys, &_aes_encrypt_table,
+	       length, dst, src);
+}
+
+void
+aes256_encrypt(const struct aes256_ctx *ctx,
+	       size_t length, uint8_t *dst,
+	       const uint8_t *src)
+{
+  assert(!(length % AES_BLOCK_SIZE) );
+  _aes_encrypt(_AES256_ROUNDS, ctx->keys, &_aes_encrypt_table,
 	       length, dst, src);
 }
diff --git a/aes-internal.h b/aes-internal.h
index e361bde93e5bc1d7f6c58456aecbd6b20de41157..9f2b8cd79ab7c027d7fe7967f484c7c6377afa68 100644
--- a/aes-internal.h
+++ b/aes-internal.h
@@ -5,7 +5,7 @@
 
 /* nettle, low-level cryptographics library
  *
- * Copyright (C) 2001 Niels Möller
+ * Copyright (C) 2001, 2013 Niels Möller
  *  
  * The nettle 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
@@ -29,6 +29,8 @@
 #include "aes.h"
 
 /* Name mangling */
+#define _aes_set_key _nettle_aes_set_key
+#define _aes_invert _nettle_aes_invert
 #define _aes_encrypt _nettle_aes_encrypt
 #define _aes_decrypt _nettle_aes_decrypt
 #define _aes_encrypt_table _nettle_aes_encrypt_table
@@ -51,13 +53,20 @@ struct aes_table
 };
 
 void
-_aes_encrypt(const struct aes_ctx *ctx,
+_aes_set_key(unsigned nr, unsigned nk,
+	     uint32_t *subkeys, const uint8_t *key);
+
+void
+_aes_invert(unsigned rounds, uint32_t *dst, const uint32_t *src);
+
+void
+_aes_encrypt(unsigned rounds, const uint32_t *keys,
 	     const struct aes_table *T,
 	     size_t length, uint8_t *dst,
 	     const uint8_t *src);
 
 void
-_aes_decrypt(const struct aes_ctx *ctx,
+_aes_decrypt(unsigned rounds, const uint32_t *keys,
 	     const struct aes_table *T,
 	     size_t length, uint8_t *dst,
 	     const uint8_t *src);
diff --git a/aes-invert-internal.c b/aes-invert-internal.c
new file mode 100644
index 0000000000000000000000000000000000000000..0ee4a38ebab7cdb4e7f9d96d4c8c2296d39b9975
--- /dev/null
+++ b/aes-invert-internal.c
@@ -0,0 +1,156 @@
+/* aes-invert-internal.c
+ *
+ * Inverse key setup for the aes/rijndael block cipher.
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2000, 2001, 2002, Rafael R. Sevilla, Niels Möller
+ * Copyright (C) 2013 Niels Möller
+ *  
+ * The nettle 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 nettle 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 nettle library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02111-1301, USA.
+ */
+
+/* Originally written by Rafael R. Sevilla <dido@pacific.net.ph> */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "aes-internal.h"
+
+#include "macros.h"
+
+/* NOTE: We don't include rotated versions of the table. */
+static const uint32_t mtable[0x100] =
+{
+  0x00000000,0x0b0d090e,0x161a121c,0x1d171b12,
+  0x2c342438,0x27392d36,0x3a2e3624,0x31233f2a,
+  0x58684870,0x5365417e,0x4e725a6c,0x457f5362,
+  0x745c6c48,0x7f516546,0x62467e54,0x694b775a,
+  0xb0d090e0,0xbbdd99ee,0xa6ca82fc,0xadc78bf2,
+  0x9ce4b4d8,0x97e9bdd6,0x8afea6c4,0x81f3afca,
+  0xe8b8d890,0xe3b5d19e,0xfea2ca8c,0xf5afc382,
+  0xc48cfca8,0xcf81f5a6,0xd296eeb4,0xd99be7ba,
+  0x7bbb3bdb,0x70b632d5,0x6da129c7,0x66ac20c9,
+  0x578f1fe3,0x5c8216ed,0x41950dff,0x4a9804f1,
+  0x23d373ab,0x28de7aa5,0x35c961b7,0x3ec468b9,
+  0x0fe75793,0x04ea5e9d,0x19fd458f,0x12f04c81,
+  0xcb6bab3b,0xc066a235,0xdd71b927,0xd67cb029,
+  0xe75f8f03,0xec52860d,0xf1459d1f,0xfa489411,
+  0x9303e34b,0x980eea45,0x8519f157,0x8e14f859,
+  0xbf37c773,0xb43ace7d,0xa92dd56f,0xa220dc61,
+  0xf66d76ad,0xfd607fa3,0xe07764b1,0xeb7a6dbf,
+  0xda595295,0xd1545b9b,0xcc434089,0xc74e4987,
+  0xae053edd,0xa50837d3,0xb81f2cc1,0xb31225cf,
+  0x82311ae5,0x893c13eb,0x942b08f9,0x9f2601f7,
+  0x46bde64d,0x4db0ef43,0x50a7f451,0x5baafd5f,
+  0x6a89c275,0x6184cb7b,0x7c93d069,0x779ed967,
+  0x1ed5ae3d,0x15d8a733,0x08cfbc21,0x03c2b52f,
+  0x32e18a05,0x39ec830b,0x24fb9819,0x2ff69117,
+  0x8dd64d76,0x86db4478,0x9bcc5f6a,0x90c15664,
+  0xa1e2694e,0xaaef6040,0xb7f87b52,0xbcf5725c,
+  0xd5be0506,0xdeb30c08,0xc3a4171a,0xc8a91e14,
+  0xf98a213e,0xf2872830,0xef903322,0xe49d3a2c,
+  0x3d06dd96,0x360bd498,0x2b1ccf8a,0x2011c684,
+  0x1132f9ae,0x1a3ff0a0,0x0728ebb2,0x0c25e2bc,
+  0x656e95e6,0x6e639ce8,0x737487fa,0x78798ef4,
+  0x495ab1de,0x4257b8d0,0x5f40a3c2,0x544daacc,
+  0xf7daec41,0xfcd7e54f,0xe1c0fe5d,0xeacdf753,
+  0xdbeec879,0xd0e3c177,0xcdf4da65,0xc6f9d36b,
+  0xafb2a431,0xa4bfad3f,0xb9a8b62d,0xb2a5bf23,
+  0x83868009,0x888b8907,0x959c9215,0x9e919b1b,
+  0x470a7ca1,0x4c0775af,0x51106ebd,0x5a1d67b3,
+  0x6b3e5899,0x60335197,0x7d244a85,0x7629438b,
+  0x1f6234d1,0x146f3ddf,0x097826cd,0x02752fc3,
+  0x335610e9,0x385b19e7,0x254c02f5,0x2e410bfb,
+  0x8c61d79a,0x876cde94,0x9a7bc586,0x9176cc88,
+  0xa055f3a2,0xab58faac,0xb64fe1be,0xbd42e8b0,
+  0xd4099fea,0xdf0496e4,0xc2138df6,0xc91e84f8,
+  0xf83dbbd2,0xf330b2dc,0xee27a9ce,0xe52aa0c0,
+  0x3cb1477a,0x37bc4e74,0x2aab5566,0x21a65c68,
+  0x10856342,0x1b886a4c,0x069f715e,0x0d927850,
+  0x64d90f0a,0x6fd40604,0x72c31d16,0x79ce1418,
+  0x48ed2b32,0x43e0223c,0x5ef7392e,0x55fa3020,
+  0x01b79aec,0x0aba93e2,0x17ad88f0,0x1ca081fe,
+  0x2d83bed4,0x268eb7da,0x3b99acc8,0x3094a5c6,
+  0x59dfd29c,0x52d2db92,0x4fc5c080,0x44c8c98e,
+  0x75ebf6a4,0x7ee6ffaa,0x63f1e4b8,0x68fcedb6,
+  0xb1670a0c,0xba6a0302,0xa77d1810,0xac70111e,
+  0x9d532e34,0x965e273a,0x8b493c28,0x80443526,
+  0xe90f427c,0xe2024b72,0xff155060,0xf418596e,
+  0xc53b6644,0xce366f4a,0xd3217458,0xd82c7d56,
+  0x7a0ca137,0x7101a839,0x6c16b32b,0x671bba25,
+  0x5638850f,0x5d358c01,0x40229713,0x4b2f9e1d,
+  0x2264e947,0x2969e049,0x347efb5b,0x3f73f255,
+  0x0e50cd7f,0x055dc471,0x184adf63,0x1347d66d,
+  0xcadc31d7,0xc1d138d9,0xdcc623cb,0xd7cb2ac5,
+  0xe6e815ef,0xede51ce1,0xf0f207f3,0xfbff0efd,
+  0x92b479a7,0x99b970a9,0x84ae6bbb,0x8fa362b5,
+  0xbe805d9f,0xb58d5491,0xa89a4f83,0xa397468d,
+};
+
+#define MIX_COLUMN(T, key) do { \
+    uint32_t _k, _nk, _t;	\
+    _k = (key);			\
+    _nk = T[_k & 0xff];		\
+    _k >>= 8;			\
+    _t = T[_k & 0xff];		\
+    _nk ^= ROTL32(8, _t);	\
+    _k >>= 8;			\
+    _t = T[_k & 0xff];		\
+    _nk ^= ROTL32(16, _t);	\
+    _k >>= 8;			\
+    _t = T[_k & 0xff];		\
+    _nk ^= ROTL32(24, _t);	\
+    (key) = _nk;		\
+  } while(0)
+  
+
+#define SWAP(a, b) \
+do { uint32_t t_swap = (a); (a) = (b); (b) = t_swap; } while(0)
+
+void
+_aes_invert(unsigned rounds, uint32_t *dst, const uint32_t *src)
+{
+  unsigned i;
+
+  /* Reverse the order of subkeys, in groups of 4. */
+  /* FIXME: Instead of reordering the subkeys, change the access order
+     of aes_decrypt, since it's a separate function anyway? */
+  if (src == dst)
+    {
+      unsigned j, k;
+
+      for (i = 0, j = rounds * 4;
+	   i < j;
+	   i += 4, j -= 4)
+	for (k = 0; k<4; k++)
+	  SWAP(dst[i+k], dst[j+k]);
+    }
+  else
+    {
+      unsigned k;
+
+      for (i = 0; i <= rounds * 4; i += 4)
+	for (k = 0; k < 4; k++)
+	  dst[i+k] = src[rounds * 4 - i + k];
+    }
+
+  /* Transform all subkeys but the first and last. */
+  for (i = 4; i < 4 * rounds; i++)
+    MIX_COLUMN (mtable, dst[i]);
+}
diff --git a/aes-set-decrypt-key.c b/aes-set-decrypt-key.c
index 04e4c992087b303278a911b0739c5f68e6eae6a1..84a644bac7d391e5aef948cab511ac92742139e3 100644
--- a/aes-set-decrypt-key.c
+++ b/aes-set-decrypt-key.c
@@ -6,6 +6,7 @@
 /* nettle, low-level cryptographics library
  *
  * Copyright (C) 2000, 2001, 2002 Rafael R. Sevilla, Niels Möller
+ * Copyright (C) 2013 Niels Möller
  *  
  * The nettle 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
@@ -31,132 +32,12 @@
 
 #include "aes-internal.h"
 
-#include "macros.h"
-
-/* NOTE: We don't include rotated versions of the table. */
-static const uint32_t mtable[0x100] =
-{
-  0x00000000,0x0b0d090e,0x161a121c,0x1d171b12,
-  0x2c342438,0x27392d36,0x3a2e3624,0x31233f2a,
-  0x58684870,0x5365417e,0x4e725a6c,0x457f5362,
-  0x745c6c48,0x7f516546,0x62467e54,0x694b775a,
-  0xb0d090e0,0xbbdd99ee,0xa6ca82fc,0xadc78bf2,
-  0x9ce4b4d8,0x97e9bdd6,0x8afea6c4,0x81f3afca,
-  0xe8b8d890,0xe3b5d19e,0xfea2ca8c,0xf5afc382,
-  0xc48cfca8,0xcf81f5a6,0xd296eeb4,0xd99be7ba,
-  0x7bbb3bdb,0x70b632d5,0x6da129c7,0x66ac20c9,
-  0x578f1fe3,0x5c8216ed,0x41950dff,0x4a9804f1,
-  0x23d373ab,0x28de7aa5,0x35c961b7,0x3ec468b9,
-  0x0fe75793,0x04ea5e9d,0x19fd458f,0x12f04c81,
-  0xcb6bab3b,0xc066a235,0xdd71b927,0xd67cb029,
-  0xe75f8f03,0xec52860d,0xf1459d1f,0xfa489411,
-  0x9303e34b,0x980eea45,0x8519f157,0x8e14f859,
-  0xbf37c773,0xb43ace7d,0xa92dd56f,0xa220dc61,
-  0xf66d76ad,0xfd607fa3,0xe07764b1,0xeb7a6dbf,
-  0xda595295,0xd1545b9b,0xcc434089,0xc74e4987,
-  0xae053edd,0xa50837d3,0xb81f2cc1,0xb31225cf,
-  0x82311ae5,0x893c13eb,0x942b08f9,0x9f2601f7,
-  0x46bde64d,0x4db0ef43,0x50a7f451,0x5baafd5f,
-  0x6a89c275,0x6184cb7b,0x7c93d069,0x779ed967,
-  0x1ed5ae3d,0x15d8a733,0x08cfbc21,0x03c2b52f,
-  0x32e18a05,0x39ec830b,0x24fb9819,0x2ff69117,
-  0x8dd64d76,0x86db4478,0x9bcc5f6a,0x90c15664,
-  0xa1e2694e,0xaaef6040,0xb7f87b52,0xbcf5725c,
-  0xd5be0506,0xdeb30c08,0xc3a4171a,0xc8a91e14,
-  0xf98a213e,0xf2872830,0xef903322,0xe49d3a2c,
-  0x3d06dd96,0x360bd498,0x2b1ccf8a,0x2011c684,
-  0x1132f9ae,0x1a3ff0a0,0x0728ebb2,0x0c25e2bc,
-  0x656e95e6,0x6e639ce8,0x737487fa,0x78798ef4,
-  0x495ab1de,0x4257b8d0,0x5f40a3c2,0x544daacc,
-  0xf7daec41,0xfcd7e54f,0xe1c0fe5d,0xeacdf753,
-  0xdbeec879,0xd0e3c177,0xcdf4da65,0xc6f9d36b,
-  0xafb2a431,0xa4bfad3f,0xb9a8b62d,0xb2a5bf23,
-  0x83868009,0x888b8907,0x959c9215,0x9e919b1b,
-  0x470a7ca1,0x4c0775af,0x51106ebd,0x5a1d67b3,
-  0x6b3e5899,0x60335197,0x7d244a85,0x7629438b,
-  0x1f6234d1,0x146f3ddf,0x097826cd,0x02752fc3,
-  0x335610e9,0x385b19e7,0x254c02f5,0x2e410bfb,
-  0x8c61d79a,0x876cde94,0x9a7bc586,0x9176cc88,
-  0xa055f3a2,0xab58faac,0xb64fe1be,0xbd42e8b0,
-  0xd4099fea,0xdf0496e4,0xc2138df6,0xc91e84f8,
-  0xf83dbbd2,0xf330b2dc,0xee27a9ce,0xe52aa0c0,
-  0x3cb1477a,0x37bc4e74,0x2aab5566,0x21a65c68,
-  0x10856342,0x1b886a4c,0x069f715e,0x0d927850,
-  0x64d90f0a,0x6fd40604,0x72c31d16,0x79ce1418,
-  0x48ed2b32,0x43e0223c,0x5ef7392e,0x55fa3020,
-  0x01b79aec,0x0aba93e2,0x17ad88f0,0x1ca081fe,
-  0x2d83bed4,0x268eb7da,0x3b99acc8,0x3094a5c6,
-  0x59dfd29c,0x52d2db92,0x4fc5c080,0x44c8c98e,
-  0x75ebf6a4,0x7ee6ffaa,0x63f1e4b8,0x68fcedb6,
-  0xb1670a0c,0xba6a0302,0xa77d1810,0xac70111e,
-  0x9d532e34,0x965e273a,0x8b493c28,0x80443526,
-  0xe90f427c,0xe2024b72,0xff155060,0xf418596e,
-  0xc53b6644,0xce366f4a,0xd3217458,0xd82c7d56,
-  0x7a0ca137,0x7101a839,0x6c16b32b,0x671bba25,
-  0x5638850f,0x5d358c01,0x40229713,0x4b2f9e1d,
-  0x2264e947,0x2969e049,0x347efb5b,0x3f73f255,
-  0x0e50cd7f,0x055dc471,0x184adf63,0x1347d66d,
-  0xcadc31d7,0xc1d138d9,0xdcc623cb,0xd7cb2ac5,
-  0xe6e815ef,0xede51ce1,0xf0f207f3,0xfbff0efd,
-  0x92b479a7,0x99b970a9,0x84ae6bbb,0x8fa362b5,
-  0xbe805d9f,0xb58d5491,0xa89a4f83,0xa397468d,
-};
-
-#define MIX_COLUMN(T, key) do { \
-    uint32_t _k, _nk, _t;	\
-    _k = (key);			\
-    _nk = T[_k & 0xff];		\
-    _k >>= 8;			\
-    _t = T[_k & 0xff];		\
-    _nk ^= ROTL32(8, _t);	\
-    _k >>= 8;			\
-    _t = T[_k & 0xff];		\
-    _nk ^= ROTL32(16, _t);	\
-    _k >>= 8;			\
-    _t = T[_k & 0xff];		\
-    _nk ^= ROTL32(24, _t);	\
-    (key) = _nk;		\
-  } while(0)
-  
-
-#define SWAP(a, b) \
-do { uint32_t t_swap = (a); (a) = (b); (b) = t_swap; } while(0)
-
 void
 aes_invert_key(struct aes_ctx *dst,
 	       const struct aes_ctx *src)
 {
-  unsigned nrounds;
-  unsigned i;
-
-  nrounds = src->nrounds;
-
-  /* Reverse the order of subkeys, in groups of 4. */
-  /* FIXME: Instead of reordering the subkeys, change the access order
-     of aes_decrypt, since it's a separate function anyway? */
-  if (src == dst)
-    {
-      unsigned j, k;
-
-      for (i = 0, j = nrounds * 4;
-	   i < j;
-	   i += 4, j -= 4)
-	for (k = 0; k<4; k++)
-	  SWAP(dst->keys[i+k], dst->keys[j+k]);
-    }
-  else
-    {
-      unsigned k;
-
-      dst->nrounds = nrounds;
-      for (i = 0; i <= nrounds * 4; i += 4)
-	for (k = 0; k < 4; k++)
-	  dst->keys[i+k] = src->keys[nrounds * 4 - i + k];
-    }
-
-  /* Transform all subkeys but the first and last. */
-  for (i = 4; i < 4 * nrounds; i++)
-    MIX_COLUMN (mtable, dst->keys[i]);
+  _aes_invert (src->rounds, dst->keys, src->keys);
+  dst->rounds = src->rounds;
 }
 
 void
diff --git a/aes-set-encrypt-key.c b/aes-set-encrypt-key.c
index 04f53270f38c8cef3ab54f63da0bcb6ae67601fd..a3f20a13d9d557f788ae03955554e30200c616c6 100644
--- a/aes-set-encrypt-key.c
+++ b/aes-set-encrypt-key.c
@@ -6,6 +6,7 @@
 /* nettle, low-level cryptographics library
  *
  * Copyright (C) 2000, 2001, 2002 Rafael R. Sevilla, Niels Möller
+ * Copyright (C) 2013 Niels Möller
  *  
  * The nettle 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
@@ -32,50 +33,28 @@
 #include <assert.h>
 
 #include "aes-internal.h"
-#include "macros.h"
 
 void
 aes_set_encrypt_key(struct aes_ctx *ctx,
 		    size_t keysize, const uint8_t *key)
 {
-  static const uint8_t rcon[10] = {
-    0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1b,0x36,
-  };
-  unsigned nk, nr, i, lastkey;
-  uint32_t temp;
-  const uint8_t *rp;
+  unsigned nk, nr;
 
   assert(keysize >= AES_MIN_KEY_SIZE);
   assert(keysize <= AES_MAX_KEY_SIZE);
   
   /* Truncate keysizes to the valid key sizes provided by Rijndael */
-  if (keysize == 32) {
+  if (keysize == AES256_KEY_SIZE) {
     nk = 8;
-    nr = 14;
-  } else if (keysize >= 24) {
+    nr = _AES256_ROUNDS;
+  } else if (keysize >= AES192_KEY_SIZE) {
     nk = 6;
-    nr = 12;
+    nr = _AES192_ROUNDS;
   } else { /* must be 16 or more */
     nk = 4;
-    nr = 10;
+    nr = _AES128_ROUNDS;
   }
 
-  lastkey = (AES_BLOCK_SIZE/4) * (nr + 1);
-  ctx->nrounds = nr;
-
-  for (i=0, rp = rcon; i<nk; i++)
-    ctx->keys[i] = LE_READ_UINT32(key + i*4);
-
-  for (i=nk; i<lastkey; i++)
-    {
-      temp = ctx->keys[i-1];
-      if (i % nk == 0)
-	temp = SUBBYTE(ROTL32(24, temp), aes_sbox) ^ *rp++;
-
-      else if (nk > 6 && (i%nk) == 4)
-	temp = SUBBYTE(temp, aes_sbox);
-
-      ctx->keys[i] = ctx->keys[i-nk] ^ temp;
-    }
+  ctx->rounds = nr;
+  _aes_set_key (nr, nk, ctx->keys, key);
 }
-  
diff --git a/aes-set-key-internal.c b/aes-set-key-internal.c
new file mode 100644
index 0000000000000000000000000000000000000000..710cabc9a003602752c839afcb22f8f21ca7af6f
--- /dev/null
+++ b/aes-set-key-internal.c
@@ -0,0 +1,63 @@
+/* aes-set-key-internal.c
+ *
+ * Key setup for the aes/rijndael block cipher.
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2000, 2001, 2002 Rafael R. Sevilla, Niels Möller
+ * Copyright (C) 2013 Niels Möller
+ * 
+ * The nettle 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 nettle 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 nettle library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02111-1301, USA.
+ */
+
+/* Originally written by Rafael R. Sevilla <dido@pacific.net.ph> */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "aes-internal.h"
+#include "macros.h"
+
+void
+_aes_set_key(unsigned nr, unsigned nk,
+	     uint32_t *subkeys, const uint8_t *key)
+{
+  static const uint8_t rcon[10] = {
+    0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1b,0x36,
+  };
+  const uint8_t *rp;
+  unsigned lastkey, i;
+  uint32_t t;
+
+  lastkey = (AES_BLOCK_SIZE/4) * (nr + 1);
+  
+  for (i=0, rp = rcon; i<nk; i++)
+    subkeys[i] = LE_READ_UINT32(key + i*4);
+
+  for (i=nk; i<lastkey; i++)
+    {
+      t = subkeys[i-1];
+      if (i % nk == 0)
+	t = SUBBYTE(ROTL32(24, t), aes_sbox) ^ *rp++;
+
+      else if (nk > 6 && (i%nk) == 4)
+	t = SUBBYTE(t, aes_sbox);
+
+      subkeys[i] = subkeys[i-nk] ^ t;
+    }  
+}
diff --git a/aes.h b/aes.h
index b3bb965912b9e65070c4cfc20e4a7d8f824f69fc..0982aa698212b8afb7a6c3a40e9caa1b86eb223f 100644
--- a/aes.h
+++ b/aes.h
@@ -5,7 +5,7 @@
 
 /* nettle, low-level cryptographics library
  *
- * Copyright (C) 2001 Niels Möller
+ * Copyright (C) 2001, 2013 Niels Möller
  *  
  * The nettle 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
@@ -38,23 +38,44 @@ extern "C" {
 #define aes_invert_key nettle_aes_invert_key
 #define aes_encrypt nettle_aes_encrypt
 #define aes_decrypt nettle_aes_decrypt
+#define aes128_set_encrypt_key nettle_aes128set_encrypt_key
+#define aes128_set_decrypt_key nettle_aes128set_decrypt_key
+#define aes128_invert_key nettle_aes128invert_key
+#define aes128_encrypt nettle_aes128encrypt
+#define aes128_decrypt nettle_aes128decrypt
+#define aes192_set_encrypt_key nettle_aes192set_encrypt_key
+#define aes192_set_decrypt_key nettle_aes192set_decrypt_key
+#define aes192_invert_key nettle_aes192invert_key
+#define aes192_encrypt nettle_aes192encrypt
+#define aes192_decrypt nettle_aes192decrypt
+#define aes256_set_encrypt_key nettle_aes256_set_encrypt_key
+#define aes256_set_decrypt_key nettle_aes256_set_decrypt_key
+#define aes256_invert_key nettle_aes256_invert_key
+#define aes256_encrypt nettle_aes256_encrypt
+#define aes256_decrypt nettle_aes256_decrypt
 
 #define AES_BLOCK_SIZE 16
 
+#define AES128_KEY_SIZE 16
+#define AES192_KEY_SIZE 24
+#define AES256_KEY_SIZE 32
+#define _AES128_ROUNDS 10
+#define _AES192_ROUNDS 12
+#define _AES256_ROUNDS 14
+
 /* Variable key size between 128 and 256 bits. But the only valid
  * values are 16 (128 bits), 24 (192 bits) and 32 (256 bits). */
-#define AES_MIN_KEY_SIZE 16
-#define AES_MAX_KEY_SIZE 32
+#define AES_MIN_KEY_SIZE AES128_KEY_SIZE
+#define AES_MAX_KEY_SIZE AES256_KEY_SIZE
+
+/* Older nettle-2.7 interface */
 
 #define AES_KEY_SIZE 32
 
-/* FIXME: Change to put nrounds first, to make it possible to use a
-   truncated ctx struct, with less subkeys, for the shorter key
-   sizes? */
 struct aes_ctx
 {
-  uint32_t keys[60];  /* maximum size of key schedule */
-  unsigned  nrounds;  /* number of rounds to use for our key size */
+  unsigned rounds;  /* number of rounds to use for our key size */
+  uint32_t keys[4*(_AES256_ROUNDS + 1)];  /* maximum size of key schedule */
 };
 
 void
@@ -78,6 +99,69 @@ aes_decrypt(const struct aes_ctx *ctx,
 	    size_t length, uint8_t *dst,
 	    const uint8_t *src);
 
+struct aes128_ctx
+{
+  uint32_t keys[4 * (_AES128_ROUNDS + 1)];
+};
+
+void
+aes128_set_encrypt_key(struct aes128_ctx *ctx, const uint8_t *key);
+void
+aes128_set_decrypt_key(struct aes128_ctx *ctx, const uint8_t *key);
+void
+aes128_invert_key(struct aes128_ctx *dst,
+		  const struct aes128_ctx *src);
+void
+aes128_encrypt(const struct aes128_ctx *ctx,
+	       size_t length, uint8_t *dst,
+	       const uint8_t *src);
+void
+aes128_decrypt(const struct aes128_ctx *ctx,
+	       size_t length, uint8_t *dst,
+	       const uint8_t *src);
+
+struct aes192_ctx
+{
+  uint32_t keys[4 * (_AES192_ROUNDS + 1)];
+};
+
+void
+aes192_set_encrypt_key(struct aes192_ctx *ctx, const uint8_t *key);
+void
+aes192_set_decrypt_key(struct aes192_ctx *ctx, const uint8_t *key);
+void
+aes192_invert_key(struct aes192_ctx *dst,
+		  const struct aes192_ctx *src);
+void
+aes192_encrypt(const struct aes192_ctx *ctx,
+	       size_t length, uint8_t *dst,
+	       const uint8_t *src);
+void
+aes192_decrypt(const struct aes192_ctx *ctx,
+	       size_t length, uint8_t *dst,
+	       const uint8_t *src);
+
+struct aes256_ctx
+{
+  uint32_t keys[4 * (_AES256_ROUNDS + 1)];
+};
+
+void
+aes256_set_encrypt_key(struct aes256_ctx *ctx, const uint8_t *key);
+void
+aes256_set_decrypt_key(struct aes256_ctx *ctx, const uint8_t *key);
+void
+aes256_invert_key(struct aes256_ctx *dst,
+		  const struct aes256_ctx *src);
+void
+aes256_encrypt(const struct aes256_ctx *ctx,
+	       size_t length, uint8_t *dst,
+	       const uint8_t *src);
+void
+aes256_decrypt(const struct aes256_ctx *ctx,
+	       size_t length, uint8_t *dst,
+	       const uint8_t *src);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/aes128-meta.c b/aes128-meta.c
new file mode 100644
index 0000000000000000000000000000000000000000..c3068990392ae4744f0a87e7913daea329f96859
--- /dev/null
+++ b/aes128-meta.c
@@ -0,0 +1,57 @@
+/* aes128-meta.c */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2013 Niels Möller
+ *  
+ * The nettle 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 nettle 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 nettle library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02111-1301, USA.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+
+#include "nettle-meta.h"
+
+#include "aes.h"
+
+static nettle_set_key_func aes128_set_encrypt_key_wrapper;
+static nettle_set_key_func aes128_set_decrypt_key_wrapper;
+
+static void
+aes128_set_encrypt_key_wrapper (void *ctx, size_t length, const uint8_t *key)
+{
+  assert (length == AES128_KEY_SIZE);
+  aes128_set_encrypt_key (ctx, key);
+}
+
+static void
+aes128_set_decrypt_key_wrapper (void *ctx, size_t length, const uint8_t *key)
+{
+  assert (length == AES128_KEY_SIZE);
+  aes128_set_decrypt_key (ctx, key);
+}
+
+const struct nettle_cipher nettle_aes128 =
+  { "aes128", sizeof(struct aes128_ctx),
+    AES_BLOCK_SIZE, AES128_KEY_SIZE,
+    aes128_set_encrypt_key_wrapper,
+    aes128_set_decrypt_key_wrapper,
+    (nettle_crypt_func *) aes128_encrypt,
+    (nettle_crypt_func *) aes128_decrypt
+  };
diff --git a/aes128-set-decrypt-key.c b/aes128-set-decrypt-key.c
new file mode 100644
index 0000000000000000000000000000000000000000..ee3425693a036798d6a39ad86105982b4db1001a
--- /dev/null
+++ b/aes128-set-decrypt-key.c
@@ -0,0 +1,46 @@
+/* aes128-set-decrypt-key.c
+ *
+ * Key setup for the aes/rijndael block cipher.
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2013, Niels Möller
+ *  
+ * The nettle 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 nettle 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 nettle library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02111-1301, USA.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+
+#include "aes-internal.h"
+#include "macros.h"
+
+void
+aes128_invert_key (struct aes128_ctx *dst, const struct aes128_ctx *src)
+{
+  _aes_invert (_AES128_ROUNDS, dst->keys, src->keys); 
+}
+
+void
+aes128_set_decrypt_key(struct aes128_ctx *ctx, const uint8_t *key)
+{
+  aes128_set_encrypt_key (ctx, key);
+  aes128_invert_key (ctx, ctx);
+}
diff --git a/aes-meta.c b/aes128-set-encrypt-key.c
similarity index 73%
rename from aes-meta.c
rename to aes128-set-encrypt-key.c
index 7b9af273ed2086661e5a93db5172064e1e10f1ff..e9413cb70e4bb9fac8380548c7b69e1e4ca9c5b3 100644
--- a/aes-meta.c
+++ b/aes128-set-encrypt-key.c
@@ -1,8 +1,11 @@
-/* aes-meta.c */
+/* aes128-set-encrypt-key.c
+ *
+ * Key setup for the aes/rijndael block cipher.
+ */
 
 /* nettle, low-level cryptographics library
  *
- * Copyright (C) 2002 Niels Möller
+ * Copyright (C) 2013, Niels Möller
  *  
  * The nettle 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
@@ -24,15 +27,12 @@
 # include "config.h"
 #endif
 
-#include "nettle-meta.h"
-
-#include "aes.h"
-
-const struct nettle_cipher nettle_aes128
-= _NETTLE_CIPHER_SEP(aes, AES, 128);
+#include <assert.h>
 
-const struct nettle_cipher nettle_aes192
-= _NETTLE_CIPHER_SEP(aes, AES, 192);
+#include "aes-internal.h"
 
-const struct nettle_cipher nettle_aes256
-= _NETTLE_CIPHER_SEP(aes, AES, 256);
+void
+aes128_set_encrypt_key(struct aes128_ctx *ctx, const uint8_t *key)
+{
+  _aes_set_key (_AES128_ROUNDS, AES128_KEY_SIZE / 4, ctx->keys, key);
+}
diff --git a/aes192-meta.c b/aes192-meta.c
new file mode 100644
index 0000000000000000000000000000000000000000..0ee0c1aa2974ffff4fcf6e4a67a4fd1b964dc3e7
--- /dev/null
+++ b/aes192-meta.c
@@ -0,0 +1,57 @@
+/* aes192-meta.c */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2013 Niels Möller
+ *  
+ * The nettle 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 nettle 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 nettle library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02111-1301, USA.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+
+#include "nettle-meta.h"
+
+#include "aes.h"
+
+static nettle_set_key_func aes192_set_encrypt_key_wrapper;
+static nettle_set_key_func aes192_set_decrypt_key_wrapper;
+
+static void
+aes192_set_encrypt_key_wrapper (void *ctx, size_t length, const uint8_t *key)
+{
+  assert (length == AES192_KEY_SIZE);
+  aes192_set_encrypt_key (ctx, key);
+}
+
+static void
+aes192_set_decrypt_key_wrapper (void *ctx, size_t length, const uint8_t *key)
+{
+  assert (length == AES192_KEY_SIZE);
+  aes192_set_decrypt_key (ctx, key);
+}
+
+const struct nettle_cipher nettle_aes192 =
+  { "aes192", sizeof(struct aes192_ctx),
+    AES_BLOCK_SIZE, AES192_KEY_SIZE,
+    aes192_set_encrypt_key_wrapper,
+    aes192_set_decrypt_key_wrapper,
+    (nettle_crypt_func *) aes192_encrypt,
+    (nettle_crypt_func *) aes192_decrypt
+  };
diff --git a/aes192-set-decrypt-key.c b/aes192-set-decrypt-key.c
new file mode 100644
index 0000000000000000000000000000000000000000..496bee69429af02d6eca1fd5d643908f31e3471d
--- /dev/null
+++ b/aes192-set-decrypt-key.c
@@ -0,0 +1,46 @@
+/* aes192-set-decrypt-key.c
+ *
+ * Key setup for the aes/rijndael block cipher.
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2013, Niels Möller
+ *  
+ * The nettle 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 nettle 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 nettle library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02111-1301, USA.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+
+#include "aes-internal.h"
+#include "macros.h"
+
+void
+aes192_invert_key (struct aes192_ctx *dst, const struct aes192_ctx *src)
+{
+  _aes_invert (_AES192_ROUNDS, dst->keys, src->keys); 
+}
+
+void
+aes192_set_decrypt_key(struct aes192_ctx *ctx, const uint8_t *key)
+{
+  aes192_set_encrypt_key (ctx, key);
+  aes192_invert_key (ctx, ctx);
+}
diff --git a/aes192-set-encrypt-key.c b/aes192-set-encrypt-key.c
new file mode 100644
index 0000000000000000000000000000000000000000..53bf36787b1ba4f9d57e147c5ee256c97a7b9ca8
--- /dev/null
+++ b/aes192-set-encrypt-key.c
@@ -0,0 +1,38 @@
+/* aes192-set-encrypt-key.c
+ *
+ * Key setup for the aes/rijndael block cipher.
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2013, Niels Möller
+ *  
+ * The nettle 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 nettle 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 nettle library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02111-1301, USA.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+
+#include "aes-internal.h"
+
+void
+aes192_set_encrypt_key(struct aes192_ctx *ctx, const uint8_t *key)
+{
+  _aes_set_key (_AES192_ROUNDS, AES192_KEY_SIZE / 4, ctx->keys, key);
+}
diff --git a/aes256-meta.c b/aes256-meta.c
new file mode 100644
index 0000000000000000000000000000000000000000..197441e0ed529f492c4be692e325a87c8c0bae18
--- /dev/null
+++ b/aes256-meta.c
@@ -0,0 +1,57 @@
+/* aes256-meta.c */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2013 Niels Möller
+ *  
+ * The nettle 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 nettle 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 nettle library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02111-1301, USA.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+
+#include "nettle-meta.h"
+
+#include "aes.h"
+
+static nettle_set_key_func aes256_set_encrypt_key_wrapper;
+static nettle_set_key_func aes256_set_decrypt_key_wrapper;
+
+static void
+aes256_set_encrypt_key_wrapper (void *ctx, size_t length, const uint8_t *key)
+{
+  assert (length == AES256_KEY_SIZE);
+  aes256_set_encrypt_key (ctx, key);
+}
+
+static void
+aes256_set_decrypt_key_wrapper (void *ctx, size_t length, const uint8_t *key)
+{
+  assert (length == AES256_KEY_SIZE);
+  aes256_set_decrypt_key (ctx, key);
+}
+
+const struct nettle_cipher nettle_aes256 =
+  { "aes256", sizeof(struct aes256_ctx),
+    AES_BLOCK_SIZE, AES256_KEY_SIZE,
+    aes256_set_encrypt_key_wrapper,
+    aes256_set_decrypt_key_wrapper,
+    (nettle_crypt_func *) aes256_encrypt,
+    (nettle_crypt_func *) aes256_decrypt
+  };
diff --git a/aes256-set-decrypt-key.c b/aes256-set-decrypt-key.c
new file mode 100644
index 0000000000000000000000000000000000000000..60b70e294bb54b9816fb1a062a4b0c226dfc2753
--- /dev/null
+++ b/aes256-set-decrypt-key.c
@@ -0,0 +1,46 @@
+/* aes256-set-decrypt-key.c
+ *
+ * Key setup for the aes/rijndael block cipher.
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2013, Niels Möller
+ *  
+ * The nettle 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 nettle 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 nettle library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02111-1301, USA.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+
+#include "aes-internal.h"
+#include "macros.h"
+
+void
+aes256_invert_key (struct aes256_ctx *dst, const struct aes256_ctx *src)
+{
+  _aes_invert (_AES256_ROUNDS, dst->keys, src->keys); 
+}
+
+void
+aes256_set_decrypt_key(struct aes256_ctx *ctx, const uint8_t *key)
+{
+  aes256_set_encrypt_key (ctx, key);
+  aes256_invert_key (ctx, ctx);
+}
diff --git a/aes256-set-encrypt-key.c b/aes256-set-encrypt-key.c
new file mode 100644
index 0000000000000000000000000000000000000000..9e11ff123e64a1e22c480beb880341192387d949
--- /dev/null
+++ b/aes256-set-encrypt-key.c
@@ -0,0 +1,38 @@
+/* aes256-set-encrypt-key.c
+ *
+ * Key setup for the aes/rijndael block cipher.
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2013, Niels Möller
+ *  
+ * The nettle 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 nettle 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 nettle library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02111-1301, USA.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+
+#include "aes-internal.h"
+
+void
+aes256_set_encrypt_key(struct aes256_ctx *ctx, const uint8_t *key)
+{
+  _aes_set_key (_AES256_ROUNDS, AES256_KEY_SIZE / 4, ctx->keys, key);
+}
diff --git a/arm/aes-decrypt-internal.asm b/arm/aes-decrypt-internal.asm
index 37abf1ec8ffd4f8f9fb064808603a6a0c9e70795..947178720101b9cdcfdf675df011ef7613295928 100644
--- a/arm/aes-decrypt-internal.asm
+++ b/arm/aes-decrypt-internal.asm
@@ -19,26 +19,32 @@ C MA 02111-1301, USA.
 
 include_src(<arm/aes.m4>)
 
-C define(<CTX>, <r0>)
-define(<TABLE>, <r1>)
-define(<LENGTH>, <r2>)
-define(<DST>, <r3>)
-define(<SRC>, <r12>)
-
+define(<PARAM_ROUNDS>, <r0>)
+define(<PARAM_KEYS>, <r1>)
+define(<TABLE>, <r2>)
+define(<PARAM_LENGTH>, <r3>)
+C On stack: DST, SRC
+	
 define(<W0>, <r4>)
 define(<W1>, <r5>)
 define(<W2>, <r6>)
 define(<W3>, <r7>)
 define(<T0>, <r8>)
-define(<KEY>, <r10>)
-define(<ROUND>, <r11>)
+define(<COUNT>, <r10>)
+define(<KEY>, <r11>)
 
-define(<X0>, <r2>)	C Overlaps LENGTH, SRC, DST
+define(<MASK>, <r0>)	C Overlaps inputs, except TABLE
+define(<X0>, <r1>)
 define(<X1>, <r3>)
 define(<X2>, <r12>)
 define(<X3>, <r14>)	C lr
-define(<MASK>, <r0>)	C Overlaps CTX input
-define(<CTX>, <[sp]>)
+
+define(<FRAME_ROUNDS>,  <[sp]>)
+define(<FRAME_KEYS>,  <[sp, #+4]>)
+define(<FRAME_LENGTH>,  <[sp, #+8]>)
+C 8 saved registers
+define(<FRAME_DST>,  <[sp, #+44]>)
+define(<FRAME_SRC>,  <[sp, #+48]>)
 
 
 define(<AES_DECRYPT_ROUND>, <
@@ -103,29 +109,30 @@ define(<AES_DECRYPT_ROUND>, <
 
 	.file "aes-decrypt-internal.asm"
 	
-	C _aes_decrypt(struct aes_context *ctx, 
+	C _aes_decrypt(unsigned rounds, const uint32_t *keys,
 	C	       const struct aes_table *T,
 	C	       size_t length, uint8_t *dst,
 	C	       uint8_t *src)
 	.text
 	ALIGN(4)
 PROLOGUE(_nettle_aes_decrypt)
-	teq	LENGTH, #0
+	teq	PARAM_LENGTH, #0
 	beq	.Lend
-	ldr	SRC, [sp]
 
-	push	{r0, r4,r5,r6,r7,r8,r10,r11,lr}
+	push	{r0,r1,r3, r4,r5,r6,r7,r8,r10,r11,lr}
 	mov	MASK, #0x3fc
 	ALIGN(16)
 .Lblock_loop:
-	ldr	KEY, CTX
-	ldr	ROUND, [KEY, #+AES_NROUNDS]
-	AES_LOAD(SRC,KEY,W0)
-	AES_LOAD(SRC,KEY,W1)
-	AES_LOAD(SRC,KEY,W2)
-	AES_LOAD(SRC,KEY,W3)
-
-	push	{LENGTH, DST, SRC}
+	ldr	X0, FRAME_SRC		C Use X0 as SRC pointer
+	ldm	sp, {COUNT, KEY}
+
+	AES_LOAD(X0,KEY,W0)
+	AES_LOAD(X0,KEY,W1)
+	AES_LOAD(X0,KEY,W2)
+	AES_LOAD(X0,KEY,W3)
+
+	str	X0, FRAME_SRC
+
 	add	TABLE, TABLE, #AES_TABLE0
 
 	b	.Lentry
@@ -135,31 +142,35 @@ PROLOGUE(_nettle_aes_decrypt)
 	AES_DECRYPT_ROUND(X0, X1, X2, X3, W0, W1, W2, W3, KEY)
 	
 .Lentry:
-	subs	ROUND, ROUND,#2
+	subs	COUNT, COUNT,#2
 	C	Transform W -> X
 	AES_DECRYPT_ROUND(W0, W1, W2, W3, X0, X1, X2, X3, KEY)
 
 	bne	.Lround_loop
 
-	lsr	ROUND, MASK, #2	C Put the needed mask in the unused ROUND register
+	lsr	COUNT, MASK, #2	C Put the needed mask in the unused COUNT register
 	sub	TABLE, TABLE, #AES_TABLE0
 	C	Final round
-	AES_FINAL_ROUND_V5(X0, X3, X2, X1, KEY, W0, ROUND)
-	AES_FINAL_ROUND_V5(X1, X0, X3, X2, KEY, W1, ROUND)
-	AES_FINAL_ROUND_V5(X2, X1, X0, X3, KEY, W2, ROUND)
-	AES_FINAL_ROUND_V5(X3, X2, X1, X0, KEY, W3, ROUND)
+	AES_FINAL_ROUND_V5(X0, X3, X2, X1, KEY, W0, COUNT)
+	AES_FINAL_ROUND_V5(X1, X0, X3, X2, KEY, W1, COUNT)
+	AES_FINAL_ROUND_V5(X2, X1, X0, X3, KEY, W2, COUNT)
+	AES_FINAL_ROUND_V5(X3, X2, X1, X0, KEY, W3, COUNT)
 
-	pop	{LENGTH, DST, SRC}
-	
-	AES_STORE(DST,W0)
-	AES_STORE(DST,W1)
-	AES_STORE(DST,W2)
-	AES_STORE(DST,W3)
+	ldr	X0, FRAME_DST
+	ldr	X1, FRAME_LENGTH
+
+	AES_STORE(X0,W0)
+	AES_STORE(X0,W1)
+	AES_STORE(X0,W2)
+	AES_STORE(X0,W3)
+
+	subs	X1, X1, #16
+	str	X0, FRAME_DST
+	str	X1, FRAME_LENGTH
 
-	subs	LENGTH, LENGTH, #16
 	bhi	.Lblock_loop
 
-	add	sp, sp, #4	C Drop saved r0
+	add	sp, sp, #12	C Drop saved r0, r1, r3
 	pop	{r4,r5,r6,r7,r8,r10,r11,pc}
 	
 .Lend:
diff --git a/arm/aes-encrypt-internal.asm b/arm/aes-encrypt-internal.asm
index eb2f1489dae6a2f2377948e816eda07711f07561..0d396185be3a722463ee2accf16ca2acd95d7108 100644
--- a/arm/aes-encrypt-internal.asm
+++ b/arm/aes-encrypt-internal.asm
@@ -19,32 +19,38 @@ C MA 02111-1301, USA.
 
 include_src(<arm/aes.m4>)
 
-C	Benchmarked at at 725, 930, 990 cycles/block on cortex A9,
+C	Benchmarked at at 725, 815, 990 cycles/block on cortex A9,
 C	for 128, 192 and 256 bit key sizes.
 
 C	Possible improvements: More efficient load and store with
 C	aligned accesses. Better scheduling.
 
-C define(<CTX>, <r0>)
-define(<TABLE>, <r1>)
-define(<LENGTH>, <r2>)
-define(<DST>, <r3>)
-define(<SRC>, <r12>)
-
+define(<PARAM_ROUNDS>, <r0>)
+define(<PARAM_KEYS>, <r1>)
+define(<TABLE>, <r2>)
+define(<PARAM_LENGTH>, <r3>)
+C On stack: DST, SRC
+	
 define(<W0>, <r4>)
 define(<W1>, <r5>)
 define(<W2>, <r6>)
 define(<W3>, <r7>)
 define(<T0>, <r8>)
-define(<KEY>, <r10>)
-define(<ROUND>, <r11>)
+define(<COUNT>, <r10>)
+define(<KEY>, <r11>)
 
-define(<X0>, <r2>)	C Overlaps LENGTH, SRC, DST
+define(<MASK>, <r0>)	C Overlaps inputs, except TABLE
+define(<X0>, <r1>)
 define(<X1>, <r3>)
 define(<X2>, <r12>)
 define(<X3>, <r14>)	C lr
-define(<MASK>, <r0>)	C Overlaps CTX input
-define(<CTX>, <[sp]>)
+
+define(<FRAME_ROUNDS>,  <[sp]>)
+define(<FRAME_KEYS>,  <[sp, #+4]>)
+define(<FRAME_LENGTH>,  <[sp, #+8]>)
+C 8 saved registers
+define(<FRAME_DST>,  <[sp, #+44]>)
+define(<FRAME_SRC>,  <[sp, #+48]>)
 
 
 C AES_ENCRYPT_ROUND(x0,x1,x2,x3,w0,w1,w2,w3,key)
@@ -112,29 +118,30 @@ define(<AES_ENCRYPT_ROUND>, <
 
 	.file "aes-encrypt-internal.asm"
 	
-	C _aes_encrypt(struct aes_context *ctx, 
+	C _aes_encrypt(unsigned rounds, const uint32_t *keys,
 	C	       const struct aes_table *T,
 	C	       size_t length, uint8_t *dst,
 	C	       uint8_t *src)
 	.text
 	ALIGN(4)
 PROLOGUE(_nettle_aes_encrypt)
-	teq	LENGTH, #0
+	teq	PARAM_LENGTH, #0
 	beq	.Lend
-	ldr	SRC, [sp]
 
-	push	{r0, r4,r5,r6,r7,r8,r10,r11,lr}
+	push	{r0,r1,r3, r4,r5,r6,r7,r8,r10,r11,lr}
 	mov	MASK, #0x3fc
 	ALIGN(16)
 .Lblock_loop:
-	ldr	KEY, CTX
-	ldr	ROUND, [KEY, #+AES_NROUNDS]
-	AES_LOAD(SRC,KEY,W0)
-	AES_LOAD(SRC,KEY,W1)
-	AES_LOAD(SRC,KEY,W2)
-	AES_LOAD(SRC,KEY,W3)
-
-	push	{LENGTH, DST, SRC}
+	ldr	X0, FRAME_SRC		C Use X0 as SRC pointer
+	ldm	sp, {COUNT, KEY}
+
+	AES_LOAD(X0,KEY,W0)
+	AES_LOAD(X0,KEY,W1)
+	AES_LOAD(X0,KEY,W2)
+	AES_LOAD(X0,KEY,W3)
+
+	str	X0, FRAME_SRC
+
 	add	TABLE, TABLE, #AES_TABLE0
 
 	b	.Lentry
@@ -144,31 +151,35 @@ PROLOGUE(_nettle_aes_encrypt)
 	AES_ENCRYPT_ROUND(X0, X1, X2, X3, W0, W1, W2, W3, KEY)
 	
 .Lentry:
-	subs	ROUND, ROUND,#2
+	subs	COUNT, COUNT,#2
 	C	Transform W -> X
 	AES_ENCRYPT_ROUND(W0, W1, W2, W3, X0, X1, X2, X3, KEY)
 
 	bne	.Lround_loop
 
-	lsr	ROUND, MASK, #2	C Put the needed mask in the unused ROUND register
+	lsr	COUNT, MASK, #2	C Put the needed mask in the unused COUNT register
 	sub	TABLE, TABLE, #AES_TABLE0
 	C	Final round
-	AES_FINAL_ROUND_V5(X0, X1, X2, X3, KEY, W0, ROUND)
-	AES_FINAL_ROUND_V5(X1, X2, X3, X0, KEY, W1, ROUND)
-	AES_FINAL_ROUND_V5(X2, X3, X0, X1, KEY, W2, ROUND)
-	AES_FINAL_ROUND_V5(X3, X0, X1, X2, KEY, W3, ROUND)
+	AES_FINAL_ROUND_V5(X0, X1, X2, X3, KEY, W0, COUNT)
+	AES_FINAL_ROUND_V5(X1, X2, X3, X0, KEY, W1, COUNT)
+	AES_FINAL_ROUND_V5(X2, X3, X0, X1, KEY, W2, COUNT)
+	AES_FINAL_ROUND_V5(X3, X0, X1, X2, KEY, W3, COUNT)
 
-	pop	{LENGTH, DST, SRC}
-	
-	AES_STORE(DST,W0)
-	AES_STORE(DST,W1)
-	AES_STORE(DST,W2)
-	AES_STORE(DST,W3)
+	ldr	X0, FRAME_DST
+	ldr	X1, FRAME_LENGTH
+
+	AES_STORE(X0,W0)
+	AES_STORE(X0,W1)
+	AES_STORE(X0,W2)
+	AES_STORE(X0,W3)
+
+	subs	X1, X1, #16
+	str	X0, FRAME_DST
+	str	X1, FRAME_LENGTH
 
-	subs	LENGTH, LENGTH, #16
 	bhi	.Lblock_loop
 
-	add	sp, sp, #4	C Drop saved r0
+	add	sp, sp, #12	C Drop saved r0, r1, r3
 	pop	{r4,r5,r6,r7,r8,r10,r11,pc}
 	
 .Lend:
diff --git a/arm/v6/aes-decrypt-internal.asm b/arm/v6/aes-decrypt-internal.asm
index f550506ddb3d4a10737ef32507715f7c0a0c15df..f9f0b7ad8e05daead1c0a39038da474822c269fe 100644
--- a/arm/v6/aes-decrypt-internal.asm
+++ b/arm/v6/aes-decrypt-internal.asm
@@ -19,25 +19,33 @@ C MA 02111-1301, USA.
 
 include_src(<arm/aes.m4>)
 
-define(<CTX>, <r0>)
-define(<TABLE>, <r1>)
-define(<LENGTH>, <r2>)
-define(<DST>, <r3>)
-define(<SRC>, <r12>)
+define(<PARAM_ROUNDS>, <r0>)
+define(<PARAM_KEYS>, <r1>)
+define(<TABLE>, <r2>)
+define(<LENGTH>, <r3>)
+C On stack: DST, SRC
 
 define(<W0>, <r4>)
 define(<W1>, <r5>)
 define(<W2>, <r6>)
 define(<W3>, <r7>)
 define(<T0>, <r8>)
-define(<KEY>, <r10>)
-define(<ROUND>, <r11>)
+define(<COUNT>, <r10>)
+define(<KEY>, <r11>)
 
-define(<X0>, <r2>)	C Overlaps LENGTH, SRC, DST
-define(<X1>, <r3>)
+define(<X0>, <r0>)	C Overlaps PARAM_ROUNDS and PARAM_KEYS
+define(<X1>, <r1>)
 define(<X2>, <r12>)
 define(<X3>, <r14>)	C lr
 
+define(<FRAME_ROUNDS>>,  <[sp]>)
+define(<FRAME_KEYS>,  <[sp, #+4]>)
+C 8 saved registers
+define(<FRAME_DST>,  <[sp, #+40]>)
+define(<FRAME_SRC>,  <[sp, #+44]>)
+
+define(<SRC>, <%r12>)	C Overlap registers used in inner loop.
+define(<DST>, <COUNT>)
 
 C AES_DECRYPT_ROUND(x0,x1,x2,x3,w0,w1,w2,w3,key)
 define(<AES_DECRYPT_ROUND>, <
@@ -102,7 +110,7 @@ define(<AES_DECRYPT_ROUND>, <
 
 	.file "aes-decrypt-internal.asm"
 	
-	C _aes_decrypt(struct aes_context *ctx, 
+	C _aes_decrypt(unsigned rounds, const uint32_t *keys,
 	C	       const struct aes_table *T,
 	C	       size_t length, uint8_t *dst,
 	C	       uint8_t *src)
@@ -111,22 +119,23 @@ define(<AES_DECRYPT_ROUND>, <
 PROLOGUE(_nettle_aes_decrypt)
 	teq	LENGTH, #0
 	beq	.Lend
-	ldr	SRC, [sp]
 
-	push	{r4,r5,r6,r7,r8,r10,r11,lr}
-	nop	C For some mysterious reason, taking out this nop
-		C slows this function down by 10(!) % on Cortex-A9.
+	ldr	SRC, [sp, #+4]
+
+	push	{r0,r1, r4,r5,r6,r7,r8,r10,r11,lr}
+
 	ALIGN(16)
 .Lblock_loop:
-	mov	KEY, CTX
+	ldm	sp, {COUNT, KEY}
+
+	add	TABLE, TABLE, #AES_TABLE0
+
 	AES_LOAD(SRC,KEY,W0)
 	AES_LOAD(SRC,KEY,W1)
 	AES_LOAD(SRC,KEY,W2)
 	AES_LOAD(SRC,KEY,W3)
 
-	push	{LENGTH, DST, SRC}
-	ldr	ROUND, [CTX, #+AES_NROUNDS]
-	add	TABLE, TABLE, #AES_TABLE0
+	str	SRC, FRAME_SRC
 
 	b	.Lentry
 	ALIGN(16)
@@ -135,29 +144,34 @@ PROLOGUE(_nettle_aes_decrypt)
 	AES_DECRYPT_ROUND(X0, X1, X2, X3, W0, W1, W2, W3, KEY)
 	
 .Lentry:
-	subs	ROUND, ROUND,#2
+	subs	COUNT, COUNT,#2
 	C	Transform W -> X
 	AES_DECRYPT_ROUND(W0, W1, W2, W3, X0, X1, X2, X3, KEY)
 
 	bne	.Lround_loop
 
 	sub	TABLE, TABLE, #AES_TABLE0
+
 	C	Final round
+	ldr	DST, FRAME_DST
+
 	AES_FINAL_ROUND_V6(X0, X3, X2, X1, KEY, W0)
 	AES_FINAL_ROUND_V6(X1, X0, X3, X2, KEY, W1)
 	AES_FINAL_ROUND_V6(X2, X1, X0, X3, KEY, W2)
 	AES_FINAL_ROUND_V6(X3, X2, X1, X0, KEY, W3)
 
-	pop	{LENGTH, DST, SRC}
+	ldr	SRC, FRAME_SRC
 	
 	AES_STORE(DST,W0)
 	AES_STORE(DST,W1)
 	AES_STORE(DST,W2)
 	AES_STORE(DST,W3)
 
+	str	DST, FRAME_DST
 	subs	LENGTH, LENGTH, #16
 	bhi	.Lblock_loop
 
+	add	sp, sp, #8	C Drop saved r0, r1
 	pop	{r4,r5,r6,r7,r8,r10,r11,pc}
 	
 .Lend:
diff --git a/arm/v6/aes-encrypt-internal.asm b/arm/v6/aes-encrypt-internal.asm
index 3cf13072c29aeaa8e7d8a32ce6241aacc1c364d2..3c817de18d27e70421652cc52e1670ba8b2ab079 100644
--- a/arm/v6/aes-encrypt-internal.asm
+++ b/arm/v6/aes-encrypt-internal.asm
@@ -19,31 +19,39 @@ C MA 02111-1301, USA.
 
 include_src(<arm/aes.m4>)
 
-C	Benchmarked at at 680, 818, 929 cycles/block on cortex A9,
+C	Benchmarked at at 706, 870, 963 cycles/block on cortex A9,
 C	for 128, 192 and 256 bit key sizes.
 
 C	Possible improvements: More efficient load and store with
 C	aligned accesses. Better scheduling.
 
-define(<CTX>, <r0>)
-define(<TABLE>, <r1>)
-define(<LENGTH>, <r2>)
-define(<DST>, <r3>)
-define(<SRC>, <r12>)
+define(<PARAM_ROUNDS>, <r0>)
+define(<PARAM_KEYS>, <r1>)
+define(<TABLE>, <r2>)
+define(<LENGTH>, <r3>)
+C On stack: DST, SRC
 
 define(<W0>, <r4>)
 define(<W1>, <r5>)
 define(<W2>, <r6>)
 define(<W3>, <r7>)
 define(<T0>, <r8>)
-define(<KEY>, <r10>)
-define(<ROUND>, <r11>)
+define(<COUNT>, <r10>)
+define(<KEY>, <r11>)
 
-define(<X0>, <r2>)	C Overlaps LENGTH, SRC, DST
-define(<X1>, <r3>)
+define(<X0>, <r0>)	C Overlaps PARAM_ROUNDS and PARAM_KEYS
+define(<X1>, <r1>)
 define(<X2>, <r12>)
 define(<X3>, <r14>)	C lr
 
+define(<FRAME_ROUNDS>>,  <[sp]>)
+define(<FRAME_KEYS>,  <[sp, #+4]>)
+C 8 saved registers
+define(<FRAME_DST>,  <[sp, #+40]>)
+define(<FRAME_SRC>,  <[sp, #+44]>)
+
+define(<SRC>, <%r12>)	C Overlap registers used in inner loop.
+define(<DST>, <COUNT>)
 
 C 53 instr.
 C It's tempting to use eor with rotation, but that's slower.
@@ -110,7 +118,7 @@ define(<AES_ENCRYPT_ROUND>, <
 
 	.file "aes-encrypt-internal.asm"
 	
-	C _aes_encrypt(struct aes_context *ctx, 
+	C _aes_encrypt(unsigned rounds, const uint32_t *keys,
 	C	       const struct aes_table *T,
 	C	       size_t length, uint8_t *dst,
 	C	       uint8_t *src)
@@ -119,20 +127,23 @@ define(<AES_ENCRYPT_ROUND>, <
 PROLOGUE(_nettle_aes_encrypt)
 	teq	LENGTH, #0
 	beq	.Lend
-	ldr	SRC, [sp]
 
-	push	{r4,r5,r6,r7,r8,r10,r11,lr}
+	ldr	SRC, [sp, #+4]
+
+	push	{r0,r1, r4,r5,r6,r7,r8,r10,r11,lr}
+
 	ALIGN(16)
 .Lblock_loop:
-	mov	KEY, CTX
+	ldm	sp, {COUNT, KEY}
+
+	add	TABLE, TABLE, #AES_TABLE0
+
 	AES_LOAD(SRC,KEY,W0)
 	AES_LOAD(SRC,KEY,W1)
 	AES_LOAD(SRC,KEY,W2)
 	AES_LOAD(SRC,KEY,W3)
 
-	push	{LENGTH, DST, SRC}
-	ldr	ROUND, [CTX, #+AES_NROUNDS]
-	add	TABLE, TABLE, #AES_TABLE0
+	str	SRC, FRAME_SRC
 
 	b	.Lentry
 	ALIGN(16)
@@ -141,29 +152,34 @@ PROLOGUE(_nettle_aes_encrypt)
 	AES_ENCRYPT_ROUND(X0, X1, X2, X3, W0, W1, W2, W3, KEY)
 	
 .Lentry:
-	subs	ROUND, ROUND,#2
+	subs	COUNT, COUNT,#2
 	C	Transform W -> X
 	AES_ENCRYPT_ROUND(W0, W1, W2, W3, X0, X1, X2, X3, KEY)
 
 	bne	.Lround_loop
 
 	sub	TABLE, TABLE, #AES_TABLE0
+
 	C	Final round
+	ldr	DST, FRAME_DST
+
 	AES_FINAL_ROUND_V6(X0, X1, X2, X3, KEY, W0)
 	AES_FINAL_ROUND_V6(X1, X2, X3, X0, KEY, W1)
 	AES_FINAL_ROUND_V6(X2, X3, X0, X1, KEY, W2)
 	AES_FINAL_ROUND_V6(X3, X0, X1, X2, KEY, W3)
 
-	pop	{LENGTH, DST, SRC}
+	ldr	SRC, FRAME_SRC
 	
 	AES_STORE(DST,W0)
 	AES_STORE(DST,W1)
 	AES_STORE(DST,W2)
 	AES_STORE(DST,W3)
 
+	str	DST, FRAME_DST
 	subs	LENGTH, LENGTH, #16
 	bhi	.Lblock_loop
 
+	add	sp, sp, #8	C Drop saved r0, r1
 	pop	{r4,r5,r6,r7,r8,r10,r11,pc}
 	
 .Lend:
diff --git a/nettle-internal.c b/nettle-internal.c
index 5cd582884d0c9355a5e1fdbd803d06cb9565b6c9..8308df69f1a99090996377ea82a984357e49c553 100644
--- a/nettle-internal.c
+++ b/nettle-internal.c
@@ -112,3 +112,13 @@ const struct nettle_aead
 nettle_gcm_aes192 = _NETTLE_AEAD(gcm, GCM, aes, 192);
 const struct nettle_aead
 nettle_gcm_aes256 = _NETTLE_AEAD(gcm, GCM, aes, 256);
+
+/* Old, unified, interface */
+const struct nettle_cipher nettle_unified_aes128
+= _NETTLE_CIPHER_SEP(aes, AES, 128);
+
+const struct nettle_cipher nettle_unified_aes192
+= _NETTLE_CIPHER_SEP(aes, AES, 192);
+
+const struct nettle_cipher nettle_unified_aes256
+= _NETTLE_CIPHER_SEP(aes, AES, 256);
diff --git a/nettle-internal.h b/nettle-internal.h
index e094064f6f32c6daf7f33324b288d96f1b0cf6e3..09881ce9b607228d03ab393645a60085c08a1ba0 100644
--- a/nettle-internal.h
+++ b/nettle-internal.h
@@ -64,6 +64,10 @@ extern const struct nettle_cipher nettle_blowfish128;
 extern const struct nettle_cipher nettle_salsa20;
 extern const struct nettle_cipher nettle_salsa20r12;
 
+extern const struct nettle_cipher nettle_unified_aes128;
+extern const struct nettle_cipher nettle_unified_aes192;
+extern const struct nettle_cipher nettle_unified_aes256;
+
 /* Glue to openssl, for comparative benchmarking. Code in
  * examples/nettle-openssl.c. */
 extern const struct nettle_cipher nettle_openssl_aes128;
diff --git a/sparc32/aes-decrypt-internal.asm b/sparc32/aes-decrypt-internal.asm
index cbcf43c56e4f03d5d1526a25ce20f4393f8e3e8a..eac60ed56c5b387fbfddb53bf2fe138899e0a0d6 100644
--- a/sparc32/aes-decrypt-internal.asm
+++ b/sparc32/aes-decrypt-internal.asm
@@ -1,6 +1,6 @@
 C nettle, low-level cryptographics library
 C 
-C Copyright (C) 2002, 2005 Niels Möller
+C Copyright (C) 2002, 2005, 2013 Niels Möller
 C  
 C The nettle library is free software; you can redistribute it and/or modify
 C it under the terms of the GNU Lesser General Public License as published by
@@ -20,11 +20,12 @@ C MA 02111-1301, USA.
 include_src(<sparc32/aes.m4>)
 
 C	Arguments
-define(<CTX>,	<%i0>)
-define(<T>,	<%i1>)
-define(<LENGTH>,<%i2>)
-define(<DST>,	<%i3>)
-define(<SRC>,	<%i4>)
+define(<ROUNDS>,<%i0>)
+define(<KEYS>,	<%i1>)
+define(<T>,	<%i2>)
+define(<LENGTH>,<%i3>)
+define(<DST>,	<%i4>)
+define(<SRC>,	<%i5>)
 
 C	AES state, two copies for unrolling
 
@@ -40,7 +41,7 @@ define(<X3>,	<%l7>)
 
 C	%o0-%03 are used for loop invariants T0-T3
 define(<KEY>,	<%o4>)
-define(<ROUND>, <%o5>)
+define(<COUNT>, <%o5>)
 
 C %g1, %g2, %g3 are TMP1, TMP2 and TMP3
 
@@ -53,7 +54,7 @@ define(<FRAME_SIZE>, 104)
 
 	.file "aes-decrypt-internal.asm"
 
-	C _aes_decrypt(struct aes_context *ctx, 
+	C _aes_decrypt(unsigned rounds, const uint32_t *keys,
 	C	       const struct aes_table *T,
 	C	       size_t length, uint8_t *dst,
 	C	       uint8_t *src)
@@ -74,22 +75,23 @@ PROLOGUE(_nettle_aes_decrypt)
 	add	T, AES_TABLE2, T2
 	add	T, AES_TABLE3, T3
 
+	C	Must be even, and includes the final round
+	srl	ROUNDS, 1, ROUNDS
+	C	Last two rounds handled specially
+	sub	ROUNDS, 1, ROUNDS
+
 .Lblock_loop:
 	C  Read src, and add initial subkey
-	add	CTX, AES_KEYS, KEY
+	mov	KEYS, KEY
 	AES_LOAD(0, SRC, KEY, W0)
 	AES_LOAD(1, SRC, KEY, W1)
 	AES_LOAD(2, SRC, KEY, W2)
 	AES_LOAD(3, SRC, KEY, W3)
 
-	C	Must be even, and includes the final round
-	ld	[AES_NROUNDS + CTX], ROUND
+	mov	ROUNDS, COUNT
 	add	SRC, 16, SRC
 	add	KEY, 16, KEY
 
-	srl	ROUND, 1, ROUND
-	C	Last two rounds handled specially
-	sub	ROUND, 1, ROUND
 .Lround_loop:
 	C The AES_ROUND macro uses T0,... T3
 	C	Transform W -> X
@@ -104,7 +106,7 @@ PROLOGUE(_nettle_aes_decrypt)
 	AES_ROUND(6, X2, X1, X0, X3, KEY, W2)
 	AES_ROUND(7, X3, X2, X1, X0, KEY, W3)
 
-	subcc	ROUND, 1, ROUND
+	subcc	COUNT, 1, COUNT
 	bne	.Lround_loop
 	add	KEY, 32, KEY
 
diff --git a/sparc32/aes-encrypt-internal.asm b/sparc32/aes-encrypt-internal.asm
index 490886fa029678b15f77e7686e8b87e9d624da85..fe99fa6cf3c2a19b500d5c79fc7a83127cd776e8 100644
--- a/sparc32/aes-encrypt-internal.asm
+++ b/sparc32/aes-encrypt-internal.asm
@@ -1,6 +1,6 @@
 C nettle, low-level cryptographics library
 C 
-C Copyright (C) 2002, 2005 Niels Möller
+C Copyright (C) 2002, 2005, 2013 Niels Möller
 C  
 C The nettle library is free software; you can redistribute it and/or modify
 C it under the terms of the GNU Lesser General Public License as published by
@@ -20,11 +20,12 @@ C MA 02111-1301, USA.
 include_src(<sparc32/aes.m4>)
 
 C	Arguments
-define(<CTX>,	<%i0>)
-define(<T>,	<%i1>)
-define(<LENGTH>,<%i2>)
-define(<DST>,	<%i3>)
-define(<SRC>,	<%i4>)
+define(<ROUNDS>,<%i0>)
+define(<KEYS>,	<%i1>)
+define(<T>,	<%i2>)
+define(<LENGTH>,<%i3>)
+define(<DST>,	<%i4>)
+define(<SRC>,	<%i5>)
 
 C	AES state, two copies for unrolling
 
@@ -40,7 +41,7 @@ define(<X3>,	<%l7>)
 
 C	%o0-%03 are used for loop invariants T0-T3
 define(<KEY>,	<%o4>)
-define(<ROUND>, <%o5>)
+define(<COUNT>, <%o5>)
 
 C %g1, %g2, %g3 are TMP1, TMP2 and TMP3
 
@@ -58,7 +59,7 @@ define(<FRAME_SIZE>, 104)
 
 	.file "aes-encrypt-internal.asm"
 
-	C _aes_encrypt(struct aes_context *ctx, 
+	C _aes_encrypt(unsigned rounds, const uint32_t *keys,
 	C	       const struct aes_table *T,
 	C	       size_t length, uint8_t *dst,
 	C	       uint8_t *src)
@@ -79,22 +80,23 @@ PROLOGUE(_nettle_aes_encrypt)
 	add	T, AES_TABLE2, T2
 	add	T, AES_TABLE3, T3
 
+	C	Must be even, and includes the final round
+	srl	ROUNDS, 1, ROUNDS
+	C	Last two rounds handled specially
+	sub	ROUNDS, 1, ROUNDS
+
 .Lblock_loop:
 	C  Read src, and add initial subkey
-	add	CTX, AES_KEYS, KEY
+	mov	KEYS, KEY
 	AES_LOAD(0, SRC, KEY, W0)
 	AES_LOAD(1, SRC, KEY, W1)
 	AES_LOAD(2, SRC, KEY, W2)
 	AES_LOAD(3, SRC, KEY, W3)
 
-	C	Must be even, and includes the final round
-	ld	[AES_NROUNDS + CTX], ROUND
+	mov	ROUNDS, COUNT
 	add	SRC, 16, SRC
 	add	KEY, 16, KEY
 
-	srl	ROUND, 1, ROUND
-	C	Last two rounds handled specially
-	sub	ROUND, 1, ROUND
 .Lround_loop:
 	C The AES_ROUND macro uses T0,... T3
 	C	Transform W -> X
@@ -109,7 +111,7 @@ PROLOGUE(_nettle_aes_encrypt)
 	AES_ROUND(6, X2, X3, X0, X1, KEY, W2)
 	AES_ROUND(7, X3, X0, X1, X2, KEY, W3)
 
-	subcc	ROUND, 1, ROUND
+	subcc	COUNT, 1, COUNT
 	bne	.Lround_loop
 	add	KEY, 32, KEY
 
diff --git a/sparc64/aes-decrypt-internal.asm b/sparc64/aes-decrypt-internal.asm
index 4f70c32c95fb19f39da9267464af34691094bee5..c5269c6762d8c580c4f2ea9d29c8a705155da9d1 100644
--- a/sparc64/aes-decrypt-internal.asm
+++ b/sparc64/aes-decrypt-internal.asm
@@ -1,6 +1,6 @@
 C nettle, low-level cryptographics library
 C 
-C Copyright (C) 2002, 2005 Niels Möller
+C Copyright (C) 2002, 2005, 2013 Niels Möller
 C  
 C The nettle library is free software; you can redistribute it and/or modify
 C it under the terms of the GNU Lesser General Public License as published by
@@ -23,14 +23,15 @@ C doesn't matter, since we don't access any data on the stack).
 
 
 C Use the same AES macros as on sparc32.
-include_src(sparc32/aes.m4)
+include_src(<sparc32/aes.m4>)
 
 C	Arguments
-define(<CTX>,	<%i0>)
-define(<T>,	<%i1>)
-define(<LENGTH>,<%i2>)
-define(<DST>,	<%i3>)
-define(<SRC>,	<%i4>)
+define(<ROUNDS>,<%i0>)
+define(<KEYS>,	<%i1>)
+define(<T>,	<%i2>)
+define(<LENGTH>,<%i3>)
+define(<DST>,	<%i4>)
+define(<SRC>,	<%i5>)
 
 C	AES state, two copies for unrolling
 
@@ -46,7 +47,7 @@ define(<X3>,	<%l7>)
 
 C	%o0-%03 are used for loop invariants T0-T3
 define(<KEY>,	<%o4>)
-define(<ROUND>, <%o5>)
+define(<COUNT>, <%o5>)
 
 C %g1, %g2, %g3 are TMP1, TMP2 and TMP3
 
@@ -59,7 +60,7 @@ define(<FRAME_SIZE>, 192)
 
 	.file "aes-decrypt-internal.asm"
 
-	C _aes_decrypt(struct aes_context *ctx, 
+	C _aes_decrypt(unsigned rounds, const uint32_t *keys,
 	C	       const struct aes_table *T,
 	C	       size_t length, uint8_t *dst,
 	C	       uint8_t *src)
@@ -80,22 +81,23 @@ PROLOGUE(_nettle_aes_decrypt)
 	add	T, AES_TABLE2, T2
 	add	T, AES_TABLE3, T3
 
+	C	Must be even, and includes the final round
+	srl	ROUNDS, 1, ROUNDS
+	C	Last two rounds handled specially
+	sub	ROUNDS, 1, ROUNDS
+
 .Lblock_loop:
 	C  Read src, and add initial subkey
-	add	CTX, AES_KEYS, KEY
+	mov	KEYS, KEY
 	AES_LOAD(0, SRC, KEY, W0)
 	AES_LOAD(1, SRC, KEY, W1)
 	AES_LOAD(2, SRC, KEY, W2)
 	AES_LOAD(3, SRC, KEY, W3)
 
-	C	Must be even, and includes the final round
-	ld	[AES_NROUNDS + CTX], ROUND
+	mov	ROUNDS, COUNT
 	add	SRC, 16, SRC
 	add	KEY, 16, KEY
 
-	srl	ROUND, 1, ROUND
-	C	Last two rounds handled specially
-	sub	ROUND, 1, ROUND
 .Lround_loop:
 	C The AES_ROUND macro uses T0,... T3
 	C	Transform W -> X
@@ -110,7 +112,7 @@ PROLOGUE(_nettle_aes_decrypt)
 	AES_ROUND(6, X2, X1, X0, X3, KEY, W2)
 	AES_ROUND(7, X3, X2, X1, X0, KEY, W3)
 
-	subcc	ROUND, 1, ROUND
+	subcc	COUNT, 1, COUNT
 	bne	.Lround_loop
 	add	KEY, 32, KEY
 
diff --git a/sparc64/aes-encrypt-internal.asm b/sparc64/aes-encrypt-internal.asm
index f24157555720da6c6fccec3bc8fc746e8515c74e..7d1631600867c2080aa14ca36e27a4755b5b6417 100644
--- a/sparc64/aes-encrypt-internal.asm
+++ b/sparc64/aes-encrypt-internal.asm
@@ -1,6 +1,6 @@
 C nettle, low-level cryptographics library
 C 
-C Copyright (C) 2002, 2005 Niels Möller
+C Copyright (C) 2002, 2005, 2013 Niels Möller
 C  
 C The nettle library is free software; you can redistribute it and/or modify
 C it under the terms of the GNU Lesser General Public License as published by
@@ -23,14 +23,15 @@ C doesn't matter, since we don't access any data on the stack).
 
 
 C Use the same AES macros as on sparc32.
-include_src(sparc32/aes.m4)
+include_src(<sparc32/aes.m4>)
 
 C	Arguments
-define(<CTX>,	<%i0>)
-define(<T>,	<%i1>)
-define(<LENGTH>,<%i2>)
-define(<DST>,	<%i3>)
-define(<SRC>,	<%i4>)
+define(<ROUNDS>,<%i0>)
+define(<KEYS>,	<%i1>)
+define(<T>,	<%i2>)
+define(<LENGTH>,<%i3>)
+define(<DST>,	<%i4>)
+define(<SRC>,	<%i5>)
 
 C	AES state, two copies for unrolling
 
@@ -46,10 +47,10 @@ define(<X3>,	<%l7>)
 
 C	%o0-%03 are used for loop invariants T0-T3
 define(<KEY>,	<%o4>)
-define(<ROUND>, <%o5>)
+define(<COUNT>, <%o5>)
 
 C %g1, %g2, %g3 are TMP1, TMP2 and TMP3
-		
+
 C The sparc64 stack frame looks like
 C
 C %fp -   8: OS-dependent link field
@@ -59,7 +60,7 @@ define(<FRAME_SIZE>, 192)
 
 	.file "aes-encrypt-internal.asm"
 
-	C _aes_encrypt(struct aes_context *ctx, 
+	C _aes_encrypt(unsigned rounds, const uint32_t *keys,
 	C	       const struct aes_table *T,
 	C	       size_t length, uint8_t *dst,
 	C	       uint8_t *src)
@@ -80,22 +81,23 @@ PROLOGUE(_nettle_aes_encrypt)
 	add	T, AES_TABLE2, T2
 	add	T, AES_TABLE3, T3
 
+	C	Must be even, and includes the final round
+	srl	ROUNDS, 1, ROUNDS
+	C	Last two rounds handled specially
+	sub	ROUNDS, 1, ROUNDS
+
 .Lblock_loop:
 	C  Read src, and add initial subkey
-	add	CTX, AES_KEYS, KEY
+	mov	KEYS, KEY
 	AES_LOAD(0, SRC, KEY, W0)
 	AES_LOAD(1, SRC, KEY, W1)
 	AES_LOAD(2, SRC, KEY, W2)
 	AES_LOAD(3, SRC, KEY, W3)
 
-	C	Must be even, and includes the final round
-	ld	[AES_NROUNDS + CTX], ROUND
+	mov	ROUNDS, COUNT
 	add	SRC, 16, SRC
 	add	KEY, 16, KEY
 
-	srl	ROUND, 1, ROUND
-	C	Last two rounds handled specially
-	sub	ROUND, 1, ROUND
 .Lround_loop:
 	C The AES_ROUND macro uses T0,... T3
 	C	Transform W -> X
@@ -110,7 +112,7 @@ PROLOGUE(_nettle_aes_encrypt)
 	AES_ROUND(6, X2, X3, X0, X1, KEY, W2)
 	AES_ROUND(7, X3, X0, X1, X2, KEY, W3)
 
-	subcc	ROUND, 1, ROUND
+	subcc	COUNT, 1, COUNT
 	bne	.Lround_loop
 	add	KEY, 32, KEY
 
diff --git a/testsuite/aes-test.c b/testsuite/aes-test.c
index 62936d1b74c3612da06d4e6300a20106d73c7d49..964114e3c84b0c221921b94d86e39cb75f8a4103 100644
--- a/testsuite/aes-test.c
+++ b/testsuite/aes-test.c
@@ -1,5 +1,6 @@
 #include "testutils.h"
 #include "aes.h"
+#include "nettle-internal.h"
 
 static void
 test_invert(const struct tstring *key,
@@ -45,58 +46,69 @@ test_invert(const struct tstring *key,
   free (data);
 }
 
+static void
+test_cipher2(const struct nettle_cipher *c1,
+	     const struct nettle_cipher *c2,	     
+	     const struct tstring *key,
+	     const struct tstring *cleartext,
+	     const struct tstring *ciphertext)
+{
+  test_cipher (c1, key, cleartext, ciphertext);
+  test_cipher (c2, key, cleartext, ciphertext);
+}
+
 void
 test_main(void)
 {
+  /* Test both the new interface and the older unified interface. */
+
   /* 128 bit keys */
-  test_cipher(&nettle_aes128, 
-	      SHEX("0001020305060708 0A0B0C0D0F101112"),
-	      SHEX("506812A45F08C889 B97F5980038B8359"),
-	      SHEX("D8F532538289EF7D 06B506A4FD5BE9C9"));
+  test_cipher2(&nettle_aes128, &nettle_unified_aes128,
+	       SHEX("0001020305060708 0A0B0C0D0F101112"),
+	       SHEX("506812A45F08C889 B97F5980038B8359"),
+	       SHEX("D8F532538289EF7D 06B506A4FD5BE9C9"));
   
-  test_cipher(&nettle_aes128, 
-	      SHEX("14151617191A1B1C 1E1F202123242526"),
-	      SHEX("5C6D71CA30DE8B8B 00549984D2EC7D4B"),
-	      SHEX("59AB30F4D4EE6E4F F9907EF65B1FB68C"));
-
-  test_cipher(&nettle_aes128, 
-	      SHEX("28292A2B2D2E2F30 323334353738393A"),
-	      SHEX("53F3F4C64F8616E4 E7C56199F48F21F6"),
-	      SHEX("BF1ED2FCB2AF3FD4 1443B56D85025CB1"));
+  test_cipher2(&nettle_aes128, &nettle_unified_aes128,
+	       SHEX("14151617191A1B1C 1E1F202123242526"),
+	       SHEX("5C6D71CA30DE8B8B 00549984D2EC7D4B"),
+	       SHEX("59AB30F4D4EE6E4F F9907EF65B1FB68C"));
+
+  test_cipher2(&nettle_aes128, &nettle_unified_aes128,
+	       SHEX("28292A2B2D2E2F30 323334353738393A"),
+	       SHEX("53F3F4C64F8616E4 E7C56199F48F21F6"),
+	       SHEX("BF1ED2FCB2AF3FD4 1443B56D85025CB1"));
   
-  test_cipher(&nettle_aes128, 
-	      SHEX("A0A1A2A3A5A6A7A8 AAABACADAFB0B1B2"),
-	      SHEX("F5F4F7F684878689 A6A7A0A1D2CDCCCF"),
-	      SHEX("CE52AF650D088CA5 59425223F4D32694"));
+  test_cipher2(&nettle_aes128, &nettle_unified_aes128,
+	       SHEX("A0A1A2A3A5A6A7A8 AAABACADAFB0B1B2"),
+	       SHEX("F5F4F7F684878689 A6A7A0A1D2CDCCCF"),
+	       SHEX("CE52AF650D088CA5 59425223F4D32694"));
 
   /* 192 bit keys */
-  
-  test_cipher(&nettle_aes192, 
-	      SHEX("0001020305060708 0A0B0C0D0F101112"
-		   "14151617191A1B1C"),
-	      SHEX("2D33EEF2C0430A8A 9EBF45E809C40BB6"),
-	      SHEX("DFF4945E0336DF4C 1C56BC700EFF837F"));
+  test_cipher2(&nettle_aes192, &nettle_unified_aes192, 
+	       SHEX("0001020305060708 0A0B0C0D0F101112"
+		    "14151617191A1B1C"),
+	       SHEX("2D33EEF2C0430A8A 9EBF45E809C40BB6"),
+	       SHEX("DFF4945E0336DF4C 1C56BC700EFF837F"));
 
   /* 256 bit keys */
-  
-  test_cipher(&nettle_aes256,
-	      SHEX("0001020305060708 0A0B0C0D0F101112"
-		   "14151617191A1B1C 1E1F202123242526"),
-	      SHEX("834EADFCCAC7E1B30664B1ABA44815AB"),
-	      SHEX("1946DABF6A03A2A2 C3D0B05080AED6FC"));
+  test_cipher2(&nettle_aes256, &nettle_unified_aes256,
+	       SHEX("0001020305060708 0A0B0C0D0F101112"
+		    "14151617191A1B1C 1E1F202123242526"),
+	       SHEX("834EADFCCAC7E1B30664B1ABA44815AB"),
+	       SHEX("1946DABF6A03A2A2 C3D0B05080AED6FC"));
 
   
   /* This test case has been problematic with the CBC test case */
-  test_cipher(&nettle_aes256,
-	      SHEX("8d ae 93 ff fc 78 c9 44"
-		   "2a bd 0c 1e 68 bc a6 c7"
-		   "05 c7 84 e3 5a a9 11 8b"
-		   "d3 16 aa 54 9b 44 08 9e"),
-	      SHEX("a5 ce 55 d4 21 15 a1 c6 4a a4 0c b2 ca a6 d1 37"),
-	      /* In the cbc test, I once got the bad value
-	       *   "b2 a0 6c d2 2f df 7d 2c  26 d2 42 88 8f 20 74 a2" */
-	      SHEX("1f 94 fc 85 f2 36 21 06"
-		   "4a ea e3 c9 cc 38 01 0e"));
+  test_cipher2(&nettle_aes256, &nettle_unified_aes256,
+	       SHEX("8d ae 93 ff fc 78 c9 44"
+		    "2a bd 0c 1e 68 bc a6 c7"
+		    "05 c7 84 e3 5a a9 11 8b"
+		    "d3 16 aa 54 9b 44 08 9e"),
+	       SHEX("a5 ce 55 d4 21 15 a1 c6 4a a4 0c b2 ca a6 d1 37"),
+	       /* In the cbc test, I once got the bad value
+		*   "b2 a0 6c d2 2f df 7d 2c  26 d2 42 88 8f 20 74 a2" */
+	       SHEX("1f 94 fc 85 f2 36 21 06"
+		    "4a ea e3 c9 cc 38 01 0e"));
   
   /* From draft NIST spec on AES modes.
    *
@@ -104,42 +116,42 @@ test_main(void)
    * F.1.1 ECB-AES128-Encrypt
    */
 
-  test_cipher(&nettle_aes128,
-	      SHEX("2b7e151628aed2a6abf7158809cf4f3c"),
-	      SHEX("6bc1bee22e409f96e93d7e117393172a"
-		   "ae2d8a571e03ac9c9eb76fac45af8e51"
-		   "30c81c46a35ce411e5fbc1191a0a52ef"
-		   "f69f2445df4f9b17ad2b417be66c3710"),
-	      SHEX("3ad77bb40d7a3660a89ecaf32466ef97"
-		   "f5d3d58503b9699de785895a96fdbaaf"
-		   "43b1cd7f598ece23881b00e3ed030688"
-		   "7b0c785e27e8ad3f8223207104725dd4"));
+  test_cipher2(&nettle_aes128, &nettle_unified_aes128,
+	       SHEX("2b7e151628aed2a6abf7158809cf4f3c"),
+	       SHEX("6bc1bee22e409f96e93d7e117393172a"
+		    "ae2d8a571e03ac9c9eb76fac45af8e51"
+		    "30c81c46a35ce411e5fbc1191a0a52ef"
+		    "f69f2445df4f9b17ad2b417be66c3710"),
+	       SHEX("3ad77bb40d7a3660a89ecaf32466ef97"
+		    "f5d3d58503b9699de785895a96fdbaaf"
+		    "43b1cd7f598ece23881b00e3ed030688"
+		    "7b0c785e27e8ad3f8223207104725dd4"));
 
   /* F.1.3 ECB-AES192-Encrypt */
 
-  test_cipher(&nettle_aes192,
-	      SHEX("8e73b0f7da0e6452c810f32b809079e5 62f8ead2522c6b7b"),
-	      SHEX("6bc1bee22e409f96e93d7e117393172a"
-		   "ae2d8a571e03ac9c9eb76fac45af8e51"
-		   "30c81c46a35ce411e5fbc1191a0a52ef"
-		   "f69f2445df4f9b17ad2b417be66c3710"),
-	      SHEX("bd334f1d6e45f25ff712a214571fa5cc"
-		   "974104846d0ad3ad7734ecb3ecee4eef"
-		   "ef7afd2270e2e60adce0ba2face6444e"
-		   "9a4b41ba738d6c72fb16691603c18e0e"));
+  test_cipher2(&nettle_aes192, &nettle_unified_aes192, 
+	       SHEX("8e73b0f7da0e6452c810f32b809079e5 62f8ead2522c6b7b"),
+	       SHEX("6bc1bee22e409f96e93d7e117393172a"
+		    "ae2d8a571e03ac9c9eb76fac45af8e51"
+		    "30c81c46a35ce411e5fbc1191a0a52ef"
+		    "f69f2445df4f9b17ad2b417be66c3710"),
+	       SHEX("bd334f1d6e45f25ff712a214571fa5cc"
+		    "974104846d0ad3ad7734ecb3ecee4eef"
+		    "ef7afd2270e2e60adce0ba2face6444e"
+		    "9a4b41ba738d6c72fb16691603c18e0e"));
 
   /* F.1.5 ECB-AES256-Encrypt */
-  test_cipher(&nettle_aes256,
-	      SHEX("603deb1015ca71be2b73aef0857d7781"
-		   "1f352c073b6108d72d9810a30914dff4"),
-	      SHEX("6bc1bee22e409f96e93d7e117393172a"
-		   "ae2d8a571e03ac9c9eb76fac45af8e51" 
-		   "30c81c46a35ce411e5fbc1191a0a52ef"
-		   "f69f2445df4f9b17ad2b417be66c3710"),
-	      SHEX("f3eed1bdb5d2a03c064b5a7e3db181f8"
-		   "591ccb10d410ed26dc5ba74a31362870"
-		   "b6ed21b99ca6f4f9f153e7b1beafed1d"
-		   "23304b7a39f9f3ff067d8d8f9e24ecc7"));
+  test_cipher2(&nettle_aes256, &nettle_unified_aes256,
+	       SHEX("603deb1015ca71be2b73aef0857d7781"
+		    "1f352c073b6108d72d9810a30914dff4"),
+	       SHEX("6bc1bee22e409f96e93d7e117393172a"
+		    "ae2d8a571e03ac9c9eb76fac45af8e51" 
+		    "30c81c46a35ce411e5fbc1191a0a52ef"
+		    "f69f2445df4f9b17ad2b417be66c3710"),
+	       SHEX("f3eed1bdb5d2a03c064b5a7e3db181f8"
+		    "591ccb10d410ed26dc5ba74a31362870"
+		    "b6ed21b99ca6f4f9f153e7b1beafed1d"
+		    "23304b7a39f9f3ff067d8d8f9e24ecc7"));
 
   /* Test aes_invert_key with src != dst */
   test_invert(SHEX("0001020305060708 0A0B0C0D0F101112"),
diff --git a/umac-set-key.c b/umac-set-key.c
index 03057a460f8d9e075fd6ad041e98723bb35a3571..63a1a7e3ffa034acf5226b967e35e36f403442dc 100644
--- a/umac-set-key.c
+++ b/umac-set-key.c
@@ -32,7 +32,7 @@
 #include "macros.h"
 
 static void
-umac_kdf (struct aes_ctx *aes, unsigned index, unsigned length, uint8_t *dst)
+umac_kdf (struct aes128_ctx *aes, unsigned index, unsigned length, uint8_t *dst)
 {
   uint8_t block[AES_BLOCK_SIZE];
   uint64_t count;
@@ -41,12 +41,12 @@ umac_kdf (struct aes_ctx *aes, unsigned index, unsigned length, uint8_t *dst)
        length -= AES_BLOCK_SIZE, dst += AES_BLOCK_SIZE, count++)
     {
       WRITE_UINT64 (block + 8, count);
-      aes_encrypt (aes, AES_BLOCK_SIZE, dst, block);
+      aes128_encrypt (aes, AES_BLOCK_SIZE, dst, block);
     }
   if (length > 0)
     {
       WRITE_UINT64 (block + 8, count);
-      aes_encrypt (aes, AES_BLOCK_SIZE, block, block);
+      aes128_encrypt (aes, AES_BLOCK_SIZE, block, block);
       memcpy (dst, block, length);
     }
 }
@@ -71,12 +71,12 @@ umac_kdf (struct aes_ctx *aes, unsigned index, unsigned length, uint8_t *dst)
 void
 _umac_set_key (uint32_t *l1_key, uint32_t *l2_key,
 	       uint64_t *l3_key1, uint32_t *l3_key2,
-	       struct aes_ctx *aes, const uint8_t *key, unsigned n)
+	       struct aes128_ctx *aes, const uint8_t *key, unsigned n)
 {
   unsigned size;
   uint8_t buffer[UMAC_KEY_SIZE];
 
-  aes_set_encrypt_key (aes, UMAC_KEY_SIZE, key);
+  aes128_set_encrypt_key (aes, key);
 
   size = UMAC_DATA_SIZE / 4 + 4*(n-1);
   umac_kdf (aes, 1, size * sizeof(uint32_t), (uint8_t *) l1_key);
@@ -94,5 +94,5 @@ _umac_set_key (uint32_t *l1_key, uint32_t *l2_key,
   umac_kdf (aes, 4, n * sizeof(uint32_t), (uint8_t *) l3_key2);
 
   umac_kdf (aes, 0, UMAC_KEY_SIZE, buffer);
-  aes_set_encrypt_key (aes, UMAC_KEY_SIZE, buffer);
+  aes128_set_encrypt_key (aes, buffer);
 }
diff --git a/umac.h b/umac.h
index b6cec8aa656f7997c1511311c12d7981c7c1428e..ab66d9a7300b98cfb9e5dd5ff0dd5d88c92843be 100644
--- a/umac.h
+++ b/umac.h
@@ -61,7 +61,7 @@ extern "C" {
 #include "nettle-types.h"
 #include "aes.h"
 
-#define UMAC_KEY_SIZE 16
+#define UMAC_KEY_SIZE AES128_KEY_SIZE
 #define UMAC32_DIGEST_SIZE 4
 #define UMAC64_DIGEST_SIZE 8
 #define UMAC96_DIGEST_SIZE 12
@@ -76,7 +76,7 @@ extern "C" {
   uint64_t l3_key1[8*(n)];				\
   uint32_t l3_key2[(n)];				\
   /* AES cipher for encrypting the nonce */		\
-  struct aes_ctx pdf_key;				\
+  struct aes128_ctx pdf_key;				\
   /* The l2_state consists of 2*n uint64_t, for poly64	\
      and poly128 hashing, followed by n additional	\
      uint64_t used as an input buffer. */		\
@@ -192,7 +192,7 @@ umac128_digest (struct umac128_ctx *ctx,
 void
 _umac_set_key (uint32_t *l1_key, uint32_t *l2_key,
 	       uint64_t *l3_key1, uint32_t *l3_key2,
-	       struct aes_ctx *pad, const uint8_t *key, unsigned n);
+	       struct aes128_ctx *pad, const uint8_t *key, unsigned n);
 
 uint64_t
 _umac_nh (const uint32_t *key, unsigned length, const uint8_t *msg);
diff --git a/umac128.c b/umac128.c
index 3ce0c05ed8fd6d58cb7375e11416e2fbddacf147..56d15d759e4a3f79e58b01ca77e841e1d7d9a549 100644
--- a/umac128.c
+++ b/umac128.c
@@ -103,8 +103,8 @@ umac128_digest (struct umac128_ctx *ctx,
     }
   assert (ctx->count > 0);
 
-  aes_encrypt (&ctx->pdf_key, AES_BLOCK_SIZE,
-	       (uint8_t *) tag, ctx->nonce);
+  aes128_encrypt (&ctx->pdf_key, AES_BLOCK_SIZE,
+		  (uint8_t *) tag, ctx->nonce);
 
   INCREMENT (ctx->nonce_length, ctx->nonce);
 
diff --git a/umac32.c b/umac32.c
index c266a4166dc6ac43aec9e1effed723f5cfa9d358..8d6eb7dccd320c321552f4d2c5406e88554f3b96 100644
--- a/umac32.c
+++ b/umac32.c
@@ -100,8 +100,8 @@ umac32_digest (struct umac32_ctx *ctx,
   assert (ctx->count > 0);
   if ( !(ctx->nonce_low & _UMAC_NONCE_CACHED))
     {
-      aes_encrypt (&ctx->pdf_key, AES_BLOCK_SIZE,
-		   (uint8_t *) ctx->pad_cache, ctx->nonce);
+      aes128_encrypt (&ctx->pdf_key, AES_BLOCK_SIZE,
+		      (uint8_t *) ctx->pad_cache, ctx->nonce);
       ctx->nonce_low |= _UMAC_NONCE_CACHED;
     }
 
diff --git a/umac64.c b/umac64.c
index 133f2783588ba84e3aa8deb16c7ea017522bf707..01b9dc81525935e94494304b15fc29fb59c64f7e 100644
--- a/umac64.c
+++ b/umac64.c
@@ -103,8 +103,8 @@ umac64_digest (struct umac64_ctx *ctx,
   assert (ctx->count > 0);
   if ( !(ctx->nonce_low & _UMAC_NONCE_CACHED))
     {
-      aes_encrypt (&ctx->pdf_key, AES_BLOCK_SIZE,
-		   (uint8_t *) ctx->pad_cache, ctx->nonce);
+      aes128_encrypt (&ctx->pdf_key, AES_BLOCK_SIZE,
+		      (uint8_t *) ctx->pad_cache, ctx->nonce);
       ctx->nonce_low |= _UMAC_NONCE_CACHED;
     }
   pad = ctx->pad_cache + 2*(ctx->nonce_low & 1);
diff --git a/umac96.c b/umac96.c
index 3c7905a9a4df9c52e95fac5e81632f43ac119f71..0dc51418db08e1c1316dbef818bc0069a8171936 100644
--- a/umac96.c
+++ b/umac96.c
@@ -101,8 +101,8 @@ umac96_digest (struct umac96_ctx *ctx,
     }
   assert (ctx->count > 0);
 
-  aes_encrypt (&ctx->pdf_key, AES_BLOCK_SIZE,
-	       (uint8_t *) tag, ctx->nonce);
+  aes128_encrypt (&ctx->pdf_key, AES_BLOCK_SIZE,
+		  (uint8_t *) tag, ctx->nonce);
 
   INCREMENT (ctx->nonce_length, ctx->nonce);
 
diff --git a/x86/aes-decrypt-internal.asm b/x86/aes-decrypt-internal.asm
index 6220c11d3eb5fac2a4602f3bdc9f7ab4a7453fee..61339e2f5a40fd7f28d356a14a0a563f7e6aad69 100644
--- a/x86/aes-decrypt-internal.asm
+++ b/x86/aes-decrypt-internal.asm
@@ -1,6 +1,7 @@
 C nettle, low-level cryptographics library
 C 
 C Copyright (C) 2001, 2002, 2005 Rafael R. Sevilla, Niels Möller
+C Copyright (C) 2013, Niels Möller
 C  
 C The nettle library is free software; you can redistribute it and/or modify
 C it under the terms of the GNU Lesser General Public License as published by
@@ -32,11 +33,12 @@ define(<T>,<%ebp>)
 define(<TMP>,<%edi>)
 define(<KEY>,<%esi>)
 
-define(<FRAME_CTX>,	<40(%esp)>)
-define(<FRAME_TABLE>,	<44(%esp)>)
-define(<FRAME_LENGTH>,	<48(%esp)>)
-define(<FRAME_DST>,	<52(%esp)>)
-define(<FRAME_SRC>,	<56(%esp)>)
+define(<PARAM_ROUNDS>,	<40(%esp)>)
+define(<PARAM_KEYS>,	<44(%esp)>)
+define(<PARAM_TABLE>,	<48(%esp)>)
+define(<PARAM_LENGTH>,	<52(%esp)>)
+define(<PARAM_DST>,	<56(%esp)>)
+define(<PARAM_SRC>,	<60(%esp)>)
 
 define(<FRAME_KEY>,	<16(%esp)>)
 define(<FRAME_COUNT>,	<12(%esp)>)
@@ -55,7 +57,7 @@ C %edi is a temporary, often used as an accumulator.
 
 	.file "aes-decrypt-internal.asm"
 	
-	C _aes_decrypt(struct aes_context *ctx, 
+	C _aes_decrypt(unsigned rounds, const uint32_t *keys,
 	C	       const struct aes_table *T,
 	C	       size_t length, uint8_t *dst,
 	C	       uint8_t *src)
@@ -70,24 +72,21 @@ PROLOGUE(_nettle_aes_decrypt)
 
 	subl	$20, %esp	C  loop counter and save area for the key pointer
 
-	movl	FRAME_LENGTH, %ebp
+	movl	PARAM_LENGTH, %ebp
 	testl	%ebp,%ebp
 	jz	.Lend
 
-	shrl	$4, FRAME_LENGTH
-
+	shrl	$4, PARAM_LENGTH
+	subl	$1, PARAM_ROUNDS
 .Lblock_loop:
-	movl	FRAME_CTX,KEY	C  address of context struct ctx
+	movl	PARAM_KEYS, KEY	C  address of subkeys
 	
-	movl	FRAME_SRC,TMP	C  address of plaintext
+	movl	PARAM_SRC, TMP	C  address of plaintext
 	AES_LOAD(SA, SB, SC, SD, TMP, KEY)
-	addl	$16, FRAME_SRC	C Increment src pointer
-	movl	FRAME_TABLE, T
-
-	C  get number of rounds to do from ctx struct	
-	movl	AES_NROUNDS (KEY),TMP
-	subl	$1,TMP
+	addl	$16, PARAM_SRC	C Increment src pointer
+	movl	PARAM_TABLE, T
 
+	movl	PARAM_ROUNDS, TMP
 	C Loop counter on stack
 	movl	TMP, FRAME_COUNT
 
@@ -140,18 +139,18 @@ PROLOGUE(_nettle_aes_decrypt)
 	C Inverse S-box substitution
 	mov	$3,TMP
 .Lsubst:
-	AES_SUBST_BYTE(SA,SB,SC,SD,T, KEY)
+	AES_SUBST_BYTE(SA,SB,SC,SD, T, KEY)
 
 	decl	TMP
 	jnz	.Lsubst
 
 	C Add last subkey, and store decrypted data
-	movl	FRAME_DST,TMP
+	movl	PARAM_DST,TMP
 	movl	FRAME_KEY, KEY
 	AES_STORE(SA,SB,SC,SD, KEY, TMP)
 	
-	addl	$16, FRAME_DST		C Increment destination pointer
-	decl	FRAME_LENGTH
+	addl	$16, PARAM_DST		C Increment destination pointer
+	decl	PARAM_LENGTH
 
 	jnz	.Lblock_loop
 
diff --git a/x86/aes-encrypt-internal.asm b/x86/aes-encrypt-internal.asm
index 86985ec62c569d3701c9b6c00cda29873cbd31f1..6ddda58dcef5983555615daa6ff05a6a029dfb9c 100644
--- a/x86/aes-encrypt-internal.asm
+++ b/x86/aes-encrypt-internal.asm
@@ -1,6 +1,7 @@
 C nettle, low-level cryptographics library
 C 
 C Copyright (C) 2001, 2002, 2005 Rafael R. Sevilla, Niels Möller
+C Copyright (C) 2013, Niels Möller
 C  
 C The nettle library is free software; you can redistribute it and/or modify
 C it under the terms of the GNU Lesser General Public License as published by
@@ -32,11 +33,12 @@ define(<T>,<%ebp>)
 define(<TMP>,<%edi>)
 define(<KEY>,<%esi>)
 
-define(<FRAME_CTX>,	<40(%esp)>)
-define(<FRAME_TABLE>,	<44(%esp)>)
-define(<FRAME_LENGTH>,	<48(%esp)>)
-define(<FRAME_DST>,	<52(%esp)>)
-define(<FRAME_SRC>,	<56(%esp)>)
+define(<PARAM_ROUNDS>,	<40(%esp)>)
+define(<PARAM_KEYS>,	<44(%esp)>)
+define(<PARAM_TABLE>,	<48(%esp)>)
+define(<PARAM_LENGTH>,	<52(%esp)>)
+define(<PARAM_DST>,	<56(%esp)>)
+define(<PARAM_SRC>,	<60(%esp)>)
 
 define(<FRAME_KEY>,	<16(%esp)>)
 define(<FRAME_COUNT>,	<12(%esp)>)
@@ -55,7 +57,7 @@ C %edi is a temporary, often used as an accumulator.
 
 	.file "aes-encrypt-internal.asm"
 	
-	C _aes_encrypt(struct aes_context *ctx, 
+	C _aes_encrypt(unsigned rounds, const uint32_t *keys,
 	C	       const struct aes_table *T,
 	C	       size_t length, uint8_t *dst,
 	C	       uint8_t *src)
@@ -70,24 +72,21 @@ PROLOGUE(_nettle_aes_encrypt)
 
 	subl	$20, %esp	C  loop counter and save area for the key pointer
 
-	movl	FRAME_LENGTH, %ebp
+	movl	PARAM_LENGTH, %ebp
 	testl	%ebp,%ebp
 	jz	.Lend
 
-	shrl	$4, FRAME_LENGTH
-
+	shrl	$4, PARAM_LENGTH
+	subl	$1, PARAM_ROUNDS
 .Lblock_loop:
-	movl	FRAME_CTX,KEY	C  address of context struct ctx
+	movl	PARAM_KEYS, KEY	C  address of subkeys
 	
-	movl	FRAME_SRC,TMP	C  address of plaintext
+	movl	PARAM_SRC, TMP	C  address of plaintext
 	AES_LOAD(SA, SB, SC, SD, TMP, KEY)
-	addl	$16, FRAME_SRC	C Increment src pointer
-	movl	FRAME_TABLE, T
-
-	C  get number of rounds to do from ctx struct	
-	movl	AES_NROUNDS (KEY),TMP
-	subl	$1,TMP
+	addl	$16, PARAM_SRC	C Increment src pointer
+	movl	PARAM_TABLE, T
 
+	movl	PARAM_ROUNDS, TMP
 	C Loop counter on stack
 	movl	TMP, FRAME_COUNT
 
@@ -146,12 +145,12 @@ PROLOGUE(_nettle_aes_encrypt)
 	jnz	.Lsubst
 
 	C Add last subkey, and store encrypted data
-	movl	FRAME_DST,TMP
+	movl	PARAM_DST,TMP
 	movl	FRAME_KEY, KEY
 	AES_STORE(SA,SB,SC,SD, KEY, TMP)
 	
-	addl	$16, FRAME_DST		C Increment destination pointer
-	decl	FRAME_LENGTH
+	addl	$16, PARAM_DST		C Increment destination pointer
+	decl	PARAM_LENGTH
 
 	jnz	.Lblock_loop
 
diff --git a/x86_64/aes-decrypt-internal.asm b/x86_64/aes-decrypt-internal.asm
index 606b7c89e559dd69e1006e2001093d1665ea2476..f3451deb7ade185d4f3b0172bdac78f0e2468e67 100644
--- a/x86_64/aes-decrypt-internal.asm
+++ b/x86_64/aes-decrypt-internal.asm
@@ -1,7 +1,8 @@
 C nettle, low-level cryptographics library
 C 
-C Copyright (C) 2001, 2002, 2005, 2008 Rafael R. Sevilla, Niels Möller
-C  
+C Copyright (C) 2001, 2002, 2005, Rafael R. Sevilla, Niels Möller
+C Copyright (C) 2008, 2013 Niels Möller
+C
 C The nettle library is free software; you can redistribute it and/or modify
 C it under the terms of the GNU Lesser General Public License as published by
 C the Free Software Foundation; either version 2.1 of the License, or (at your
@@ -31,16 +32,17 @@ define(<TA>,<%r10d>)
 define(<TB>,<%r11d>)
 define(<TC>,<%r12d>)
 
-define(<CTX>,	<%rdi>)
-define(<TABLE>,	<%rsi>)
-define(<PARAM_LENGTH>,<%rdx>)
-define(<PARAM_DST>,	<%rcx>)
-define(<SRC>,	<%r8>)
+C Input argument
+define(<ROUNDS>, <%rdi>)
+define(<KEYS>,	<%rsi>)
+define(<PARAM_TABLE>,	<%rdx>)
+define(<PARAM_LENGTH>,<%rcx>)
+define(<DST>,	<%r8>)
+define(<SRC>,	<%r9>)
 
-define(<DST>, <%r9>) 
-define(<KEY>,<%r14>)
-define(<COUNT>,	<%r15d>)
-define(<BLOCK_COUNT>, <%r13>)
+define(<TABLE>, <%r13>) 
+define(<LENGTH>,<%r14>)
+define(<KEY>,	<%r15>)
 
 C Must correspond to an old-style register, for movzb from %ah--%dh to
 C work.
@@ -48,14 +50,14 @@ define(<TMP>,<%rbp>)
 
 	.file "aes-decrypt-internal.asm"
 	
-	C _aes_decrypt(struct aes_context *ctx, 
+	C _aes_decrypt(unsigned rounds, const uint32_t *keys,
 	C	       const struct aes_table *T,
 	C	       size_t length, uint8_t *dst,
 	C	       uint8_t *src)
 	.text
 	ALIGN(16)
 PROLOGUE(_nettle_aes_decrypt)
-	W64_ENTRY(5, 0)
+	W64_ENTRY(6, 0)
 	test	PARAM_LENGTH, PARAM_LENGTH
 	jz	.Lend
 
@@ -67,20 +69,21 @@ PROLOGUE(_nettle_aes_decrypt)
 	push	%r14
 	push	%r15	
 
-	mov	PARAM_DST, DST
-	mov	PARAM_LENGTH, BLOCK_COUNT
-	shr	$4, BLOCK_COUNT
+	subl	$1, XREG(ROUNDS)
+	push	ROUNDS		C Rounds at (%rsp) 
+	
+	mov	PARAM_TABLE, TABLE
+	mov	PARAM_LENGTH, LENGTH
+	shr	$4, LENGTH
 .Lblock_loop:
-	mov	CTX,KEY
+	mov	KEYS, KEY
 	
 	AES_LOAD(SA, SB, SC, SD, SRC, KEY)
 	add	$16, SRC	C Increment src pointer
 
-	C  get number of rounds to do from ctx struct	
-	movl	AES_NROUNDS (CTX), COUNT
-	subl	$1, COUNT
+	movl	(%rsp), XREG(ROUNDS)
 
-	add	$16,KEY		C  point to next key
+	add	$16, KEY	C  point to next key
 	ALIGN(16)
 .Lround_loop:
 	AES_ROUND(TABLE, SA,SD,SC,SB, TA, TMP)
@@ -97,8 +100,8 @@ PROLOGUE(_nettle_aes_decrypt)
 	xorl	8(KEY),SC
 	xorl	12(KEY),SD
 
-	add	$16,KEY	C  point to next key
-	decl	COUNT
+	add	$16, KEY	C  point to next key
+	decl	XREG(ROUNDS)
 	jnz	.Lround_loop
 
 	C last round
@@ -108,28 +111,29 @@ PROLOGUE(_nettle_aes_decrypt)
 	AES_FINAL_ROUND(SD,SC,SB,SA, TABLE, SD, TMP)
 
 	C Inverse S-box substitution
-	mov	$3, COUNT
+	mov	$3, XREG(ROUNDS)
 .Lsubst:
 	AES_SUBST_BYTE(TA,TB,TC,SD, TABLE, TMP)
 
-	decl	COUNT
+	decl	XREG(ROUNDS)
 	jnz	.Lsubst
 
 	C Add last subkey, and store decrypted data
 	AES_STORE(TA,TB,TC,SD, KEY, DST)
 	
 	add	$16, DST
-	dec	BLOCK_COUNT
+	dec	LENGTH
 
 	jnz	.Lblock_loop
 
-	pop	%r15	
+	lea	8(%rsp), %rsp	C Drop ROUNDS
+	pop	%r15
 	pop	%r14
 	pop	%r13
 	pop	%r12
 	pop	%rbp
 	pop	%rbx
 .Lend:
-	W64_EXIT(5, 0)
+	W64_EXIT(6, 0)
 	ret
 EPILOGUE(_nettle_aes_decrypt)
diff --git a/x86_64/aes-encrypt-internal.asm b/x86_64/aes-encrypt-internal.asm
index e1003c69941710e6e6c621f1867784fefaca8e54..27b031b57a7b92bd32f5cad0187ba1a40ae06fcc 100644
--- a/x86_64/aes-encrypt-internal.asm
+++ b/x86_64/aes-encrypt-internal.asm
@@ -1,6 +1,7 @@
 C nettle, low-level cryptographics library
 C 
-C Copyright (C) 2001, 2002, 2005, 2008 Rafael R. Sevilla, Niels Möller
+C Copyright (C) 2001, 2002, 2005, Rafael R. Sevilla, Niels Möller
+C Copyright (C) 2008, 2013 Niels Möller
 C  
 C The nettle library is free software; you can redistribute it and/or modify
 C it under the terms of the GNU Lesser General Public License as published by
@@ -31,16 +32,17 @@ define(<TA>,<%r10d>)
 define(<TB>,<%r11d>)
 define(<TC>,<%r12d>)
 
-define(<CTX>,	<%rdi>)
-define(<TABLE>,	<%rsi>)
-define(<PARAM_LENGTH>,<%rdx>)
-define(<PARAM_DST>,	<%rcx>)
-define(<SRC>,	<%r8>)
+C Input argument
+define(<ROUNDS>, <%rdi>)
+define(<KEYS>,	<%rsi>)
+define(<PARAM_TABLE>,	<%rdx>)
+define(<PARAM_LENGTH>,<%rcx>)
+define(<DST>,	<%r8>)
+define(<SRC>,	<%r9>)
 
-define(<DST>, <%r9>) 
-define(<KEY>,<%r14>)
-define(<COUNT>,	<%r15d>)
-define(<BLOCK_COUNT>, <%r13>)
+define(<TABLE>, <%r13>) 
+define(<LENGTH>,<%r14>)
+define(<KEY>,	<%r15>)
 
 C Must correspond to an old-style register, for movzb from %ah--%dh to
 C work.
@@ -48,14 +50,14 @@ define(<TMP>,<%rbp>)
 
 	.file "aes-encrypt-internal.asm"
 	
-	C _aes_encrypt(struct aes_context *ctx, 
+	C _aes_encrypt(unsigned rounds, const uint32_t *keys,
 	C	       const struct aes_table *T,
 	C	       size_t length, uint8_t *dst,
 	C	       uint8_t *src)
 	.text
 	ALIGN(16)
 PROLOGUE(_nettle_aes_encrypt)
-	W64_ENTRY(5, 0)
+	W64_ENTRY(6, 0)
 	test	PARAM_LENGTH, PARAM_LENGTH
 	jz	.Lend
 
@@ -67,20 +69,21 @@ PROLOGUE(_nettle_aes_encrypt)
 	push	%r14
 	push	%r15	
 
-	mov	PARAM_DST, DST
-	mov	PARAM_LENGTH, BLOCK_COUNT
-	shr	$4, BLOCK_COUNT
+	subl	$1, XREG(ROUNDS)
+	push	ROUNDS		C Rounds at (%rsp) 
+	
+	mov	PARAM_TABLE, TABLE
+	mov	PARAM_LENGTH, LENGTH
+	shr	$4, LENGTH
 .Lblock_loop:
-	mov	CTX,KEY
+	mov	KEYS, KEY
 	
 	AES_LOAD(SA, SB, SC, SD, SRC, KEY)
 	add	$16, SRC	C Increment src pointer
 
-	C  get number of rounds to do from ctx struct	
-	movl	AES_NROUNDS (CTX), COUNT
-	subl	$1, COUNT
+	movl	(%rsp), XREG(ROUNDS)
 
-	add	$16,KEY		C  point to next key
+	add	$16, KEY	C  point to next key
 	ALIGN(16)
 .Lround_loop:
 	AES_ROUND(TABLE, SA,SB,SC,SD, TA, TMP)
@@ -97,8 +100,8 @@ PROLOGUE(_nettle_aes_encrypt)
 	xorl	8(KEY),SC
 	xorl	12(KEY),SD
 
-	add	$16,KEY	C  point to next key
-	decl	COUNT
+	add	$16, KEY	C  point to next key
+	decl	XREG(ROUNDS)
 	jnz	.Lround_loop
 
 	C last round
@@ -108,28 +111,29 @@ PROLOGUE(_nettle_aes_encrypt)
 	AES_FINAL_ROUND(SD,SA,SB,SC, TABLE, SD, TMP)
 
 	C S-box substitution
-	mov	$3, COUNT
+	mov	$3, XREG(ROUNDS)
 .Lsubst:
 	AES_SUBST_BYTE(TA,TB,TC,SD, TABLE, TMP)
 
-	decl	COUNT
+	decl	XREG(ROUNDS)
 	jnz	.Lsubst
 
 	C Add last subkey, and store encrypted data
 	AES_STORE(TA,TB,TC,SD, KEY, DST)
 	
 	add	$16, DST
-	dec	BLOCK_COUNT
+	dec	LENGTH
 
 	jnz	.Lblock_loop
 
-	pop	%r15	
+	lea	8(%rsp), %rsp	C Drop ROUNDS
+	pop	%r15
 	pop	%r14
 	pop	%r13
 	pop	%r12
 	pop	%rbp
 	pop	%rbx
 .Lend:
-	W64_EXIT(5, 0)
+	W64_EXIT(6, 0)
 	ret
 EPILOGUE(_nettle_aes_encrypt)
diff --git a/yarrow.h b/yarrow.h
index fc6ccf9cbbb2668846f0d1b64880c8bd2823fda9..d54122df950c31726472ede3a5b2b7a6c3bd2667 100644
--- a/yarrow.h
+++ b/yarrow.h
@@ -72,7 +72,7 @@ struct yarrow256_ctx
   int seeded;
 
   /* The current key and counter block */
-  struct aes_ctx key;
+  struct aes256_ctx key;
   uint8_t counter[AES_BLOCK_SIZE];
 
   /* The entropy sources */
diff --git a/yarrow256.c b/yarrow256.c
index 800e4fd658f516a7d40a905a54b35ff57a14a24c..270a36d91510b495608f9c02dfadc24295467c4e 100644
--- a/yarrow256.c
+++ b/yarrow256.c
@@ -118,7 +118,7 @@ yarrow_generate_block(struct yarrow256_ctx *ctx,
 {
   unsigned i;
 
-  aes_encrypt(&ctx->key, sizeof(ctx->counter), block, ctx->counter);
+  aes256_encrypt(&ctx->key, sizeof(ctx->counter), block, ctx->counter);
 
   /* Increment counter, treating it as a big-endian number. This is
    * machine independent, and follows appendix B of the NIST
@@ -190,12 +190,12 @@ yarrow256_fast_reseed(struct yarrow256_ctx *ctx)
   /* Iterate */
   yarrow_iterate(digest);
 
-  aes_set_encrypt_key(&ctx->key, sizeof(digest), digest);
+  aes256_set_encrypt_key(&ctx->key, digest);
   ctx->seeded = 1;
 
   /* Derive new counter value */
   memset(ctx->counter, 0, sizeof(ctx->counter));
-  aes_encrypt(&ctx->key, sizeof(ctx->counter), ctx->counter, ctx->counter);
+  aes256_encrypt(&ctx->key, sizeof(ctx->counter), ctx->counter, ctx->counter);
   
   /* Reset estimates. */
   for (i = 0; i<ctx->nsources; i++)
@@ -305,13 +305,13 @@ yarrow256_update(struct yarrow256_ctx *ctx,
 static void
 yarrow_gate(struct yarrow256_ctx *ctx)
 {
-  uint8_t key[AES_MAX_KEY_SIZE];
+  uint8_t key[AES256_KEY_SIZE];
   unsigned i;
 
   for (i = 0; i < sizeof(key); i+= AES_BLOCK_SIZE)
     yarrow_generate_block(ctx, key + i);
 
-  aes_set_encrypt_key(&ctx->key, sizeof(key), key);
+  aes256_set_encrypt_key(&ctx->key, key);
 }
 
 void