Add Barreto and Rijmen's Whirlpool hash function.
authormdw <mdw>
Sat, 5 Mar 2005 16:51:19 +0000 (16:51 +0000)
committermdw <mdw>
Sat, 5 Mar 2005 16:51:19 +0000 (16:51 +0000)
Makefile.m4
tests/whirlpool [new file with mode: 0644]
tests/whirlpool256 [new file with mode: 0644]
whirlpool-mktab.c [new file with mode: 0644]
whirlpool.c [new file with mode: 0644]
whirlpool.h [new file with mode: 0644]
whirlpool256.c [new file with mode: 0644]
whirlpool256.h [new file with mode: 0644]

index 36c7422..80e697d 100644 (file)
@@ -67,6 +67,7 @@ define(`cipher_modes', `_(ecb) _(cbc) _(cfb) _(ofb) _(counter)')
 define(`hashes', `dnl
 _(md5) _(md4) _(md2) _(tiger) _(has160) dnl
 _(sha) _(sha224) _(sha256) _(sha384) _(sha512) dnl
 define(`hashes', `dnl
 _(md5) _(md4) _(md2) _(tiger) _(has160) dnl
 _(sha) _(sha224) _(sha256) _(sha384) _(sha512) dnl
+_(whirlpool) _(whirlpool256) dnl
 _(rmd128) _(rmd160) _(rmd256) _(rmd320)')
 define(`hash_modes', `_(mgf) _(hmac)')
 
 _(rmd128) _(rmd160) _(rmd256) _(rmd320)')
 define(`hash_modes', `_(mgf) _(hmac)')
 
@@ -84,7 +85,7 @@ modes-stamp: genmodes
 
 define(`gen_tables', `dnl
 _(des) _(blowfish) _(twofish) dnl
 
 define(`gen_tables', `dnl
 _(des) _(blowfish) _(twofish) dnl
-_(square) _(rijndael) dnl
+_(square) _(rijndael) _(whirlpool) dnl
 _(safer) _(mars) _(tiger) dnl
 _(gfshare) _(gfx-sqr)')
 
 _(safer) _(mars) _(tiger) dnl
 _(gfshare) _(gfx-sqr)')
 
@@ -242,6 +243,7 @@ blowfish.lo: blowfish-tab.h
 twofish.lo: twofish-tab.h
 square.lo: square-tab.h
 rijndael-base.lo: rijndael-tab.h
 twofish.lo: twofish-tab.h
 square.lo: square-tab.h
 rijndael-base.lo: rijndael-tab.h
+whirlpool.lo: whirlpool-tab.h
 safer.lo: safer-tab.h
 mars.lo: mars-tab.h
 tiger.lo: tiger-tab.h
 safer.lo: safer-tab.h
 mars.lo: mars-tab.h
 tiger.lo: tiger-tab.h
diff --git a/tests/whirlpool b/tests/whirlpool
new file mode 100644 (file)
index 0000000..b1c265c
--- /dev/null
@@ -0,0 +1,66 @@
+# Test vectors for the Whirlpool hash function
+#
+# $Id: sha 2187 2004-09-04 07:50:08Z mdw $
+
+# --- Basic hash function ---
+#
+# Some of these are taken from the ISO test vectors from the Whirlpool 
+# distribution.
+
+whirlpool {
+  ""
+    19fa61d75522a4669b44e39c1d2e1726c530232130d407f89afee0964997f7a73e83be698b288febcf88e3e03c4f0757ea8964e59b63d93708b138cc42a66eb3;
+  "a"
+    8aca2602792aec6f11a67206531fb7d7f0dff59413145e6973c45001d0087b42d11bc645413aeff63a42391a39145a591a92200d560195e53b478584fdae231a;
+  "abc"
+    4e2448a4c6f486bb16b6562c73b4020bf3043e3a731bce721ae1b303d97e6d4c7181eebdb6c57e277d0e34957114cbd6c797fc9d95d8b582d225292076d4eef5;
+  "message digest"
+    378c84a4126e2dc6e56dcc7458377aac838d00032230f53ce1f5700c0ffb4d3b8421557659ef55c106b4b52ac5a4aaa692ed920052838f3362e86dbd37a8903e;
+  "abcdefghijklmnopqrstuvwxyz"
+    f1d754662636ffe92c82ebb9212a484a8d38631ead4238f5442ee13b8054e41b08bf2a9251c30b6a0b8aae86177ab4a6f68f673e7207865d5d9819a3dba4eb3b;
+  "abcdbcdecdefdefgefghfghighijhijk"
+    2a987ea40f917061f5d6f0a0e4644f488a7a5a52deee656207c562f988e95c6916bdc8031bc5be1b7b947639fe050b56939baaa0adff9ae6745b7b181c3be3fd;
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+    dc37e008cf9ee69bf11f00ed9aba26901dd7c28cdec066cc6af42e40f82f3a1e08eba26629129d8fb7cb57211b9281a65517cc879d7b962142c65f5a7af01467;
+}
+
+whirlpool-rep {
+  "1234567890" 8
+    466ef18babb0154d25b9d38a6414f5c08784372bccb204d6549c4afadb6014294d5bd8df2a6c44e538cd047b2681a51a2c60481e88c5a20b2c2a80cf3a9a083b;
+  "a" 1000000
+    0c99005beb57eff50a7cf005560ddf5d29057fd86b20bfd62deca0f1ccea4af51fc15490eddc47af32bb2b66c34ff9ad8c6008ad677f77126953b226e4ed8b01;
+}
+
+# --- HMAC mode ---
+#
+# Home-made test vectors, for regression.
+
+whirlpool-hmac {
+  "Hi There"
+       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
+       f300802099638aa1df411accbae11c2947fbcb2a4186f1c9bc6daa75dc3ad46dd89739ae5fb39b5c4afc098435c3ba0f7f55900e8c719711cbaee6d473eef0ba;
+
+  "what do ya want for nothing?"
+       4a656665
+       3d595ccd1d4f4cfd045af53ba7d5c8283fee6ded6eaf1269071b6b4ea64800056b5077c6a942cfa1221bd4e5aed791276e5dd46a407d2b8007163d3e7cd1de66;
+
+  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       4fb33849b7d0268ab9f3bc90cfc6ca90639338c32bca959b7bc47a61f4d946ca6c6a227e97205a18fe676907ce78d0f8892fcf73f44da714cb210188b92cabc9;
+
+  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
+       0102030405060708090a0b0c0d0e0f10111213141516171819
+       35bc33e2ed71e1cb01c140ddd3291ae3f84e9f0dce18005a1123df199983a211fe744b244449a1c093b17584069359bc6a95352271d78e2ef7a6f21dc28ab3c1;
+
+  "Test With Truncation"
+       0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
+       502a6d22d0f8e67196dfed2a9d9ef988714db9db2e2f0ad6c30e52eed830aa348ee98744ddd3ff1974c7fe275e078b79a6ba8c967c5a41b290f6edca01183b1a;
+
+  "Test Using Larger Than Block-Size Key - Hash Key First"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       dd90bd637cfcd27ca914c290f33402cf68576d6e70601af0295f6b9dafa9d988d8b8fb4fde8605ac544638158dba2baa90a2bf882546cd0b876d59ab3f18962e;
+
+  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       faf529af18a0f569480fd001122bb446b32a3cf758c385cec4adad9c73c77327812e260b7082011a3eb1071e71a50e1c3d37a8963f8b6a64a31cc017db1d619c;
+}
diff --git a/tests/whirlpool256 b/tests/whirlpool256
new file mode 100644 (file)
index 0000000..249fc58
--- /dev/null
@@ -0,0 +1,66 @@
+# Test vectors for the Whirlpool hash function
+#
+# $Id: sha 2187 2004-09-04 07:50:08Z mdw $
+
+# --- Basic hash function ---
+#
+# Some of these are taken from the ISO test vectors from the Whirlpool 
+# distribution.
+
+whirlpool256 {
+  ""
+    19fa61d75522a4669b44e39c1d2e1726c530232130d407f89afee0964997f7a7;
+  "a"
+    8aca2602792aec6f11a67206531fb7d7f0dff59413145e6973c45001d0087b42;
+  "abc"
+    4e2448a4c6f486bb16b6562c73b4020bf3043e3a731bce721ae1b303d97e6d4c;
+  "message digest"
+    378c84a4126e2dc6e56dcc7458377aac838d00032230f53ce1f5700c0ffb4d3b;
+  "abcdefghijklmnopqrstuvwxyz"
+    f1d754662636ffe92c82ebb9212a484a8d38631ead4238f5442ee13b8054e41b;
+  "abcdbcdecdefdefgefghfghighijhijk"
+    2a987ea40f917061f5d6f0a0e4644f488a7a5a52deee656207c562f988e95c69;
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+    dc37e008cf9ee69bf11f00ed9aba26901dd7c28cdec066cc6af42e40f82f3a1e;
+}
+
+whirlpool256-rep {
+  "1234567890" 8
+    466ef18babb0154d25b9d38a6414f5c08784372bccb204d6549c4afadb601429;
+  "a" 1000000
+    0c99005beb57eff50a7cf005560ddf5d29057fd86b20bfd62deca0f1ccea4af5;
+}
+
+# --- HMAC mode ---
+#
+# Home-made test vectors, for regression.
+
+whirlpool256-hmac {
+  "Hi There"
+       0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
+       9ab3bbb27b85df2edc51f2e05c880560439547e7c2772f8cec6ae00bead0bd7e;
+
+  "what do ya want for nothing?"
+       4a656665
+       977fd7f1d53e8af854404262630bfac20269ab3fc2fccabecd8feaa05b8cdabb;
+
+  "ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       6d418c9fe3d422200ea8cf7d0d73591ca5714f49c38907c80fc96b3934ab8fc2;
+
+  "ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ"
+       0102030405060708090a0b0c0d0e0f10111213141516171819
+       e0a3553419a54385ce04435bbb2bbf1d69d7626d8fab4f60e87a84fab731caab;
+
+  "Test With Truncation"
+       0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
+       2a4f40079e618c3a8467dd1a284af43662f84b137d93d54e5623884a047f546f;
+
+  "Test Using Larger Than Block-Size Key - Hash Key First"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       17564185de7d845576f42fbdcd027073bca1a059931ce4a901ae8662ad19caf0;
+
+  "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
+       aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+       0bdc8bf26ff0a71201fbeef2d51f35bcbc3e8b0daeddedcbec2ca2b2e8f457b2;
+}
diff --git a/whirlpool-mktab.c b/whirlpool-mktab.c
new file mode 100644 (file)
index 0000000..7276f2d
--- /dev/null
@@ -0,0 +1,233 @@
+/* -*-c-*-
+ *
+ * $Id$
+ *
+ * Generate tables for Whirlpool hash function
+ *
+ * (c) 2005 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------* 
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ * 
+ * Catacomb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <mLib/bits.h>
+
+/*----- Static variables --------------------------------------------------*/
+
+static const octet E[] = {
+  0x1, 0xb, 0x9, 0xc, 0xd, 0x6, 0xf, 0x3,
+  0xe, 0x8, 0x7, 0x4, 0xa, 0x2, 0x5, 0x0
+}, R[] = {
+  0x7, 0xc, 0xb, 0xd, 0xe, 0x4, 0x9, 0xf,
+  0x6, 0x3, 0x8, 0xa, 0x2, 0x5, 0x1, 0x0
+}, C[] = {
+  0x1, 0x1, 0x4, 0x1, 0x8, 0x5, 0x2, 0x9
+};
+
+static octet S[256], T[256][8], log[256], alog[256];
+
+/*----- Main code ---------------------------------------------------------*/
+
+#define S_MOD 0x11d
+
+static void logtable(void)
+{
+  unsigned i, x;
+
+  for (i = 0, x = 1; i < 255; i++) {
+    log[x] = i;
+    alog[i] = x;
+    x <<= 1;
+    if (x & 0x100) x ^= S_MOD;
+  }
+}
+
+static octet mul(octet x, octet y)
+  { if (!x || !y) return (0); return (alog[(log[x] + log[y]) % 255]); }
+
+static void sbox(void)
+{
+  unsigned i, j;
+  octet EI[16];
+  octet l, r, y;
+
+  for (i = 0; i < 16; i++) EI[E[i]] = i;
+  for (i = 0; i < 256; i++) {
+    l = (i >> 4) & 0xf;
+    r = (i >> 0) & 0xf;
+    l = E[l]; r = EI[r];
+    y = R[l ^ r];
+    l = E[l ^ y]; r = EI[r ^ y];
+    S[i] = (l << 4) | r;
+  }
+
+  for (i = 0; i < 256; i++) {
+    for (j = 0; j < 8; j++)
+      T[i][j] = mul(S[i], C[j]);
+  }
+}
+
+static unsigned long w32(int i, int j, int k)
+{
+  kludge64 x;
+  LOAD64_L_(x, T[j]);
+  ROL64_(x, x, i * 8);
+  return (k ? LO64(x) : HI64(x));
+}
+
+int main(void)
+{
+  int i, j;
+
+  puts("\
+/* -*-c-*-\n\
+ *\n\
+ * Whirlpool tables [generated]\n\
+ */\n\
+\n\
+#ifndef CATACOMB_WHIRLPOOL_TAB_H\n\
+#define CATACOMB_WHIRLPOOL_TAB_H\n\
+");
+
+  /* --- Write out the S-box --- */
+
+  logtable();
+  sbox();
+  fputs("\
+/* --- The byte substitution --- */\n\
+\n\
+#define WHIRLPOOL_S {                                                  \\\n\
+  ", stdout);
+  for (i = 0; i < 256; i++) {
+    printf("0x%02x", S[i]);
+    if (i == 255)
+      fputs("                  \\\n}\n\n", stdout);
+    else if (i % 8 == 7)
+      fputs(",                 \\\n  ", stdout);
+    else
+      fputs(", ", stdout);
+  }
+
+  /* --- Write out the key constant tables --- */
+
+  fputs("\
+/* --- The key generation constants --- */\n\
+\n\
+#define WHIRLPOOL_C {                                                  \\\n\
+  ", stdout);
+  for (i = 0; i < 10; i++) {
+    printf("X64(%08lx, %08lx)",
+          (unsigned long)LOAD32_L(&S[i * 8 + 4]),
+          (unsigned long)LOAD32_L(&S[i * 8 + 0]));
+    if (i == 9)
+      fputs("                  \\\n}\n\n", stdout);
+    else if (i % 2 == 1)
+      fputs(",                 \\\n  ", stdout);
+    else
+      fputs(", ", stdout);
+  }
+
+  /* --- Write out the big T tables --- */
+
+  fputs("\
+/* --- The 64-bit big round tables --- */\n\
+\n\
+#define WHIRLPOOL_T {                                                  \\\n\
+  { ", stdout);
+  for (j = 0; j < 8; j++) {
+    for (i = 0; i < 256; i++) {
+      printf("X64(%08lx, %08lx)", w32(j, i, 0), w32(j, i, 1));
+      if (i == 255) {
+       if (j == 7)
+         fputs(" }                     \\\n}\n\n", stdout);
+       else
+         fputs(" },                    \\\n\
+                                                                       \\\n\
+  { ", stdout);
+      } else if (i % 2 == 1)
+       fputs(",                        \\\n    ", stdout);
+      else
+       fputs(", ", stdout);
+    }
+  }
+
+  /* --- Write out the smaller U and V tables --- */
+
+  fputs("\
+/* --- The 32-bit round tables --- */\n\
+\n\
+#define WHIRLPOOL_U {                                                  \\\n\
+  { ", stdout);
+  for (j = 0; j < 4; j++) {
+    for (i = 0; i < 256; i++) {
+      printf("0x%08lx", w32(j, i, 1));
+      if (i == 255) {
+       if (j == 3)
+         fputs(" }                     \\\n}\n\n", stdout);
+       else
+         fputs(" },                    \\\n\
+                                                                       \\\n\
+  { ", stdout);
+      } else if (i % 4 == 3)
+       fputs(",                        \\\n    ", stdout);
+      else
+       fputs(", ", stdout);
+    }
+  }
+
+  fputs("\
+#define WHIRLPOOL_V {                                                  \\\n\
+  { ", stdout);
+  for (j = 0; j < 4; j++) {
+    for (i = 0; i < 256; i++) {
+      printf("0x%08lx", w32(j, i, 0));
+      if (i == 255) {
+       if (j == 3)
+         fputs(" }                     \\\n}\n\n", stdout);
+       else
+         fputs(" },                    \\\n\
+                                                                       \\\n\
+  { ", stdout);
+      } else if (i % 4 == 3)
+       fputs(",                        \\\n    ", stdout);
+      else
+       fputs(", ", stdout);
+    }
+  }
+
+  /* --- Done --- */
+
+  puts("#endif");
+
+  if (fclose(stdout)) {
+    fprintf(stderr, "error writing data\n");
+    exit(EXIT_FAILURE);
+  }
+
+  return (0);  
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/whirlpool.c b/whirlpool.c
new file mode 100644 (file)
index 0000000..96cbbe1
--- /dev/null
@@ -0,0 +1,306 @@
+/* -*-c-*-
+ *
+ * $Id$
+ *
+ * Whirlpool hash function
+ *
+ * (c) 2005 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------* 
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ * 
+ * Catacomb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#include "ghash.h"
+#include "ghash-def.h"
+#include "hash.h"
+#include "whirlpool.h"
+#include "whirlpool-tab.h"
+
+#if defined(HAVE_UINT64)
+#  define USE64
+#endif
+
+/*----- Static variables --------------------------------------------------*/
+
+static const kludge64 C[10] = WHIRLPOOL_C;
+
+#ifdef USE64
+static const kludge64 T[8][256] = WHIRLPOOL_T;
+#else
+static const uint32 U[4][256] = WHIRLPOOL_U, V[4][256] = WHIRLPOOL_V;
+#endif
+
+/*----- Main code ---------------------------------------------------------*/
+
+#define DUMP(k, v) do {                                                        \
+  int i;                                                               \
+  printf("\n");                                                                \
+  for (i = 0; i < 8; i++)                                              \
+    printf("  %08x %08x  :  %08x %08x\n",                              \
+          HI64(k[i]), LO64(k[i]),                                      \
+          HI64(v[i]), LO64(v[i]));                                     \
+} while (0)
+
+#define OFFSET(i, n) (((i) + 16 - (n)) % 8)
+
+#ifdef USE64
+
+#define BYTE(x, j)                                                     \
+  U8((j) < 4 ?                                                         \
+    (LO64(x) >> ((j) * 8)) :                                           \
+    (HI64(x) >> ((j) * 8 - 32)))
+
+#define TT(v, i, j) T[j][BYTE(v[OFFSET(i, j)], j)]
+
+#define XROW(vv, v, i) do {                                            \
+  XOR64(vv[i], vv[i], TT(v, i, 1));                                    \
+  XOR64(vv[i], vv[i], TT(v, i, 2));                                    \
+  XOR64(vv[i], vv[i], TT(v, i, 3));                                    \
+  XOR64(vv[i], vv[i], TT(v, i, 4));                                    \
+  XOR64(vv[i], vv[i], TT(v, i, 5));                                    \
+  XOR64(vv[i], vv[i], TT(v, i, 6));                                    \
+  XOR64(vv[i], vv[i], TT(v, i, 7));                                    \
+} while (0)
+
+#define ROWZ(vv, v, i) do {                                            \
+  vv[i] = TT(v, i, 0);                                                 \
+  XROW(vv, v, i);                                                      \
+} while (0)
+
+#define ROWK(vv, v, i, k) do {                                         \
+  vv[i] = k;                                                           \
+  XOR64(vv[i], vv[i], TT(v, i, 0));                                    \
+  XROW(vv, v, i);                                                      \
+} while (0)
+
+#else
+
+#define BYTE(x, j) U8((x) >> (((j) & 3) * 8))
+
+#define UUL(v, i, j) U[j & 3][BYTE(v[OFFSET(i, j)].lo, j)]
+#define VVL(v, i, j) V[j & 3][BYTE(v[OFFSET(i, j)].lo, j)]
+#define UUH(v, i, j) U[j & 3][BYTE(v[OFFSET(i, j)].hi, j)]
+#define VVH(v, i, j) V[j & 3][BYTE(v[OFFSET(i, j)].hi, j)]
+
+#define XROW(vv, v, i) do {                                            \
+  vv[i].lo ^= UUL(v, i, 1); vv[i].hi ^= VVL(v, i, 1);                  \
+  vv[i].lo ^= UUL(v, i, 2); vv[i].hi ^= VVL(v, i, 2);                  \
+  vv[i].lo ^= UUL(v, i, 3); vv[i].hi ^= VVL(v, i, 3);                  \
+  vv[i].lo ^= VVH(v, i, 4); vv[i].hi ^= UUH(v, i, 4);                  \
+  vv[i].lo ^= VVH(v, i, 5); vv[i].hi ^= UUH(v, i, 5);                  \
+  vv[i].lo ^= VVH(v, i, 6); vv[i].hi ^= UUH(v, i, 6);                  \
+  vv[i].lo ^= VVH(v, i, 7); vv[i].hi ^= UUH(v, i, 7);                  \
+} while (0)
+
+#define ROWZ(vv, v, i) do {                                            \
+  vv[i].lo = UUL(v, i, 0);  vv[i].hi = VVL(v, i, 0);                   \
+  XROW(vv, v, i);                                                      \
+} while (0)
+
+#define ROWK(vv, v, i, k) do {                                         \
+  vv[i] = k;                                                           \
+  vv[i].lo ^= UUL(v, i, 0); vv[i].hi ^= VVL(v, i, 0);                  \
+  XROW(vv, v, i);                                                      \
+} while (0)
+  
+#endif
+
+#define RHO(vv, v, kk, k) do {                                         \
+  ROWK(kk, k, 0, *c++);   ROWK(vv, v, 0, kk[0]);                       \
+  ROWZ(kk, k, 1);         ROWK(vv, v, 1, kk[1]);                       \
+  ROWZ(kk, k, 2);         ROWK(vv, v, 2, kk[2]);                       \
+  ROWZ(kk, k, 3);         ROWK(vv, v, 3, kk[3]);                       \
+  ROWZ(kk, k, 4);         ROWK(vv, v, 4, kk[4]);                       \
+  ROWZ(kk, k, 5);         ROWK(vv, v, 5, kk[5]);                       \
+  ROWZ(kk, k, 6);         ROWK(vv, v, 6, kk[6]);                       \
+  ROWZ(kk, k, 7);         ROWK(vv, v, 7, kk[7]);                       \
+} while (0)
+
+void whirlpool_compress(whirlpool_ctx *ctx, const void *sbuf)
+{
+  kludge64 m[8], k[8], kk[8], v[8], vv[8];
+  const kludge64 *c = C;
+  const octet *s = sbuf;
+  int i;
+  
+  for (i = 0; i < 8; i++) {
+    LOAD64_L_(m[i], &s[i * 8]);
+    XOR64(v[i], m[i], ctx->s[i]);
+  }
+
+  RHO(vv, v, kk, ctx->s);
+  RHO(v, vv, k, kk);
+  RHO(vv, v, kk, k);
+  RHO(v, vv, k, kk);
+  RHO(vv, v, kk, k);
+  RHO(v, vv, k, kk);
+  RHO(vv, v, kk, k);
+  RHO(v, vv, k, kk);
+  RHO(vv, v, kk, k);
+  RHO(v, vv, k, kk);
+
+  for (i = 0; i < 8; i++) {
+    XOR64(ctx->s[i], ctx->s[i], m[i]);
+    XOR64(ctx->s[i], ctx->s[i], v[i]);
+  }
+}
+
+/* --- @whirlpool_init@, @whirlpool256_init@ --- *
+ *
+ * Arguments:  @whirlpool_ctx *ctx@ = pointer to context block to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block ready for hashing.
+ */
+
+void whirlpool_init(whirlpool_ctx *ctx)
+{
+  int i;
+
+  for (i = 0; i < 8; i++)
+    SET64(ctx->s[i], 0, 0);
+  ctx->off = 0;
+  ctx->nh = ctx->nl = 0;
+}
+
+/* --- @whirlpool_set@, @whirlpool256_set@ --- *
+ *
+ * Arguments:  @whirlpool_ctx *ctx@ = pointer to context block
+ *             @const void *buf@ = pointer to state buffer
+ *             @unsigned long count@ = current count of bytes processed
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block from a given state.  This is
+ *             useful in cases where the initial hash state is meant to be
+ *             secret, e.g., for NMAC and HMAC support.
+ */
+
+void whirlpool_set(whirlpool_ctx *ctx, const void *buf, unsigned long count)
+{
+  const octet *p = buf;
+  int i;
+
+  for (i = 0; i < 8; i++) {
+    LOAD64_L_(ctx->s[i], p);
+    p += 8;
+  }
+  ctx->off = 0;
+  ctx->nl = U32(count);
+  ctx->nh = U32(((count & ~MASK32) >> 16) >> 16);
+}
+
+/* --- @whirlpool_hash@, @whirlpool256_hash@ --- *
+ *
+ * Arguments:  @whirlpool_ctx *ctx@ = pointer to context block
+ *             @const void *buf@ = buffer of data to hash
+ *             @size_t sz@ = size of buffer to hash
+ *
+ * Returns:    ---
+ *
+ * Use:                Hashes a buffer of data.  The buffer may be of any size and
+ *             alignment.
+ */
+
+void whirlpool_hash(whirlpool_ctx *ctx, const void *buf, size_t sz)
+{
+  HASH_BUFFER(WHIRLPOOL, whirlpool, ctx, buf, sz);
+}
+
+/* --- @whirlpool_done@, @whirlpool256_done@ --- *
+ *
+ * Arguments:  @whirlpool_ctx *ctx@ = pointer to context block
+ *             @void *hash@ = pointer to output buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Returns the hash of the data read so far.
+ */
+
+static void final(whirlpool_ctx *ctx)
+{
+  HASH_PAD(WHIRLPOOL, whirlpool, ctx, 0x80, 0, 32);
+  memset(ctx->buf + WHIRLPOOL_BUFSZ - 32, 0, 24);
+  STORE32(ctx->buf + WHIRLPOOL_BUFSZ -  8, (ctx->nl >> 29) | (ctx->nh << 3));
+  STORE32(ctx->buf + WHIRLPOOL_BUFSZ -  4, ctx->nl << 3);
+  whirlpool_compress(ctx, ctx->buf);
+}
+
+void whirlpool_done(whirlpool_ctx *ctx, void *hash)
+{
+  octet *p = hash;
+  int i;
+
+  final(ctx);
+  for (i = 0; i < 8; i++) {
+    STORE64_L_(p, ctx->s[i]);
+    p += 8;
+  }
+}
+
+void whirlpool256_done(whirlpool256_ctx *ctx, void *hash)
+{
+  octet *p = hash;
+  int i;
+
+  final(ctx);
+  for (i = 0; i < 4; i++) {
+    STORE64_L_(p, ctx->s[i]);
+    p += 8;
+  }
+}
+
+/* --- @whirlpool_state@, @whirlpool256_state@ --- *
+ *
+ * Arguments:  @whirlpool_ctx *ctx@ = pointer to context
+ *             @void *state@ = pointer to buffer for current state
+ *
+ * Returns:    Number of bytes written to the hash function so far.
+ *
+ * Use:                Returns the current state of the hash function such that
+ *             it can be passed to @whirlpool_set@.
+ */
+
+unsigned long whirlpool_state(whirlpool_ctx *ctx, void *state)
+{
+  octet *p = state;
+  int i;
+
+  for (i = 0; i < 8; i++) {
+    STORE64_L_(p, ctx->s[i]);
+    p += 8;
+  }
+  return (ctx->nl | ((ctx->nh << 16) << 16));
+}
+
+/* --- Generic interface --- */
+
+GHASH_DEF(WHIRLPOOL, whirlpool)
+
+/* --- Test code --- */
+
+HASH_TEST(WHIRLPOOL, whirlpool)
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/whirlpool.h b/whirlpool.h
new file mode 100644 (file)
index 0000000..a85a62b
--- /dev/null
@@ -0,0 +1,177 @@
+/* -*-c-*-
+ *
+ * $Id$
+ *
+ * Implementation of the Whirlpool hash function
+ *
+ * (c) 2000 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------* 
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ * 
+ * Catacomb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/*----- Notes on the Whirlpool hash function ------------------------------*
+ *
+ * Whirlpool was designed by Paulo Barreto and Vincent Rijmen.  Its
+ * compression function is based on similar ideas to Rijndael (also
+ * codesigned by Rijmen).
+ *
+ * Whirlpool256 is simply Whirlpool with its final output truncated to 256
+ * bits.  This is, I hope, about as good as a 256-bit hash function can get.
+ * It isn't vulnerable to the Kelsey-Schneier generic second-preimage attack
+ * against MD hash functions because of its larger internal state (see also
+ * Lucks).
+ */
+
+#ifndef CATACOMB_WHIRLPOOL_H
+#define CATACOMB_WHIRLPOOL_H
+#define CATACOMB_WHIRLPOOL256_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_GHASH_H
+#  include "ghash.h"
+#endif
+
+/*----- Magic numbers -----------------------------------------------------*/
+
+#define WHIRLPOOL_BUFSZ 64
+#define WHIRLPOOL_HASHSZ 64
+#define WHIRLPOOL_STATESZ 64
+
+#define WHIRLPOOL256_BUFSZ 64
+#define WHIRLPOOL256_HASHSZ 32
+#define WHIRLPOOL256_STATESZ 64
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct whirlpool_ctx {
+  kludge64 s[8];                       /* Chaining variables */
+  uint32 nh, nl;                       /* Byte count so far */
+  unsigned off;                                /* Offset into buffer */
+  octet buf[WHIRLPOOL_BUFSZ];          /* Accumulation buffer */
+} whirlpool_ctx, whirlpool256_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @whirlpool_compress@, @whirlpool256_compress@ --- *
+ *
+ * Arguments:  @whirlpool_ctx *ctx@ = pointer to context block
+ *             @const void *sbuf@ = pointer to buffer of appropriate size
+ *
+ * Returns:    ---
+ *
+ * Use:                SHA-512 compression function.
+ */
+
+extern void whirlpool_compress(whirlpool_ctx */*ctx*/, const void */*sbuf*/);
+#define whirlpool256_compress whirlpool_compress
+
+/* --- @whirlpool_init@, @whirlpool256_init@ --- *
+ *
+ * Arguments:  @whirlpool_ctx *ctx@ = pointer to context block to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block ready for hashing.
+ */
+
+extern void whirlpool_init(whirlpool_ctx */*ctx*/);
+#define whirlpool256_init whirlpool_init
+
+/* --- @whirlpool_set@, @whirlpool256_set@ --- *
+ *
+ * Arguments:  @whirlpool_ctx *ctx@ = pointer to context block
+ *             @const void *buf@ = pointer to state buffer
+ *             @unsigned long count@ = current count of bytes processed
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block from a given state.  This is
+ *             useful in cases where the initial hash state is meant to be
+ *             secret, e.g., for NMAC and HMAC support.
+ */
+
+extern void whirlpool_set(whirlpool_ctx */*ctx*/, const void */*buf*/,
+                         unsigned long /*count*/);
+#define whirlpool256_set whirlpool_set
+
+/* --- @whirlpool_hash@, @whirlpool256_hash@ --- *
+ *
+ * Arguments:  @whirlpool_ctx *ctx@ = pointer to context block
+ *             @const void *buf@ = buffer of data to hash
+ *             @size_t sz@ = size of buffer to hash
+ *
+ * Returns:    ---
+ *
+ * Use:                Hashes a buffer of data.  The buffer may be of any size and
+ *             alignment.
+ */
+
+extern void whirlpool_hash(whirlpool_ctx */*ctx*/,
+                          const void */*buf*/, size_t /*sz*/);
+#define whirlpool256_hash whirlpool_hash
+
+/* --- @whirlpool_done@, @whirlpool256_done@ --- *
+ *
+ * Arguments:  @whirlpool_ctx *ctx@ = pointer to context block
+ *             @void *hash@ = pointer to output buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Returns the hash of the data read so far.
+ */
+
+extern void whirlpool_done(whirlpool_ctx */*ctx*/, void */*hash*/);
+extern void whirlpool256_done(whirlpool_ctx */*ctx*/, void */*hash*/);
+
+/* --- @whirlpool_state@, @whirlpool256_state@ --- *
+ *
+ * Arguments:  @whirlpool_ctx *ctx@ = pointer to context
+ *             @void *state@ = pointer to buffer for current state
+ *
+ * Returns:    Number of bytes written to the hash function so far.
+ *
+ * Use:                Returns the current state of the hash function such that
+ *             it can be passed to @whirlpool_set@.
+ */
+
+extern unsigned long whirlpool_state(whirlpool_ctx */*ctx*/,
+                                    void */*state*/);
+#define whirlpool256_state whirlpool_state
+
+/*----- Generic hash interface --------------------------------------------*/
+
+extern const gchash whirlpool;
+extern const gchash whirlpool256;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
diff --git a/whirlpool256.c b/whirlpool256.c
new file mode 100644 (file)
index 0000000..38fe665
--- /dev/null
@@ -0,0 +1,14 @@
+/* -*-c-*-
+ *
+ * $Id$
+ *
+ * Stub code for Whirlpool-256
+ */
+
+#include "ghash.h"
+#include "ghash-def.h"
+#include "hash.h"
+#include "whirlpool256.h"
+
+GHASH_DEF(WHIRLPOOL256, whirlpool256)
+HASH_TEST(WHIRLPOOL256, whirlpool256)
diff --git a/whirlpool256.h b/whirlpool256.h
new file mode 100644 (file)
index 0000000..171d886
--- /dev/null
@@ -0,0 +1,13 @@
+/* -*-c-*-
+ *
+ * $Id$
+ *
+ * Stub header for Whirlpool-256
+ */
+
+#ifndef CATACOMB_WHIRLPOOL256_H
+#define CATACOMB_WHIRLPOOL256_H
+
+#include "whirlpool.h"
+
+#endif