comparison src/hashes/whirl/whirl.c @ 192:9cc34777b479 libtomcrypt

propagate from branch 'au.asn.ucc.matt.ltc-orig' (head 9ba8f01f44320e9cb9f19881105ae84f84a43ea9) to branch 'au.asn.ucc.matt.dropbear.ltc' (head dbf51c569bc34956ad948e4cc87a0eeb2170b768)
author Matt Johnston <matt@ucc.asn.au>
date Sun, 08 May 2005 06:36:47 +0000
parents 1c15b283127b
children 39d5d58461d6
comparison
equal deleted inserted replaced
164:cd1143579f00 192:9cc34777b479
1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
2 *
3 * LibTomCrypt is a library that provides various cryptographic
4 * algorithms in a highly modular and flexible manner.
5 *
6 * The library is free for all purposes without any express
7 * guarantee it works.
8 *
9 * Tom St Denis, [email protected], http://libtomcrypt.org
10 */
11
12 /**
13 @file whirl.c
14 WHIRLPOOL (using their new sbox) hash function by Tom St Denis
15 */
16
17 #include "tomcrypt.h"
18
19 #ifdef WHIRLPOOL
20
21 const struct ltc_hash_descriptor whirlpool_desc =
22 {
23 "whirlpool",
24 11,
25 64,
26 64,
27
28 /* DER encoding (not yet supported) */
29 { 0x00 },
30 0,
31
32 &whirlpool_init,
33 &whirlpool_process,
34 &whirlpool_done,
35 &whirlpool_test
36 };
37
38 /* the sboxes */
39 #include "whirltab.c"
40
41 /* get a_{i,j} */
42 #define GB(a,i,j) ((a[(i) & 7] >> (8 * (j))) & 255)
43
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)) ^ \
53 SB7(GB(a, i-7, 0))
54
55 #ifdef LTC_CLEAN_STACK
56 static int _whirlpool_compress(hash_state *md, unsigned char *buf)
57 #else
58 static int whirlpool_compress(hash_state *md, unsigned char *buf)
59 #endif
60 {
61 ulong64 K[2][8], T[3][8];
62 int x, y;
63
64 /* load the block/state */
65 for (x = 0; x < 8; x++) {
66 K[0][x] = md->whirlpool.state[x];
67
68 LOAD64H(T[0][x], buf + (8 * x));
69 T[2][x] = T[0][x];
70 T[0][x] ^= K[0][x];
71 }
72
73 /* do rounds 1..10 */
74 for (x = 0; x < 10; x += 2) {
75 /* odd round */
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);
79 }
80 /* xor the constant */
81 K[1][0] ^= cont[x];
82
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];
86 }
87
88 /* even round */
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);
92 }
93 /* xor the constant */
94 K[0][0] ^= cont[x+1];
95
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];
99 }
100 }
101
102 /* store state */
103 for (x = 0; x < 8; x++) {
104 md->whirlpool.state[x] ^= T[0][x] ^ T[2][x];
105 }
106
107 return CRYPT_OK;
108 }
109
110
111 #ifdef LTC_CLEAN_STACK
112 static int whirlpool_compress(hash_state *md, unsigned char *buf)
113 {
114 int err;
115 err = _whirlpool_compress(md, buf);
116 burn_stack((5 * 8 * sizeof(ulong64)) + (2 * sizeof(int)));
117 return err;
118 }
119 #endif
120
121
122 /**
123 Initialize the hash state
124 @param md The hash state you wish to initialize
125 @return CRYPT_OK if successful
126 */
127 int whirlpool_init(hash_state * md)
128 {
129 LTC_ARGCHK(md != NULL);
130 zeromem(&md->whirlpool, sizeof(md->whirlpool));
131 return CRYPT_OK;
132 }
133
134 /**
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
140 */
141 HASH_PROCESS(whirlpool_process, whirlpool_compress, whirlpool, 64)
142
143 /**
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
148 */
149 int whirlpool_done(hash_state * md, unsigned char *out)
150 {
151 int i;
152
153 LTC_ARGCHK(md != NULL);
154 LTC_ARGCHK(out != NULL);
155
156 if (md->whirlpool.curlen >= sizeof(md->whirlpool.buf)) {
157 return CRYPT_INVALID_ARG;
158 }
159
160 /* increase the length of the message */
161 md->whirlpool.length += md->whirlpool.curlen * 8;
162
163 /* append the '1' bit */
164 md->whirlpool.buf[md->whirlpool.curlen++] = (unsigned char)0x80;
165
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.
169 */
170 if (md->whirlpool.curlen > 32) {
171 while (md->whirlpool.curlen < 64) {
172 md->whirlpool.buf[md->whirlpool.curlen++] = (unsigned char)0;
173 }
174 whirlpool_compress(md, md->whirlpool.buf);
175 md->whirlpool.curlen = 0;
176 }
177
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;
181 }
182
183 /* store length */
184 STORE64H(md->whirlpool.length, md->whirlpool.buf+56);
185 whirlpool_compress(md, md->whirlpool.buf);
186
187 /* copy output */
188 for (i = 0; i < 8; i++) {
189 STORE64H(md->whirlpool.state[i], out+(8*i));
190 }
191 #ifdef LTC_CLEAN_STACK
192 zeromem(md, sizeof(*md));
193 #endif
194 return CRYPT_OK;
195 }
196
197 /**
198 Self-test the hash
199 @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
200 */
201 int whirlpool_test(void)
202 {
203 #ifndef LTC_TEST
204 return CRYPT_NOP;
205 #else
206 static const struct {
207 int len;
208 unsigned char msg[128], hash[64];
209 } tests[] = {
210
211 /* NULL Message */
212 {
213 0,
214 { 0x00 },
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 }
219 },
220
221
222 /* 448-bits of 0 bits */
223 {
224
225 56,
226 { 0x00 },
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 }
231 },
232
233 /* 520-bits of 0 bits */
234 {
235 65,
236 { 0x00 },
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 }
241 },
242
243 /* 512-bits, leading set */
244 {
245 64,
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 }
254 },
255
256 /* 512-bits, leading set of second byte */
257 {
258 64,
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 }
267 },
268
269 /* 512-bits, leading set of last byte */
270 {
271 64,
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 }
280 },
281
282 };
283
284 int i;
285 unsigned char tmp[64];
286 hash_state md;
287
288 for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) {
289 whirlpool_init(&md);
290 whirlpool_process(&md, (unsigned char *)tests[i].msg, tests[i].len);
291 whirlpool_done(&md, tmp);
292 if (memcmp(tmp, tests[i].hash, 64) != 0) {
293 #if 0
294 printf("\nFailed test %d\n", i);
295 for (i = 0; i < 64; ) {
296 printf("%02x ", tmp[i]);
297 if (!(++i & 15)) printf("\n");
298 }
299 #endif
300 return CRYPT_FAIL_TESTVECTOR;
301 }
302 }
303 return CRYPT_OK;
304 #endif
305 }
306
307
308 #endif
309