diff --git a/ChangeLog b/ChangeLog
index 695a50e3e5bad4a1e32d647ee511300a7a7fcc3e..f408d1ef894e8f7eae99bc70fdb5f165f7b45d50 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2014-03-15  Niels Möller  <nisse@lysator.liu.se>
 
+	* examples/nettle-benchmark.c (struct bench_aead_info): New
+	struct.
+	(bench_aead_crypt, bench_aead_update, init_nonce, time_aead): New
+	functions, for benchmarking aead algorithms.
+	(time_gcm, time_eax): Deleted functions.
+	(main): Use time_aead to benchmark gcm, eax and chacha-poly1305.
+
 	* salsa20.h (SALSA20_NONCE_SIZE): Renamed constant, old name
 	SALSA20_IV_SIZE kept as an alias.
 	(salsa20_set_nonce): Update prototype for the 2014-01-20 rename.
diff --git a/examples/nettle-benchmark.c b/examples/nettle-benchmark.c
index 5cf7f625b0ba46c3f54c301c1ed8599a435da5aa..a84e9daca6268d930a92bf25f0b6f44c20bdca03 100644
--- a/examples/nettle-benchmark.c
+++ b/examples/nettle-benchmark.c
@@ -235,6 +235,28 @@ bench_ctr(void *arg)
 	    BENCH_BLOCK, info->data, info->data);
 }
 
+struct bench_aead_info
+{
+  void *ctx;
+  nettle_crypt_func *crypt;
+  nettle_hash_update_func *update;
+  uint8_t *data;
+};
+
+static void
+bench_aead_crypt(void *arg)
+{
+  const struct bench_aead_info *info = arg;
+  info->crypt (info->ctx, BENCH_BLOCK, info->data, info->data);
+}
+
+static void
+bench_aead_update(void *arg)
+{
+  const struct bench_aead_info *info = arg;
+  info->update (info->ctx, BENCH_BLOCK, info->data);
+}
+
 /* Set data[i] = floor(sqrt(i)) */
 static void
 init_data(uint8_t *data)
@@ -257,6 +279,15 @@ init_key(unsigned length,
     key[i] = i;
 }
 
+static void
+init_nonce(unsigned length,
+	   uint8_t *nonce)
+{
+  unsigned i;
+  for (i = 0; i<length; i++)
+    nonce[i] = 3*i;
+}
+
 static void
 header(void)
 {
@@ -417,74 +448,6 @@ time_poly1305_aes(void)
 	  time_function(bench_hash, &info));
 }
 
-static void
-time_gcm(void)
-{
-  static uint8_t data[BENCH_BLOCK];
-  struct bench_hash_info hinfo;
-  struct bench_cipher_info cinfo;
-  struct gcm_aes128_ctx ctx;
-
-  uint8_t key[AES128_KEY_SIZE];
-  uint8_t iv[GCM_IV_SIZE];
-
-  gcm_aes128_set_key(&ctx, key);
-  gcm_aes128_set_iv(&ctx, sizeof(iv), iv);
-
-  hinfo.ctx = &ctx;
-  hinfo.update = (nettle_hash_update_func *) gcm_aes128_update;
-  hinfo.data = data;
-  
-  display("gcm-aes128", "update", GCM_BLOCK_SIZE,
-	  time_function(bench_hash, &hinfo));
-  
-  cinfo.ctx = &ctx;
-  cinfo.crypt = (nettle_crypt_func *) gcm_aes128_encrypt;
-  cinfo.data = data;
-
-  display("gcm-aes128", "encrypt", GCM_BLOCK_SIZE,
-	  time_function(bench_cipher, &cinfo));
-
-  cinfo.crypt = (nettle_crypt_func *) gcm_aes128_decrypt;
-
-  display("gcm-aes128", "decrypt", GCM_BLOCK_SIZE,
-	  time_function(bench_cipher, &cinfo));
-}
-
-static void
-time_eax(void)
-{
-  static uint8_t data[BENCH_BLOCK];
-  struct bench_hash_info hinfo;
-  struct bench_cipher_info cinfo;
-  struct eax_aes128_ctx ctx;
-
-  uint8_t key[AES128_KEY_SIZE];
-  uint8_t iv[EAX_BLOCK_SIZE];
-
-  eax_aes128_set_key (&ctx, key);
-  eax_aes128_set_nonce(&ctx, sizeof(iv), iv);
-
-  hinfo.ctx = &ctx;
-  hinfo.update = (nettle_hash_update_func *) eax_aes128_update;
-  hinfo.data = data;
-
-  display("eax-aes128", "update", GCM_BLOCK_SIZE,
-         time_function(bench_hash, &hinfo));
-
-  cinfo.ctx = &ctx;
-  cinfo.crypt = (nettle_crypt_func *) eax_aes128_encrypt;
-  cinfo.data = data;
-
-  display("eax-aes128", "encrypt", GCM_BLOCK_SIZE,
-	  time_function(bench_cipher, &cinfo));
-
-  cinfo.crypt = (nettle_crypt_func *) eax_aes128_decrypt;
-
-  display("eax-aes128", "decrypt", GCM_BLOCK_SIZE,
-	  time_function(bench_cipher, &cinfo));
-}
-
 static int
 prefix_p(const char *prefix, const char *s)
 {
@@ -601,6 +564,71 @@ time_cipher(const struct nettle_cipher *cipher)
   free(key);
 }
 
+static void
+time_aead(const struct nettle_aead *aead)
+{
+  void *ctx = xalloc(aead->context_size);
+  uint8_t *key = xalloc(aead->key_size);
+  uint8_t *nonce = xalloc(aead->nonce_size);
+  static uint8_t data[BENCH_BLOCK];
+
+  printf("\n");
+  
+  init_data(data);
+  if (aead->set_nonce)
+    init_nonce (aead->nonce_size, nonce);
+
+  {
+    /* Decent initializers are a GNU extension, so don't use it here. */
+    struct bench_aead_info info;
+    info.ctx = ctx;
+    info.crypt = aead->encrypt;
+    info.data = data;
+    
+    init_key(aead->key_size, key);
+    aead->set_encrypt_key(ctx, key);
+    if (aead->set_nonce)
+      aead->set_nonce (ctx, nonce);
+
+    display(aead->name, "encrypt", aead->block_size,
+	    time_function(bench_aead_crypt, &info));
+  }
+  
+  {
+    struct bench_aead_info info;
+    info.ctx = ctx;
+    info.crypt = aead->decrypt;
+    info.data = data;
+    
+    init_key(aead->key_size, key);
+    aead->set_decrypt_key(ctx, key);
+    if (aead->set_nonce)
+      aead->set_nonce (ctx, nonce);
+
+    display(aead->name, "decrypt", aead->block_size,
+	    time_function(bench_aead_crypt, &info));
+  }
+
+  if (aead->update)
+    {
+      struct bench_aead_info info;
+      info.ctx = ctx;
+      info.update = aead->update;
+      info.data = data;
+
+      aead->set_encrypt_key(ctx, key);
+
+      if (aead->set_nonce)
+	aead->set_nonce (ctx, nonce);
+    
+      display(aead->name, "update", aead->block_size,
+	      time_function(bench_aead_update, &info));
+    }
+  free(ctx);
+  free(key);
+  free(nonce);
+}
+
 /* Try to get accurate cycle times for assembler functions. */
 #if WITH_CYCLE_COUNTER
 static int
@@ -715,7 +743,18 @@ main(int argc, char **argv)
       &nettle_des3,
       &nettle_serpent256,
       &nettle_twofish128, &nettle_twofish192, &nettle_twofish256,
-      &nettle_salsa20, &nettle_salsa20r12, &nettle_chacha,
+      NULL
+    };
+
+  const struct nettle_aead *aeads[] =
+    {
+      &nettle_gcm_aes128,
+      &nettle_gcm_aes192,
+      &nettle_gcm_aes256,
+      &nettle_gcm_camellia128,
+      &nettle_gcm_camellia256,
+      &nettle_eax_aes128,
+      &nettle_chacha_poly1305,
       NULL
     };
 
@@ -778,17 +817,9 @@ main(int argc, char **argv)
     if (!alg || strstr(ciphers[i]->name, alg))
       time_cipher(ciphers[i]);
 
-  if (!alg || strstr ("gcm", alg))
-    {
-      printf("\n");
-      time_gcm();
-    }
-
-  if (!alg || strstr ("eax", alg))
-    {
-      printf("\n");
-      time_eax();
-    }
+  for (i = 0; aeads[i]; i++)
+    if (!alg || strstr(aeads[i]->name, alg))
+      time_aead(aeads[i]);
 
   return 0;
 }