summaryrefslogtreecommitdiff
path: root/cipher/whirlpool.c
diff options
context:
space:
mode:
authorJussi Kivilinna <jussi.kivilinna@iki.fi>2013-09-21 13:54:38 +0300
committerJussi Kivilinna <jussi.kivilinna@iki.fi>2013-09-30 20:04:52 +0300
commit10d7351411f19bb2c03d2e24ca5a38dabe45023b (patch)
treeebd5ccd8cd988dba1f672113d0e6372757cfece0 /cipher/whirlpool.c
parentd2076f27bb7c5d505abf25fc622d21794c4a5df3 (diff)
downloadlibgcrypt-10d7351411f19bb2c03d2e24ca5a38dabe45023b.tar.gz
whirlpool: do bitcount calculation in finalization part
* cipher/whirlpool.c (whirlpool_context_t): Remove 'length', add 'nblocks'. (whirlpool_add): Update 'nblocks' instead of 'length', and add early return at one spot. (whirlpool_write): Check for 'nblocks' overflow. (whirlpool_final): Convert 'nblocks' to bit-counter, and use whirlpool_write instead of whirlpool_add. -- Currently Whirlpool uses large 256 bit counter that is increased in the 'write' function. However, we could to bit counter calculation as is done in all the rest hash algorithms; use 64-bit block counter that is converted to bit counter in finalization function. This change does limit amount of bytes Whirlpool can process before overflowing bit counter. With 256-bit counter, overflow happens after ~1.3e67 gigabytes. With 64-bit block counter, overflow happens just after ~1.1e12 gigabytes. Patch keeps the old behaviour of halting if counter overflows. Main benefit for this patch is that after this change, we can use the _gcry_md_block_write helper for Whirlpool too. Signed-off-by: Jussi Kivilinna <jussi.kivilinna@iki.fi>
Diffstat (limited to 'cipher/whirlpool.c')
-rw-r--r--cipher/whirlpool.c58
1 files changed, 33 insertions, 25 deletions
diff --git a/cipher/whirlpool.c b/cipher/whirlpool.c
index 954640ac..1ee89162 100644
--- a/cipher/whirlpool.c
+++ b/cipher/whirlpool.c
@@ -54,7 +54,7 @@ typedef struct {
whirlpool_block_t hash_state;
unsigned char buffer[BLOCK_SIZE];
size_t count;
- unsigned char length[32];
+ u64 nblocks;
} whirlpool_context_t;
@@ -1274,11 +1274,6 @@ whirlpool_add (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->count == BLOCK_SIZE)
{
@@ -1286,6 +1281,7 @@ whirlpool_add (whirlpool_context_t *context,
whirlpool_transform (context, context->buffer);
/*_gcry_burn_stack (80+6*sizeof(void*));*/ /* FIXME */
context->count = 0;
+ context->nblocks++;
}
if (! buffer)
return; /* Nothing to add. */
@@ -1298,6 +1294,9 @@ whirlpool_add (whirlpool_context_t *context,
buffer_n--;
}
whirlpool_add (context, NULL, 0);
+ /* Can return early now that bit counter calculation is done in final. */
+ if (!buffer_n)
+ return;
}
/*_gcry_burn_stack (80+6*sizeof(void*));*/ /* FIXME */
@@ -1305,6 +1304,7 @@ whirlpool_add (whirlpool_context_t *context,
{
whirlpool_transform (context, buffer);
context->count = 0;
+ context->nblocks++;
buffer_n -= BLOCK_SIZE;
buffer += BLOCK_SIZE;
}
@@ -1313,29 +1313,17 @@ whirlpool_add (whirlpool_context_t *context,
context->buffer[context->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->length[32 - i] + (buffer_size & 0xFF);
- context->length[32 - i] = carry;
- buffer_size >>= 8;
- carry >>= 8;
- }
- gcry_assert (! (buffer_size || carry));
}
static void
whirlpool_write (void *ctx, const void *buffer, size_t buffer_n)
{
whirlpool_context_t *context = ctx;
+ u64 old_nblocks = context->nblocks;
whirlpool_add (context, buffer, buffer_n);
+
+ gcry_assert (old_nblocks <= context->nblocks);
}
static void
@@ -1343,9 +1331,25 @@ whirlpool_final (void *ctx)
{
whirlpool_context_t *context = ctx;
unsigned int i;
+ u64 t, lsb, msb;
+ unsigned char *length;
+
+ t = context->nblocks;
+ /* multiply by 64 to make a byte count */
+ lsb = t << 6;
+ msb = t >> 58;
+ /* add the count */
+ t = lsb;
+ if ((lsb += context->count) < t)
+ msb++;
+ /* multiply by 8 to make a bit count */
+ t = lsb;
+ lsb <<= 3;
+ msb <<= 3;
+ msb |= t >> 61;
/* Flush. */
- whirlpool_add (context, NULL, 0);
+ whirlpool_write (context, NULL, 0);
/* Pad. */
context->buffer[context->count++] = 0x80;
@@ -1355,15 +1359,19 @@ whirlpool_final (void *ctx)
/* An extra block is necessary. */
while (context->count < 64)
context->buffer[context->count++] = 0;
- whirlpool_add (context, NULL, 0);
+ whirlpool_write (context, NULL, 0);
}
while (context->count < 32)
context->buffer[context->count++] = 0;
/* Add length of message. */
- memcpy (context->buffer + context->count, context->length, 32);
+ length = context->buffer + context->count;
+ buf_put_be64(&length[0 * 8], 0);
+ buf_put_be64(&length[1 * 8], 0);
+ buf_put_be64(&length[2 * 8], msb);
+ buf_put_be64(&length[3 * 8], lsb);
context->count += 32;
- whirlpool_add (context, NULL, 0);
+ whirlpool_write (context, NULL, 0);
block_to_buffer (context->buffer, context->hash_state, i);
}