[git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-276-gc0b9eee

by Jussi Kivilinna cvs at cvs.gnupg.org
Sun Nov 1 20:01:41 CET 2015


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The GNU crypto library".

The branch, master has been updated
       via  c0b9eee2d93a13930244f9ce0c14ed6b4aeb6c29 (commit)
       via  28de6f9e16e386018e81a9cdaee596be7616ccab (commit)
       via  92ad19873562cfce7bcc4a0b5aed8195d8284cfc (commit)
       via  577dc2b63ceca6a8a716256d034ea4e7414f65fa (commit)
       via  cee2e122ec6c1886957a8d47498eb63a6a921725 (commit)
      from  74184c28fbe7ff58cf57f0094ef957d94045da7d (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit c0b9eee2d93a13930244f9ce0c14ed6b4aeb6c29
Author: Jussi Kivilinna <jussi.kivilinna at iki.fi>
Date:   Sun Oct 25 20:34:50 2015 +0200

    Keccak: Add SHAKE Extendable-Output Functions
    
    * src/hash-common.c (_gcry_hash_selftest_check_one): Add handling for
    XOFs.
    * src/keccak.c (keccak_ops_t): Rename 'extract_inplace' to 'extract'
    and add 'pos' argument.
    (KECCAK_CONTEXT): Add 'suffix'.
    (keccak_extract_inplace64): Rename to...
    (keccak_extract64): ...this; Add handling for 'pos' argument.
    (keccak_extract_inplace32bi): Rename to...
    (keccak_extract32bi): ...this; Add handling for 'pos' argument.
    (keccak_extract_inplace64): Rename to...
    (keccak_extract64): ...this; Add handling for 'pos' argument.
    (keccak_extract_inplace32bi_bmi2): Rename to...
    (keccak_extract32bi_bmi2): ...this; Add handling for 'pos' argument.
    (keccak_init): Setup 'suffix'; add SHAKE128 & SHAKE256.
    (shake128_init, shake256_init): New.
    (keccak_final): Do not initial permute for SHAKE output; use correct
    suffix for SHAKE.
    (keccak_extract): New.
    (keccak_selftests_keccak): Add SHAKE128 & SHAKE256 test-vectors.
    (run_selftests): Add SHAKE128 & SHAKE256.
    (shake128_asn, oid_spec_shake128, shake256_asn, oid_spec_shake256)
    (_gcry_digest_spec_shake128, _gcry_digest_spec_shake256): New.
    * cipher/md.c (digest_list): Add SHAKE128 & SHAKE256.
    * doc/gcrypt.texi: Ditto.
    * src/cipher.h (_gcry_digest_spec_shake128)
    (_gcry_digest_spec_shake256): New.
    * src/gcrypt.h.in (GCRY_MD_SHAKE128, GCRY_MD_SHAKE256): New.
    * tests/basic.c (check_one_md): Add XOF check; Add 'elen' argument.
    (check_one_md_multi): Skip if algo is XOF.
    (check_digests): Add SHAKE128 & SHAKE256 test vectors.
    * tests/bench-slope.c (kdf_bench_one): Skip XOFs.
    --
    
    Signed-off-by: Jussi Kivilinna <jussi.kivilinna at iki.fi>

diff --git a/cipher/hash-common.c b/cipher/hash-common.c
index 6743f09..a750d644 100644
--- a/cipher/hash-common.c
+++ b/cipher/hash-common.c
@@ -49,8 +49,12 @@ _gcry_hash_selftest_check_one (int algo,
   gcry_error_t err = 0;
   gcry_md_hd_t hd;
   unsigned char *digest;
+  char aaa[1000];
+  int xof = 0;
 
-  if (_gcry_md_get_algo_dlen (algo) != expectlen)
+  if (_gcry_md_get_algo_dlen (algo) == 0)
+    xof = 1;
+  else if (_gcry_md_get_algo_dlen (algo) != expectlen)
     return "digest size does not match expected size";
 
   err = _gcry_md_open (&hd, algo, 0);
@@ -65,7 +69,6 @@ _gcry_hash_selftest_check_one (int algo,
 
     case 1: /* Hash one million times an "a". */
       {
-        char aaa[1000];
         int i;
 
         /* Write in odd size chunks so that we test the buffering.  */
@@ -81,10 +84,23 @@ _gcry_hash_selftest_check_one (int algo,
 
   if (!result)
     {
-      digest = _gcry_md_read (hd, algo);
-
-      if ( memcmp (digest, expect, expectlen) )
-        result = "digest mismatch";
+      if (!xof)
+	{
+	  digest = _gcry_md_read (hd, algo);
+
+	  if ( memcmp (digest, expect, expectlen) )
+	    result = "digest mismatch";
+	}
+      else
+	{
+	  gcry_assert(expectlen <= sizeof(aaa));
+
+	  err = _gcry_md_extract (hd, algo, aaa, expectlen);
+	  if (err)
+	    result = "error extracting output from XOF";
+	  else if ( memcmp (aaa, expect, expectlen) )
+	    result = "digest mismatch";
+	}
     }
 
   _gcry_md_close (hd);
diff --git a/cipher/keccak.c b/cipher/keccak.c
index d46d9cb..f4f0ef3 100644
--- a/cipher/keccak.c
+++ b/cipher/keccak.c
@@ -90,7 +90,8 @@ typedef struct
   unsigned int (*permute)(KECCAK_STATE *hd);
   unsigned int (*absorb)(KECCAK_STATE *hd, int pos, const byte *lanes,
 			 unsigned int nlanes, int blocklanes);
-  unsigned int (*extract_inplace) (KECCAK_STATE *hd, unsigned int outlen);
+  unsigned int (*extract) (KECCAK_STATE *hd, unsigned int pos, byte *outbuf,
+			   unsigned int outlen);
 } keccak_ops_t;
 
 
@@ -100,6 +101,7 @@ typedef struct KECCAK_CONTEXT_S
   unsigned int outlen;
   unsigned int blocksize;
   unsigned int count;
+  unsigned int suffix;
   const keccak_ops_t *ops;
 } KECCAK_CONTEXT;
 
@@ -124,13 +126,18 @@ static const u64 round_consts_64bit[24] =
 };
 
 static unsigned int
-keccak_extract_inplace64(KECCAK_STATE *hd, unsigned int outlen)
+keccak_extract64(KECCAK_STATE *hd, unsigned int pos, byte *outbuf,
+		 unsigned int outlen)
 {
   unsigned int i;
 
-  for (i = 0; i < outlen / 8 + !!(outlen % 8); i++)
+  /* NOTE: when pos == 0, hd and outbuf may point to same memory (SHA-3). */
+
+  for (i = pos; i < pos + outlen / 8 + !!(outlen % 8); i++)
     {
-      hd->u.state64[i] = le_bswap64(hd->u.state64[i]);
+      u64 tmp = hd->u.state64[i];
+      buf_put_le64(outbuf, tmp);
+      outbuf += 8;
     }
 
   return 0;
@@ -158,14 +165,17 @@ static const u32 round_consts_32bit[2 * 24] =
 };
 
 static unsigned int
-keccak_extract_inplace32bi(KECCAK_STATE *hd, unsigned int outlen)
+keccak_extract32bi(KECCAK_STATE *hd, unsigned int pos, byte *outbuf,
+		   unsigned int outlen)
 {
   unsigned int i;
   u32 x0;
   u32 x1;
   u32 t;
 
-  for (i = 0; i < outlen / 8 + !!(outlen % 8); i++)
+  /* NOTE: when pos == 0, hd and outbuf may point to same memory (SHA-3). */
+
+  for (i = pos; i < pos + outlen / 8 + !!(outlen % 8); i++)
     {
       x0 = hd->u.state32bi[i * 2 + 0];
       x1 = hd->u.state32bi[i * 2 + 1];
@@ -182,8 +192,9 @@ keccak_extract_inplace32bi(KECCAK_STATE *hd, unsigned int outlen)
       t = (x1 ^ (x1 >> 2)) & 0x0C0C0C0CUL; x1 = x1 ^ t ^ (t << 2);
       t = (x1 ^ (x1 >> 1)) & 0x22222222UL; x1 = x1 ^ t ^ (t << 1);
 
-      hd->u.state32bi[i * 2 + 0] = le_bswap32(x0);
-      hd->u.state32bi[i * 2 + 1] = le_bswap32(x1);
+      buf_put_le32(&outbuf[0], x0);
+      buf_put_le32(&outbuf[4], x1);
+      outbuf += 8;
     }
 
   return 0;
@@ -249,7 +260,7 @@ static const keccak_ops_t keccak_generic64_ops =
 {
   .permute = keccak_f1600_state_permute64,
   .absorb = keccak_absorb_lanes64,
-  .extract_inplace = keccak_extract_inplace64,
+  .extract = keccak_extract64,
 };
 
 #endif /* USE_64BIT */
@@ -300,7 +311,7 @@ static const keccak_ops_t keccak_shld_64_ops =
 {
   .permute = keccak_f1600_state_permute64_shld,
   .absorb = keccak_absorb_lanes64_shld,
-  .extract_inplace = keccak_extract_inplace64,
+  .extract = keccak_extract64,
 };
 
 #endif /* USE_64BIT_SHLD */
@@ -356,7 +367,7 @@ static const keccak_ops_t keccak_bmi2_64_ops =
 {
   .permute = keccak_f1600_state_permute64_bmi2,
   .absorb = keccak_absorb_lanes64_bmi2,
-  .extract_inplace = keccak_extract_inplace64,
+  .extract = keccak_extract64,
 };
 
 #endif /* USE_64BIT_BMI2 */
@@ -404,7 +415,7 @@ static const keccak_ops_t keccak_generic32bi_ops =
 {
   .permute = keccak_f1600_state_permute32bi,
   .absorb = keccak_absorb_lanes32bi,
-  .extract_inplace = keccak_extract_inplace32bi,
+  .extract = keccak_extract32bi,
 };
 
 #endif /* USE_32BIT */
@@ -483,14 +494,17 @@ keccak_absorb_lanes32bi_bmi2(KECCAK_STATE *hd, int pos, const byte *lanes,
 }
 
 static unsigned int
-keccak_extract_inplace32bi_bmi2(KECCAK_STATE *hd, unsigned int outlen)
+keccak_extract32bi_bmi2(KECCAK_STATE *hd, unsigned int pos, byte *outbuf,
+			unsigned int outlen)
 {
   unsigned int i;
   u32 x0;
   u32 x1;
   u32 t;
 
-  for (i = 0; i < outlen / 8 + !!(outlen % 8); i++)
+  /* NOTE: when pos == 0, hd and outbuf may point to same memory (SHA-3). */
+
+  for (i = pos; i < pos + outlen / 8 + !!(outlen % 8); i++)
     {
       x0 = hd->u.state32bi[i * 2 + 0];
       x1 = hd->u.state32bi[i * 2 + 1];
@@ -502,8 +516,9 @@ keccak_extract_inplace32bi_bmi2(KECCAK_STATE *hd, unsigned int outlen)
       x0 = pdep(pext(x0, 0xffff0001), 0xaaaaaaab) | pdep(x0 >> 1, 0x55555554);
       x1 = pdep(pext(x1, 0xffff0001), 0xaaaaaaab) | pdep(x1 >> 1, 0x55555554);
 
-      hd->u.state32bi[i * 2 + 0] = le_bswap32(x0);
-      hd->u.state32bi[i * 2 + 1] = le_bswap32(x1);
+      buf_put_le32(&outbuf[0], x0);
+      buf_put_le32(&outbuf[4], x1);
+      outbuf += 8;
     }
 
   return 0;
@@ -513,7 +528,7 @@ static const keccak_ops_t keccak_bmi2_32bi_ops =
 {
   .permute = keccak_f1600_state_permute32bi_bmi2,
   .absorb = keccak_absorb_lanes32bi_bmi2,
-  .extract_inplace = keccak_extract_inplace32bi_bmi2,
+  .extract = keccak_extract32bi_bmi2,
 };
 
 #endif /* USE_32BIT */
@@ -638,21 +653,35 @@ keccak_init (int algo, void *context, unsigned int flags)
   switch (algo)
     {
     case GCRY_MD_SHA3_224:
+      ctx->suffix = SHA3_DELIMITED_SUFFIX;
       ctx->blocksize = 1152 / 8;
       ctx->outlen = 224 / 8;
       break;
     case GCRY_MD_SHA3_256:
+      ctx->suffix = SHA3_DELIMITED_SUFFIX;
       ctx->blocksize = 1088 / 8;
       ctx->outlen = 256 / 8;
       break;
     case GCRY_MD_SHA3_384:
+      ctx->suffix = SHA3_DELIMITED_SUFFIX;
       ctx->blocksize = 832 / 8;
       ctx->outlen = 384 / 8;
       break;
     case GCRY_MD_SHA3_512:
+      ctx->suffix = SHA3_DELIMITED_SUFFIX;
       ctx->blocksize = 576 / 8;
       ctx->outlen = 512 / 8;
       break;
+    case GCRY_MD_SHAKE128:
+      ctx->suffix = SHAKE_DELIMITED_SUFFIX;
+      ctx->blocksize = 1344 / 8;
+      ctx->outlen = 0;
+      break;
+    case GCRY_MD_SHAKE256:
+      ctx->suffix = SHAKE_DELIMITED_SUFFIX;
+      ctx->blocksize = 1088 / 8;
+      ctx->outlen = 0;
+      break;
     default:
       BUG();
     }
@@ -682,6 +711,17 @@ sha3_512_init (void *context, unsigned int flags)
   keccak_init (GCRY_MD_SHA3_512, context, flags);
 }
 
+static void
+shake128_init (void *context, unsigned int flags)
+{
+  keccak_init (GCRY_MD_SHAKE128, context, flags);
+}
+
+static void
+shake256_init (void *context, unsigned int flags)
+{
+  keccak_init (GCRY_MD_SHAKE256, context, flags);
+}
 
 /* The routine final terminates the computation and
  * returns the digest.
@@ -696,7 +736,7 @@ keccak_final (void *context)
   KECCAK_CONTEXT *ctx = context;
   KECCAK_STATE *hd = &ctx->state;
   const size_t bsize = ctx->blocksize;
-  const byte suffix = SHA3_DELIMITED_SUFFIX;
+  const byte suffix = ctx->suffix;
   unsigned int nburn, burn = 0;
   unsigned int lastbytes;
   byte lane[8];
@@ -716,21 +756,21 @@ keccak_final (void *context)
   nburn = ctx->ops->absorb(&ctx->state, (bsize - 1) / 8, lane, 1, -1);
   burn = nburn > burn ? nburn : burn;
 
-  /* Switch to the squeezing phase. */
-  nburn = ctx->ops->permute(hd);
-  burn = nburn > burn ? nburn : burn;
-
-  /* Squeeze out all the output blocks */
-  if (ctx->outlen < bsize)
+  if (suffix == SHA3_DELIMITED_SUFFIX)
     {
-      /* Output SHA3 digest. */
-      nburn = ctx->ops->extract_inplace(hd, ctx->outlen);
+      /* Switch to the squeezing phase. */
+      nburn = ctx->ops->permute(hd);
+      burn = nburn > burn ? nburn : burn;
+
+      /* Squeeze out the SHA3 digest. */
+      nburn = ctx->ops->extract(hd, 0, (void *)hd, ctx->outlen);
       burn = nburn > burn ? nburn : burn;
     }
   else
     {
-      /* Output SHAKE digest. */
-      BUG();
+      /* Output for SHAKE can now be read with md_extract(). */
+
+      ctx->count = 0;
     }
 
   wipememory(lane, sizeof(lane));
@@ -748,6 +788,124 @@ keccak_read (void *context)
 }
 
 
+static void
+keccak_extract (void *context, void *out, size_t outlen)
+{
+  KECCAK_CONTEXT *ctx = context;
+  KECCAK_STATE *hd = &ctx->state;
+  const size_t bsize = ctx->blocksize;
+  unsigned int nburn, burn = 0;
+  byte *outbuf = out;
+  unsigned int nlanes;
+  unsigned int nleft;
+  unsigned int count;
+  unsigned int i;
+  byte lane[8];
+
+  count = ctx->count;
+
+  while (count && outlen && (outlen < 8 || count % 8))
+    {
+      /* Extract partial lane. */
+      nburn = ctx->ops->extract(hd, count / 8, lane, 8);
+      burn = nburn > burn ? nburn : burn;
+
+      for (i = count % 8; outlen && i < 8; i++)
+	{
+	  *outbuf++ = lane[i];
+	  outlen--;
+	  count++;
+	}
+
+      gcry_assert(count <= bsize);
+
+      if (count == bsize)
+	count = 0;
+    }
+
+  if (outlen >= 8 && count)
+    {
+      /* Extract tail of partial block. */
+      nlanes = outlen / 8;
+      nleft = (bsize - count) / 8;
+      nlanes = nlanes < nleft ? nlanes : nleft;
+
+      nburn = ctx->ops->extract(hd, count / 8, outbuf, nlanes * 8);
+      burn = nburn > burn ? nburn : burn;
+      outlen -= nlanes * 8;
+      outbuf += nlanes * 8;
+      count += nlanes * 8;
+
+      gcry_assert(count <= bsize);
+
+      if (count == bsize)
+	count = 0;
+    }
+
+  while (outlen >= bsize)
+    {
+      gcry_assert(count == 0);
+
+      /* Squeeze more. */
+      nburn = ctx->ops->permute(hd);
+      burn = nburn > burn ? nburn : burn;
+
+      /* Extract full block. */
+      nburn = ctx->ops->extract(hd, 0, outbuf, bsize);
+      burn = nburn > burn ? nburn : burn;
+
+      outlen -= bsize;
+      outbuf += bsize;
+    }
+
+  if (outlen)
+    {
+      gcry_assert(outlen < bsize);
+
+      if (count == 0)
+	{
+	  /* Squeeze more. */
+	  nburn = ctx->ops->permute(hd);
+	  burn = nburn > burn ? nburn : burn;
+	}
+
+      if (outlen >= 8)
+	{
+	  /* Extract head of partial block. */
+	  nlanes = outlen / 8;
+	  nburn = ctx->ops->extract(hd, count / 8, outbuf, nlanes * 8);
+	  burn = nburn > burn ? nburn : burn;
+	  outlen -= nlanes * 8;
+	  outbuf += nlanes * 8;
+	  count += nlanes * 8;
+
+	  gcry_assert(count < bsize);
+	}
+
+      if (outlen)
+	{
+	  /* Extract head of partial lane. */
+	  nburn = ctx->ops->extract(hd, count / 8, lane, 8);
+	  burn = nburn > burn ? nburn : burn;
+
+	  for (i = count % 8; outlen && i < 8; i++)
+	    {
+	      *outbuf++ = lane[i];
+	      outlen--;
+	      count++;
+	    }
+
+	  gcry_assert(count < bsize);
+	}
+    }
+
+  ctx->count = count;
+
+  if (burn)
+    _gcry_burn_stack (burn);
+}
+
+
 
 /*
      Self-test section.
@@ -829,6 +987,32 @@ selftests_keccak (int algo, int extended, selftest_report_func_t report)
 	"\xa8\xaa\x18\xac\xe8\x28\x2a\x0e\x0d\xb5\x96\xc9\x0b\x0a\x7b\x87";
       hash_len = 64;
       break;
+
+    case GCRY_MD_SHAKE128:
+      short_hash =
+	"\x58\x81\x09\x2d\xd8\x18\xbf\x5c\xf8\xa3\xdd\xb7\x93\xfb\xcb\xa7"
+	"\x40\x97\xd5\xc5\x26\xa6\xd3\x5f\x97\xb8\x33\x51\x94\x0f\x2c\xc8";
+      long_hash =
+	"\x7b\x6d\xf6\xff\x18\x11\x73\xb6\xd7\x89\x8d\x7f\xf6\x3f\xb0\x7b"
+	"\x7c\x23\x7d\xaf\x47\x1a\x5a\xe5\x60\x2a\xdb\xcc\xef\x9c\xcf\x4b";
+      one_million_a_hash =
+	"\x9d\x22\x2c\x79\xc4\xff\x9d\x09\x2c\xf6\xca\x86\x14\x3a\xa4\x11"
+	"\xe3\x69\x97\x38\x08\xef\x97\x09\x32\x55\x82\x6c\x55\x72\xef\x58";
+      hash_len = 32;
+      break;
+
+    case GCRY_MD_SHAKE256:
+      short_hash =
+	"\x48\x33\x66\x60\x13\x60\xa8\x77\x1c\x68\x63\x08\x0c\xc4\x11\x4d"
+	"\x8d\xb4\x45\x30\xf8\xf1\xe1\xee\x4f\x94\xea\x37\xe7\x8b\x57\x39";
+      long_hash =
+	"\x98\xbe\x04\x51\x6c\x04\xcc\x73\x59\x3f\xef\x3e\xd0\x35\x2e\xa9"
+	"\xf6\x44\x39\x42\xd6\x95\x0e\x29\xa3\x72\xa6\x81\xc3\xde\xaf\x45";
+      one_million_a_hash =
+	"\x35\x78\xa7\xa4\xca\x91\x37\x56\x9c\xdf\x76\xed\x61\x7d\x31\xbb"
+	"\x99\x4f\xca\x9c\x1b\xbf\x8b\x18\x40\x13\xde\x82\x34\xdf\xd1\x3a";
+      hash_len = 32;
+      break;
   }
 
   what = "short string";
@@ -876,6 +1060,8 @@ run_selftests (int algo, int extended, selftest_report_func_t report)
     case GCRY_MD_SHA3_256:
     case GCRY_MD_SHA3_384:
     case GCRY_MD_SHA3_512:
+    case GCRY_MD_SHAKE128:
+    case GCRY_MD_SHAKE256:
       ec = selftests_keccak (algo, extended, report);
       break;
     default:
@@ -921,7 +1107,22 @@ static gcry_md_oid_spec_t oid_spec_sha3_512[] =
     { "?" },
     { NULL }
   };
-
+static byte shake128_asn[] = { 0x30 };
+static gcry_md_oid_spec_t oid_spec_shake128[] =
+  {
+    { "2.16.840.1.101.3.4.2.11" },
+    /* PKCS#1 shake128WithRSAEncryption */
+    { "?" },
+    { NULL }
+  };
+static byte shake256_asn[] = { 0x30 };
+static gcry_md_oid_spec_t oid_spec_shake256[] =
+  {
+    { "2.16.840.1.101.3.4.2.12" },
+    /* PKCS#1 shake256WithRSAEncryption */
+    { "?" },
+    { NULL }
+  };
 
 gcry_md_spec_t _gcry_digest_spec_sha3_224 =
   {
@@ -955,3 +1156,19 @@ gcry_md_spec_t _gcry_digest_spec_sha3_512 =
     sizeof (KECCAK_CONTEXT),
     run_selftests
   };
+gcry_md_spec_t _gcry_digest_spec_shake128 =
+  {
+    GCRY_MD_SHAKE128, {0, 1},
+    "SHAKE128", shake128_asn, DIM (shake128_asn), oid_spec_shake128, 0,
+    shake128_init, keccak_write, keccak_final, NULL, keccak_extract,
+    sizeof (KECCAK_CONTEXT),
+    run_selftests
+  };
+gcry_md_spec_t _gcry_digest_spec_shake256 =
+  {
+    GCRY_MD_SHAKE256, {0, 1},
+    "SHAKE256", shake256_asn, DIM (shake256_asn), oid_spec_shake256, 0,
+    shake256_init, keccak_write, keccak_final, NULL, keccak_extract,
+    sizeof (KECCAK_CONTEXT),
+    run_selftests
+  };
diff --git a/cipher/md.c b/cipher/md.c
index 6ef8fee..15d944d 100644
--- a/cipher/md.c
+++ b/cipher/md.c
@@ -56,6 +56,8 @@ static gcry_md_spec_t *digest_list[] =
      &_gcry_digest_spec_sha3_256,
      &_gcry_digest_spec_sha3_384,
      &_gcry_digest_spec_sha3_512,
+     &_gcry_digest_spec_shake128,
+     &_gcry_digest_spec_shake256,
 #endif
 #ifdef USE_GOST_R_3411_94
      &_gcry_digest_spec_gost3411_94,
diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi
index facdf65..cdb7644 100644
--- a/doc/gcrypt.texi
+++ b/doc/gcrypt.texi
@@ -3037,7 +3037,7 @@ are also supported.
 @c begin table of hash algorithms
 @cindex SHA-1
 @cindex SHA-224, SHA-256, SHA-384, SHA-512
- at cindex SHA3-224, SHA3-256, SHA3-384, SHA3-512
+ at cindex SHA3-224, SHA3-256, SHA3-384, SHA3-512, SHAKE128, SHAKE256
 @cindex RIPE-MD-160
 @cindex MD2, MD4, MD5
 @cindex TIGER, TIGER1, TIGER2
@@ -3126,6 +3126,16 @@ See FIPS 202 for the specification.
 This is the SHA3-384 algorithm which yields a message digest of 64 bytes.
 See FIPS 202 for the specification.
 
+ at item GCRY_MD_SHAKE128
+This is the SHAKE128 extendable-output function (XOF) algorithm with 128 bit
+security strength.
+See FIPS 202 for the specification.
+
+ at item GCRY_MD_SHAKE256
+This is the SHAKE256 extendable-output function (XOF) algorithm with 256 bit
+security strength.
+See FIPS 202 for the specification.
+
 @item GCRY_MD_CRC32
 This is the ISO 3309 and ITU-T V.42 cyclic redundancy check.  It yields
 an output of 4 bytes.  Note that this is not a hash algorithm in the
diff --git a/src/cipher.h b/src/cipher.h
index d96fdb9..c4b306a 100644
--- a/src/cipher.h
+++ b/src/cipher.h
@@ -295,6 +295,8 @@ extern gcry_md_spec_t _gcry_digest_spec_sha3_224;
 extern gcry_md_spec_t _gcry_digest_spec_sha3_256;
 extern gcry_md_spec_t _gcry_digest_spec_sha3_512;
 extern gcry_md_spec_t _gcry_digest_spec_sha3_384;
+extern gcry_md_spec_t _gcry_digest_spec_shake128;
+extern gcry_md_spec_t _gcry_digest_spec_shake256;
 extern gcry_md_spec_t _gcry_digest_spec_tiger;
 extern gcry_md_spec_t _gcry_digest_spec_tiger1;
 extern gcry_md_spec_t _gcry_digest_spec_tiger2;
diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in
index 39be37a..5ddeee3 100644
--- a/src/gcrypt.h.in
+++ b/src/gcrypt.h.in
@@ -1174,7 +1174,9 @@ enum gcry_md_algos
     GCRY_MD_SHA3_224      = 312,
     GCRY_MD_SHA3_256      = 313,
     GCRY_MD_SHA3_384      = 314,
-    GCRY_MD_SHA3_512      = 315
+    GCRY_MD_SHA3_512      = 315,
+    GCRY_MD_SHAKE128      = 316,
+    GCRY_MD_SHAKE256      = 317
   };
 
 /* Flags used with the open function.  */
diff --git a/tests/basic.c b/tests/basic.c
index 75ff349..0762a89 100644
--- a/tests/basic.c
+++ b/tests/basic.c
@@ -5265,13 +5265,15 @@ check_cipher_modes(void)
     fprintf (stderr, "Completed Cipher Mode checks.\n");
 }
 
+
 static void
-check_one_md (int algo, const char *data, int len, const char *expect)
+check_one_md (int algo, const char *data, int len, const char *expect, int elen)
 {
   gcry_md_hd_t hd, hd2;
   unsigned char *p;
   int mdlen;
   int i;
+  int xof = 0;
   gcry_error_t err = 0;
 
   err = gcry_md_open (&hd, algo, 0);
@@ -5284,8 +5286,15 @@ check_one_md (int algo, const char *data, int len, const char *expect)
   mdlen = gcry_md_get_algo_dlen (algo);
   if (mdlen < 1 || mdlen > 500)
     {
-      fail ("algo %d, gcry_md_get_algo_dlen failed: %d\n", algo, mdlen);
-      return;
+      if (mdlen == 0 && (algo == GCRY_MD_SHAKE128 || algo == GCRY_MD_SHAKE256))
+        {
+          xof = 1;
+        }
+      else
+        {
+          fail ("algo %d, gcry_md_get_algo_dlen failed: %d\n", algo, mdlen);
+          return;
+        }
     }
 
   if (*data == '!' && !data[1])
@@ -5326,19 +5335,168 @@ check_one_md (int algo, const char *data, int len, const char *expect)
 
   gcry_md_close (hd);
 
-  p = gcry_md_read (hd2, algo);
+  if (!xof)
+    {
+      p = gcry_md_read (hd2, algo);
 
-  if (memcmp (p, expect, mdlen))
+      if (memcmp (p, expect, mdlen))
+        {
+          printf ("computed: ");
+          for (i = 0; i < mdlen; i++)
+            printf ("%02x ", p[i] & 0xFF);
+          printf ("\nexpected: ");
+          for (i = 0; i < mdlen; i++)
+            printf ("%02x ", expect[i] & 0xFF);
+          printf ("\n");
+
+          fail ("algo %d, digest mismatch\n", algo);
+        }
+
+    }
+  else
     {
-      printf ("computed: ");
-      for (i = 0; i < mdlen; i++)
-	printf ("%02x ", p[i] & 0xFF);
-      printf ("\nexpected: ");
-      for (i = 0; i < mdlen; i++)
-	printf ("%02x ", expect[i] & 0xFF);
-      printf ("\n");
+      char buf[1000];
+      int outmax = sizeof(buf) > elen ? elen : sizeof(buf);
 
-      fail ("algo %d, digest mismatch\n", algo);
+      err = gcry_md_copy (&hd, hd2);
+      if (err)
+	{
+	  fail ("algo %d, gcry_md_copy failed: %s\n", algo, gpg_strerror (err));
+	}
+
+      err = gcry_md_extract(hd2, algo, buf, outmax);
+      if (err)
+	{
+	  fail ("algo %d, gcry_md_extract failed: %s\n", algo, gpg_strerror (err));
+	}
+
+      if (memcmp (buf, expect, outmax))
+	{
+	  printf ("computed: ");
+	  for (i = 0; i < outmax; i++)
+	    printf ("%02x ", buf[i] & 0xFF);
+	  printf ("\nexpected: ");
+	  for (i = 0; i < outmax; i++)
+	    printf ("%02x ", expect[i] & 0xFF);
+	  printf ("\n");
+
+	  fail ("algo %d, digest mismatch\n", algo);
+	}
+
+      memset(buf, 0, sizeof(buf));
+
+      /* Extract one byte at time. */
+      for (i = 0; i < outmax && !err; i++)
+	err = gcry_md_extract(hd, algo, &buf[i], 1);
+      if (err)
+	{
+	  fail ("algo %d, gcry_md_extract failed: %s\n", algo, gpg_strerror (err));
+	}
+
+      if (memcmp (buf, expect, outmax))
+	{
+	  printf ("computed: ");
+	  for (i = 0; i < outmax; i++)
+	    printf ("%02x ", buf[i] & 0xFF);
+	  printf ("\nexpected: ");
+	  for (i = 0; i < outmax; i++)
+	    printf ("%02x ", expect[i] & 0xFF);
+	  printf ("\n");
+
+	  fail ("algo %d, digest mismatch\n", algo);
+	}
+
+      if (*data == '!' && !data[1])
+	{
+	  int crcalgo = GCRY_MD_RMD160;
+	  gcry_md_hd_t crc1, crc2;
+	  size_t startlen;
+	  size_t piecelen;
+	  size_t left;
+	  const unsigned char *p1, *p2;
+	  int crclen;
+
+	  crclen = gcry_md_get_algo_dlen (crcalgo);
+
+	  err = gcry_md_open (&crc1, crcalgo, 0);
+	  if (err)
+	    {
+	      fail ("algo %d, crcalgo: %d, gcry_md_open failed: %s\n", algo,
+		    crcalgo, gpg_strerror (err));
+	      return;
+	    }
+
+	  err = gcry_md_open (&crc2, crcalgo, 0);
+	  if (err)
+	    {
+	      fail ("algo %d, crcalgo: %d, gcry_md_open failed: %s\n", algo,
+		    crcalgo, gpg_strerror (err));
+	      return;
+	    }
+
+	  /* Extract large chucks, total 1000000 additional bytes. */
+	  for (i = 0; i < 1000; i++)
+	    {
+	      err = gcry_md_extract(hd, algo, buf, 1000);
+	      if (!err)
+		gcry_md_write(crc1, buf, 1000);
+	    }
+	  if (err)
+	    {
+	      fail ("algo %d, gcry_md_extract failed: %s\n", algo,
+		    gpg_strerror (err));
+	    }
+
+	  /* Extract in odd size chunks, total 1000000 additional bytes.  */
+	  left = 1000 * 1000;
+	  startlen = 1;
+	  piecelen = startlen;
+
+	  while (!err && left > 0)
+	    {
+	      if (piecelen > sizeof(buf))
+		piecelen = sizeof(buf);
+	      if (piecelen > left)
+		piecelen = left;
+
+	      err = gcry_md_extract (hd2, algo, buf, piecelen);
+	      if (!err)
+		gcry_md_write(crc2, buf, piecelen);
+	      if (err)
+		{
+		  fail ("algo %d, gcry_md_extract failed: %s\n", algo,
+			gpg_strerror (err));
+		}
+
+	      left -= piecelen;
+
+	      if (piecelen == sizeof(buf))
+		piecelen = ++startlen;
+	      else
+		piecelen = piecelen * 2 - ((piecelen != startlen) ? startlen : 0);
+	    }
+
+	  p1 = gcry_md_read (crc1, crcalgo);
+	  p2 = gcry_md_read (crc2, crcalgo);
+
+	  if (memcmp (p1, p2, crclen))
+	    {
+	      printf ("computed: ");
+	      for (i = 0; i < crclen; i++)
+		printf ("%02x ", p2[i] & 0xFF);
+	      printf ("\nexpected: ");
+	      for (i = 0; i < crclen; i++)
+		printf ("%02x ", p1[i] & 0xFF);
+	      printf ("\n");
+
+	      fail ("algo %d, large xof output mismatch\n", algo);
+	    }
+
+	  gcry_md_close (crc1);
+	  gcry_md_close (crc2);
+	}
+
+      gcry_md_close (hd);
     }
 
   gcry_md_close (hd2);
@@ -5358,6 +5516,9 @@ check_one_md_multi (int algo, const char *data, int len, const char *expect)
   mdlen = gcry_md_get_algo_dlen (algo);
   if (mdlen < 1 || mdlen > 64)
     {
+      if (mdlen == 0 && (algo == GCRY_MD_SHAKE128 || algo == GCRY_MD_SHAKE256))
+        return;
+
       fail ("check_one_md_multi: algo %d, gcry_md_get_algo_dlen failed: %d\n",
             algo, mdlen);
       return;
@@ -5420,6 +5581,7 @@ check_digests (void)
     const char *data;
     const char *expect;
     int datalen;
+    int expectlen;
   } algos[] =
     {
       { GCRY_MD_MD2, "",
@@ -5917,7 +6079,238 @@ check_digests (void)
 #include "./sha3-256.h"
 #include "./sha3-384.h"
 #include "./sha3-512.h"
-      {	0 }
+      { GCRY_MD_SHAKE128,
+	"",
+	"\x7F\x9C\x2B\xA4\xE8\x8F\x82\x7D\x61\x60\x45\x50\x76\x05\x85\x3E"
+	"\xD7\x3B\x80\x93\xF6\xEF\xBC\x88\xEB\x1A\x6E\xAC\xFA\x66\xEF\x26"
+	"\x3C\xB1\xEE\xA9\x88\x00\x4B\x93\x10\x3C\xFB\x0A\xEE\xFD\x2A\x68"
+	"\x6E\x01\xFA\x4A\x58\xE8\xA3\x63\x9C\xA8\xA1\xE3\xF9\xAE\x57\xE2"
+	"\x35\xB8\xCC\x87\x3C\x23\xDC\x62\xB8\xD2\x60\x16\x9A\xFA\x2F\x75"
+	"\xAB\x91\x6A\x58\xD9\x74\x91\x88\x35\xD2\x5E\x6A\x43\x50\x85\xB2"
+	"\xBA\xDF\xD6\xDF\xAA\xC3\x59\xA5\xEF\xBB\x7B\xCC\x4B\x59\xD5\x38"
+	"\xDF\x9A\x04\x30\x2E\x10\xC8\xBC\x1C\xBF\x1A\x0B\x3A\x51\x20\xEA"
+	"\x17\xCD\xA7\xCF\xAD\x76\x5F\x56\x23\x47\x4D\x36\x8C\xCC\xA8\xAF"
+	"\x00\x07\xCD\x9F\x5E\x4C\x84\x9F\x16\x7A\x58\x0B\x14\xAA\xBD\xEF"
+	"\xAE\xE7\xEE\xF4\x7C\xB0\xFC\xA9\x76\x7B\xE1\xFD\xA6\x94\x19\xDF"
+	"\xB9\x27\xE9\xDF\x07\x34\x8B\x19\x66\x91\xAB\xAE\xB5\x80\xB3\x2D"
+	"\xEF\x58\x53\x8B\x8D\x23\xF8\x77\x32\xEA\x63\xB0\x2B\x4F\xA0\xF4"
+	"\x87\x33\x60\xE2\x84\x19\x28\xCD\x60\xDD\x4C\xEE\x8C\xC0\xD4\xC9"
+	"\x22\xA9\x61\x88\xD0\x32\x67\x5C\x8A\xC8\x50\x93\x3C\x7A\xFF\x15"
+	"\x33\xB9\x4C\x83\x4A\xDB\xB6\x9C\x61\x15\xBA\xD4\x69\x2D\x86\x19"
+	"\xF9\x0B\x0C\xDF\x8A\x7B\x9C\x26\x40\x29\xAC\x18\x5B\x70\xB8\x3F"
+	"\x28\x01\xF2\xF4\xB3\xF7\x0C\x59\x3E\xA3\xAE\xEB\x61\x3A\x7F\x1B"
+	"\x1D\xE3\x3F\xD7\x50\x81\xF5\x92\x30\x5F\x2E\x45\x26\xED\xC0\x96"
+	"\x31\xB1\x09\x58\xF4\x64\xD8\x89\xF3\x1B\xA0\x10\x25\x0F\xDA\x7F"
+	"\x13\x68\xEC\x29\x67\xFC\x84\xEF\x2A\xE9\xAF\xF2\x68\xE0\xB1\x70"
+	"\x0A\xFF\xC6\x82\x0B\x52\x3A\x3D\x91\x71\x35\xF2\xDF\xF2\xEE\x06"
+	"\xBF\xE7\x2B\x31\x24\x72\x1D\x4A\x26\xC0\x4E\x53\xA7\x5E\x30\xE7"
+	"\x3A\x7A\x9C\x4A\x95\xD9\x1C\x55\xD4\x95\xE9\xF5\x1D\xD0\xB5\xE9"
+	"\xD8\x3C\x6D\x5E\x8C\xE8\x03\xAA\x62\xB8\xD6\x54\xDB\x53\xD0\x9B"
+	"\x8D\xCF\xF2\x73\xCD\xFE\xB5\x73\xFA\xD8\xBC\xD4\x55\x78\xBE\xC2"
+	"\xE7\x70\xD0\x1E\xFD\xE8\x6E\x72\x1A\x3F\x7C\x6C\xCE\x27\x5D\xAB"
+	"\xE6\xE2\x14\x3F\x1A\xF1\x8D\xA7\xEF\xDD\xC4\xC7\xB7\x0B\x5E\x34"
+	"\x5D\xB9\x3C\xC9\x36\xBE\xA3\x23\x49\x1C\xCB\x38\xA3\x88\xF5\x46"
+	"\xA9\xFF\x00\xDD\x4E\x13\x00\xB9\xB2\x15\x3D\x20\x41\xD2\x05\xB4"
+	"\x43\xE4\x1B\x45\xA6\x53\xF2\xA5\xC4\x49\x2C\x1A\xDD\x54\x45\x12"
+	"\xDD\xA2\x52\x98\x33\x46\x2B\x71\xA4\x1A\x45\xBE\x97\x29\x0B\x6F",
+	0, 512, },
+      { GCRY_MD_SHAKE128,
+	"\x5A\xAB\x62\x75\x6D\x30\x7A\x66\x9D\x14\x6A\xBA\x98\x8D\x90\x74"
+	"\xC5\xA1\x59\xB3\xDE\x85\x15\x1A\x81\x9B\x11\x7C\xA1\xFF\x65\x97"
+	"\xF6\x15\x6E\x80\xFD\xD2\x8C\x9C\x31\x76\x83\x51\x64\xD3\x7D\xA7"
+	"\xDA\x11\xD9\x4E\x09\xAD\xD7\x70\xB6\x8A\x6E\x08\x1C\xD2\x2C\xA0"
+	"\xC0\x04\xBF\xE7\xCD\x28\x3B\xF4\x3A\x58\x8D\xA9\x1F\x50\x9B\x27"
+	"\xA6\x58\x4C\x47\x4A\x4A\x2F\x3E\xE0\xF1\xF5\x64\x47\x37\x92\x40"
+	"\xA5\xAB\x1F\xB7\x7F\xDC\xA4\x9B\x30\x5F\x07\xBA\x86\xB6\x27\x56"
+	"\xFB\x9E\xFB\x4F\xC2\x25\xC8\x68\x45\xF0\x26\xEA\x54\x20\x76\xB9"
+	"\x1A\x0B\xC2\xCD\xD1\x36\xE1\x22\xC6\x59\xBE\x25\x9D\x98\xE5\x84"
+	"\x1D\xF4\xC2\xF6\x03\x30\xD4\xD8\xCD\xEE\x7B\xF1\xA0\xA2\x44\x52"
+	"\x4E\xEC\xC6\x8F\xF2\xAE\xF5\xBF\x00\x69\xC9\xE8\x7A\x11\xC6\xE5"
+	"\x19\xDE\x1A\x40\x62\xA1\x0C\x83\x83\x73\x88\xF7\xEF\x58\x59\x8A"
+	"\x38\x46\xF4\x9D\x49\x96\x82\xB6\x83\xC4\xA0\x62\xB4\x21\x59\x4F"
+	"\xAF\xBC\x13\x83\xC9\x43\xBA\x83\xBD\xEF\x51\x5E\xFC\xF1\x0D",
+	"\xF0\x71\x5D\xE3\x56\x92\xFD\x70\x12\x3D\xC6\x83\x68\xD0\xFE\xEC"
+	"\x06\xA0\xC7\x4C\xF8\xAD\xB0\x5D\xDC\x25\x54\x87\xB1\xA8\xD4\xD1"
+	"\x21\x3E\x9E\xAB\xAF\x41\xF1\x16\x17\x19\xD0\x65\xD7\x94\xB7\x50"
+	"\xF8\x4B\xE3\x2A\x32\x34\xB4\xD5\x36\x46\x0D\x55\x20\x68\x8A\x5A"
+	"\x79\xA1\x7A\x4B\xA8\x98\x7F\xCB\x61\xBF\x7D\xAA\x8B\x54\x7B\xF5"
+	"\xC1\xCE\x36\xB5\x6A\x73\x25\x7D\xBB\xF1\xBA\xBB\x64\xF2\x49\xBD"
+	"\xCE\xB6\x7B\xA1\xC8\x88\x37\x0A\x96\x3D\xFD\x6B\x6A\x2A\xDE\x2C"
+	"\xEF\xD1\x4C\x32\x52\xCB\x37\x58\x52\x0F\x0C\x65\xF4\x52\x46\x82"
+	"\x77\x24\x99\x46\x3A\xE1\xA3\x41\x80\x01\x83\xAA\x60\xEF\xA0\x51"
+	"\x18\xA2\x82\x01\x74\x4F\x7B\xA0\xB0\xA3\x92\x8D\xD7\xC0\x26\x3F"
+	"\xD2\x64\xB7\xCD\x7B\x2E\x2E\x09\xB3\x22\xBF\xCE\xA8\xEE\xD0\x42"
+	"\x75\x79\x5B\xE7\xC0\xF0\x0E\x11\x38\x27\x37\x0D\x05\x1D\x50\x26"
+	"\x95\x80\x30\x00\x05\xAC\x12\x88\xFE\xA6\xCD\x9A\xE9\xF4\xF3\x7C"
+	"\xE0\xF8\xAC\xE8\xBF\x3E\xBE\x1D\x70\x56\x25\x59\x54\xC7\x61\x93"
+	"\x1D\x3C\x42\xED\x62\xF7\xF1\xCE\x1B\x94\x5C\xDE\xCC\x0A\x74\x32"
+	"\x2D\x7F\x64\xD6\x00\x4F\xF2\x16\x84\x14\x93\x07\x28\x8B\x44\x8E"
+	"\x45\x43\x34\x75\xB1\xEA\x13\x14\xB0\x0F\x1F\xC4\x50\x08\x9A\x9D"
+	"\x1F\x77\x10\xC6\xD7\x65\x2E\xCF\x65\x4F\x3B\x48\x7D\x02\x83\xD4"
+	"\xD8\xA2\x8E\xFB\x50\x66\xC4\x25\x0D\x5A\xD6\x98\xE1\x5D\xBA\x88"
+	"\xE9\x25\xE4\xDE\x99\xB6\x9B\xC3\x83\xAC\x80\x45\xB7\xF1\x02\x2A"
+	"\xDD\x39\xD4\x43\x54\x6A\xE0\x92\x4F\x13\xF4\x89\x60\x96\xDF\xDF"
+	"\x37\xCA\x72\x20\x79\x87\xC4\xA7\x70\x5A\x7A\xBE\x72\x4B\x7F\xA1"
+	"\x0C\x90\x9F\x39\x25\x44\x9F\x01\x0D\x61\xE2\x07\xAD\xD9\x52\x19"
+	"\x07\x1A\xCE\xED\xB9\xB9\xDC\xED\x32\xA9\xE1\x23\x56\x1D\x60\x82"
+	"\xD4\x6A\xEF\xAE\x07\xEE\x1B\xD1\x32\x76\x5E\x3E\x51\x3C\x66\x50"
+	"\x1B\x38\x7A\xB2\xEE\x09\xA0\x4A\xE6\x3E\x25\x80\x85\x17\xAF\xEA"
+	"\x3E\x05\x11\x69\xCF\xD2\xFF\xF8\xC5\x85\x8E\x2D\x96\x23\x89\x7C"
+	"\x9E\x85\x17\x5A\xC5\xA8\x63\x94\xCD\x0A\x32\xA0\xA6\x2A\x8F\x5D"
+	"\x6C\xCC\xBF\x49\x3D\xAA\x43\xF7\x83\x62\xBB\xCA\x40\xAD\xF7\x33"
+	"\xF8\x71\xE0\xC0\x09\x98\xD9\xBF\xD6\x88\x06\x56\x66\x6C\xD7\xBE"
+	"\x4F\xE9\x89\x2C\x61\xDC\xD5\xCD\x23\xA5\xE4\x27\x7E\xEE\x8B\x4A"
+	"\xFD\x29\xB6\x9B\xBA\x55\x66\x0A\x21\x71\x12\xFF\x6E\x34\x56\xB1",
+	223, 512, },
+      { GCRY_MD_SHAKE128,
+	"!",
+	"\x9d\x22\x2c\x79\xc4\xff\x9d\x09\x2c\xf6\xca\x86\x14\x3a\xa4\x11"
+	"\xe3\x69\x97\x38\x08\xef\x97\x09\x32\x55\x82\x6c\x55\x72\xef\x58"
+	"\x42\x4c\x4b\x5c\x28\x47\x5f\xfd\xcf\x98\x16\x63\x86\x7f\xec\x63"
+	"\x21\xc1\x26\x2e\x38\x7b\xcc\xf8\xca\x67\x68\x84\xc4\xa9\xd0\xc1"
+	"\x3b\xfa\x68\x69\x76\x3d\x5a\xe4\xbb\xc9\xb3\xcc\xd0\x9d\x1c\xa5"
+	"\xea\x74\x46\x53\x8d\x69\xb3\xfb\x98\xc7\x2b\x59\xa2\xb4\x81\x7d"
+	"\xb5\xea\xdd\x90\x11\xf9\x0f\xa7\x10\x91\x93\x1f\x81\x34\xf4\xf0"
+	"\x0b\x56\x2e\x2f\xe1\x05\x93\x72\x70\x36\x1c\x19\x09\x86\x2a\xd4"
+	"\x50\x46\xe3\x93\x2f\x5d\xd3\x11\xec\x72\xfe\xc5\xf8\xfb\x8f\x60"
+	"\xb4\x5a\x3b\xee\x3f\x85\xbb\xf7\xfc\xed\xc6\xa5\x55\x67\x76\x48"
+	"\xe0\x65\x4b\x38\x19\x41\xa8\x6b\xd3\xe5\x12\x65\x7b\x0d\x57\xa7"
+	"\x99\x1f\xc4\x54\x3f\x89\xd8\x29\x04\x92\x22\x2c\xe4\xa3\x3e\x17"
+	"\x60\x2b\x3b\x99\xc0\x09\xf7\x65\x5f\x87\x53\x5c\xda\xa3\x71\x6f"
+	"\x58\xc4\x7b\x8a\x15\x7a\xd1\x95\xf0\x28\x09\xf2\x75\x00\xb9\x25"
+	"\x49\x79\x31\x1c\x6b\xb4\x15\x96\x8c\xd1\x04\x31\x16\x9a\x27\xd5"
+	"\xa8\xd6\x1e\x13\xa6\xb8\xb7\x7a\xf1\xf8\xb6\xdd\x2e\xef\xde\xa0"
+	"\x40\x78\x96\x80\x49\x0b\x5e\xdc\xb1\xd3\xe5\x38\xa4\x66\xf7\x57"
+	"\xad\x71\x8f\xe1\xfd\x9f\xae\xef\xa4\x72\x46\xad\x5e\x36\x7f\x87"
+	"\xd3\xb4\x85\x0d\x44\x86\xeb\x21\x99\xe9\x4a\x79\x79\xe2\x09\x1a"
+	"\xbc\xdf\x3b\xc1\x33\x79\xc8\x96\xdc\xeb\x79\xa8\xfd\x08\xf1\x10"
+	"\x73\xf3\x3e\x3f\x99\x23\x22\xb3\x12\x02\xde\xe2\x34\x33\x0c\xf3"
+	"\x30\x4a\x58\x8f\x0d\x59\xda\xe4\xe6\x3b\xa2\xac\x3c\xe6\x82\xcc"
+	"\x19\xd4\xe3\x41\x67\x8c\xc3\xa6\x7a\x47\xc1\x13\xb4\xdb\x89\x0f"
+	"\x30\xa9\x2a\xa0\x8a\x1f\x6d\xc8\xfb\x64\x63\xf8\x03\x8c\x2b\x40"
+	"\xb2\x53\x00\x77\xb2\x36\xce\x88\xaf\xcc\xcd\xa0\x8a\xd6\xd7\x5e"
+	"\xee\x18\x99\xb1\x0c\xd8\x00\xc2\xce\x53\x72\xbf\xf2\x2e\xe3\xa3"
+	"\x39\xd4\xb9\xc1\xa2\xf5\xf4\xb8\x20\xf6\x87\xe5\x51\x9b\xd0\x5b"
+	"\x1f\xc5\xda\x0e\xb4\x53\x36\x81\x4f\x48\x13\x2c\x64\x0e\x66\xc3"
+	"\xa0\x2a\x22\xe6\x35\x98\xf9\x4f\x22\xf3\x51\x84\x11\x04\x46\xb6"
+	"\x48\xcf\x84\x74\xf3\x0c\x43\xea\xd5\x83\x09\xfb\x25\x90\x16\x09"
+	"\xe2\x41\x87\xe8\x01\xc8\x09\x56\x1a\x64\x80\x94\x50\xe6\x03\xc4"
+	"\xa8\x03\x95\x25\xc4\x76\xb5\x8e\x32\xce\x2c\x47\xb3\x7d\xa5\x91",
+	0, 512, },
+      { GCRY_MD_SHAKE256,
+	"",
+	"\x46\xB9\xDD\x2B\x0B\xA8\x8D\x13\x23\x3B\x3F\xEB\x74\x3E\xEB\x24"
+	"\x3F\xCD\x52\xEA\x62\xB8\x1B\x82\xB5\x0C\x27\x64\x6E\xD5\x76\x2F"
+	"\xD7\x5D\xC4\xDD\xD8\xC0\xF2\x00\xCB\x05\x01\x9D\x67\xB5\x92\xF6"
+	"\xFC\x82\x1C\x49\x47\x9A\xB4\x86\x40\x29\x2E\xAC\xB3\xB7\xC4\xBE"
+	"\x14\x1E\x96\x61\x6F\xB1\x39\x57\x69\x2C\xC7\xED\xD0\xB4\x5A\xE3"
+	"\xDC\x07\x22\x3C\x8E\x92\x93\x7B\xEF\x84\xBC\x0E\xAB\x86\x28\x53"
+	"\x34\x9E\xC7\x55\x46\xF5\x8F\xB7\xC2\x77\x5C\x38\x46\x2C\x50\x10"
+	"\xD8\x46\xC1\x85\xC1\x51\x11\xE5\x95\x52\x2A\x6B\xCD\x16\xCF\x86"
+	"\xF3\xD1\x22\x10\x9E\x3B\x1F\xDD\x94\x3B\x6A\xEC\x46\x8A\x2D\x62"
+	"\x1A\x7C\x06\xC6\xA9\x57\xC6\x2B\x54\xDA\xFC\x3B\xE8\x75\x67\xD6"
+	"\x77\x23\x13\x95\xF6\x14\x72\x93\xB6\x8C\xEA\xB7\xA9\xE0\xC5\x8D"
+	"\x86\x4E\x8E\xFD\xE4\xE1\xB9\xA4\x6C\xBE\x85\x47\x13\x67\x2F\x5C"
+	"\xAA\xAE\x31\x4E\xD9\x08\x3D\xAB\x4B\x09\x9F\x8E\x30\x0F\x01\xB8"
+	"\x65\x0F\x1F\x4B\x1D\x8F\xCF\x3F\x3C\xB5\x3F\xB8\xE9\xEB\x2E\xA2"
+	"\x03\xBD\xC9\x70\xF5\x0A\xE5\x54\x28\xA9\x1F\x7F\x53\xAC\x26\x6B"
+	"\x28\x41\x9C\x37\x78\xA1\x5F\xD2\x48\xD3\x39\xED\xE7\x85\xFB\x7F"
+	"\x5A\x1A\xAA\x96\xD3\x13\xEA\xCC\x89\x09\x36\xC1\x73\xCD\xCD\x0F"
+	"\xAB\x88\x2C\x45\x75\x5F\xEB\x3A\xED\x96\xD4\x77\xFF\x96\x39\x0B"
+	"\xF9\xA6\x6D\x13\x68\xB2\x08\xE2\x1F\x7C\x10\xD0\x4A\x3D\xBD\x4E"
+	"\x36\x06\x33\xE5\xDB\x4B\x60\x26\x01\xC1\x4C\xEA\x73\x7D\xB3\xDC"
+	"\xF7\x22\x63\x2C\xC7\x78\x51\xCB\xDD\xE2\xAA\xF0\xA3\x3A\x07\xB3"
+	"\x73\x44\x5D\xF4\x90\xCC\x8F\xC1\xE4\x16\x0F\xF1\x18\x37\x8F\x11"
+	"\xF0\x47\x7D\xE0\x55\xA8\x1A\x9E\xDA\x57\xA4\xA2\xCF\xB0\xC8\x39"
+	"\x29\xD3\x10\x91\x2F\x72\x9E\xC6\xCF\xA3\x6C\x6A\xC6\xA7\x58\x37"
+	"\x14\x30\x45\xD7\x91\xCC\x85\xEF\xF5\xB2\x19\x32\xF2\x38\x61\xBC"
+	"\xF2\x3A\x52\xB5\xDA\x67\xEA\xF7\xBA\xAE\x0F\x5F\xB1\x36\x9D\xB7"
+	"\x8F\x3A\xC4\x5F\x8C\x4A\xC5\x67\x1D\x85\x73\x5C\xDD\xDB\x09\xD2"
+	"\xB1\xE3\x4A\x1F\xC0\x66\xFF\x4A\x16\x2C\xB2\x63\xD6\x54\x12\x74"
+	"\xAE\x2F\xCC\x86\x5F\x61\x8A\xBE\x27\xC1\x24\xCD\x8B\x07\x4C\xCD"
+	"\x51\x63\x01\xB9\x18\x75\x82\x4D\x09\x95\x8F\x34\x1E\xF2\x74\xBD"
+	"\xAB\x0B\xAE\x31\x63\x39\x89\x43\x04\xE3\x58\x77\xB0\xC2\x8A\x9B"
+	"\x1F\xD1\x66\xC7\x96\xB9\xCC\x25\x8A\x06\x4A\x8F\x57\xE2\x7F\x2A",
+	0, 512, },
+      { GCRY_MD_SHAKE256,
+	"\xB3\x2D\x95\xB0\xB9\xAA\xD2\xA8\x81\x6D\xE6\xD0\x6D\x1F\x86\x00"
+	"\x85\x05\xBD\x8C\x14\x12\x4F\x6E\x9A\x16\x3B\x5A\x2A\xDE\x55\xF8"
+	"\x35\xD0\xEC\x38\x80\xEF\x50\x70\x0D\x3B\x25\xE4\x2C\xC0\xAF\x05"
+	"\x0C\xCD\x1B\xE5\xE5\x55\xB2\x30\x87\xE0\x4D\x7B\xF9\x81\x36\x22"
+	"\x78\x0C\x73\x13\xA1\x95\x4F\x87\x40\xB6\xEE\x2D\x3F\x71\xF7\x68"
+	"\xDD\x41\x7F\x52\x04\x82\xBD\x3A\x08\xD4\xF2\x22\xB4\xEE\x9D\xBD"
+	"\x01\x54\x47\xB3\x35\x07\xDD\x50\xF3\xAB\x42\x47\xC5\xDE\x9A\x8A"
+	"\xBD\x62\xA8\xDE\xCE\xA0\x1E\x3B\x87\xC8\xB9\x27\xF5\xB0\x8B\xEB"
+	"\x37\x67\x4C\x6F\x8E\x38\x0C\x04",
+	"\xCC\x2E\xAA\x04\xEE\xF8\x47\x9C\xDA\xE8\x56\x6E\xB8\xFF\xA1\x10"
+	"\x0A\x40\x79\x95\xBF\x99\x9A\xE9\x7E\xDE\x52\x66\x81\xDC\x34\x90"
+	"\x61\x6F\x28\x44\x2D\x20\xDA\x92\x12\x4C\xE0\x81\x58\x8B\x81\x49"
+	"\x1A\xED\xF6\x5C\xAA\xF0\xD2\x7E\x82\xA4\xB0\xE1\xD1\xCA\xB2\x38"
+	"\x33\x32\x8F\x1B\x8D\xA4\x30\xC8\xA0\x87\x66\xA8\x63\x70\xFA\x84"
+	"\x8A\x79\xB5\x99\x8D\xB3\xCF\xFD\x05\x7B\x96\xE1\xE2\xEE\x0E\xF2"
+	"\x29\xEC\xA1\x33\xC1\x55\x48\xF9\x83\x99\x02\x04\x37\x30\xE4\x4B"
+	"\xC5\x2C\x39\xFA\xDC\x1D\xDE\xEA\xD9\x5F\x99\x39\xF2\x20\xCA\x30"
+	"\x06\x61\x54\x0D\xF7\xED\xD9\xAF\x37\x8A\x5D\x4A\x19\xB2\xB9\x3E"
+	"\x6C\x78\xF4\x9C\x35\x33\x43\xA0\xB5\xF1\x19\x13\x2B\x53\x12\xD0"
+	"\x04\x83\x1D\x01\x76\x9A\x31\x6D\x2F\x51\xBF\x64\xCC\xB2\x0A\x21"
+	"\xC2\xCF\x7A\xC8\xFB\x6F\x6E\x90\x70\x61\x26\xBD\xAE\x06\x11\xDD"
+	"\x13\x96\x2E\x8B\x53\xD6\xEA\xE2\x6C\x7B\x0D\x25\x51\xDA\xF6\x24"
+	"\x8E\x9D\x65\x81\x73\x82\xB0\x4D\x23\x39\x2D\x10\x8E\x4D\x34\x43"
+	"\xDE\x5A\xDC\x72\x73\xC7\x21\xA8\xF8\x32\x0E\xCF\xE8\x17\x7A\xC0"
+	"\x67\xCA\x8A\x50\x16\x9A\x6E\x73\x00\x0E\xBC\xDC\x1E\x4E\xE6\x33"
+	"\x9F\xC8\x67\xC3\xD7\xAE\xAB\x84\x14\x63\x98\xD7\xBA\xDE\x12\x1D"
+	"\x19\x89\xFA\x45\x73\x35\x56\x4E\x97\x57\x70\xA3\xA0\x02\x59\xCA"
+	"\x08\x70\x61\x08\x26\x1A\xA2\xD3\x4D\xE0\x0F\x8C\xAC\x7D\x45\xD3"
+	"\x5E\x5A\xA6\x3E\xA6\x9E\x1D\x1A\x2F\x7D\xAB\x39\x00\xD5\x1E\x0B"
+	"\xC6\x53\x48\xA2\x55\x54\x00\x70\x39\xA5\x2C\x3C\x30\x99\x80\xD1"
+	"\x7C\xAD\x20\xF1\x15\x63\x10\xA3\x9C\xD3\x93\x76\x0C\xFE\x58\xF6"
+	"\xF8\xAD\xE4\x21\x31\x28\x82\x80\xA3\x5E\x1D\xB8\x70\x81\x83\xB9"
+	"\x1C\xFA\xF5\x82\x7E\x96\xB0\xF7\x74\xC4\x50\x93\xB4\x17\xAF\xF9"
+	"\xDD\x64\x17\xE5\x99\x64\xA0\x1B\xD2\xA6\x12\xFF\xCF\xBA\x18\xA0"
+	"\xF1\x93\xDB\x29\x7B\x9A\x6C\xC1\xD2\x70\xD9\x7A\xAE\x8F\x8A\x3A"
+	"\x6B\x26\x69\x5A\xB6\x64\x31\xC2\x02\xE1\x39\xD6\x3D\xD3\xA2\x47"
+	"\x78\x67\x6C\xEF\xE3\xE2\x1B\x02\xEC\x4E\x8F\x5C\xFD\x66\x58\x7A"
+	"\x12\xB4\x40\x78\xFC\xD3\x9E\xEE\x44\xBB\xEF\x4A\x94\x9A\x63\xC0"
+	"\xDF\xD5\x8C\xF2\xFB\x2C\xD5\xF0\x02\xE2\xB0\x21\x92\x66\xCF\xC0"
+	"\x31\x81\x74\x86\xDE\x70\xB4\x28\x5A\x8A\x70\xF3\xD3\x8A\x61\xD3"
+	"\x15\x5D\x99\xAA\xF4\xC2\x53\x90\xD7\x36\x45\xAB\x3E\x8D\x80\xF0",
+	136, 512, },
+      { GCRY_MD_SHAKE256,
+	"!",
+	"\x35\x78\xa7\xa4\xca\x91\x37\x56\x9c\xdf\x76\xed\x61\x7d\x31\xbb"
+	"\x99\x4f\xca\x9c\x1b\xbf\x8b\x18\x40\x13\xde\x82\x34\xdf\xd1\x3a"
+	"\x3f\xd1\x24\xd4\xdf\x76\xc0\xa5\x39\xee\x7d\xd2\xf6\xe1\xec\x34"
+	"\x61\x24\xc8\x15\xd9\x41\x0e\x14\x5e\xb5\x61\xbc\xd9\x7b\x18\xab"
+	"\x6c\xe8\xd5\x55\x3e\x0e\xab\x3d\x1f\x7d\xfb\x8f\x9d\xee\xfe\x16"
+	"\x84\x7e\x21\x92\xf6\xf6\x1f\xb8\x2f\xb9\x0d\xde\x60\xb1\x90\x63"
+	"\xc5\x6a\x4c\x55\xcd\xd7\xb6\x72\xb7\x5b\xf5\x15\xad\xbf\xe2\x04"
+	"\x90\x3c\x8c\x00\x36\xde\x54\xa2\x99\x9a\x92\x0d\xe9\x0f\x66\xd7"
+	"\xff\x6e\xc8\xe4\xc9\x3d\x24\xae\x34\x6f\xdc\xb3\xa5\xa5\xbd\x57"
+	"\x39\xec\x15\xa6\xed\xdb\x5c\xe5\xb0\x2d\xa5\x30\x39\xfa\xc6\x3e"
+	"\x19\x55\x5f\xaa\x2e\xdd\xc6\x93\xb1\xf0\xc2\xa6\xfc\xbe\x7c\x0a"
+	"\x0a\x09\x1d\x0e\xe7\x00\xd7\x32\x2e\x4b\x0f\xf0\x95\x90\xde\x16"
+	"\x64\x22\xf9\xea\xd5\xda\x4c\x99\x3d\x60\x5f\xe4\xd9\xc6\x34\x84"
+	"\x3a\xa1\x78\xb1\x76\x72\xc6\x56\x8c\x8a\x2e\x62\xab\xeb\xea\x2c"
+	"\x21\xc3\x02\xbd\x36\x6a\xd6\x98\x95\x9e\x1f\x6e\x43\x4a\xf1\x55"
+	"\x56\x8b\x27\x34\xd8\x37\x9f\xcd\x3f\xfe\x64\x89\xba\xff\xa6\xd7"
+	"\x11\x09\x44\x2e\x1b\x34\x4f\x13\x8a\x09\xca\xe3\xe2\xd3\x94\x2e"
+	"\xee\x82\x8f\xc4\x7e\x64\xde\xb5\xe0\x0a\x02\x4a\xe1\xf2\xc0\x77"
+	"\xe6\xb7\xb1\x33\xf6\xc1\xde\x91\x30\x92\xd4\xe8\x29\xec\xd2\xb2"
+	"\xef\x28\xca\x80\x20\x82\x1e\x2b\x8b\xe5\x17\xd9\x3e\xd0\x88\x36"
+	"\xf6\xf0\x66\xcc\x3d\x03\xb6\x25\xd8\x49\x7f\x29\xdb\xc1\xc3\x9e"
+	"\x6f\xe4\x63\x22\x6f\x85\xc1\x28\xa2\xc2\x98\x88\x11\x2e\x06\xa9"
+	"\x9c\x5d\x17\xb2\x5e\x90\x0d\x20\x4f\x39\x72\x31\xcd\xf7\x9c\x31"
+	"\x34\x46\x53\x2d\xad\x07\xf4\xc0\xbd\x9f\xba\x1d\xd4\x13\xd8\xa7"
+	"\xe6\xcb\xc0\xa0\x86\x2c\xc7\x69\x23\x9a\x89\xf9\xdb\x08\x5b\x78"
+	"\xa0\x54\x59\x6a\xd7\x08\x0d\xdf\x96\x01\x9b\x73\x99\xb5\x03\x48"
+	"\x0e\x5a\x65\xa2\x20\x8d\x74\x72\x4c\x98\x7d\x32\x5e\x9b\x0e\x82"
+	"\xfe\xcd\x4f\x27\xf3\x13\x5b\x1d\x9e\x27\xb4\x8e\x69\xdd\x6f\x59"
+	"\x62\xb8\xa6\x3b\x48\x92\x1e\xc8\xee\x53\x86\x9f\x1a\xc1\xc8\x18"
+	"\x23\x87\xee\x0d\x6c\xfe\xf6\x53\xff\x8b\xf6\x05\xf1\x47\x04\xb7"
+	"\x1b\xeb\x65\x53\xf2\x81\xfa\x75\x69\x48\xc4\x38\x49\x4b\x19\xb4"
+	"\xee\x69\xa5\x43\x6b\x22\x2b\xc9\x88\xed\xa4\xac\x60\x00\x24\xc9",
+	0, 512, },
+      { 0 }
     };
   gcry_error_t err;
   int i;
@@ -5950,7 +6343,7 @@ check_digests (void)
       check_one_md (algos[i].md, algos[i].data,
 		    algos[i].datalen > 0 ? algos[i].datalen
 					 : strlen (algos[i].data),
-		    algos[i].expect);
+		    algos[i].expect, algos[i].expectlen);
       check_one_md_multi (algos[i].md, algos[i].data,
 			  algos[i].datalen > 0 ? algos[i].datalen
 					       : strlen (algos[i].data),
diff --git a/tests/bench-slope.c b/tests/bench-slope.c
index 2679556..3a2aa38 100644
--- a/tests/bench-slope.c
+++ b/tests/bench-slope.c
@@ -1651,6 +1651,12 @@ kdf_bench_one (int algo, int subalgo)
       return;
     }
 
+  if (gcry_md_get_algo_dlen (subalgo) == 0)
+    {
+      /* Skip XOFs */
+      return;
+    }
+
   *algo_name = 0;
 
   if (algo == GCRY_KDF_PBKDF2)

commit 28de6f9e16e386018e81a9cdaee596be7616ccab
Author: Jussi Kivilinna <jussi.kivilinna at iki.fi>
Date:   Sun Oct 25 18:57:15 2015 +0200

    Few updates to documentation
    
    * doc/gcrypt.text: Add mention of new 'intel-fast-shld' hw feature
    flag; Add mention of x86 RDRAND support in rndhw.
    --
    
    Signed-off-by: Jussi Kivilinna <jussi.kivilinna at iki.fi>

diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi
index 3450bb2..facdf65 100644
--- a/doc/gcrypt.texi
+++ b/doc/gcrypt.texi
@@ -556,6 +556,7 @@ are
 @item padlock-sha
 @item padlock-mmul
 @item intel-cpu
+ at item intel-fast-shld
 @item intel-bmi2
 @item intel-ssse3
 @item intel-pclmul
@@ -5610,9 +5611,9 @@ that system and is the only gathering module available for that OS.
 
 @item rndhw
 Extra module to collect additional entropy by utilizing a hardware
-random number generator.  As of now the only supported hardware RNG is
-the Padlock engine of VIA (Centaur) CPUs.  It is not available in FIPS
-mode.
+random number generator.  As of now the supported hardware RNG is
+the Padlock engine of VIA (Centaur) CPUs and x86 CPUs with the RDRAND
+instruction.  It is not available in FIPS mode.
 
 @end table
 

commit 92ad19873562cfce7bcc4a0b5aed8195d8284cfc
Author: Jussi Kivilinna <jussi.kivilinna at iki.fi>
Date:   Sun Oct 25 17:59:33 2015 +0200

    Add HMAC-SHA3 test vectors
    
    * tests/basic.c (check_mac): Add HMAC_SHA3 test vectors.
    --
    
    Signed-off-by: Jussi Kivilinna <jussi.kivilinna at iki.fi>

diff --git a/tests/basic.c b/tests/basic.c
index 4ea91a9..75ff349 100644
--- a/tests/basic.c
+++ b/tests/basic.c
@@ -6784,6 +6784,169 @@ check_mac (void)
         "\xde\xbd\x71\xf8\x86\x72\x89\x86\x5d\xf5\xa3\x2d\x20\xcd\xc9\x44"
         "\xb6\x02\x2c\xac\x3c\x49\x82\xb1\x0d\x5e\xeb\x55\xc3\xe4\xde\x15"
         "\x13\x46\x76\xfb\x6d\xe0\x44\x60\x65\xc9\x74\x40\xfa\x8c\x6a\x58" },
+      /* HMAC-SHA3 test vectors from
+       * http://wolfgang-ehrhardt.de/hmac-sha3-testvectors.html */
+      { GCRY_MAC_HMAC_SHA3_224,
+	"Hi There",
+	"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
+	"\x0b\x0b\x0b",
+	"\x3b\x16\x54\x6b\xbc\x7b\xe2\x70\x6a\x03\x1d\xca\xfd\x56\x37\x3d"
+	"\x98\x84\x36\x76\x41\xd8\xc5\x9a\xf3\xc8\x60\xf7" },
+      { GCRY_MAC_HMAC_SHA3_256,
+	"Hi There",
+	"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
+	"\x0b\x0b\x0b",
+	"\xba\x85\x19\x23\x10\xdf\xfa\x96\xe2\xa3\xa4\x0e\x69\x77\x43\x51"
+	"\x14\x0b\xb7\x18\x5e\x12\x02\xcd\xcc\x91\x75\x89\xf9\x5e\x16\xbb" },
+      { GCRY_MAC_HMAC_SHA3_512,
+	"Hi There",
+	"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
+	"\x0b\x0b\x0b",
+	"\xeb\x3f\xbd\x4b\x2e\xaa\xb8\xf5\xc5\x04\xbd\x3a\x41\x46\x5a\xac"
+	"\xec\x15\x77\x0a\x7c\xab\xac\x53\x1e\x48\x2f\x86\x0b\x5e\xc7\xba"
+	"\x47\xcc\xb2\xc6\xf2\xaf\xce\x8f\x88\xd2\x2b\x6d\xc6\x13\x80\xf2"
+	"\x3a\x66\x8f\xd3\x88\x8b\xb8\x05\x37\xc0\xa0\xb8\x64\x07\x68\x9e" },
+      { GCRY_MAC_HMAC_SHA3_224, "what do ya want for nothing?", "Jefe",
+	"\x7f\xdb\x8d\xd8\x8b\xd2\xf6\x0d\x1b\x79\x86\x34\xad\x38\x68\x11"
+	"\xc2\xcf\xc8\x5b\xfa\xf5\xd5\x2b\xba\xce\x5e\x66" },
+      { GCRY_MAC_HMAC_SHA3_256, "what do ya want for nothing?", "Jefe",
+	"\xc7\xd4\x07\x2e\x78\x88\x77\xae\x35\x96\xbb\xb0\xda\x73\xb8\x87"
+	"\xc9\x17\x1f\x93\x09\x5b\x29\x4a\xe8\x57\xfb\xe2\x64\x5e\x1b\xa5" },
+      { GCRY_MAC_HMAC_SHA3_384, "what do ya want for nothing?", "Jefe",
+	"\xf1\x10\x1f\x8c\xbf\x97\x66\xfd\x67\x64\xd2\xed\x61\x90\x3f\x21"
+	"\xca\x9b\x18\xf5\x7c\xf3\xe1\xa2\x3c\xa1\x35\x08\xa9\x32\x43\xce"
+	"\x48\xc0\x45\xdc\x00\x7f\x26\xa2\x1b\x3f\x5e\x0e\x9d\xf4\xc2\x0a" },
+      { GCRY_MAC_HMAC_SHA3_512, "what do ya want for nothing?", "Jefe",
+	"\x5a\x4b\xfe\xab\x61\x66\x42\x7c\x7a\x36\x47\xb7\x47\x29\x2b\x83"
+	"\x84\x53\x7c\xdb\x89\xaf\xb3\xbf\x56\x65\xe4\xc5\xe7\x09\x35\x0b"
+	"\x28\x7b\xae\xc9\x21\xfd\x7c\xa0\xee\x7a\x0c\x31\xd0\x22\xa9\x5e"
+	"\x1f\xc9\x2b\xa9\xd7\x7d\xf8\x83\x96\x02\x75\xbe\xb4\xe6\x20\x24" },
+      { GCRY_MAC_HMAC_SHA3_224,
+	"Test Using Larger Than Block-Size Key - Hash Key First",
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa",
+	"\xb9\x6d\x73\x0c\x14\x8c\x2d\xaa\xd8\x64\x9d\x83\xde\xfa\xa3\x71"
+	"\x97\x38\xd3\x47\x75\x39\x7b\x75\x71\xc3\x85\x15" },
+      { GCRY_MAC_HMAC_SHA3_256,
+	"Test Using Larger Than Block-Size Key - Hash Key First",
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa",
+	"\xa6\x07\x2f\x86\xde\x52\xb3\x8b\xb3\x49\xfe\x84\xcd\x6d\x97\xfb"
+	"\x6a\x37\xc4\xc0\xf6\x2a\xae\x93\x98\x11\x93\xa7\x22\x9d\x34\x67" },
+      { GCRY_MAC_HMAC_SHA3_384,
+	"Test Using Larger Than Block-Size Key - Hash Key First",
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa",
+	"\x71\x3d\xff\x03\x02\xc8\x50\x86\xec\x5a\xd0\x76\x8d\xd6\x5a\x13"
+	"\xdd\xd7\x90\x68\xd8\xd4\xc6\x21\x2b\x71\x2e\x41\x64\x94\x49\x11"
+	"\x14\x80\x23\x00\x44\x18\x5a\x99\x10\x3e\xd8\x20\x04\xdd\xbf\xcc" },
+      { GCRY_MAC_HMAC_SHA3_512,
+	"Test Using Larger Than Block-Size Key - Hash Key First",
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa",
+	"\xb1\x48\x35\xc8\x19\xa2\x90\xef\xb0\x10\xac\xe6\xd8\x56\x8d\xc6"
+	"\xb8\x4d\xe6\x0b\xc4\x9b\x00\x4c\x3b\x13\xed\xa7\x63\x58\x94\x51"
+	"\xe5\xdd\x74\x29\x28\x84\xd1\xbd\xce\x64\xe6\xb9\x19\xdd\x61\xdc"
+	"\x9c\x56\xa2\x82\xa8\x1c\x0b\xd1\x4f\x1f\x36\x5b\x49\xb8\x3a\x5b" },
+      { GCRY_MAC_HMAC_SHA3_224,
+	"This is a test using a larger than block-size key and a larger "
+	"than block-size data. The key needs to be hashed before being "
+	"used by the HMAC algorithm.",
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa",
+	"\xc7\x9c\x9b\x09\x34\x24\xe5\x88\xa9\x87\x8b\xbc\xb0\x89\xe0\x18"
+	"\x27\x00\x96\xe9\xb4\xb1\xa9\xe8\x22\x0c\x86\x6a" },
+      { GCRY_MAC_HMAC_SHA3_256,
+	"This is a test using a larger than block-size key and a larger "
+	"than block-size data. The key needs to be hashed before being "
+	"used by the HMAC algorithm.",
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa",
+	"\xe6\xa3\x6d\x9b\x91\x5f\x86\xa0\x93\xca\xc7\xd1\x10\xe9\xe0\x4c"
+	"\xf1\xd6\x10\x0d\x30\x47\x55\x09\xc2\x47\x5f\x57\x1b\x75\x8b\x5a" },
+      { GCRY_MAC_HMAC_SHA3_384,
+	"This is a test using a larger than block-size key and a larger "
+	"than block-size data. The key needs to be hashed before being "
+	"used by the HMAC algorithm.",
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa",
+	"\xca\xd1\x8a\x8f\xf6\xc4\xcc\x3a\xd4\x87\xb9\x5f\x97\x69\xe9\xb6"
+	"\x1c\x06\x2a\xef\xd6\x95\x25\x69\xe6\xe6\x42\x18\x97\x05\x4c\xfc"
+	"\x70\xb5\xfd\xc6\x60\x5c\x18\x45\x71\x12\xfc\x6a\xaa\xd4\x55\x85" },
+      { GCRY_MAC_HMAC_SHA3_512,
+	"This is a test using a larger than block-size key and a larger "
+	"than block-size data. The key needs to be hashed before being "
+	"used by the HMAC algorithm.",
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa",
+	"\xdc\x03\x0e\xe7\x88\x70\x34\xf3\x2c\xf4\x02\xdf\x34\x62\x2f\x31"
+	"\x1f\x3e\x6c\xf0\x48\x60\xc6\xbb\xd7\xfa\x48\x86\x74\x78\x2b\x46"
+	"\x59\xfd\xbd\xf3\xfd\x87\x78\x52\x88\x5c\xfe\x6e\x22\x18\x5f\xe7"
+	"\xb2\xee\x95\x20\x43\x62\x9b\xc9\xd5\xf3\x29\x8a\x41\xd0\x2c\x66" },
       /* CMAC AES and DES test vectors from
          http://web.archive.org/web/20130930212819/http://csrc.nist.gov/publica\
          tions/nistpubs/800-38B/Updated_CMAC_Examples.pdf */

commit 577dc2b63ceca6a8a716256d034ea4e7414f65fa
Author: Jussi Kivilinna <jussi.kivilinna at iki.fi>
Date:   Sun Oct 25 14:50:41 2015 +0200

    md: add variable length output interface
    
    * cipher/crc.c (_gcry_digest_spec_crc32)
    (_gcry_digest_spec_crc32_rfc1510, _gcry_digest_spec_crc24_rfc2440): Set
    'extract' NULL.
    * cipher/gostr3411-94.c (_gcry_digest_spec_gost3411_94)
    (_gcry_digest_spec_gost3411_cp): Ditto.
    * cipher/keccak.c (_gcry_digest_spec_sha3_224)
    (_gcry_digest_spec_sha3_256, _gcry_digest_spec_sha3_384)
    (_gcry_digest_spec_sha3_512): Ditto.
    * cipher/md2.c (_gcry_digest_spec_md2): Ditto.
    * cipher/md4.c (_gcry_digest_spec_md4): Ditto.
    * cipher/md5.c (_gcry_digest_spec_md5): Ditto.
    * cipher/rmd160.c (_gcry_digest_spec_rmd160): Ditto.
    * cipher/sha1.c (_gcry_digest_spec_sha1): Ditto.
    * cipher/sha256.c (_gcry_digest_spec_sha224)
    (_gcry_digest_spec_sha256): Ditto.
    * cipher/sha512.c (_gcry_digest_spec_sha384)
    (_gcry_digest_spec_sha512): Ditto.
    * cipher/stribog.c (_gcry_digest_spec_stribog_256)
    (_gcry_digest_spec_stribog_512): Ditto.
    * cipher/tiger.c (_gcry_digest_spec_tiger)
    (_gcry_digest_spec_tiger1, _gcry_digest_spec_tiger2): Ditto.
    * cipher/whirlpool.c (_gcry_digest_spec_whirlpool): Ditto.
    * cipher/md.c (md_enable): Do not allow combination of HMAC and
    'expandable-output function'.
    (md_final): Check if spec->read is NULL before calling.
    (md_read): Ditto.
    (md_extract, _gcry_md_extract): New.
    * doc/gcrypt.texi: Add SHA3 algorithms and gcry_md_extract.
    * src/cipher-proto.h (gcry_md_extract_t): New.
    (gcry_md_spec_t): Add 'extract'.
    * src/gcrypt-int.g (_gcry_md_extract): New.
    * src/gcrypt.h.in (gcry_md_extract): New.
    * src/libgcrypt.def: Add gcry_md_extract.
    * src/libgcrypt.vers: Add gcry_md_extract.
    * src/visibility.c (gcry_md_extract): New.
    * src/visibility.h (gcry_md_extract): New.
    --
    
    Patch adds new interface for reading output from 'expandable-output
    function' MD algorithms that can give variable length output (ie.
    SHAKE algorithms from FIPS-202). New function to read output is
    
     gpg_error_t gcry_md_extract(gcry_md_hd_t md, int algo,
    			     void *buffer, size_t length);
    
    Function implicitly finalizes algorithm so that no new input can
    be given. Subsequents calls of the function return more output
    bytes from the algorithm.
    
    Signed-off-by: Jussi Kivilinna <jussi.kivilinna at iki.fi>

diff --git a/cipher/crc.c b/cipher/crc.c
index 9105dfe..46a185a 100644
--- a/cipher/crc.c
+++ b/cipher/crc.c
@@ -785,7 +785,7 @@ gcry_md_spec_t _gcry_digest_spec_crc32 =
   {
     GCRY_MD_CRC32, {0, 1},
     "CRC32", NULL, 0, NULL, 4,
-    crc32_init, crc32_write, crc32_final, crc32_read,
+    crc32_init, crc32_write, crc32_final, crc32_read, NULL,
     sizeof (CRC_CONTEXT)
   };
 
@@ -793,8 +793,7 @@ gcry_md_spec_t _gcry_digest_spec_crc32_rfc1510 =
   {
     GCRY_MD_CRC32_RFC1510, {0, 1},
     "CRC32RFC1510", NULL, 0, NULL, 4,
-    crc32rfc1510_init, crc32_write,
-    crc32rfc1510_final, crc32_read,
+    crc32rfc1510_init, crc32_write, crc32rfc1510_final, crc32_read, NULL,
     sizeof (CRC_CONTEXT)
   };
 
@@ -802,7 +801,6 @@ gcry_md_spec_t _gcry_digest_spec_crc24_rfc2440 =
   {
     GCRY_MD_CRC24_RFC2440, {0, 1},
     "CRC24RFC2440", NULL, 0, NULL, 3,
-    crc24rfc2440_init, crc24rfc2440_write,
-    crc24rfc2440_final, crc32_read,
+    crc24rfc2440_init, crc24rfc2440_write, crc24rfc2440_final, crc32_read, NULL,
     sizeof (CRC_CONTEXT)
   };
diff --git a/cipher/gostr3411-94.c b/cipher/gostr3411-94.c
index 7b16e61..a782427 100644
--- a/cipher/gostr3411-94.c
+++ b/cipher/gostr3411-94.c
@@ -343,13 +343,13 @@ gcry_md_spec_t _gcry_digest_spec_gost3411_94 =
   {
     GCRY_MD_GOSTR3411_94, {0, 0},
     "GOSTR3411_94", NULL, 0, NULL, 32,
-    gost3411_init, _gcry_md_block_write, gost3411_final, gost3411_read,
+    gost3411_init, _gcry_md_block_write, gost3411_final, gost3411_read, NULL,
     sizeof (GOSTR3411_CONTEXT)
   };
 gcry_md_spec_t _gcry_digest_spec_gost3411_cp =
   {
     GCRY_MD_GOSTR3411_CP, {0, 0},
     "GOSTR3411_CP", asn, DIM (asn), oid_spec_gostr3411, 32,
-    gost3411_cp_init, _gcry_md_block_write, gost3411_final, gost3411_read,
+    gost3411_cp_init, _gcry_md_block_write, gost3411_final, gost3411_read, NULL,
     sizeof (GOSTR3411_CONTEXT)
   };
diff --git a/cipher/keccak.c b/cipher/keccak.c
index 3a72294..d46d9cb 100644
--- a/cipher/keccak.c
+++ b/cipher/keccak.c
@@ -927,7 +927,7 @@ gcry_md_spec_t _gcry_digest_spec_sha3_224 =
   {
     GCRY_MD_SHA3_224, {0, 1},
     "SHA3-224", sha3_224_asn, DIM (sha3_224_asn), oid_spec_sha3_224, 28,
-    sha3_224_init, keccak_write, keccak_final, keccak_read,
+    sha3_224_init, keccak_write, keccak_final, keccak_read, NULL,
     sizeof (KECCAK_CONTEXT),
     run_selftests
   };
@@ -935,7 +935,7 @@ gcry_md_spec_t _gcry_digest_spec_sha3_256 =
   {
     GCRY_MD_SHA3_256, {0, 1},
     "SHA3-256", sha3_256_asn, DIM (sha3_256_asn), oid_spec_sha3_256, 32,
-    sha3_256_init, keccak_write, keccak_final, keccak_read,
+    sha3_256_init, keccak_write, keccak_final, keccak_read, NULL,
     sizeof (KECCAK_CONTEXT),
     run_selftests
   };
@@ -943,7 +943,7 @@ gcry_md_spec_t _gcry_digest_spec_sha3_384 =
   {
     GCRY_MD_SHA3_384, {0, 1},
     "SHA3-384", sha3_384_asn, DIM (sha3_384_asn), oid_spec_sha3_384, 48,
-    sha3_384_init, keccak_write, keccak_final, keccak_read,
+    sha3_384_init, keccak_write, keccak_final, keccak_read, NULL,
     sizeof (KECCAK_CONTEXT),
     run_selftests
   };
@@ -951,7 +951,7 @@ gcry_md_spec_t _gcry_digest_spec_sha3_512 =
   {
     GCRY_MD_SHA3_512, {0, 1},
     "SHA3-512", sha3_512_asn, DIM (sha3_512_asn), oid_spec_sha3_512, 64,
-    sha3_512_init, keccak_write, keccak_final, keccak_read,
+    sha3_512_init, keccak_write, keccak_final, keccak_read, NULL,
     sizeof (KECCAK_CONTEXT),
     run_selftests
   };
diff --git a/cipher/md.c b/cipher/md.c
index 948d269..6ef8fee 100644
--- a/cipher/md.c
+++ b/cipher/md.c
@@ -408,6 +408,12 @@ md_enable (gcry_md_hd_t hd, int algorithm)
         }
     }
 
+  if (!err && h->flags.hmac && spec->read == NULL)
+    {
+      /* Expandable output function cannot act as part of HMAC. */
+      err = GPG_ERR_DIGEST_ALGO;
+    }
+
   if (!err)
     {
       size_t size = (sizeof (*entry)
@@ -638,11 +644,16 @@ md_final (gcry_md_hd_t a)
 
   for (r = a->ctx->list; r; r = r->next)
     {
-      byte *p = r->spec->read (&r->context.c);
+      byte *p;
       size_t dlen = r->spec->mdlen;
       byte *hash;
       gcry_err_code_t err;
 
+      if (r->spec->read == NULL)
+        continue;
+
+      p = r->spec->read (&r->context.c);
+
       if (a->ctx->flags.secure)
         hash = xtrymalloc_secure (dlen);
       else
@@ -821,6 +832,8 @@ md_read( gcry_md_hd_t a, int algo )
         {
           if (r->next)
             log_debug ("more than one algorithm in md_read(0)\n");
+          if (r->spec->read == NULL)
+            return NULL;
           return r->spec->read (&r->context.c);
         }
     }
@@ -828,7 +841,11 @@ md_read( gcry_md_hd_t a, int algo )
     {
       for (r = a->ctx->list; r; r = r->next)
 	if (r->spec->algo == algo)
-	  return r->spec->read (&r->context.c);
+	  {
+	    if (r->spec->read == NULL)
+	      return NULL;
+	    return r->spec->read (&r->context.c);
+	  }
     }
   BUG();
   return NULL;
@@ -850,6 +867,52 @@ _gcry_md_read (gcry_md_hd_t hd, int algo)
 }
 
 
+/****************
+ * If ALGO is null get the digest for the used algo (which should be
+ * only one)
+ */
+static gcry_err_code_t
+md_extract(gcry_md_hd_t a, int algo, void *out, size_t outlen)
+{
+  GcryDigestEntry *r = a->ctx->list;
+
+  if (!algo)
+    {
+      /* Return the first algorithm */
+      if (r && r->spec->extract)
+	{
+	  if (r->next)
+	    log_debug ("more than one algorithm in md_extract(0)\n");
+	  r->spec->extract (&r->context.c, out, outlen);
+	  return 0;
+	}
+    }
+  else
+    {
+      for (r = a->ctx->list; r; r = r->next)
+	if (r->spec->algo == algo && r->spec->extract)
+	  {
+	    r->spec->extract (&r->context.c, out, outlen);
+	    return 0;
+	  }
+    }
+
+  return GPG_ERR_DIGEST_ALGO;
+}
+
+
+/*
+ * Expand the output from XOF class digest, this function implictly finalizes
+ * the hash.
+ */
+gcry_err_code_t
+_gcry_md_extract (gcry_md_hd_t hd, int algo, void *out, size_t outlen)
+{
+  _gcry_md_ctl (hd, GCRYCTL_FINALIZE, NULL, 0);
+  return md_extract (hd, algo, out, outlen);
+}
+
+
 /*
  * Read out an intermediate digest.  Not yet functional.
  */
diff --git a/cipher/md2.c b/cipher/md2.c
index 97682e5..e339b28 100644
--- a/cipher/md2.c
+++ b/cipher/md2.c
@@ -177,6 +177,6 @@ gcry_md_spec_t _gcry_digest_spec_md2 =
   {
     GCRY_MD_MD2, {0, 0},
     "MD2", asn, DIM (asn), oid_spec_md2, 16,
-    md2_init, _gcry_md_block_write, md2_final, md2_read,
+    md2_init, _gcry_md_block_write, md2_final, md2_read, NULL,
     sizeof (MD2_CONTEXT)
   };
diff --git a/cipher/md4.c b/cipher/md4.c
index c9b4154..afa6382 100644
--- a/cipher/md4.c
+++ b/cipher/md4.c
@@ -286,6 +286,6 @@ gcry_md_spec_t _gcry_digest_spec_md4 =
   {
     GCRY_MD_MD4, {0, 0},
     "MD4", asn, DIM (asn), oid_spec_md4,16,
-    md4_init, _gcry_md_block_write, md4_final, md4_read,
+    md4_init, _gcry_md_block_write, md4_final, md4_read, NULL,
     sizeof (MD4_CONTEXT)
   };
diff --git a/cipher/md5.c b/cipher/md5.c
index f17af7a..66cc5f6 100644
--- a/cipher/md5.c
+++ b/cipher/md5.c
@@ -312,6 +312,6 @@ gcry_md_spec_t _gcry_digest_spec_md5 =
   {
     GCRY_MD_MD5, {0, 1},
     "MD5", asn, DIM (asn), oid_spec_md5, 16,
-    md5_init, _gcry_md_block_write, md5_final, md5_read,
+    md5_init, _gcry_md_block_write, md5_final, md5_read, NULL,
     sizeof (MD5_CONTEXT)
   };
diff --git a/cipher/rmd160.c b/cipher/rmd160.c
index 2695db2..cf7531e 100644
--- a/cipher/rmd160.c
+++ b/cipher/rmd160.c
@@ -526,6 +526,6 @@ gcry_md_spec_t _gcry_digest_spec_rmd160 =
   {
     GCRY_MD_RMD160, {0, 0},
     "RIPEMD160", asn, DIM (asn), oid_spec_rmd160, 20,
-    rmd160_init, _gcry_md_block_write, rmd160_final, rmd160_read,
+    rmd160_init, _gcry_md_block_write, rmd160_final, rmd160_read, NULL,
     sizeof (RMD160_CONTEXT)
   };
diff --git a/cipher/sha1.c b/cipher/sha1.c
index 554d55c..0de8412 100644
--- a/cipher/sha1.c
+++ b/cipher/sha1.c
@@ -573,7 +573,7 @@ gcry_md_spec_t _gcry_digest_spec_sha1 =
   {
     GCRY_MD_SHA1, {0, 1},
     "SHA1", asn, DIM (asn), oid_spec_sha1, 20,
-    sha1_init, _gcry_md_block_write, sha1_final, sha1_read,
+    sha1_init, _gcry_md_block_write, sha1_final, sha1_read, NULL,
     sizeof (SHA1_CONTEXT),
     run_selftests
   };
diff --git a/cipher/sha256.c b/cipher/sha256.c
index 63869d5..bc326e0 100644
--- a/cipher/sha256.c
+++ b/cipher/sha256.c
@@ -633,7 +633,7 @@ gcry_md_spec_t _gcry_digest_spec_sha224 =
   {
     GCRY_MD_SHA224, {0, 1},
     "SHA224", asn224, DIM (asn224), oid_spec_sha224, 28,
-    sha224_init, _gcry_md_block_write, sha256_final, sha256_read,
+    sha224_init, _gcry_md_block_write, sha256_final, sha256_read, NULL,
     sizeof (SHA256_CONTEXT),
     run_selftests
   };
@@ -642,7 +642,7 @@ gcry_md_spec_t _gcry_digest_spec_sha256 =
   {
     GCRY_MD_SHA256, {0, 1},
     "SHA256", asn256, DIM (asn256), oid_spec_sha256, 32,
-    sha256_init, _gcry_md_block_write, sha256_final, sha256_read,
+    sha256_init, _gcry_md_block_write, sha256_final, sha256_read, NULL,
     sizeof (SHA256_CONTEXT),
     run_selftests
   };
diff --git a/cipher/sha512.c b/cipher/sha512.c
index 4be1cab..1196db9 100644
--- a/cipher/sha512.c
+++ b/cipher/sha512.c
@@ -877,7 +877,7 @@ gcry_md_spec_t _gcry_digest_spec_sha512 =
   {
     GCRY_MD_SHA512, {0, 1},
     "SHA512", sha512_asn, DIM (sha512_asn), oid_spec_sha512, 64,
-    sha512_init, _gcry_md_block_write, sha512_final, sha512_read,
+    sha512_init, _gcry_md_block_write, sha512_final, sha512_read, NULL,
     sizeof (SHA512_CONTEXT),
     run_selftests
   };
@@ -903,7 +903,7 @@ gcry_md_spec_t _gcry_digest_spec_sha384 =
   {
     GCRY_MD_SHA384, {0, 1},
     "SHA384", sha384_asn, DIM (sha384_asn), oid_spec_sha384, 48,
-    sha384_init, _gcry_md_block_write, sha512_final, sha512_read,
+    sha384_init, _gcry_md_block_write, sha512_final, sha512_read, NULL,
     sizeof (SHA512_CONTEXT),
     run_selftests
   };
diff --git a/cipher/stribog.c b/cipher/stribog.c
index de167a7..7f38e6f 100644
--- a/cipher/stribog.c
+++ b/cipher/stribog.c
@@ -1326,6 +1326,7 @@ gcry_md_spec_t _gcry_digest_spec_stribog_256 =
     GCRY_MD_STRIBOG256, {0, 0},
     "STRIBOG256", NULL, 0, NULL, 32,
     stribog_init_256, _gcry_md_block_write, stribog_final, stribog_read_256,
+    NULL,
     sizeof (STRIBOG_CONTEXT)
   };
 
@@ -1334,5 +1335,6 @@ gcry_md_spec_t _gcry_digest_spec_stribog_512 =
     GCRY_MD_STRIBOG512, {0, 0},
     "STRIBOG512", NULL, 0, NULL, 64,
     stribog_init_512, _gcry_md_block_write, stribog_final, stribog_read_512,
+    NULL,
     sizeof (STRIBOG_CONTEXT)
   };
diff --git a/cipher/tiger.c b/cipher/tiger.c
index 8a08953..078133a 100644
--- a/cipher/tiger.c
+++ b/cipher/tiger.c
@@ -840,7 +840,7 @@ gcry_md_spec_t _gcry_digest_spec_tiger =
   {
     GCRY_MD_TIGER, {0, 0},
     "TIGER192", NULL, 0, NULL, 24,
-    tiger_init, _gcry_md_block_write, tiger_final, tiger_read,
+    tiger_init, _gcry_md_block_write, tiger_final, tiger_read, NULL,
     sizeof (TIGER_CONTEXT)
   };
 
@@ -863,7 +863,7 @@ gcry_md_spec_t _gcry_digest_spec_tiger1 =
   {
     GCRY_MD_TIGER1, {0, 0},
     "TIGER", asn1, DIM (asn1), oid_spec_tiger1, 24,
-    tiger1_init, _gcry_md_block_write, tiger_final, tiger_read,
+    tiger1_init, _gcry_md_block_write, tiger_final, tiger_read, NULL,
     sizeof (TIGER_CONTEXT)
   };
 
@@ -874,7 +874,7 @@ gcry_md_spec_t _gcry_digest_spec_tiger2 =
   {
     GCRY_MD_TIGER2, {0, 0},
     "TIGER2", NULL, 0, NULL, 24,
-    tiger2_init, _gcry_md_block_write, tiger_final, tiger_read,
+    tiger2_init, _gcry_md_block_write, tiger_final, tiger_read, NULL,
     sizeof (TIGER_CONTEXT)
   };
 
diff --git a/cipher/whirlpool.c b/cipher/whirlpool.c
index 5f224a1..8a06939 100644
--- a/cipher/whirlpool.c
+++ b/cipher/whirlpool.c
@@ -1525,6 +1525,6 @@ gcry_md_spec_t _gcry_digest_spec_whirlpool =
   {
     GCRY_MD_WHIRLPOOL, {0, 0},
     "WHIRLPOOL", NULL, 0, NULL, 64,
-    whirlpool_init, whirlpool_write, whirlpool_final, whirlpool_read,
+    whirlpool_init, whirlpool_write, whirlpool_final, whirlpool_read, NULL,
     sizeof (whirlpool_context_t)
   };
diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi
index f13695a..3450bb2 100644
--- a/doc/gcrypt.texi
+++ b/doc/gcrypt.texi
@@ -3036,6 +3036,7 @@ are also supported.
 @c begin table of hash algorithms
 @cindex SHA-1
 @cindex SHA-224, SHA-256, SHA-384, SHA-512
+ at cindex SHA3-224, SHA3-256, SHA3-384, SHA3-512
 @cindex RIPE-MD-160
 @cindex MD2, MD4, MD5
 @cindex TIGER, TIGER1, TIGER2
@@ -3108,6 +3109,22 @@ See FIPS 180-2 for the specification.
 This is the SHA-384 algorithm which yields a message digest of 64 bytes.
 See FIPS 180-2 for the specification.
 
+ at item GCRY_MD_SHA3_224
+This is the SHA3-224 algorithm which yields a message digest of 28 bytes.
+See FIPS 202 for the specification.
+
+ at item GCRY_MD_SHA3_256
+This is the SHA3-256 algorithm which yields a message digest of 32 bytes.
+See FIPS 202 for the specification.
+
+ at item GCRY_MD_SHA3_384
+This is the SHA3-384 algorithm which yields a message digest of 48 bytes.
+See FIPS 202 for the specification.
+
+ at item GCRY_MD_SHA3_512
+This is the SHA3-384 algorithm which yields a message digest of 64 bytes.
+See FIPS 202 for the specification.
+
 @item GCRY_MD_CRC32
 This is the ISO 3309 and ITU-T V.42 cyclic redundancy check.  It yields
 an output of 4 bytes.  Note that this is not a hash algorithm in the
@@ -3170,11 +3187,12 @@ this is the hashed data is highly confidential.
 @item GCRY_MD_FLAG_HMAC
 @cindex HMAC
 Turn the algorithm into a HMAC message authentication algorithm.  This
-only works if just one algorithm is enabled for the handle.  Note that
-the function @code{gcry_md_setkey} must be used to set the MAC key.
-The size of the MAC is equal to the message digest of the underlying
-hash algorithm.  If you want CBC message authentication codes based on
-a cipher, see @xref{Working with cipher handles}.
+only works if just one algorithm is enabled for the handle and that
+algorithm is not an extendable-output function.  Note that the function
+ at code{gcry_md_setkey} must be used to set the MAC key.  The size of the
+MAC is equal to the message digest of the underlying hash algorithm.
+If you want CBC message authentication codes based on a cipher,
+see @xref{Working with cipher handles}.
 
 @item GCRY_MD_FLAG_BUGEMU1
 @cindex bug emulation
@@ -3293,9 +3311,9 @@ message digest or some padding.
 @deftypefun void gcry_md_final (gcry_md_hd_t @var{h})
 
 Finalize the message digest calculation.  This is not really needed
-because @code{gcry_md_read} does this implicitly.  After this has been
-done no further updates (by means of @code{gcry_md_write} or
- at code{gcry_md_putc} should be done; However, to mitigate timing
+because @code{gcry_md_read} and @code{gcry_md_extract} do this implicitly.
+After this has been done no further updates (by means of @code{gcry_md_write}
+or @code{gcry_md_putc} should be done; However, to mitigate timing
 attacks it is sometimes useful to keep on updating the context after
 having stored away the actual digest.  Only the first call to this function
 has an effect. It is implemented as a macro.
@@ -3318,6 +3336,22 @@ The function does return @code{NULL} if the requested algorithm has not
 been enabled.
 @end deftypefun
 
+The way to read output of extendable-output function is by using the
+function:
+
+ at deftypefun gpg_err_code_t gcry_md_extract (gcry_md_hd_t @var{h}, @
+  int @var{algo}, void *@var{buffer}, size_t @var{length})
+
+ at code{gcry_mac_read} returns output from extendable-output function.
+This function may be used as often as required to generate more output
+byte stream from the algorithm.  Function extracts the new output bytes
+to @var{buffer} of the length @var{length}.  Buffer will be fully
+populated with new output.  @var{algo} may be given as 0 to return the only
+enabled message digest or it may specify one of the enabled algorithms.
+The function does return non-zero value if the requested algorithm has not
+been enabled.
+ at end deftypefun
+
 Because it is often necessary to get the message digest of blocks of
 memory, two fast convenience function are available for this task:
 
@@ -3493,6 +3527,7 @@ provided by Libgcrypt.
 @c begin table of MAC algorithms
 @cindex HMAC-SHA-1
 @cindex HMAC-SHA-224, HMAC-SHA-256, HMAC-SHA-384, HMAC-SHA-512
+ at cindex HMAC-SHA3-224, HMAC-SHA3-256, HMAC-SHA3-384, HMAC-SHA3-512
 @cindex HMAC-RIPE-MD-160
 @cindex HMAC-MD2, HMAC-MD4, HMAC-MD5
 @cindex HMAC-TIGER1
@@ -3520,6 +3555,22 @@ algorithm.
 This is HMAC message authentication algorithm based on the SHA-384 hash
 algorithm.
 
+ at item GCRY_MAC_HMAC_SHA3_256
+This is HMAC message authentication algorithm based on the SHA3-384 hash
+algorithm.
+
+ at item GCRY_MAC_HMAC_SHA3_224
+This is HMAC message authentication algorithm based on the SHA3-224 hash
+algorithm.
+
+ at item GCRY_MAC_HMAC_SHA3_512
+This is HMAC message authentication algorithm based on the SHA3-512 hash
+algorithm.
+
+ at item GCRY_MAC_HMAC_SHA3_384
+This is HMAC message authentication algorithm based on the SHA3-384 hash
+algorithm.
+
 @item GCRY_MAC_HMAC_SHA1
 This is HMAC message authentication algorithm based on the SHA-1 hash
 algorithm.
diff --git a/src/cipher-proto.h b/src/cipher-proto.h
index 8267791..3bca9c7 100644
--- a/src/cipher-proto.h
+++ b/src/cipher-proto.h
@@ -215,6 +215,9 @@ typedef void (*gcry_md_final_t) (void *c);
 /* Type for the md_read function.  */
 typedef unsigned char *(*gcry_md_read_t) (void *c);
 
+/* Type for the md_extract function.  */
+typedef void (*gcry_md_extract_t) (void *c, void *outbuf, size_t nbytes);
+
 typedef struct gcry_md_oid_spec
 {
   const char *oidstring;
@@ -237,6 +240,7 @@ typedef struct gcry_md_spec
   gcry_md_write_t write;
   gcry_md_final_t final;
   gcry_md_read_t read;
+  gcry_md_extract_t extract;
   size_t contextsize; /* allocate this amount of context */
   selftest_func_t selftest;
 } gcry_md_spec_t;
diff --git a/src/gcrypt-int.h b/src/gcrypt-int.h
index 8014d61..d367307 100644
--- a/src/gcrypt-int.h
+++ b/src/gcrypt-int.h
@@ -129,6 +129,8 @@ gpg_err_code_t _gcry_md_ctl (gcry_md_hd_t hd, int cmd,
                           void *buffer, size_t buflen);
 void _gcry_md_write (gcry_md_hd_t hd, const void *buffer, size_t length);
 unsigned char *_gcry_md_read (gcry_md_hd_t hd, int algo);
+gpg_error_t _gcry_md_extract (gcry_md_hd_t hd, int algo, void *buffer,
+                              size_t length);
 void _gcry_md_hash_buffer (int algo, void *digest,
                            const void *buffer, size_t length);
 gpg_err_code_t _gcry_md_hash_buffers (int algo, unsigned int flags,
diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in
index 585da6a..39be37a 100644
--- a/src/gcrypt.h.in
+++ b/src/gcrypt.h.in
@@ -473,7 +473,7 @@ char *gcry_sexp_nth_string (gcry_sexp_t list, int number);
    value can't be converted to an MPI, `NULL' is returned.  */
 gcry_mpi_t gcry_sexp_nth_mpi (gcry_sexp_t list, int number, int mpifmt);
 
-/* Convenience fucntion to extract parameters from an S-expression
+/* Convenience function to extract parameters from an S-expression
  * using a list of single letter parameters.  */
 gpg_error_t gcry_sexp_extract_param (gcry_sexp_t sexp,
                                      const char *path,
@@ -1170,7 +1170,7 @@ enum gcry_md_algos
     GCRY_MD_GOSTR3411_94  = 308, /* GOST R 34.11-94.  */
     GCRY_MD_STRIBOG256    = 309, /* GOST R 34.11-2012, 256 bit.  */
     GCRY_MD_STRIBOG512    = 310, /* GOST R 34.11-2012, 512 bit.  */
-    GCRY_MD_GOSTR3411_CP  = 311,  /* GOST R 34.11-94 with CryptoPro-A S-Box.  */
+    GCRY_MD_GOSTR3411_CP  = 311, /* GOST R 34.11-94 with CryptoPro-A S-Box.  */
     GCRY_MD_SHA3_224      = 312,
     GCRY_MD_SHA3_256      = 313,
     GCRY_MD_SHA3_384      = 314,
@@ -1239,6 +1239,11 @@ void gcry_md_write (gcry_md_hd_t hd, const void *buffer, size_t length);
    algorithm ALGO. */
 unsigned char *gcry_md_read (gcry_md_hd_t hd, int algo);
 
+/* Read more output from algorithm ALGO to BUFFER of size LENGTH from
+ * digest object HD. Algorithm needs to be 'expendable-output function'. */
+gpg_error_t gcry_md_extract (gcry_md_hd_t hd, int algo, void *buffer,
+                             size_t length);
+
 /* Convenience function to calculate the hash from the data in BUFFER
    of size LENGTH using the algorithm ALGO avoiding the creating of a
    hash object.  The hash is returned in the caller provided buffer
diff --git a/src/libgcrypt.def b/src/libgcrypt.def
index 924f17f..f3e074b 100644
--- a/src/libgcrypt.def
+++ b/src/libgcrypt.def
@@ -278,5 +278,6 @@ EXPORTS
 
       gcry_mpi_ec_sub           @244
 
+      gcry_md_extract           @245
 
 ;; end of file with public symbols for Windows.
diff --git a/src/libgcrypt.vers b/src/libgcrypt.vers
index 7e8df3f..5b3d419 100644
--- a/src/libgcrypt.vers
+++ b/src/libgcrypt.vers
@@ -41,7 +41,7 @@ GCRYPT_1.6 {
     gcry_md_get_algo; gcry_md_get_algo_dlen; gcry_md_hash_buffer;
     gcry_md_hash_buffers;
     gcry_md_info; gcry_md_is_enabled; gcry_md_is_secure;
-    gcry_md_map_name; gcry_md_open; gcry_md_read;
+    gcry_md_map_name; gcry_md_open; gcry_md_read; gcry_md_extract;
     gcry_md_reset; gcry_md_setkey;
     gcry_md_write; gcry_md_debug;
 
diff --git a/src/visibility.c b/src/visibility.c
index cbf24e7..23a2705 100644
--- a/src/visibility.c
+++ b/src/visibility.c
@@ -1165,6 +1165,12 @@ gcry_md_read (gcry_md_hd_t hd, int algo)
   return _gcry_md_read (hd, algo);
 }
 
+gcry_err_code_t
+gcry_md_extract (gcry_md_hd_t hd, int algo, void *buffer, size_t length)
+{
+  return _gcry_md_extract(hd, algo, buffer, length);
+}
+
 void
 gcry_md_hash_buffer (int algo, void *digest,
                      const void *buffer, size_t length)
diff --git a/src/visibility.h b/src/visibility.h
index fa3c763..bb25de0 100644
--- a/src/visibility.h
+++ b/src/visibility.h
@@ -110,6 +110,7 @@ MARK_VISIBLEX (gcry_md_is_secure)
 MARK_VISIBLEX (gcry_md_map_name)
 MARK_VISIBLEX (gcry_md_open)
 MARK_VISIBLEX (gcry_md_read)
+MARK_VISIBLEX (gcry_md_extract)
 MARK_VISIBLEX (gcry_md_reset)
 MARK_VISIBLEX (gcry_md_setkey)
 MARK_VISIBLEX (gcry_md_write)
@@ -374,6 +375,7 @@ MARK_VISIBLEX (_gcry_mpi_get_const)
 #define gcry_md_map_name            _gcry_USE_THE_UNDERSCORED_FUNCTION
 #define gcry_md_open                _gcry_USE_THE_UNDERSCORED_FUNCTION
 #define gcry_md_read                _gcry_USE_THE_UNDERSCORED_FUNCTION
+#define gcry_md_extract             _gcry_USE_THE_UNDERSCORED_FUNCTION
 #define gcry_md_reset               _gcry_USE_THE_UNDERSCORED_FUNCTION
 #define gcry_md_setkey              _gcry_USE_THE_UNDERSCORED_FUNCTION
 #define gcry_md_write               _gcry_USE_THE_UNDERSCORED_FUNCTION

commit cee2e122ec6c1886957a8d47498eb63a6a921725
Author: Jussi Kivilinna <jussi.kivilinna at iki.fi>
Date:   Sun Oct 25 15:11:14 2015 +0200

    md: check hmac flag in prepare_macpads
    
    * cipher/md.c (prepare_macpads): Check hmac flag.
    --
    
    Signed-off-by: Jussi Kivilinna <jussi.kivilinna at iki.fi>

diff --git a/cipher/md.c b/cipher/md.c
index c6bf90d..948d269 100644
--- a/cipher/md.c
+++ b/cipher/md.c
@@ -671,6 +671,9 @@ prepare_macpads (gcry_md_hd_t a, const unsigned char *key, size_t keylen)
   if (!a->ctx->list)
     return GPG_ERR_DIGEST_ALGO; /* Might happen if no algo is enabled.  */
 
+  if (!a->ctx->flags.hmac)
+    return GPG_ERR_DIGEST_ALGO; /* Tried setkey for non-HMAC md. */
+
   for (r = a->ctx->list; r; r = r->next)
     {
       const unsigned char *k;

-----------------------------------------------------------------------

Summary of changes:
 cipher/crc.c          |   8 +-
 cipher/gostr3411-94.c |   4 +-
 cipher/hash-common.c  |  28 ++-
 cipher/keccak.c       | 283 +++++++++++++++++++++---
 cipher/md.c           |  72 ++++++-
 cipher/md2.c          |   2 +-
 cipher/md4.c          |   2 +-
 cipher/md5.c          |   2 +-
 cipher/rmd160.c       |   2 +-
 cipher/sha1.c         |   2 +-
 cipher/sha256.c       |   4 +-
 cipher/sha512.c       |   4 +-
 cipher/stribog.c      |   2 +
 cipher/tiger.c        |   6 +-
 cipher/whirlpool.c    |   2 +-
 doc/gcrypt.texi       |  84 +++++++-
 src/cipher-proto.h    |   4 +
 src/cipher.h          |   2 +
 src/gcrypt-int.h      |   2 +
 src/gcrypt.h.in       |  13 +-
 src/libgcrypt.def     |   1 +
 src/libgcrypt.vers    |   2 +-
 src/visibility.c      |   6 +
 src/visibility.h      |   2 +
 tests/basic.c         | 586 ++++++++++++++++++++++++++++++++++++++++++++++++--
 tests/bench-slope.c   |   6 +
 26 files changed, 1040 insertions(+), 91 deletions(-)


hooks/post-receive
-- 
The GNU crypto library
http://git.gnupg.org


_______________________________________________
Gnupg-commits mailing list
Gnupg-commits at gnupg.org
http://lists.gnupg.org/mailman/listinfo/gnupg-commits




More information about the Gcrypt-devel mailing list