From 7fcfe7de9c3227fedee03b56e7f69fd9646d4e38 Mon Sep 17 00:00:00 2001 From: mdw Date: Sat, 5 Mar 2005 16:51:19 +0000 Subject: [PATCH] Add Barreto and Rijmen's Whirlpool hash function. --- Makefile.m4 | 4 +- tests/whirlpool | 66 ++++++++++++ tests/whirlpool256 | 66 ++++++++++++ whirlpool-mktab.c | 233 ++++++++++++++++++++++++++++++++++++++++ whirlpool.c | 306 +++++++++++++++++++++++++++++++++++++++++++++++++++++ whirlpool.h | 177 +++++++++++++++++++++++++++++++ whirlpool256.c | 14 +++ whirlpool256.h | 13 +++ 8 files changed, 878 insertions(+), 1 deletion(-) create mode 100644 tests/whirlpool create mode 100644 tests/whirlpool256 create mode 100644 whirlpool-mktab.c create mode 100644 whirlpool.c create mode 100644 whirlpool.h create mode 100644 whirlpool256.c create mode 100644 whirlpool256.h diff --git a/Makefile.m4 b/Makefile.m4 index 36c7422..80e697d 100644 --- a/Makefile.m4 +++ b/Makefile.m4 @@ -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 +_(whirlpool) _(whirlpool256) dnl _(rmd128) _(rmd160) _(rmd256) _(rmd320)') define(`hash_modes', `_(mgf) _(hmac)') @@ -84,7 +85,7 @@ modes-stamp: genmodes define(`gen_tables', `dnl _(des) _(blowfish) _(twofish) dnl -_(square) _(rijndael) dnl +_(square) _(rijndael) _(whirlpool) dnl _(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 +whirlpool.lo: whirlpool-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 index 0000000..b1c265c --- /dev/null +++ b/tests/whirlpool @@ -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 index 0000000..249fc58 --- /dev/null +++ b/tests/whirlpool256 @@ -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 index 0000000..7276f2d --- /dev/null +++ b/whirlpool-mktab.c @@ -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 +#include +#include + +#include + +/*----- 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 index 0000000..96cbbe1 --- /dev/null +++ b/whirlpool.c @@ -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 + +#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 index 0000000..a85a62b --- /dev/null +++ b/whirlpool.h @@ -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 + +#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 index 0000000..38fe665 --- /dev/null +++ b/whirlpool256.c @@ -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 index 0000000..171d886 --- /dev/null +++ b/whirlpool256.h @@ -0,0 +1,13 @@ +/* -*-c-*- + * + * $Id$ + * + * Stub header for Whirlpool-256 + */ + +#ifndef CATACOMB_WHIRLPOOL256_H +#define CATACOMB_WHIRLPOOL256_H + +#include "whirlpool.h" + +#endif -- 2.11.0