[git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-37-g94030e4

by Werner Koch cvs at cvs.gnupg.org
Sun Jan 19 15:15:14 CET 2014


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  94030e44aaff805d754e368507f16dd51a531b72 (commit)
       via  c3b30bae7d1e157f8b65e32ba1b3a516f2bbf58b (commit)
      from  cfc151ba637200e4fc05d9481a8df2071b2f9a47 (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 94030e44aaff805d754e368507f16dd51a531b72
Author: Werner Koch <wk at gnupg.org>
Date:   Thu Jan 9 19:14:09 2014 +0100

    md: Add Whirlpool bug emulation feature.
    
    * src/gcrypt.h.in (GCRY_MD_FLAG_BUGEMU1): New.
    * src/cipher-proto.h (gcry_md_init_t): Add arg FLAGS.  Change all code
    to implement that flag.
    * cipher/md.c (gcry_md_context):  Replace SECURE and FINALIZED by bit
    field FLAGS.  Add flag BUGEMU1.  Change all users.
    (md_open): Replace args SECURE and HMAC by FLAGS.  Init flags.bugemu1.
    (_gcry_md_open): Add for GCRY_MD_FLAG_BUGEMU1.
    (md_enable): Pass bugemu1 flag to the hash init function.
    (_gcry_md_reset): Ditto.
    --
    
    This problem is for example exhibited in the Linux cryptsetup tool.
    See https://bbs.archlinux.org/viewtopic.php?id=175737 .  It has be
    been tracked down by Milan Broz.
    
    The suggested way of using the flag is:
    
      if (whirlpool_bug_assumed)
        {
    #if GCRYPT_VERSION_NUMBER >= 0x010601
          err = gcry_md_open (&hd, GCRY_MD_WHIRLPOOL, GCRY_MD_FLAG_BUGEMU1)
          if (gpg_err_code (err) == GPG_ERR_INV_ARG)
             error ("Need at least Libggcrypt 1.6.1 for the fix");
          else
             {
                do_hash (hd);
                gcry_md_close (hd);
              }
    #endif
        }
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/NEWS b/NEWS
index 4bf4a06..5e21eb6 100644
--- a/NEWS
+++ b/NEWS
@@ -8,10 +8,13 @@ Noteworthy changes in version 1.7.0 (unreleased)
 
  * Support curves GOST R 34.10-2001 and GOST R 34.10-2012.
 
+ * Add emulation from broken Whirlpool code prior to 1.6.0.
+
  * Interface changes relative to the 1.6.0 release:
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  gcry_mac_get_algo               NEW.
  GCRY_MAC_HMAC_MD2               NEW.
+ GCRY_MD_FLAG_BUGEMU1            NEW.
 
 
 Noteworthy changes in version 1.6.0 (2013-12-16)
diff --git a/cipher/crc.c b/cipher/crc.c
index 4f72ffb..1322f0d 100644
--- a/cipher/crc.c
+++ b/cipher/crc.c
@@ -149,9 +149,12 @@ CRC_CONTEXT;
 /* CRC32 */
 
 static void
-crc32_init (void *context)
+crc32_init (void *context, unsigned int flags)
 {
   CRC_CONTEXT *ctx = (CRC_CONTEXT *) context;
+
+  (void)flags;
+
   ctx->CRC = 0 ^ 0xffffffffL;
 }
 
@@ -184,9 +187,12 @@ crc32_final (void *context)
 
 /* CRC32 a'la RFC 1510 */
 static void
-crc32rfc1510_init (void *context)
+crc32rfc1510_init (void *context, unsigned int flags)
 {
   CRC_CONTEXT *ctx = (CRC_CONTEXT *) context;
+
+  (void)flags;
+
   ctx->CRC = 0;
 }
 
@@ -237,9 +243,12 @@ crc32rfc1510_final (void *context)
 #define CRC24_POLY 0x1864cfbL
 
 static void
-crc24rfc2440_init (void *context)
+crc24rfc2440_init (void *context, unsigned int flags)
 {
   CRC_CONTEXT *ctx = (CRC_CONTEXT *) context;
+
+  (void)flags;
+
   ctx->CRC = CRC24_INIT;
 }
 
diff --git a/cipher/gostr3411-94.c b/cipher/gostr3411-94.c
index b3326aa..9a39733 100644
--- a/cipher/gostr3411-94.c
+++ b/cipher/gostr3411-94.c
@@ -44,10 +44,12 @@ static unsigned int
 transform (void *c, const unsigned char *data, size_t nblks);
 
 static void
-gost3411_init (void *context)
+gost3411_init (void *context, unsigned int flags)
 {
   GOSTR3411_CONTEXT *hd = context;
 
+  (void)flags;
+
   memset (&hd->hd, 0, sizeof(hd->hd));
   memset (hd->h, 0, 32);
   memset (hd->sigma, 0, 32);
diff --git a/cipher/md.c b/cipher/md.c
index f4fb129..a332e03 100644
--- a/cipher/md.c
+++ b/cipher/md.c
@@ -1,7 +1,7 @@
 /* md.c  -  message digest dispatcher
  * Copyright (C) 1998, 1999, 2002, 2003, 2006,
  *               2008 Free Software Foundation, Inc.
- * Copyright (C) 2013 g10 Code GmbH
+ * Copyright (C) 2013, 2014 g10 Code GmbH
  *
  * This file is part of Libgcrypt.
  *
@@ -93,9 +93,12 @@ struct gcry_md_context
 {
   int  magic;
   size_t actual_handle_size;     /* Allocated size of this handle. */
-  int  secure;
   FILE  *debug;
-  int finalized;
+  struct {
+    unsigned int secure: 1;
+    unsigned int finalized:1;
+    unsigned int bugemu1:1;
+  } flags;
   GcryDigestEntry *list;
   byte *macpads;
   int macpads_Bsize;             /* Blocksize as used for the HMAC pads. */
@@ -269,9 +272,11 @@ check_digest_algo (int algorithm)
  * may be 0.
  */
 static gcry_err_code_t
-md_open (gcry_md_hd_t *h, int algo, int secure, int hmac)
+md_open (gcry_md_hd_t *h, int algo, unsigned int flags)
 {
-  gcry_err_code_t err = GPG_ERR_NO_ERROR;
+  gcry_err_code_t err = 0;
+  int secure = !!(flags & GCRY_MD_FLAG_SECURE);
+  int hmac =   !!(flags & GCRY_MD_FLAG_HMAC);
   int bufsize = secure ? 512 : 1024;
   struct gcry_md_context *ctx;
   gcry_md_hd_t hd;
@@ -315,7 +320,8 @@ md_open (gcry_md_hd_t *h, int algo, int secure, int hmac)
       memset (hd->ctx, 0, sizeof *hd->ctx);
       ctx->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL;
       ctx->actual_handle_size = n + sizeof (struct gcry_md_context);
-      ctx->secure = secure;
+      ctx->flags.secure = secure;
+      ctx->flags.bugemu1 = !!(flags & GCRY_MD_FLAG_BUGEMU1);
 
       if (hmac)
 	{
@@ -371,13 +377,12 @@ _gcry_md_open (gcry_md_hd_t *h, int algo, unsigned int flags)
   gcry_err_code_t rc;
   gcry_md_hd_t hd;
 
-  if ((flags & ~(GCRY_MD_FLAG_SECURE | GCRY_MD_FLAG_HMAC)))
+  if ((flags & ~(GCRY_MD_FLAG_SECURE
+                 | GCRY_MD_FLAG_HMAC
+                 | GCRY_MD_FLAG_BUGEMU1)))
     rc = GPG_ERR_INV_ARG;
   else
-    {
-      rc = md_open (&hd, algo, (flags & GCRY_MD_FLAG_SECURE),
-                    (flags & GCRY_MD_FLAG_HMAC));
-    }
+    rc = md_open (&hd, algo, flags);
 
   *h = rc? NULL : hd;
   return rc;
@@ -423,7 +428,7 @@ md_enable (gcry_md_hd_t hd, int algorithm)
                      - sizeof (entry->context));
 
       /* And allocate a new list entry. */
-      if (h->secure)
+      if (h->flags.secure)
 	entry = xtrymalloc_secure (size);
       else
 	entry = xtrymalloc (size);
@@ -438,7 +443,8 @@ md_enable (gcry_md_hd_t hd, int algorithm)
 	  h->list = entry;
 
 	  /* And init this instance. */
-	  entry->spec->init (&entry->context.c);
+	  entry->spec->init (&entry->context.c,
+                             h->flags.bugemu1? GCRY_MD_FLAG_BUGEMU1:0);
 	}
     }
 
@@ -467,7 +473,7 @@ md_copy (gcry_md_hd_t ahd, gcry_md_hd_t *b_hd)
     md_write (ahd, NULL, 0);
 
   n = (char *) ahd->ctx - (char *) ahd;
-  if (a->secure)
+  if (a->flags.secure)
     bhd = xtrymalloc_secure (n + sizeof (struct gcry_md_context));
   else
     bhd = xtrymalloc (n + sizeof (struct gcry_md_context));
@@ -505,7 +511,7 @@ md_copy (gcry_md_hd_t ahd, gcry_md_hd_t *b_hd)
     {
       for (ar = a->list; ar; ar = ar->next)
         {
-          if (a->secure)
+          if (a->flags.secure)
             br = xtrymalloc_secure (sizeof *br
                                     + ar->spec->contextsize
                                     - sizeof(ar->context));
@@ -560,12 +566,13 @@ _gcry_md_reset (gcry_md_hd_t a)
 
   /* Note: We allow this even in fips non operational mode.  */
 
-  a->bufpos = a->ctx->finalized = 0;
+  a->bufpos = a->ctx->flags.finalized = 0;
 
   for (r = a->ctx->list; r; r = r->next)
     {
       memset (r->context.c, 0, r->spec->contextsize);
-      (*r->spec->init) (&r->context.c);
+      (*r->spec->init) (&r->context.c,
+                        a->ctx->flags.bugemu1? GCRY_MD_FLAG_BUGEMU1:0);
     }
   if (a->ctx->macpads)
     md_write (a, a->ctx->macpads, a->ctx->macpads_Bsize); /* inner pad */
@@ -642,7 +649,7 @@ md_final (gcry_md_hd_t a)
 {
   GcryDigestEntry *r;
 
-  if (a->ctx->finalized)
+  if (a->ctx->flags.finalized)
     return;
 
   if (a->bufpos)
@@ -651,7 +658,7 @@ md_final (gcry_md_hd_t a)
   for (r = a->ctx->list; r; r = r->next)
     (*r->spec->final) (&r->context.c);
 
-  a->ctx->finalized = 1;
+  a->ctx->flags.finalized = 1;
 
   if (a->ctx->macpads)
     {
@@ -660,8 +667,11 @@ md_final (gcry_md_hd_t a)
       byte *p = md_read (a, algo);
       size_t dlen = md_digest_length (algo);
       gcry_md_hd_t om;
-      gcry_err_code_t err = md_open (&om, algo, a->ctx->secure, 0);
+      gcry_err_code_t err;
 
+      err = md_open (&om, algo,
+                     ((a->ctx->flags.secure? GCRY_MD_FLAG_SECURE:0)
+                      | (a->ctx->flags.bugemu1? GCRY_MD_FLAG_BUGEMU1:0)));
       if (err)
 	_gcry_fatal_error (err, NULL);
       md_write (om,
@@ -864,7 +874,7 @@ _gcry_md_hash_buffer (int algo, void *digest,
             }
         }
 
-      err = md_open (&h, algo, 0, 0);
+      err = md_open (&h, algo, 0);
       if (err)
 	log_bug ("gcry_md_open failed for algo %d: %s",
                  algo, gpg_strerror (gcry_error(err)));
@@ -925,7 +935,7 @@ _gcry_md_hash_buffers (int algo, unsigned int flags, void *digest,
             }
         }
 
-      rc = md_open (&h, algo, 0, hmac);
+      rc = md_open (&h, algo, (hmac? GCRY_MD_FLAG_HMAC:0));
       if (rc)
         return rc;
 
@@ -1158,7 +1168,7 @@ _gcry_md_info (gcry_md_hd_t h, int cmd, void *buffer, size_t *nbytes)
   switch (cmd)
     {
     case GCRYCTL_IS_SECURE:
-      *nbytes = h->ctx->secure;
+      *nbytes = h->ctx->flags.secure;
       break;
 
     case GCRYCTL_IS_ALGO_ENABLED:
diff --git a/cipher/md4.c b/cipher/md4.c
index 40dc058..7291254 100644
--- a/cipher/md4.c
+++ b/cipher/md4.c
@@ -69,10 +69,12 @@ static unsigned int
 transform ( void *c, const unsigned char *data, size_t nblks );
 
 static void
-md4_init( void *context )
+md4_init (void *context, unsigned int flags)
 {
   MD4_CONTEXT *ctx = context;
 
+  (void)flags;
+
   ctx->A = 0x67452301;
   ctx->B = 0xefcdab89;
   ctx->C = 0x98badcfe;
diff --git a/cipher/md5.c b/cipher/md5.c
index d06d3f7..73ad968 100644
--- a/cipher/md5.c
+++ b/cipher/md5.c
@@ -53,10 +53,12 @@ static unsigned int
 transform ( void *ctx, const unsigned char *data, size_t datalen );
 
 static void
-md5_init( void *context )
+md5_init( void *context, unsigned int flags)
 {
   MD5_CONTEXT *ctx = context;
 
+  (void)flags;
+
   ctx->A = 0x67452301;
   ctx->B = 0xefcdab89;
   ctx->C = 0x98badcfe;
diff --git a/cipher/rmd160.c b/cipher/rmd160.c
index 224694f..1a58ba6 100644
--- a/cipher/rmd160.c
+++ b/cipher/rmd160.c
@@ -143,11 +143,13 @@
 static unsigned int
 transform ( void *ctx, const unsigned char *data, size_t nblks );
 
-void
-_gcry_rmd160_init (void *context)
+static void
+rmd160_init (void *context, unsigned int flags)
 {
   RMD160_CONTEXT *hd = context;
 
+  (void)flags;
+
   hd->h0 = 0x67452301;
   hd->h1 = 0xEFCDAB89;
   hd->h2 = 0x98BADCFE;
@@ -162,6 +164,12 @@ _gcry_rmd160_init (void *context)
 }
 
 
+void
+_gcry_rmd160_init (void *context)
+{
+  rmd160_init (context, 0);
+}
+
 
 /****************
  * Transform the message X which consists of 16 32-bit-words
@@ -528,6 +536,6 @@ gcry_md_spec_t _gcry_digest_spec_rmd160 =
   {
     GCRY_MD_RMD160, {0, 0},
     "RIPEMD160", asn, DIM (asn), oid_spec_rmd160, 20,
-    _gcry_rmd160_init, _gcry_md_block_write, rmd160_final, rmd160_read,
+    rmd160_init, _gcry_md_block_write, rmd160_final, rmd160_read,
     sizeof (RMD160_CONTEXT)
   };
diff --git a/cipher/sha1.c b/cipher/sha1.c
index 889a7ea..65bd686 100644
--- a/cipher/sha1.c
+++ b/cipher/sha1.c
@@ -106,11 +106,13 @@ transform (void *c, const unsigned char *data, size_t nblks);
 
 
 static void
-sha1_init (void *context)
+sha1_init (void *context, unsigned int flags)
 {
   SHA1_CONTEXT *hd = context;
   unsigned int features = _gcry_get_hw_features ();
 
+  (void)flags;
+
   hd->h0 = 0x67452301;
   hd->h1 = 0xefcdab89;
   hd->h2 = 0x98badcfe;
@@ -425,7 +427,7 @@ _gcry_sha1_hash_buffer (void *outbuf, const void *buffer, size_t length)
 {
   SHA1_CONTEXT hd;
 
-  sha1_init (&hd);
+  sha1_init (&hd, 0);
   _gcry_md_block_write (&hd, buffer, length);
   sha1_final (&hd);
   memcpy (outbuf, hd.bctx.buf, 20);
@@ -438,7 +440,7 @@ _gcry_sha1_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt)
 {
   SHA1_CONTEXT hd;
 
-  sha1_init (&hd);
+  sha1_init (&hd, 0);
   for (;iovcnt > 0; iov++, iovcnt--)
     _gcry_md_block_write (&hd,
                           (const char*)iov[0].data + iov[0].off, iov[0].len);
diff --git a/cipher/sha256.c b/cipher/sha256.c
index 601e9c0..4efaec6 100644
--- a/cipher/sha256.c
+++ b/cipher/sha256.c
@@ -92,11 +92,13 @@ transform (void *c, const unsigned char *data, size_t nblks);
 
 
 static void
-sha256_init (void *context)
+sha256_init (void *context, unsigned int flags)
 {
   SHA256_CONTEXT *hd = context;
   unsigned int features = _gcry_get_hw_features ();
 
+  (void)flags;
+
   hd->h0 = 0x6a09e667;
   hd->h1 = 0xbb67ae85;
   hd->h2 = 0x3c6ef372;
@@ -128,11 +130,13 @@ sha256_init (void *context)
 
 
 static void
-sha224_init (void *context)
+sha224_init (void *context, unsigned int flags)
 {
   SHA256_CONTEXT *hd = context;
   unsigned int features = _gcry_get_hw_features ();
 
+  (void)flags;
+
   hd->h0 = 0xc1059ed8;
   hd->h1 = 0x367cd507;
   hd->h2 = 0x3070dd17;
diff --git a/cipher/sha512.c b/cipher/sha512.c
index 3474694..92b4913 100644
--- a/cipher/sha512.c
+++ b/cipher/sha512.c
@@ -119,12 +119,14 @@ static unsigned int
 transform (void *context, const unsigned char *data, size_t nblks);
 
 static void
-sha512_init (void *context)
+sha512_init (void *context, unsigned int flags)
 {
   SHA512_CONTEXT *ctx = context;
   SHA512_STATE *hd = &ctx->state;
   unsigned int features = _gcry_get_hw_features ();
 
+  (void)flags;
+
   hd->h0 = U64_C(0x6a09e667f3bcc908);
   hd->h1 = U64_C(0xbb67ae8584caa73b);
   hd->h2 = U64_C(0x3c6ef372fe94f82b);
@@ -157,12 +159,14 @@ sha512_init (void *context)
 }
 
 static void
-sha384_init (void *context)
+sha384_init (void *context, unsigned int flags)
 {
   SHA512_CONTEXT *ctx = context;
   SHA512_STATE *hd = &ctx->state;
   unsigned int features = _gcry_get_hw_features ();
 
+  (void)flags;
+
   hd->h0 = U64_C(0xcbbb9d5dc1059ed8);
   hd->h1 = U64_C(0x629a292a367cd507);
   hd->h2 = U64_C(0x9159015a3070dd17);
diff --git a/cipher/stribog.c b/cipher/stribog.c
index 6d1d342..942bbf4 100644
--- a/cipher/stribog.c
+++ b/cipher/stribog.c
@@ -1198,10 +1198,12 @@ transform (void *context, const unsigned char *inbuf_arg, size_t datalen);
 
 
 static void
-stribog_init_512 (void *context)
+stribog_init_512 (void *context, unsigned int flags)
 {
   STRIBOG_CONTEXT *hd = context;
 
+  (void)flags;
+
   memset (hd, 0, sizeof (*hd));
 
   hd->bctx.blocksize = 64;
@@ -1209,10 +1211,11 @@ stribog_init_512 (void *context)
 }
 
 static void
-stribog_init_256 (void *context)
+stribog_init_256 (void *context, unsigned int flags)
 {
   STRIBOG_CONTEXT *hd = context;
-  stribog_init_512 (context);
+
+  stribog_init_512 (context, flags);
   memset (hd->h, 1, 64);
 }
 
diff --git a/cipher/whirlpool.c b/cipher/whirlpool.c
index 57ca882..ffc6662 100644
--- a/cipher/whirlpool.c
+++ b/cipher/whirlpool.c
@@ -54,6 +54,11 @@ typedef u64 whirlpool_block_t[BLOCK_SIZE / 8];
 typedef struct {
   gcry_md_block_ctx_t bctx;
   whirlpool_block_t hash_state;
+  int use_bugemu;
+  struct {
+    size_t count;
+    unsigned char length[32];
+  } bugemu;
 } whirlpool_context_t;
 
 
@@ -1166,7 +1171,7 @@ whirlpool_transform (void *ctx, const unsigned char *data, size_t nblks);
 
 
 static void
-whirlpool_init (void *ctx)
+whirlpool_init (void *ctx, unsigned int flags)
 {
   whirlpool_context_t *context = ctx;
 
@@ -1174,9 +1179,17 @@ whirlpool_init (void *ctx)
 
   context->bctx.blocksize = BLOCK_SIZE;
   context->bctx.bwrite = whirlpool_transform;
+  if ((flags & GCRY_MD_FLAG_BUGEMU1))
+    {
+      memset (&context->bugemu, 0, sizeof context->bugemu);
+      context->use_bugemu = 1;
+    }
+  else
+    context->use_bugemu = 0;
 }
 
 
+
 /*
  * Transform block.
  */
@@ -1295,15 +1308,120 @@ whirlpool_transform ( void *c, const unsigned char *data, size_t nblks )
   return burn;
 }
 
+
+/* Bug compatibility Whirlpool version.  */
+static void
+whirlpool_add_bugemu (whirlpool_context_t *context,
+                      const void *buffer_arg, size_t buffer_n)
+{
+  const unsigned char *buffer = buffer_arg;
+  u64 buffer_size;
+  unsigned int carry;
+  unsigned int i;
+
+  buffer_size = buffer_n;
+
+  if (context->bugemu.count == BLOCK_SIZE)
+    {
+      /* Flush the buffer.  */
+      whirlpool_transform (context, context->bctx.buf, 1);
+      context->bugemu.count = 0;
+    }
+  if (! buffer)
+    return; /* Nothing to add.  */
+
+  if (context->bugemu.count)
+    {
+      while (buffer_n && (context->bugemu.count < BLOCK_SIZE))
+	{
+	  context->bctx.buf[context->bugemu.count++] = *buffer++;
+	  buffer_n--;
+	}
+      whirlpool_add_bugemu (context, NULL, 0);
+      if (!buffer_n)
+        return; /* Done.  This is the bug we emulate.  */
+    }
+
+  while (buffer_n >= BLOCK_SIZE)
+    {
+      whirlpool_transform (context, buffer, 1);
+      context->bugemu.count = 0;
+      buffer_n -= BLOCK_SIZE;
+      buffer += BLOCK_SIZE;
+    }
+  while (buffer_n && (context->bugemu.count < BLOCK_SIZE))
+    {
+      context->bctx.buf[context->bugemu.count++] = *buffer++;
+      buffer_n--;
+    }
+
+  /* Update bit counter.  */
+  carry = 0;
+  buffer_size <<= 3;
+  for (i = 1; i <= 32; i++)
+    {
+      if (! (buffer_size || carry))
+	break;
+
+      carry += context->bugemu.length[32 - i] + (buffer_size & 0xFF);
+      context->bugemu.length[32 - i] = carry;
+      buffer_size >>= 8;
+      carry >>= 8;
+    }
+  gcry_assert (! (buffer_size || carry));
+}
+
+
+/* Bug compatibility Whirlpool version.  */
+static void
+whirlpool_final_bugemu (void *ctx)
+{
+  whirlpool_context_t *context = ctx;
+  unsigned int i;
+
+  /* Flush.  */
+  whirlpool_add_bugemu (context, NULL, 0);
+
+  /* Pad.  */
+  context->bctx.buf[context->bugemu.count++] = 0x80;
+
+  if (context->bugemu.count > 32)
+    {
+      /* An extra block is necessary.  */
+      while (context->bugemu.count < 64)
+	context->bctx.buf[context->bugemu.count++] = 0;
+      whirlpool_add_bugemu (context, NULL, 0);
+    }
+  while (context->bugemu.count < 32)
+    context->bctx.buf[context->bugemu.count++] = 0;
+
+  /* Add length of message.  */
+  memcpy (context->bctx.buf + context->bugemu.count,
+          context->bugemu.length, 32);
+  context->bugemu.count += 32;
+  whirlpool_add_bugemu (context, NULL, 0);
+
+  block_to_buffer (context->bctx.buf, context->hash_state, i);
+}
+
+
 static void
 whirlpool_write (void *ctx, const void *buffer, size_t buffer_n)
 {
   whirlpool_context_t *context = ctx;
-  u64 old_nblocks = context->bctx.nblocks;
 
-  _gcry_md_block_write (context, buffer, buffer_n);
+  if (context->use_bugemu)
+    {
+      whirlpool_add_bugemu (context, buffer, buffer_n);
+    }
+  else
+    {
+      u64 old_nblocks = context->bctx.nblocks;
+
+      _gcry_md_block_write (context, buffer, buffer_n);
 
-  gcry_assert (old_nblocks <= context->bctx.nblocks);
+      gcry_assert (old_nblocks <= context->bctx.nblocks);
+    }
 }
 
 static void
@@ -1314,6 +1432,12 @@ whirlpool_final (void *ctx)
   u64 t, th, lsb, msb;
   unsigned char *length;
 
+  if (context->use_bugemu)
+    {
+      whirlpool_final_bugemu (ctx);
+      return;
+    }
+
   t = context->bctx.nblocks;
   /* if (sizeof t == sizeof context->bctx.nblocks) */
   th = context->bctx.nblocks_high;
diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi
index 7712b80..4a91790 100644
--- a/doc/gcrypt.texi
+++ b/doc/gcrypt.texi
@@ -3111,6 +3111,22 @@ 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}.
 
+ at item GCRY_MD_FLAG_BUGEMU1
+ at cindex bug emulation
+Versions of Libgcrypt before 1.6.0 had a bug in the Whirlpool code
+which led to a wrong result for certain input sizes and write
+patterns.  Using this flag emulates that bug.  This may for example be
+useful for applications which use Whirlpool as part of their key
+generation.  It is strongly suggested to use this flag only if really
+needed and if possible to the data should be re-processed using the
+regular Whirlpool algorithm.
+
+Note that this flag works for the entire hash context.  If needed
+arises it may be used to enable bug emulation for other hash
+algorithms.  Thus you should not use this flag for a multi-algorithm
+hash context.
+
+
 @end table
 @c begin table of hash flags
 
diff --git a/src/cipher-proto.h b/src/cipher-proto.h
index 0955ef5..8267791 100644
--- a/src/cipher-proto.h
+++ b/src/cipher-proto.h
@@ -204,7 +204,7 @@ typedef struct gcry_cipher_spec
  */
 
 /* Type for the md_init function.  */
-typedef void (*gcry_md_init_t) (void *c);
+typedef void (*gcry_md_init_t) (void *c, unsigned int flags);
 
 /* Type for the md_write function.  */
 typedef void (*gcry_md_write_t) (void *c, const void *buf, size_t nbytes);
diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in
index f8318c0..b06f259 100644
--- a/src/gcrypt.h.in
+++ b/src/gcrypt.h.in
@@ -1151,7 +1151,8 @@ enum gcry_md_algos
 enum gcry_md_flags
   {
     GCRY_MD_FLAG_SECURE = 1,  /* Allocate all buffers in "secure" memory.  */
-    GCRY_MD_FLAG_HMAC   = 2   /* Make an HMAC out of this algorithm.  */
+    GCRY_MD_FLAG_HMAC   = 2,  /* Make an HMAC out of this algorithm.  */
+    GCRY_MD_FLAG_BUGEMU1 = 0x0100
   };
 
 /* (Forward declaration.)  */
diff --git a/tests/basic.c b/tests/basic.c
index 697485e..5fd7131 100644
--- a/tests/basic.c
+++ b/tests/basic.c
@@ -4046,6 +4046,7 @@ check_digests (void)
 #endif
       {	0 }
     };
+  gcry_error_t err;
   int i;
 
   if (verbose)
@@ -4074,6 +4075,58 @@ check_digests (void)
                           algos[i].expect);
     }
 
+  /* Check the Whirlpool bug emulation.  */
+  if (!gcry_md_test_algo (GCRY_MD_WHIRLPOOL) && !in_fips_mode)
+    {
+      static const char expect[] =
+        "\x35\x28\xd6\x4c\x56\x2c\x55\x2e\x3b\x91\x93\x95\x7b\xdd\xcc\x6e"
+        "\x6f\xb7\xbf\x76\x22\x9c\xc6\x23\xda\x3e\x09\x9b\x36\xe8\x6d\x76"
+        "\x2f\x94\x3b\x0c\x63\xa0\xba\xa3\x4d\x66\x71\xe6\x5d\x26\x67\x28"
+        "\x36\x1f\x0e\x1a\x40\xf0\xce\x83\x50\x90\x1f\xfa\x3f\xed\x6f\xfd";
+      gcry_md_hd_t hd;
+      int algo = GCRY_MD_WHIRLPOOL;
+      unsigned char *p;
+      int mdlen;
+
+      err = gcry_md_open (&hd, GCRY_MD_WHIRLPOOL, GCRY_MD_FLAG_BUGEMU1);
+      if (err)
+        {
+          fail ("algo %d, gcry_md_open failed: %s\n", algo, gpg_strerror (err));
+          goto leave;
+        }
+
+      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);
+          gcry_md_close (hd);
+          goto leave;
+        }
+
+      /* Hash 62 byes in chunks.  */
+      gcry_md_write (hd, "1234567890", 10);
+      gcry_md_write (hd, "1234567890123456789012345678901234567890123456789012",
+                     52);
+
+      p = gcry_md_read (hd, algo);
+
+      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);
+        }
+
+      gcry_md_close (hd);
+    }
+
+ leave:
   if (verbose)
     fprintf (stderr, "Completed hash checks.\n");
 }

commit c3b30bae7d1e157f8b65e32ba1b3a516f2bbf58b
Author: Werner Koch <wk at gnupg.org>
Date:   Thu Jan 9 19:14:09 2014 +0100

    Actually check for uint64_t.
    
    * configure.ac: Check size of uint64_t and the UINT64_C macro.
    --
    
    configure.ac used $ac_cv_sizeof_uint64_t but never set this variable.
    Due to the availability of long long on all platforms supporting
    uint64_t this was not a real problem.  Found while remove the
    corresponding test from gnupg.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/configure.ac b/configure.ac
index 6272871..c3ab96f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -350,6 +350,15 @@ if test "$ac_cv_sizeof_unsigned_short" = "0" \
     AC_MSG_WARN([Hmmm, something is wrong with the sizes - using defaults]);
 fi
 
+# Ensure that we have UINT64_C before we bother to check for uint64_t
+AC_CACHE_CHECK([for UINT64_C],[gnupg_cv_uint64_c_works],
+   AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <inttypes.h>]],
+       [[uint64_t foo=UINT64_C(42);]])],
+     gnupg_cv_uint64_c_works=yes,gnupg_cv_uint64_c_works=no))
+if test "$gnupg_cv_uint64_c_works" = "yes" ; then
+   AC_CHECK_SIZEOF(uint64_t)
+fi
+
 # Do we have any 64-bit data types?
 if test "$ac_cv_sizeof_unsigned_int" != "8" \
    && test "$ac_cv_sizeof_unsigned_long" != "8" \

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

Summary of changes:
 NEWS                  |    3 ++
 cipher/crc.c          |   15 ++++--
 cipher/gostr3411-94.c |    4 +-
 cipher/md.c           |   56 ++++++++++++---------
 cipher/md4.c          |    4 +-
 cipher/md5.c          |    4 +-
 cipher/rmd160.c       |   14 ++++--
 cipher/sha1.c         |    8 +--
 cipher/sha256.c       |    8 ++-
 cipher/sha512.c       |    8 ++-
 cipher/stribog.c      |    9 ++--
 cipher/whirlpool.c    |  132 +++++++++++++++++++++++++++++++++++++++++++++++--
 configure.ac          |    9 ++++
 doc/gcrypt.texi       |   16 ++++++
 src/cipher-proto.h    |    2 +-
 src/gcrypt.h.in       |    3 +-
 tests/basic.c         |   53 ++++++++++++++++++++
 17 files changed, 300 insertions(+), 48 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