[git] GCRYPT - branch, LIBGCRYPT-1-6-BRANCH, updated. libgcrypt-1.6.0-11-g77f2879
by Werner Koch
cvs at cvs.gnupg.org
Mon Jan 20 10:08:23 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, LIBGCRYPT-1-6-BRANCH has been updated
via 77f28793481d1f41755242377164e4caaa1d106d (commit)
from ead3a097a9ee5908e562e6ec683707c38191acf3 (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 77f28793481d1f41755242377164e4caaa1d106d
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
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>
(cherry picked from commit 94030e44aaff805d754e368507f16dd51a531b72)
Reolved conflicts:
NEWS
cipher/whirlpool.c: Remove NBLOCKS arg from whirlpool_transform.
diff --git a/NEWS b/NEWS
index 97fb089..9c3df10 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,12 @@ Noteworthy changes in version 1.6.1 (unreleased)
* Fix build problem on NetBSD.
+ * Add emulation for broken Whirlpool code prior to 1.6.0.
+
+ * Interface changes relative to the 1.6.0 release:
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ 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 1267216..5486964 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);
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 1b59765..22da30a 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.
*
@@ -94,9 +94,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. */
@@ -270,9 +273,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;
@@ -316,7 +321,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)
{
@@ -372,13 +378,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;
@@ -424,7 +429,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);
@@ -439,7 +444,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);
}
}
@@ -468,7 +474,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));
@@ -506,7 +512,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));
@@ -561,12 +567,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 */
@@ -643,7 +650,7 @@ md_final (gcry_md_hd_t a)
{
GcryDigestEntry *r;
- if (a->ctx->finalized)
+ if (a->ctx->flags.finalized)
return;
if (a->bufpos)
@@ -652,7 +659,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)
{
@@ -661,8 +668,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,
@@ -865,7 +875,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)));
@@ -926,7 +936,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;
@@ -1159,7 +1169,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 b9a1a95..624ae99 100644
--- a/cipher/md4.c
+++ b/cipher/md4.c
@@ -69,10 +69,12 @@ static unsigned int
transform ( void *c, const unsigned char *data );
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 79b6e87..b0187c9 100644
--- a/cipher/md5.c
+++ b/cipher/md5.c
@@ -53,10 +53,12 @@ static unsigned int
transform ( void *ctx, const unsigned char *data );
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 a6d9a80..08e8cb0 100644
--- a/cipher/rmd160.c
+++ b/cipher/rmd160.c
@@ -143,11 +143,13 @@
static unsigned int
transform ( void *ctx, const unsigned char *data );
-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
@@ -512,6 +520,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 18b6daa..2e0b030 100644
--- a/cipher/sha1.c
+++ b/cipher/sha1.c
@@ -74,10 +74,12 @@ transform (void *c, const unsigned char *data);
static void
-sha1_init (void *context)
+sha1_init (void *context, unsigned int flags)
{
SHA1_CONTEXT *hd = context;
+ (void)flags;
+
hd->h0 = 0x67452301;
hd->h1 = 0xefcdab89;
hd->h2 = 0x98badcfe;
@@ -337,7 +339,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);
@@ -350,7 +352,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 f3c1d62..d92303c 100644
--- a/cipher/sha256.c
+++ b/cipher/sha256.c
@@ -70,10 +70,12 @@ transform (void *c, const unsigned char *data);
static void
-sha256_init (void *context)
+sha256_init (void *context, unsigned int flags)
{
SHA256_CONTEXT *hd = context;
+ (void)flags;
+
hd->h0 = 0x6a09e667;
hd->h1 = 0xbb67ae85;
hd->h2 = 0x3c6ef372;
@@ -96,10 +98,12 @@ sha256_init (void *context)
static void
-sha224_init (void *context)
+sha224_init (void *context, unsigned int flags)
{
SHA256_CONTEXT *hd = context;
+ (void)flags;
+
hd->h0 = 0xc1059ed8;
hd->h1 = 0x367cd507;
hd->h2 = 0x3070dd17;
diff --git a/cipher/sha512.c b/cipher/sha512.c
index 586c809..26ed031 100644
--- a/cipher/sha512.c
+++ b/cipher/sha512.c
@@ -119,12 +119,14 @@ static unsigned int
transform (void *context, const unsigned char *data);
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 a3cab36..297b64a 100644
--- a/cipher/stribog.c
+++ b/cipher/stribog.c
@@ -1198,10 +1198,12 @@ transform64 (void *context, const unsigned char *inbuf_arg);
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 e562781..338d44e 100644
--- a/cipher/whirlpool.c
+++ b/cipher/whirlpool.c
@@ -46,7 +46,7 @@
/* Number of rounds. */
#define R 10
-
+
/* Types. */
typedef u64 whirlpool_block_t[BLOCK_SIZE / 8];
@@ -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;
@@ -1158,25 +1163,8 @@ static const u64 C7[256] =
U64_C (0xf8c7f8933fed6bf8), U64_C (0x86228644a411c286),
};
-
-
-static unsigned int
-whirlpool_transform (void *ctx, const unsigned char *data);
-
-static void
-whirlpool_init (void *ctx)
-{
- whirlpool_context_t *context = ctx;
-
- memset (context, 0, sizeof (*context));
-
- context->bctx.blocksize = BLOCK_SIZE;
- context->bctx.bwrite = whirlpool_transform;
-}
-
-
/*
* Transform block.
*/
@@ -1280,15 +1268,139 @@ whirlpool_transform (void *ctx, const unsigned char *data)
4 * sizeof(void*);
}
+
+static void
+whirlpool_init (void *ctx, unsigned int flags)
+{
+ whirlpool_context_t *context = ctx;
+
+ memset (context, 0, sizeof (*context));
+
+ 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;
+}
+
+
+/* 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);
+ 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);
+ 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
@@ -1299,6 +1411,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 7af1706..c2534a2 100644
--- a/doc/gcrypt.texi
+++ b/doc/gcrypt.texi
@@ -3194,6 +3194,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 5c771e5..9e94e87 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 0eb8215..97276d0 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");
}
-----------------------------------------------------------------------
Summary of changes:
NEWS | 6 ++
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 | 160 ++++++++++++++++++++++++++++++++++++++++++-------
doc/gcrypt.texi | 16 +++++
src/cipher-proto.h | 2 +-
src/gcrypt.h.in | 3 +-
tests/basic.c | 53 ++++++++++++++++
16 files changed, 305 insertions(+), 65 deletions(-)
hooks/post-receive
--
The GNU crypto library
http://git.gnupg.org
More information about the Gnupg-commits
mailing list