diff --git a/testsuite/testutils.c b/testsuite/testutils.c
index 776be8a68677a86e2bffc021b289fa19fed5a8e8..8279735261019e50fed0cb097f7e3c150331ee56 100644
--- a/testsuite/testutils.c
+++ b/testsuite/testutils.c
@@ -386,6 +386,24 @@ test_hash_large(const struct nettle_hash *hash,
   free(data);
 }
 
+void
+test_mac(const struct nettle_mac *mac,
+	 unsigned key_length, const uint8_t *key,
+	 unsigned msg_length, const uint8_t *msg,
+	 const uint8_t *digest)
+{
+  void *ctx = xalloc(mac->context_size);
+  uint8_t *buffer = xalloc(mac->digest_size);
+
+  mac->set_key(ctx, key_length, key);
+  mac->update(ctx, msg_length, msg);
+  mac->digest(ctx, mac->digest_size, buffer);
+  ASSERT(MEMEQ(mac->digest_size, digest, buffer));
+
+  free(ctx);
+  free(buffer);
+}
+
 void
 test_armor(const struct nettle_armor *armor,
            unsigned data_length,
@@ -801,14 +819,14 @@ test_rsa_key(struct rsa_public_key *pub,
   mpz_clear(tmp); mpz_clear(phi);
 }
 
-#define DSA_VERIFY(key, hash, msg, signature) (	\
-  sha1_update(hash, LDATA(msg)),		\
-  dsa_sha1_verify(key, hash, signature)		\
-)
+/* Requires that the context is named like the hash algorithm. */
+#define DSA_VERIFY(key, hash, msg, signature)	\
+  (hash##_update(&hash, LDATA(msg)),		\
+   dsa_##hash##_verify(key, &hash, signature))
 
 void
-test_dsa(const struct dsa_public_key *pub,
-	 const struct dsa_private_key *key)
+test_dsa160(const struct dsa_public_key *pub,
+	    const struct dsa_private_key *key)
 {
   struct sha1_ctx sha1;
   struct dsa_signature signature;
@@ -825,7 +843,53 @@ test_dsa(const struct dsa_public_key *pub,
   
   if (verbose)
     {
-      fprintf(stderr, "dsa signature: ");
+      fprintf(stderr, "dsa160 signature: ");
+      mpz_out_str(stderr, 16, signature.r);
+      fprintf(stderr, ", ");
+      mpz_out_str(stderr, 16, signature.s);
+      fprintf(stderr, "\n");
+    }
+  
+  /* Try bad data */
+  if (DSA_VERIFY(pub, sha1,
+		 "The magick words are squeamish ossifrage", &signature))
+    FAIL();
+
+  /* Try correct data */
+  if (!DSA_VERIFY(pub, sha1,
+		 "The magic words are squeamish ossifrage", &signature))
+    FAIL();
+
+  /* Try bad signature */
+  mpz_togglebit(signature.r, 17);
+
+  if (DSA_VERIFY(pub, sha1,
+		 "The magic words are squeamish ossifrage", &signature))
+    FAIL();
+
+  dsa_signature_clear(&signature);
+}
+
+void
+test_dsa256(const struct dsa_public_key *pub,
+	    const struct dsa_private_key *key)
+{
+  struct sha256_ctx sha256;
+  struct dsa_signature signature;
+  struct knuth_lfib_ctx lfib;
+  
+  sha256_init(&sha256);
+  dsa_signature_init(&signature);
+  knuth_lfib_init(&lfib, 1111);
+  
+  sha256_update(&sha256, LDATA("The magic words are squeamish ossifrage"));
+  ASSERT (dsa_sha256_sign(pub, key,
+			&lfib, (nettle_random_func *) knuth_lfib_random,
+			&sha256, &signature));
+  
+  if (verbose)
+    {
+      fprintf(stderr, "dsa256 signature: ");
       mpz_out_str(stderr, 16, signature.r);
       fprintf(stderr, ", ");
       mpz_out_str(stderr, 16, signature.s);
@@ -838,19 +902,19 @@ test_dsa(const struct dsa_public_key *pub,
 #endif
   
   /* Try bad data */
-  if (DSA_VERIFY(pub, &sha1,
+  if (DSA_VERIFY(pub, sha256,
 		 "The magick words are squeamish ossifrage", &signature))
     FAIL();
 
   /* Try correct data */
-  if (!DSA_VERIFY(pub, &sha1,
+  if (!DSA_VERIFY(pub, sha256,
 		 "The magic words are squeamish ossifrage", &signature))
     FAIL();
 
   /* Try bad signature */
   mpz_togglebit(signature.r, 17);
 
-  if (DSA_VERIFY(pub, &sha1,
+  if (DSA_VERIFY(pub, sha256,
 		 "The magic words are squeamish ossifrage", &signature))
     FAIL();
 
@@ -859,13 +923,14 @@ test_dsa(const struct dsa_public_key *pub,
 
 void
 test_dsa_key(struct dsa_public_key *pub,
-	     struct dsa_private_key *key)
+	     struct dsa_private_key *key,
+	     unsigned q_size)
 {
   mpz_t t;
 
   mpz_init(t);
 
-  ASSERT(mpz_sizeinbase(pub->q, 2) == DSA_Q_BITS);
+  ASSERT(mpz_sizeinbase(pub->q, 2) == q_size);
   ASSERT(mpz_sizeinbase(pub->p, 2) >= DSA_MIN_P_BITS);
   
   ASSERT(mpz_probab_prime_p(pub->p, 10));
diff --git a/testsuite/testutils.h b/testsuite/testutils.h
index d46b5d839d054f322a68a5e8e3b8b5dc501c053a..966eca383ca7a0748ec4072301c177fdce94ea9a 100644
--- a/testsuite/testutils.h
+++ b/testsuite/testutils.h
@@ -50,6 +50,35 @@ test_main(void);
 
 extern int verbose;
 
+/* FIXME: When interface stabilizes, move to nettle-meta.h */
+struct nettle_mac
+{
+  const char *name;
+
+  /* Size of the context struct */
+  unsigned context_size;
+
+  /* Size of digests */
+  unsigned digest_size;
+
+  /* Suggested key size; other sizes are sometimes possible. */
+  unsigned key_size;
+  
+  nettle_set_key_func *set_key;
+  nettle_hash_update_func *update;
+  nettle_hash_digest_func *digest;
+};
+
+#define _NETTLE_HMAC(name, NAME, keysize) {	\
+  #name,					\
+  sizeof(struct hmac_##name##_ctx),		\
+  NAME##_DIGEST_SIZE,				\
+  NAME##_DIGEST_SIZE,				\
+  hmac_##name##_set_key,			\
+  hmac_##name##_update,				\
+  hmac_##name##_digest,				\
+}
+ 
 void
 test_cipher(const struct nettle_cipher *cipher,
 	    unsigned key_length,
@@ -96,6 +125,12 @@ test_hash_large(const struct nettle_hash *hash,
 		uint8_t c,
 		const uint8_t *digest);
 
+void
+test_mac(const struct nettle_mac *mac,
+	 unsigned key_length, const uint8_t *key,
+	 unsigned msg_length, const uint8_t *msg,
+	 const uint8_t *digest);
+
 void
 test_armor(const struct nettle_armor *armor,
            unsigned data_length,
@@ -132,12 +167,17 @@ test_rsa_key(struct rsa_public_key *pub,
 	     struct rsa_private_key *key);
 
 void
-test_dsa(const struct dsa_public_key *pub,
-	 const struct dsa_private_key *key);
+test_dsa160(const struct dsa_public_key *pub,
+	    const struct dsa_private_key *key);
+
+void
+test_dsa256(const struct dsa_public_key *pub,
+	    const struct dsa_private_key *key);
 
 void
 test_dsa_key(struct dsa_public_key *pub,
-	     struct dsa_private_key *key);
+	     struct dsa_private_key *key,
+	     unsigned q_size);
 
 #endif /* WITH_HOGWEED */