]> pd.if.org Git - zpackage/blob - libtomcrypt/src/hashes/whirl/whirl.c
commit files needed for zpm-fetchurl
[zpackage] / libtomcrypt / src / hashes / whirl / whirl.c
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
10 /**
11    @file whirl.c
12    LTC_WHIRLPOOL (using their new sbox) hash function by Tom St Denis
13 */
14
15 #include "tomcrypt.h"
16
17 #ifdef LTC_WHIRLPOOL
18
19 const struct ltc_hash_descriptor whirlpool_desc =
20 {
21     "whirlpool",
22     11,
23     64,
24     64,
25
26    /* OID */
27    { 1, 0, 10118, 3, 0, 55 },
28    6,
29
30     &whirlpool_init,
31     &whirlpool_process,
32     &whirlpool_done,
33     &whirlpool_test,
34     NULL
35 };
36
37 /* the sboxes */
38 #define __LTC_WHIRLTAB_C__
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 (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "WHIRLPOOL", i)) {
293          return CRYPT_FAIL_TESTVECTOR;
294       }
295   }
296   return CRYPT_OK;
297  #endif
298 }
299
300
301 #endif
302
303
304 /* ref:         $Format:%D$ */
305 /* git commit:  $Format:%H$ */
306 /* commit time: $Format:%ai$ */