]> git.ipfire.org Git - thirdparty/nettle.git/commitdiff
New gcm-aes interface.
authorNiels Möller <nisse@lysator.liu.se>
Sun, 26 Jan 2014 20:35:40 +0000 (21:35 +0100)
committerNiels Möller <nisse@lysator.liu.se>
Sun, 26 Jan 2014 20:35:40 +0000 (21:35 +0100)
ChangeLog
Makefile.in
examples/nettle-benchmark.c
gcm-aes128.c [new file with mode: 0644]
gcm-aes192.c [new file with mode: 0644]
gcm-aes256.c [new file with mode: 0644]
gcm.h
nettle-internal.c
nettle-internal.h
testsuite/gcm-test.c

index 53348ae4f9a207e2fd46313f38501c7883873911..ee6afd1c0b66d20091ce82fabf41f99abd4b6e39 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+2014-01-26  Niels Möller  <nisse@lysator.liu.se>
+
+       * nettle-internal.h (_NETTLE_AEAD_FIX): Renamed to...
+       (_NETTLE_AEAD): ... new name, and deleted old definition. Also use
+       _set_nonce instead of _set_iv.
+       * nettle-internal.c (nettle_gcm_aes128, nettle_gcm_aes192)
+       (nettle_gcm_aes256): Define in terms of new interface.
+       (nettle_eax_aes128): Updated for _NETTLE_AEAD changes.
+
+       * testsuite/gcm-test.c (test_gcm_hash): Likewise use struct
+       gcm_aes128_ctx.
+       (test_main): Added a testcase using the old interface based on
+       struct gcm_aes_ctx.
+
+       * examples/nettle-benchmark.c (time_gcm): Update to use new struct
+       gcm_aes128_ctx. Also use name "gcm-aes128" in output.
+
+       * gcm.h: New interface for gcm_aes128, gcm_aes192, gcm_aes256,
+       using the new AES interface.
+       (GCM_CTX): Reorder fields, putting the cipher context
+       last.
+
+       * Makefile.in (nettle_SOURCES): Added gcm-aes128.c, gcm-aes192.c,
+       and gcm-aes256.c.
+
+       * gcm-aes128.c: New file.
+       * gcm-aes192.c: New file
+       * gcm-aes256.c: New file.
+
 2014-01-25  Niels Möller  <nisse@lysator.liu.se>
 
        * gcm.h (GCM_SET_KEY): Deleted length argument.
index 878d62166e10620bf425f76f0e6e2c5b0c41a123..7292ea26b783058c60cebfbedf2c29c6d15b6917 100644 (file)
@@ -87,7 +87,8 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c \
                 camellia256-meta.c \
                 cast128.c cast128-meta.c \
                 blowfish.c \
-                cbc.c ctr.c gcm.c gcm-aes.c \
+                cbc.c ctr.c gcm.c \
+                gcm-aes.c gcm-aes128.c gcm-aes192.c gcm-aes256.c \
                 des.c des3.c des-compat.c eax.c \
                 hmac.c hmac-md5.c hmac-ripemd160.c hmac-sha1.c \
                 hmac-sha224.c hmac-sha256.c hmac-sha384.c hmac-sha512.c \
index c139e1a8930b61263c56f60d47ec9288ccafe38a..6de7dbcf70b8cd45914bf035b05392466e240b4c 100644 (file)
@@ -422,31 +422,31 @@ time_gcm(void)
   static uint8_t data[BENCH_BLOCK];
   struct bench_hash_info hinfo;
   struct bench_cipher_info cinfo;
-  struct gcm_aes_ctx ctx;
+  struct gcm_aes128_ctx ctx;
 
-  uint8_t key[16];
+  uint8_t key[AES128_KEY_SIZE];
   uint8_t iv[GCM_IV_SIZE];
 
-  gcm_aes_set_key(&ctx, sizeof(key), key);
-  gcm_aes_set_iv(&ctx, sizeof(iv), iv);
+  gcm_aes128_set_key(&ctx, sizeof(key), key);
+  gcm_aes128_set_iv(&ctx, sizeof(iv), iv);
 
   hinfo.ctx = &ctx;
-  hinfo.update = (nettle_hash_update_func *) gcm_aes_update;
+  hinfo.update = (nettle_hash_update_func *) gcm_aes128_update;
   hinfo.data = data;
   
-  display("gcm-aes", "update", GCM_BLOCK_SIZE,
+  display("gcm-aes128", "update", GCM_BLOCK_SIZE,
          time_function(bench_hash, &hinfo));
   
   cinfo.ctx = &ctx;
-  cinfo.crypt = (nettle_crypt_func *) gcm_aes_encrypt;
+  cinfo.crypt = (nettle_crypt_func *) gcm_aes128_encrypt;
   cinfo.data = data;
 
-  display("gcm-aes", "encrypt", GCM_BLOCK_SIZE,
+  display("gcm-aes128", "encrypt", GCM_BLOCK_SIZE,
          time_function(bench_cipher, &cinfo));
 
-  cinfo.crypt = (nettle_crypt_func *) gcm_aes_decrypt;
+  cinfo.crypt = (nettle_crypt_func *) gcm_aes128_decrypt;
 
-  display("gcm-aes", "decrypt", GCM_BLOCK_SIZE,
+  display("gcm-aes128", "decrypt", GCM_BLOCK_SIZE,
          time_function(bench_cipher, &cinfo));
 }
 
diff --git a/gcm-aes128.c b/gcm-aes128.c
new file mode 100644 (file)
index 0000000..4a2ec97
--- /dev/null
@@ -0,0 +1,74 @@
+/* gcm-aes128.c
+ *
+ * Galois counter mode using AES128 as the underlying cipher.
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2011, 2014 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 "gcm.h"
+
+void
+gcm_aes128_set_key(struct gcm_aes128_ctx *ctx, size_t length, const uint8_t *key)
+{
+  assert (length == AES128_KEY_SIZE);
+  GCM_SET_KEY(ctx, aes128_set_encrypt_key, aes128_encrypt, key);
+}
+
+void
+gcm_aes128_set_iv (struct gcm_aes128_ctx *ctx,
+                     size_t length, const uint8_t *iv)
+{
+  GCM_SET_IV (ctx, length, iv);
+}
+
+void
+gcm_aes128_update (struct gcm_aes128_ctx *ctx,
+                  size_t length, const uint8_t *data)
+{
+  GCM_UPDATE (ctx, length, data);
+}
+
+void
+gcm_aes128_encrypt(struct gcm_aes128_ctx *ctx,
+               size_t length, uint8_t *dst, const uint8_t *src)
+{
+  GCM_ENCRYPT(ctx, aes128_encrypt, length, dst, src);
+}
+
+void
+gcm_aes128_decrypt(struct gcm_aes128_ctx *ctx,
+                  size_t length, uint8_t *dst, const uint8_t *src)
+{
+  GCM_DECRYPT(ctx, aes128_encrypt, length, dst, src);
+}
+
+void
+gcm_aes128_digest(struct gcm_aes128_ctx *ctx,
+                 size_t length, uint8_t *digest)
+{
+  GCM_DIGEST(ctx, aes128_encrypt, length, digest);
+}
diff --git a/gcm-aes192.c b/gcm-aes192.c
new file mode 100644 (file)
index 0000000..3671829
--- /dev/null
@@ -0,0 +1,74 @@
+/* gcm-aes192.c
+ *
+ * Galois counter mode using AES192 as the underlying cipher.
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2011, 2014 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 "gcm.h"
+
+void
+gcm_aes192_set_key(struct gcm_aes192_ctx *ctx, size_t length, const uint8_t *key)
+{
+  assert (length == AES192_KEY_SIZE);
+  GCM_SET_KEY(ctx, aes192_set_encrypt_key, aes192_encrypt, key);
+}
+
+void
+gcm_aes192_set_iv (struct gcm_aes192_ctx *ctx,
+                     size_t length, const uint8_t *iv)
+{
+  GCM_SET_IV (ctx, length, iv);
+}
+
+void
+gcm_aes192_update (struct gcm_aes192_ctx *ctx,
+                  size_t length, const uint8_t *data)
+{
+  GCM_UPDATE (ctx, length, data);
+}
+
+void
+gcm_aes192_encrypt(struct gcm_aes192_ctx *ctx,
+               size_t length, uint8_t *dst, const uint8_t *src)
+{
+  GCM_ENCRYPT(ctx, aes192_encrypt, length, dst, src);
+}
+
+void
+gcm_aes192_decrypt(struct gcm_aes192_ctx *ctx,
+                  size_t length, uint8_t *dst, const uint8_t *src)
+{
+  GCM_DECRYPT(ctx, aes192_encrypt, length, dst, src);
+}
+
+void
+gcm_aes192_digest(struct gcm_aes192_ctx *ctx,
+                 size_t length, uint8_t *digest)
+{
+  GCM_DIGEST(ctx, aes192_encrypt, length, digest);
+}
diff --git a/gcm-aes256.c b/gcm-aes256.c
new file mode 100644 (file)
index 0000000..3fb6c68
--- /dev/null
@@ -0,0 +1,74 @@
+/* gcm-aes256.c
+ *
+ * Galois counter mode using AES256 as the underlying cipher.
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2011, 2014 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 "gcm.h"
+
+void
+gcm_aes256_set_key(struct gcm_aes256_ctx *ctx, size_t length, const uint8_t *key)
+{
+  assert (length == AES256_KEY_SIZE);
+  GCM_SET_KEY(ctx, aes256_set_encrypt_key, aes256_encrypt, key);
+}
+
+void
+gcm_aes256_set_iv (struct gcm_aes256_ctx *ctx,
+                  size_t length, const uint8_t *iv)
+{
+  GCM_SET_IV (ctx, length, iv);
+}
+
+void
+gcm_aes256_update (struct gcm_aes256_ctx *ctx,
+                  size_t length, const uint8_t *data)
+{
+  GCM_UPDATE (ctx, length, data);
+}
+
+void
+gcm_aes256_encrypt(struct gcm_aes256_ctx *ctx,
+               size_t length, uint8_t *dst, const uint8_t *src)
+{
+  GCM_ENCRYPT(ctx, aes256_encrypt, length, dst, src);
+}
+
+void
+gcm_aes256_decrypt(struct gcm_aes256_ctx *ctx,
+                  size_t length, uint8_t *dst, const uint8_t *src)
+{
+  GCM_DECRYPT(ctx, aes256_encrypt, length, dst, src);
+}
+
+void
+gcm_aes256_digest(struct gcm_aes256_ctx *ctx,
+                 size_t length, uint8_t *digest)
+{
+  GCM_DIGEST(ctx, aes256_encrypt, length, digest);
+}
diff --git a/gcm.h b/gcm.h
index 10578107dcb87bc083021aa3a79f6eed7ce0c4e2..f05485162368094e0b6e5f12c310ae9932ef3b7e 100644 (file)
--- a/gcm.h
+++ b/gcm.h
@@ -5,13 +5,10 @@
  *
  */
 
-/* NOTE: Tentative interface, subject to change. No effort will be
-   made to avoid incompatible changes. */
-
 /* nettle, low-level cryptographics library
  *
- * Copyright (C) 2011 Niels Möller
  * Copyright (C) 2011 Katholieke Universiteit Leuven
+ * Copyright (C) 2011, 2014 Niels Möller
  * 
  * Contributed by Nikos Mavrogiannopoulos
  *
@@ -48,6 +45,27 @@ extern "C" {
 #define gcm_decrypt nettle_gcm_decrypt
 #define gcm_digest nettle_gcm_digest
 
+#define gcm_aes128_set_key nettle_gcm_aes128_set_key
+#define gcm_aes128_set_iv nettle_gcm_aes128_set_iv
+#define gcm_aes128_update nettle_gcm_aes128_update
+#define gcm_aes128_encrypt nettle_gcm_aes128_encrypt
+#define gcm_aes128_decrypt nettle_gcm_aes128_decrypt
+#define gcm_aes128_digest nettle_gcm_aes128_digest
+
+#define gcm_aes192_set_key nettle_gcm_aes192_set_key
+#define gcm_aes192_set_iv nettle_gcm_aes192_set_iv
+#define gcm_aes192_update nettle_gcm_aes192_update
+#define gcm_aes192_encrypt nettle_gcm_aes192_encrypt
+#define gcm_aes192_decrypt nettle_gcm_aes192_decrypt
+#define gcm_aes192_digest nettle_gcm_aes192_digest
+
+#define gcm_aes256_set_key nettle_gcm_aes256_set_key
+#define gcm_aes256_set_iv nettle_gcm_aes256_set_iv
+#define gcm_aes256_update nettle_gcm_aes256_update
+#define gcm_aes256_encrypt nettle_gcm_aes256_encrypt
+#define gcm_aes256_decrypt nettle_gcm_aes256_decrypt
+#define gcm_aes256_digest nettle_gcm_aes256_digest
+
 #define gcm_aes_set_key nettle_gcm_aes_set_key
 #define gcm_aes_set_iv nettle_gcm_aes_set_iv
 #define gcm_aes_update nettle_gcm_aes_update
@@ -65,7 +83,7 @@ struct gcm_key
 {
   union nettle_block16 h[1 << GCM_TABLE_BITS];
 };
-  
+
 /* Per-message state, depending on the iv */
 struct gcm_ctx {
   /* Original counter block */
@@ -109,10 +127,9 @@ gcm_digest(struct gcm_ctx *ctx, const struct gcm_key *key,
           size_t length, uint8_t *digest);
 
 /* Convenience macrology (not sure how useful it is) */
-
-/* All-in-one context, with cipher, hash subkey, and message state. */
+/* All-in-one context, with hash subkey, message state, and cipher. */
 #define GCM_CTX(type) \
-{ type cipher; struct gcm_key key; struct gcm_ctx gcm; }
+  { struct gcm_key key; struct gcm_ctx gcm; type cipher; }
 
 /* NOTE: Avoid using NULL, as we don't include anything defining it. */
 #define GCM_SET_KEY(ctx, set_key, encrypt, key)                        \
@@ -147,6 +164,84 @@ gcm_digest(struct gcm_ctx *ctx, const struct gcm_key *key,
                  (nettle_crypt_func *) (encrypt),                      \
                  (length), (digest)))
 
+struct gcm_aes128_ctx GCM_CTX(struct aes128_ctx);
+
+void
+gcm_aes128_set_key(struct gcm_aes128_ctx *ctx,
+                  size_t length, const uint8_t *key);
+
+/* FIXME: Define _update and _set_iv as some kind of aliaes,
+   there's nothing aes-specific. */
+void
+gcm_aes128_update (struct gcm_aes128_ctx *ctx,
+                  size_t length, const uint8_t *data);
+void
+gcm_aes128_set_iv (struct gcm_aes128_ctx *ctx,
+                  size_t length, const uint8_t *iv);
+
+void
+gcm_aes128_encrypt(struct gcm_aes128_ctx *ctx,
+                  size_t length, uint8_t *dst, const uint8_t *src);
+
+void
+gcm_aes128_decrypt(struct gcm_aes128_ctx *ctx,
+                  size_t length, uint8_t *dst, const uint8_t *src);
+
+void
+gcm_aes128_digest(struct gcm_aes128_ctx *ctx,
+                 size_t length, uint8_t *digest);
+
+struct gcm_aes192_ctx GCM_CTX(struct aes192_ctx);
+
+void
+gcm_aes192_set_key(struct gcm_aes192_ctx *ctx,
+                  size_t length, const uint8_t *key);
+
+void
+gcm_aes192_update (struct gcm_aes192_ctx *ctx,
+                  size_t length, const uint8_t *data);
+void
+gcm_aes192_set_iv (struct gcm_aes192_ctx *ctx,
+                  size_t length, const uint8_t *iv);
+
+void
+gcm_aes192_encrypt(struct gcm_aes192_ctx *ctx,
+                  size_t length, uint8_t *dst, const uint8_t *src);
+
+void
+gcm_aes192_decrypt(struct gcm_aes192_ctx *ctx,
+                  size_t length, uint8_t *dst, const uint8_t *src);
+
+void
+gcm_aes192_digest(struct gcm_aes192_ctx *ctx,
+                 size_t length, uint8_t *digest);
+
+struct gcm_aes256_ctx GCM_CTX(struct aes256_ctx);
+
+void
+gcm_aes256_set_key(struct gcm_aes256_ctx *ctx,
+                  size_t length, const uint8_t *key);
+
+void
+gcm_aes256_update (struct gcm_aes256_ctx *ctx,
+                  size_t length, const uint8_t *data);
+void
+gcm_aes256_set_iv (struct gcm_aes256_ctx *ctx,
+                  size_t length, const uint8_t *iv);
+
+void
+gcm_aes256_encrypt(struct gcm_aes256_ctx *ctx,
+                  size_t length, uint8_t *dst, const uint8_t *src);
+
+void
+gcm_aes256_decrypt(struct gcm_aes256_ctx *ctx,
+                  size_t length, uint8_t *dst, const uint8_t *src);
+
+void
+gcm_aes256_digest(struct gcm_aes256_ctx *ctx,
+                 size_t length, uint8_t *digest);
+
+/* Old aes interface, for backwards compatibility */
 struct gcm_aes_ctx GCM_CTX(struct aes_ctx);
 
 void
index e4e717618d3aedaf8e674d56fc209b325e657649..40f2dd453c026460fcf0e9fefac92fb692ca5a33 100644 (file)
@@ -107,12 +107,16 @@ nettle_salsa20r12 = {
   (nettle_crypt_func *) salsa20r12_crypt
 };
 
+#define gcm_aes128_set_nonce gcm_aes128_set_iv
+#define gcm_aes192_set_nonce gcm_aes192_set_iv
+#define gcm_aes256_set_nonce gcm_aes256_set_iv
 const struct nettle_aead
-nettle_gcm_aes128 = _NETTLE_AEAD(gcm, GCM, aes, 128);
+nettle_gcm_aes128 = _NETTLE_AEAD(gcm, GCM, aes128, 128);
 const struct nettle_aead
-nettle_gcm_aes192 = _NETTLE_AEAD(gcm, GCM, aes, 192);
+nettle_gcm_aes192 = _NETTLE_AEAD(gcm, GCM, aes192, 192);
 const struct nettle_aead
-nettle_gcm_aes256 = _NETTLE_AEAD(gcm, GCM, aes, 256);
+nettle_gcm_aes256 = _NETTLE_AEAD(gcm, GCM, aes256, 256);
+
 
 /* Old, unified, interface */
 const struct nettle_cipher nettle_unified_aes128
@@ -172,8 +176,5 @@ eax_aes128_digest(struct eax_aes128_ctx *ctx,
   EAX_DIGEST(ctx, aes128_encrypt, length, digest);
 }
 
-/* FIXME: Rename to set_nonce, in struct nettle_aead. */
-#define eax_aes128_set_iv eax_aes128_set_nonce
-
 const struct nettle_aead
-nettle_eax_aes128 = _NETTLE_AEAD_FIX(eax, EAX, aes128, 128);
+nettle_eax_aes128 = _NETTLE_AEAD(eax, EAX, aes128, 128);
index 19e242c98a0fa80b8ee6e1300b7ccb266e8ddf3f..b5a168e579c0ebbbdcf957e2a13578cb2d54dda9 100644 (file)
@@ -103,25 +103,12 @@ struct nettle_aead
 };
 
 #define _NETTLE_AEAD(type, TYPE, name, key_size) {     \
-  #type "-" #name #key_size,                           \
-  sizeof(struct type##_##name##_ctx),                  \
-  TYPE##_BLOCK_SIZE,                                   \
-  key_size / 8,                                                \
-  (nettle_set_key_func *) type##_##name##_set_key,     \
-  (nettle_set_key_func *) type##_##name##_set_iv,      \
-  (nettle_hash_update_func *) type##_##name##_update,  \
-  (nettle_crypt_func *) type##_##name##_encrypt,       \
-  (nettle_crypt_func *) type##_##name##_decrypt,       \
-  (nettle_hash_digest_func *) type##_##name##_digest,  \
-}
-
-#define _NETTLE_AEAD_FIX(type, TYPE, name, key_size) { \
   #type "-" #name,                             \
   sizeof(struct type##_##name##_ctx),                  \
   TYPE##_BLOCK_SIZE,                                   \
   key_size / 8,                                                \
   (nettle_set_key_func *) type##_##name##_set_key,     \
-  (nettle_set_key_func *) type##_##name##_set_iv,      \
+  (nettle_set_key_func *) type##_##name##_set_nonce,   \
   (nettle_hash_update_func *) type##_##name##_update,  \
   (nettle_crypt_func *) type##_##name##_encrypt,       \
   (nettle_crypt_func *) type##_##name##_decrypt,       \
index ce8d59339ae440f2d0ca0f0e0326cce18c8b6826..5b7ed697fccd0011887a411cfffa99327c6f0d44 100644 (file)
@@ -5,15 +5,15 @@
 static void
 test_gcm_hash (const struct tstring *msg, const struct tstring *ref)
 {
-  struct gcm_aes_ctx ctx;
+  struct gcm_aes128_ctx ctx;
   const uint8_t z16[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
   uint8_t digest[16];
 
   ASSERT (ref->length == sizeof(digest));
-  gcm_aes_set_key (&ctx, 16, z16);
-  gcm_aes_set_iv (&ctx, 16, z16);
-  gcm_aes_update (&ctx, msg->length, msg->data);
-  gcm_aes_digest (&ctx, sizeof(digest), digest);
+  gcm_aes128_set_key (&ctx, 16, z16);
+  gcm_aes128_set_iv (&ctx, 16, z16);
+  gcm_aes128_update (&ctx, msg->length, msg->data);
+  gcm_aes128_digest (&ctx, sizeof(digest), digest);
   if (!MEMEQ (ref->length, ref->data, digest))
     {
       fprintf (stderr, "gcm_hash failed, msg: %s\nOutput: ", msg->data);
@@ -25,6 +25,27 @@ test_gcm_hash (const struct tstring *msg, const struct tstring *ref)
     }
 }
 
+static void
+gcm_aes128_set_key_wrapper (void *ctx, size_t length, const uint8_t *key)
+{
+  ASSERT (length == AES128_KEY_SIZE);
+  gcm_aes_set_key (ctx, length, key);
+}
+static const struct nettle_aead
+nettle_gcm_unified_aes128 = {
+  "gcm-aes128",
+  sizeof (struct gcm_aes_ctx),
+  GCM_BLOCK_SIZE,
+  AES128_KEY_SIZE,
+  gcm_aes128_set_key_wrapper,
+  (nettle_set_key_func *) gcm_aes_set_iv,
+  (nettle_hash_update_func *) gcm_aes_update,
+  (nettle_crypt_func *) gcm_aes_encrypt,
+  (nettle_crypt_func *) gcm_aes_decrypt,
+  (nettle_hash_digest_func *) gcm_aes_digest
+};
+    
+
 void
 test_main(void)
 {
@@ -117,6 +138,25 @@ test_main(void)
                 "16aedbf5a0de6a57a637b39b"),
            SHEX("619cc5aefffe0bfa462af43c1699d050"));
 
+  /* Same test, but with old gcm_aes interface */
+  test_aead(&nettle_gcm_unified_aes128,
+           SHEX("feffe9928665731c6d6a8f9467308308"),
+           SHEX("feedfacedeadbeeffeedfacedeadbeef"
+                "abaddad2"),
+           SHEX("d9313225f88406e5a55909c5aff5269a"
+                "86a7a9531534f7da2e4c303d8a318a72"
+                "1c3c0c95956809532fcf0e2449a6b525"
+                "b16aedf5aa0de657ba637b39"),
+           SHEX("8ce24998625615b603a033aca13fb894"
+                "be9112a5c3a211a8ba262a3cca7e2ca7"
+                "01e4a9a4fba43c90ccdcb281d48c7c6f"
+                "d62875d2aca417034c34aee5"),
+           SHEX("9313225df88406e555909c5aff5269aa"
+                "6a7a9538534f7da1e4c303d2a318a728"
+                "c3c0c95156809539fcf0e2429a6b5254"
+                "16aedbf5a0de6a57a637b39b"),
+           SHEX("619cc5aefffe0bfa462af43c1699d050"));
+
   /* Test case 7 */
   test_aead(&nettle_gcm_aes192,
            SHEX("00000000000000000000000000000000"