summaryrefslogtreecommitdiff
path: root/plugins/MirOTR/Libgcrypt/cipher/whirlpool.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/MirOTR/Libgcrypt/cipher/whirlpool.c')
-rw-r--r--plugins/MirOTR/Libgcrypt/cipher/whirlpool.c227
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)