diff options
author | Jussi Kivilinna <jussi.kivilinna@iki.fi> | 2013-09-21 13:54:38 +0300 |
---|---|---|
committer | Jussi Kivilinna <jussi.kivilinna@iki.fi> | 2013-09-30 20:04:52 +0300 |
commit | 10d7351411f19bb2c03d2e24ca5a38dabe45023b (patch) | |
tree | ebd5ccd8cd988dba1f672113d0e6372757cfece0 /cipher/whirlpool.c | |
parent | d2076f27bb7c5d505abf25fc622d21794c4a5df3 (diff) | |
download | libgcrypt-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.c | 58 |
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); } |