[PATCH 1/3] whirlpool: do bitcount calculation in finalization part
Jussi Kivilinna
jussi.kivilinna at iki.fi
Thu Sep 19 20:16:13 CEST 2013
* 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.
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 at iki.fi>
---
cipher/whirlpool.c | 58 ++++++++++++++++++++++++++++++----------------------
1 file changed, 33 insertions(+), 25 deletions(-)
diff --git a/cipher/whirlpool.c b/cipher/whirlpool.c
index 954640a..1ee8916 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);
}
More information about the Gcrypt-devel
mailing list