diff options
Diffstat (limited to 'plugins/MirOTR/Libgcrypt/cipher/whirlpool.c')
-rw-r--r-- | plugins/MirOTR/Libgcrypt/cipher/whirlpool.c | 227 |
1 files changed, 151 insertions, 76 deletions
diff --git a/plugins/MirOTR/Libgcrypt/cipher/whirlpool.c b/plugins/MirOTR/Libgcrypt/cipher/whirlpool.c index 9b029ee367..338d44e0c4 100644 --- a/plugins/MirOTR/Libgcrypt/cipher/whirlpool.c +++ b/plugins/MirOTR/Libgcrypt/cipher/whirlpool.c @@ -14,20 +14,19 @@ * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - * + * License along with this program; if not, see <http://www.gnu.org/licenses/>. */ /* This is an implementation of the Whirlpool hashing algorithm, which has been developed by Vincent Rijmen and Paulo S. L. M. Barreto; it's homepage is located at: - http://planeta.terra.com.br/informatica/paulobarreto/WhirlpoolPage.html. + http://www.larc.usp.br/~pbarreto/WhirlpoolPage.html The S-Boxes and the structure of the main transformation function, which implements an optimized version of the algorithm, is taken from the reference implementation available from - http://planeta.terra.com.br/informatica/paulobarreto/whirlpool.zip. */ + http://www.larc.usp.br/~pbarreto/whirlpool.zip + */ #include <config.h> #include <stdio.h> @@ -36,10 +35,10 @@ #include "types.h" #include "g10lib.h" -#include "memory.h" #include "cipher.h" -#include "bithelp.h" +#include "bufhelp.h" +#include "hash-common.h" /* Size of a whirlpool block (in bytes). */ #define BLOCK_SIZE 64 @@ -47,16 +46,19 @@ /* Number of rounds. */ #define R 10 - + /* Types. */ typedef u64 whirlpool_block_t[BLOCK_SIZE / 8]; typedef struct { + gcry_md_block_ctx_t bctx; whirlpool_block_t hash_state; - unsigned char buffer[BLOCK_SIZE]; - size_t count; - unsigned char length[32]; + int use_bugemu; + struct { + size_t count; + unsigned char length[32]; + } bugemu; } whirlpool_context_t; @@ -67,30 +69,13 @@ typedef struct { counter. */ #define buffer_to_block(buffer, block, i) \ for (i = 0; i < 8; i++) \ - (block)[i] = ((u64) (0 \ - | (((u64) (buffer)[i * 8 + 0]) << 56) \ - | (((u64) (buffer)[i * 8 + 1]) << 48) \ - | (((u64) (buffer)[i * 8 + 2]) << 40) \ - | (((u64) (buffer)[i * 8 + 3]) << 32) \ - | (((u64) (buffer)[i * 8 + 4]) << 24) \ - | (((u64) (buffer)[i * 8 + 5]) << 16) \ - | (((u64) (buffer)[i * 8 + 6]) << 8) \ - | (((u64) (buffer)[i * 8 + 7]) << 0))); + (block)[i] = buf_get_be64((buffer) + i * 8); /* Convert the block BLOCK into a buffer BUFFER, using I as counter. */ #define block_to_buffer(buffer, block, i) \ for (i = 0; i < 8; i++) \ - { \ - (buffer)[i * 8 + 0] = (block[i] >> 56) & 0xFF; \ - (buffer)[i * 8 + 1] = (block[i] >> 48) & 0xFF; \ - (buffer)[i * 8 + 2] = (block[i] >> 40) & 0xFF; \ - (buffer)[i * 8 + 3] = (block[i] >> 32) & 0xFF; \ - (buffer)[i * 8 + 4] = (block[i] >> 24) & 0xFF; \ - (buffer)[i * 8 + 5] = (block[i] >> 16) & 0xFF; \ - (buffer)[i * 8 + 6] = (block[i] >> 8) & 0xFF; \ - (buffer)[i * 8 + 7] = (block[i] >> 0) & 0xFF; \ - } + buf_put_be64((buffer) + i * 8, (block)[i]); /* Copy the block BLOCK_SRC to BLOCK_DST, using I as counter. */ #define block_copy(block_dst, block_src, i) \ @@ -118,7 +103,7 @@ static const u64 rc[R] = U64_C (0xfbee7c66dd17479e), U64_C (0xca2dbf07ad5a8333), }; - + /* Main lookup boxes. */ @@ -1178,23 +1163,15 @@ static const u64 C7[256] = U64_C (0xf8c7f8933fed6bf8), U64_C (0x86228644a411c286), }; - - -static void -whirlpool_init (void *ctx) -{ - whirlpool_context_t *context = ctx; - - memset (context, 0, sizeof (*context)); -} - + /* * Transform block. */ -static void -whirlpool_transform (whirlpool_context_t *context, const unsigned char *data) +static unsigned int +whirlpool_transform (void *ctx, const unsigned char *data) { + whirlpool_context_t *context = ctx; whirlpool_block_t data_block; whirlpool_block_t key; whirlpool_block_t state; @@ -1286,11 +1263,35 @@ whirlpool_transform (whirlpool_context_t *context, const unsigned char *data) block_xor (context->hash_state, data_block, i); block_xor (context->hash_state, state, i); + + return /*burn_stack*/ 4 * sizeof(whirlpool_block_t) + 2 * sizeof(int) + + 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 (whirlpool_context_t *context, - const void *buffer_arg, size_t buffer_n) +whirlpool_add_bugemu (whirlpool_context_t *context, + const void *buffer_arg, size_t buffer_n) { const unsigned char *buffer = buffer_arg; u64 buffer_size; @@ -1299,40 +1300,37 @@ whirlpool_add (whirlpool_context_t *context, buffer_size = buffer_n; - if (context->count == BLOCK_SIZE) + if (context->bugemu.count == BLOCK_SIZE) { /* Flush the buffer. */ - whirlpool_transform (context, context->buffer); - /*_gcry_burn_stack (80+6*sizeof(void*));*/ /* FIXME */ - context->count = 0; + whirlpool_transform (context, context->bctx.buf); + context->bugemu.count = 0; } if (! buffer) return; /* Nothing to add. */ - if (context->count) + if (context->bugemu.count) { - while (buffer_n && (context->count < BLOCK_SIZE)) + while (buffer_n && (context->bugemu.count < BLOCK_SIZE)) { - context->buffer[context->count++] = *buffer++; + context->bctx.buf[context->bugemu.count++] = *buffer++; buffer_n--; } - whirlpool_add (context, NULL, 0); + whirlpool_add_bugemu (context, NULL, 0); if (!buffer_n) - /* Done. */ - return; + return; /* Done. This is the bug we emulate. */ } - /*_gcry_burn_stack (80+6*sizeof(void*));*/ /* FIXME */ - while (buffer_n >= BLOCK_SIZE) + while (buffer_n >= BLOCK_SIZE) { whirlpool_transform (context, buffer); - context->count = 0; + context->bugemu.count = 0; buffer_n -= BLOCK_SIZE; buffer += BLOCK_SIZE; } - while (buffer_n && (context->count < BLOCK_SIZE)) + while (buffer_n && (context->bugemu.count < BLOCK_SIZE)) { - context->buffer[context->count++] = *buffer++; + context->bctx.buf[context->bugemu.count++] = *buffer++; buffer_n--; } @@ -1344,20 +1342,65 @@ whirlpool_add (whirlpool_context_t *context, if (! (buffer_size || carry)) break; - carry += context->length[32 - i] + (buffer_size & 0xFF); - context->length[32 - i] = carry; + 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; - whirlpool_add (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); + } } static void @@ -1365,29 +1408,60 @@ whirlpool_final (void *ctx) { whirlpool_context_t *context = ctx; unsigned int i; + 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; + /* else */ + /* th = context->bctx.nblocks >> 64; In case we ever use u128 */ + + /* multiply by 64 to make a byte count */ + lsb = t << 6; + msb = (th << 6) | (t >> 58); + /* add the count */ + t = lsb; + if ((lsb += context->bctx.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; + context->bctx.buf[context->bctx.count++] = 0x80; - if (context->count > 32) + if (context->bctx.count > 32) { /* An extra block is necessary. */ - while (context->count < 64) - context->buffer[context->count++] = 0; - whirlpool_add (context, NULL, 0); + while (context->bctx.count < 64) + context->bctx.buf[context->bctx.count++] = 0; + whirlpool_write (context, NULL, 0); } - while (context->count < 32) - context->buffer[context->count++] = 0; + while (context->bctx.count < 32) + context->bctx.buf[context->bctx.count++] = 0; /* Add length of message. */ - memcpy (context->buffer + context->count, context->length, 32); - context->count += 32; - whirlpool_add (context, NULL, 0); + length = context->bctx.buf + context->bctx.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->bctx.count += 32; + whirlpool_write (context, NULL, 0); - block_to_buffer (context->buffer, context->hash_state, i); + block_to_buffer (context->bctx.buf, context->hash_state, i); } static byte * @@ -1395,11 +1469,12 @@ whirlpool_read (void *ctx) { whirlpool_context_t *context = ctx; - return context->buffer; + return context->bctx.buf; } gcry_md_spec_t _gcry_digest_spec_whirlpool = { + GCRY_MD_WHIRLPOOL, {0, 0}, "WHIRLPOOL", NULL, 0, NULL, 64, whirlpool_init, whirlpool_write, whirlpool_final, whirlpool_read, sizeof (whirlpool_context_t) |