1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3 * LibTomCrypt is a library that provides various cryptographic
4 * algorithms in a highly modular and flexible manner.
6 * The library is free for all purposes without any express
12 LTC_WHIRLPOOL (using their new sbox) hash function by Tom St Denis
19 const struct ltc_hash_descriptor whirlpool_desc =
27 { 1, 0, 10118, 3, 0, 55 },
38 #define __LTC_WHIRLTAB_C__
42 #define GB(a,i,j) ((a[(i) & 7] >> (8 * (j))) & 255)
44 /* shortcut macro to perform three functions at once */
45 #define theta_pi_gamma(a, i) \
46 (SB0(GB(a, i-0, 7)) ^ \
47 SB1(GB(a, i-1, 6)) ^ \
48 SB2(GB(a, i-2, 5)) ^ \
49 SB3(GB(a, i-3, 4)) ^ \
50 SB4(GB(a, i-4, 3)) ^ \
51 SB5(GB(a, i-5, 2)) ^ \
52 SB6(GB(a, i-6, 1)) ^ \
55 #ifdef LTC_CLEAN_STACK
56 static int _whirlpool_compress(hash_state *md, unsigned char *buf)
58 static int whirlpool_compress(hash_state *md, unsigned char *buf)
61 ulong64 K[2][8], T[3][8];
64 /* load the block/state */
65 for (x = 0; x < 8; x++) {
66 K[0][x] = md->whirlpool.state[x];
68 LOAD64H(T[0][x], buf + (8 * x));
74 for (x = 0; x < 10; x += 2) {
76 /* apply main transform to K[0] into K[1] */
77 for (y = 0; y < 8; y++) {
78 K[1][y] = theta_pi_gamma(K[0], y);
80 /* xor the constant */
83 /* apply main transform to T[0] into T[1] */
84 for (y = 0; y < 8; y++) {
85 T[1][y] = theta_pi_gamma(T[0], y) ^ K[1][y];
89 /* apply main transform to K[1] into K[0] */
90 for (y = 0; y < 8; y++) {
91 K[0][y] = theta_pi_gamma(K[1], y);
93 /* xor the constant */
96 /* apply main transform to T[1] into T[0] */
97 for (y = 0; y < 8; y++) {
98 T[0][y] = theta_pi_gamma(T[1], y) ^ K[0][y];
103 for (x = 0; x < 8; x++) {
104 md->whirlpool.state[x] ^= T[0][x] ^ T[2][x];
111 #ifdef LTC_CLEAN_STACK
112 static int whirlpool_compress(hash_state *md, unsigned char *buf)
115 err = _whirlpool_compress(md, buf);
116 burn_stack((5 * 8 * sizeof(ulong64)) + (2 * sizeof(int)));
123 Initialize the hash state
124 @param md The hash state you wish to initialize
125 @return CRYPT_OK if successful
127 int whirlpool_init(hash_state * md)
129 LTC_ARGCHK(md != NULL);
130 zeromem(&md->whirlpool, sizeof(md->whirlpool));
135 Process a block of memory though the hash
136 @param md The hash state
137 @param in The data to hash
138 @param inlen The length of the data (octets)
139 @return CRYPT_OK if successful
141 HASH_PROCESS(whirlpool_process, whirlpool_compress, whirlpool, 64)
144 Terminate the hash to get the digest
145 @param md The hash state
146 @param out [out] The destination of the hash (64 bytes)
147 @return CRYPT_OK if successful
149 int whirlpool_done(hash_state * md, unsigned char *out)
153 LTC_ARGCHK(md != NULL);
154 LTC_ARGCHK(out != NULL);
156 if (md->whirlpool.curlen >= sizeof(md->whirlpool.buf)) {
157 return CRYPT_INVALID_ARG;
160 /* increase the length of the message */
161 md->whirlpool.length += md->whirlpool.curlen * 8;
163 /* append the '1' bit */
164 md->whirlpool.buf[md->whirlpool.curlen++] = (unsigned char)0x80;
166 /* if the length is currently above 32 bytes we append zeros
167 * then compress. Then we can fall back to padding zeros and length
168 * encoding like normal.
170 if (md->whirlpool.curlen > 32) {
171 while (md->whirlpool.curlen < 64) {
172 md->whirlpool.buf[md->whirlpool.curlen++] = (unsigned char)0;
174 whirlpool_compress(md, md->whirlpool.buf);
175 md->whirlpool.curlen = 0;
178 /* pad upto 56 bytes of zeroes (should be 32 but we only support 64-bit lengths) */
179 while (md->whirlpool.curlen < 56) {
180 md->whirlpool.buf[md->whirlpool.curlen++] = (unsigned char)0;
184 STORE64H(md->whirlpool.length, md->whirlpool.buf+56);
185 whirlpool_compress(md, md->whirlpool.buf);
188 for (i = 0; i < 8; i++) {
189 STORE64H(md->whirlpool.state[i], out+(8*i));
191 #ifdef LTC_CLEAN_STACK
192 zeromem(md, sizeof(*md));
199 @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
201 int whirlpool_test(void)
206 static const struct {
208 unsigned char msg[128], hash[64];
215 { 0x19, 0xFA, 0x61, 0xD7, 0x55, 0x22, 0xA4, 0x66, 0x9B, 0x44, 0xE3, 0x9C, 0x1D, 0x2E, 0x17, 0x26,
216 0xC5, 0x30, 0x23, 0x21, 0x30, 0xD4, 0x07, 0xF8, 0x9A, 0xFE, 0xE0, 0x96, 0x49, 0x97, 0xF7, 0xA7,
217 0x3E, 0x83, 0xBE, 0x69, 0x8B, 0x28, 0x8F, 0xEB, 0xCF, 0x88, 0xE3, 0xE0, 0x3C, 0x4F, 0x07, 0x57,
218 0xEA, 0x89, 0x64, 0xE5, 0x9B, 0x63, 0xD9, 0x37, 0x08, 0xB1, 0x38, 0xCC, 0x42, 0xA6, 0x6E, 0xB3 }
222 /* 448-bits of 0 bits */
227 { 0x0B, 0x3F, 0x53, 0x78, 0xEB, 0xED, 0x2B, 0xF4, 0xD7, 0xBE, 0x3C, 0xFD, 0x81, 0x8C, 0x1B, 0x03,
228 0xB6, 0xBB, 0x03, 0xD3, 0x46, 0x94, 0x8B, 0x04, 0xF4, 0xF4, 0x0C, 0x72, 0x6F, 0x07, 0x58, 0x70,
229 0x2A, 0x0F, 0x1E, 0x22, 0x58, 0x80, 0xE3, 0x8D, 0xD5, 0xF6, 0xED, 0x6D, 0xE9, 0xB1, 0xE9, 0x61,
230 0xE4, 0x9F, 0xC1, 0x31, 0x8D, 0x7C, 0xB7, 0x48, 0x22, 0xF3, 0xD0, 0xE2, 0xE9, 0xA7, 0xE7, 0xB0 }
233 /* 520-bits of 0 bits */
237 { 0x85, 0xE1, 0x24, 0xC4, 0x41, 0x5B, 0xCF, 0x43, 0x19, 0x54, 0x3E, 0x3A, 0x63, 0xFF, 0x57, 0x1D,
238 0x09, 0x35, 0x4C, 0xEE, 0xBE, 0xE1, 0xE3, 0x25, 0x30, 0x8C, 0x90, 0x69, 0xF4, 0x3E, 0x2A, 0xE4,
239 0xD0, 0xE5, 0x1D, 0x4E, 0xB1, 0xE8, 0x64, 0x28, 0x70, 0x19, 0x4E, 0x95, 0x30, 0xD8, 0xD8, 0xAF,
240 0x65, 0x89, 0xD1, 0xBF, 0x69, 0x49, 0xDD, 0xF9, 0x0A, 0x7F, 0x12, 0x08, 0x62, 0x37, 0x95, 0xB9 }
243 /* 512-bits, leading set */
246 { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
247 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
248 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
249 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
250 { 0x10, 0x3E, 0x00, 0x55, 0xA9, 0xB0, 0x90, 0xE1, 0x1C, 0x8F, 0xDD, 0xEB, 0xBA, 0x06, 0xC0, 0x5A,
251 0xCE, 0x8B, 0x64, 0xB8, 0x96, 0x12, 0x8F, 0x6E, 0xED, 0x30, 0x71, 0xFC, 0xF3, 0xDC, 0x16, 0x94,
252 0x67, 0x78, 0xE0, 0x72, 0x23, 0x23, 0x3F, 0xD1, 0x80, 0xFC, 0x40, 0xCC, 0xDB, 0x84, 0x30, 0xA6,
253 0x40, 0xE3, 0x76, 0x34, 0x27, 0x1E, 0x65, 0x5C, 0xA1, 0x67, 0x4E, 0xBF, 0xF5, 0x07, 0xF8, 0xCB }
256 /* 512-bits, leading set of second byte */
259 { 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
260 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
261 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
262 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
263 { 0x35, 0x7B, 0x42, 0xEA, 0x79, 0xBC, 0x97, 0x86, 0x97, 0x5A, 0x3C, 0x44, 0x70, 0xAA, 0xB2, 0x3E,
264 0x62, 0x29, 0x79, 0x7B, 0xAD, 0xBD, 0x54, 0x36, 0x5B, 0x54, 0x96, 0xE5, 0x5D, 0x9D, 0xD7, 0x9F,
265 0xE9, 0x62, 0x4F, 0xB4, 0x22, 0x66, 0x93, 0x0A, 0x62, 0x8E, 0xD4, 0xDB, 0x08, 0xF9, 0xDD, 0x35,
266 0xEF, 0x1B, 0xE1, 0x04, 0x53, 0xFC, 0x18, 0xF4, 0x2C, 0x7F, 0x5E, 0x1F, 0x9B, 0xAE, 0x55, 0xE0 }
269 /* 512-bits, leading set of last byte */
272 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
273 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
274 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
275 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 },
276 { 0x8B, 0x39, 0x04, 0xDD, 0x19, 0x81, 0x41, 0x26, 0xFD, 0x02, 0x74, 0xAB, 0x49, 0xC5, 0x97, 0xF6,
277 0xD7, 0x75, 0x33, 0x52, 0xA2, 0xDD, 0x91, 0xFD, 0x8F, 0x9F, 0x54, 0x05, 0x4C, 0x54, 0xBF, 0x0F,
278 0x06, 0xDB, 0x4F, 0xF7, 0x08, 0xA3, 0xA2, 0x8B, 0xC3, 0x7A, 0x92, 0x1E, 0xEE, 0x11, 0xED, 0x7B,
279 0x6A, 0x53, 0x79, 0x32, 0xCC, 0x5E, 0x94, 0xEE, 0x1E, 0xA6, 0x57, 0x60, 0x7E, 0x36, 0xC9, 0xF7 }
285 unsigned char tmp[64];
288 for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) {
290 whirlpool_process(&md, (unsigned char *)tests[i].msg, tests[i].len);
291 whirlpool_done(&md, tmp);
292 if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "WHIRLPOOL", i)) {
293 return CRYPT_FAIL_TESTVECTOR;
304 /* ref: $Format:%D$ */
305 /* git commit: $Format:%H$ */
306 /* commit time: $Format:%ai$ */