whirlpool.c
Go to the documentation of this file.
1 /**
2  * @file whirlpool.c
3  * @brief Whirlpool hash function
4  *
5  * @section License
6  *
7  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This file is part of CycloneCrypto Open.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @section Description
26  *
27  * Whirlpool is a hash function that operates on messages less than 2^256 bits
28  * in length, and produces a message digest of 512 bits
29  *
30  * @author Oryx Embedded SARL (www.oryx-embedded.com)
31  * @version 1.9.0
32  **/
33 
34 //Switch to the appropriate trace level
35 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
36 
37 //Dependencies
38 #include "core/crypto.h"
39 #include "hash/whirlpool.h"
40 
41 //Check crypto library configuration
42 #if (WHIRLPOOL_SUPPORT == ENABLED)
43 
44 //Round function
45 #define RHO(b, a, n, c) \
46 { \
47  b = t[(a[n] >> 56) & 0xFF]; \
48  b ^= ROR64(t[(a[(n + 7) % 8] >> 48) & 0xFF], 8); \
49  b ^= ROR64(t[(a[(n + 6) % 8] >> 40) & 0xFF], 16); \
50  b ^= ROR64(t[(a[(n + 5) % 8] >> 32) & 0xFF], 24); \
51  b ^= ROR64(t[(a[(n + 4) % 8] >> 24) & 0xFF], 32); \
52  b ^= ROR64(t[(a[(n + 3) % 8] >> 16) & 0xFF], 40); \
53  b ^= ROR64(t[(a[(n + 2) % 8] >> 8) & 0xFF], 48); \
54  b ^= ROR64(t[a[(n + 1) % 8] & 0xFF], 56); \
55  b ^= c; \
56 }
57 
58 //Whirlpool padding
59 static const uint8_t padding[64] =
60 {
61  0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
65 };
66 
67 //Whirlpool constants
68 static const uint64_t rc[10] =
69 {
70  0x1823C6E887B8014F,
71  0x36A6D2F5796F9152,
72  0x60BC9B8EA30C7B35,
73  0x1DE0D7C22E4BFE57,
74  0x157737E59FF04ADA,
75  0x58C9290AB1A06B85,
76  0xBD5D10F4CB3E0567,
77  0xE427418BA77D95D8,
78  0xFBEE7C66DD17479E,
79  0xCA2DBF07AD5A8333
80 };
81 
82 //Whirlpool look-up table
83 static const uint64_t t[256] =
84 {
85  0x18186018C07830D8, 0x23238C2305AF4626, 0xC6C63FC67EF991B8, 0xE8E887E8136FCDFB,
86  0x878726874CA113CB, 0xB8B8DAB8A9626D11, 0x0101040108050209, 0x4F4F214F426E9E0D,
87  0x3636D836ADEE6C9B, 0xA6A6A2A6590451FF, 0xD2D26FD2DEBDB90C, 0xF5F5F3F5FB06F70E,
88  0x7979F979EF80F296, 0x6F6FA16F5FCEDE30, 0x91917E91FCEF3F6D, 0x52525552AA07A4F8,
89  0x60609D6027FDC047, 0xBCBCCABC89766535, 0x9B9B569BACCD2B37, 0x8E8E028E048C018A,
90  0xA3A3B6A371155BD2, 0x0C0C300C603C186C, 0x7B7BF17BFF8AF684, 0x3535D435B5E16A80,
91  0x1D1D741DE8693AF5, 0xE0E0A7E05347DDB3, 0xD7D77BD7F6ACB321, 0xC2C22FC25EED999C,
92  0x2E2EB82E6D965C43, 0x4B4B314B627A9629, 0xFEFEDFFEA321E15D, 0x575741578216AED5,
93  0x15155415A8412ABD, 0x7777C1779FB6EEE8, 0x3737DC37A5EB6E92, 0xE5E5B3E57B56D79E,
94  0x9F9F469F8CD92313, 0xF0F0E7F0D317FD23, 0x4A4A354A6A7F9420, 0xDADA4FDA9E95A944,
95  0x58587D58FA25B0A2, 0xC9C903C906CA8FCF, 0x2929A429558D527C, 0x0A0A280A5022145A,
96  0xB1B1FEB1E14F7F50, 0xA0A0BAA0691A5DC9, 0x6B6BB16B7FDAD614, 0x85852E855CAB17D9,
97  0xBDBDCEBD8173673C, 0x5D5D695DD234BA8F, 0x1010401080502090, 0xF4F4F7F4F303F507,
98  0xCBCB0BCB16C08BDD, 0x3E3EF83EEDC67CD3, 0x0505140528110A2D, 0x676781671FE6CE78,
99  0xE4E4B7E47353D597, 0x27279C2725BB4E02, 0x4141194132588273, 0x8B8B168B2C9D0BA7,
100  0xA7A7A6A7510153F6, 0x7D7DE97DCF94FAB2, 0x95956E95DCFB3749, 0xD8D847D88E9FAD56,
101  0xFBFBCBFB8B30EB70, 0xEEEE9FEE2371C1CD, 0x7C7CED7CC791F8BB, 0x6666856617E3CC71,
102  0xDDDD53DDA68EA77B, 0x17175C17B84B2EAF, 0x4747014702468E45, 0x9E9E429E84DC211A,
103  0xCACA0FCA1EC589D4, 0x2D2DB42D75995A58, 0xBFBFC6BF9179632E, 0x07071C07381B0E3F,
104  0xADAD8EAD012347AC, 0x5A5A755AEA2FB4B0, 0x838336836CB51BEF, 0x3333CC3385FF66B6,
105  0x636391633FF2C65C, 0x02020802100A0412, 0xAAAA92AA39384993, 0x7171D971AFA8E2DE,
106  0xC8C807C80ECF8DC6, 0x19196419C87D32D1, 0x494939497270923B, 0xD9D943D9869AAF5F,
107  0xF2F2EFF2C31DF931, 0xE3E3ABE34B48DBA8, 0x5B5B715BE22AB6B9, 0x88881A8834920DBC,
108  0x9A9A529AA4C8293E, 0x262698262DBE4C0B, 0x3232C8328DFA64BF, 0xB0B0FAB0E94A7D59,
109  0xE9E983E91B6ACFF2, 0x0F0F3C0F78331E77, 0xD5D573D5E6A6B733, 0x80803A8074BA1DF4,
110  0xBEBEC2BE997C6127, 0xCDCD13CD26DE87EB, 0x3434D034BDE46889, 0x48483D487A759032,
111  0xFFFFDBFFAB24E354, 0x7A7AF57AF78FF48D, 0x90907A90F4EA3D64, 0x5F5F615FC23EBE9D,
112  0x202080201DA0403D, 0x6868BD6867D5D00F, 0x1A1A681AD07234CA, 0xAEAE82AE192C41B7,
113  0xB4B4EAB4C95E757D, 0x54544D549A19A8CE, 0x93937693ECE53B7F, 0x222288220DAA442F,
114  0x64648D6407E9C863, 0xF1F1E3F1DB12FF2A, 0x7373D173BFA2E6CC, 0x12124812905A2482,
115  0x40401D403A5D807A, 0x0808200840281048, 0xC3C32BC356E89B95, 0xECEC97EC337BC5DF,
116  0xDBDB4BDB9690AB4D, 0xA1A1BEA1611F5FC0, 0x8D8D0E8D1C830791, 0x3D3DF43DF5C97AC8,
117  0x97976697CCF1335B, 0x0000000000000000, 0xCFCF1BCF36D483F9, 0x2B2BAC2B4587566E,
118  0x7676C57697B3ECE1, 0x8282328264B019E6, 0xD6D67FD6FEA9B128, 0x1B1B6C1BD87736C3,
119  0xB5B5EEB5C15B7774, 0xAFAF86AF112943BE, 0x6A6AB56A77DFD41D, 0x50505D50BA0DA0EA,
120  0x45450945124C8A57, 0xF3F3EBF3CB18FB38, 0x3030C0309DF060AD, 0xEFEF9BEF2B74C3C4,
121  0x3F3FFC3FE5C37EDA, 0x55554955921CAAC7, 0xA2A2B2A2791059DB, 0xEAEA8FEA0365C9E9,
122  0x656589650FECCA6A, 0xBABAD2BAB9686903, 0x2F2FBC2F65935E4A, 0xC0C027C04EE79D8E,
123  0xDEDE5FDEBE81A160, 0x1C1C701CE06C38FC, 0xFDFDD3FDBB2EE746, 0x4D4D294D52649A1F,
124  0x92927292E4E03976, 0x7575C9758FBCEAFA, 0x06061806301E0C36, 0x8A8A128A249809AE,
125  0xB2B2F2B2F940794B, 0xE6E6BFE66359D185, 0x0E0E380E70361C7E, 0x1F1F7C1FF8633EE7,
126  0x6262956237F7C455, 0xD4D477D4EEA3B53A, 0xA8A89AA829324D81, 0x96966296C4F43152,
127  0xF9F9C3F99B3AEF62, 0xC5C533C566F697A3, 0x2525942535B14A10, 0x59597959F220B2AB,
128  0x84842A8454AE15D0, 0x7272D572B7A7E4C5, 0x3939E439D5DD72EC, 0x4C4C2D4C5A619816,
129  0x5E5E655ECA3BBC94, 0x7878FD78E785F09F, 0x3838E038DDD870E5, 0x8C8C0A8C14860598,
130  0xD1D163D1C6B2BF17, 0xA5A5AEA5410B57E4, 0xE2E2AFE2434DD9A1, 0x616199612FF8C24E,
131  0xB3B3F6B3F1457B42, 0x2121842115A54234, 0x9C9C4A9C94D62508, 0x1E1E781EF0663CEE,
132  0x4343114322528661, 0xC7C73BC776FC93B1, 0xFCFCD7FCB32BE54F, 0x0404100420140824,
133  0x51515951B208A2E3, 0x99995E99BCC72F25, 0x6D6DA96D4FC4DA22, 0x0D0D340D68391A65,
134  0xFAFACFFA8335E979, 0xDFDF5BDFB684A369, 0x7E7EE57ED79BFCA9, 0x242490243DB44819,
135  0x3B3BEC3BC5D776FE, 0xABAB96AB313D4B9A, 0xCECE1FCE3ED181F0, 0x1111441188552299,
136  0x8F8F068F0C890383, 0x4E4E254E4A6B9C04, 0xB7B7E6B7D1517366, 0xEBEB8BEB0B60CBE0,
137  0x3C3CF03CFDCC78C1, 0x81813E817CBF1FFD, 0x94946A94D4FE3540, 0xF7F7FBF7EB0CF31C,
138  0xB9B9DEB9A1676F18, 0x13134C13985F268B, 0x2C2CB02C7D9C5851, 0xD3D36BD3D6B8BB05,
139  0xE7E7BBE76B5CD38C, 0x6E6EA56E57CBDC39, 0xC4C437C46EF395AA, 0x03030C03180F061B,
140  0x565645568A13ACDC, 0x44440D441A49885E, 0x7F7FE17FDF9EFEA0, 0xA9A99EA921374F88,
141  0x2A2AA82A4D825467, 0xBBBBD6BBB16D6B0A, 0xC1C123C146E29F87, 0x53535153A202A6F1,
142  0xDCDC57DCAE8BA572, 0x0B0B2C0B58271653, 0x9D9D4E9D9CD32701, 0x6C6CAD6C47C1D82B,
143  0x3131C43195F562A4, 0x7474CD7487B9E8F3, 0xF6F6FFF6E309F115, 0x464605460A438C4C,
144  0xACAC8AAC092645A5, 0x89891E893C970FB5, 0x14145014A04428B4, 0xE1E1A3E15B42DFBA,
145  0x16165816B04E2CA6, 0x3A3AE83ACDD274F7, 0x6969B9696FD0D206, 0x09092409482D1241,
146  0x7070DD70A7ADE0D7, 0xB6B6E2B6D954716F, 0xD0D067D0CEB7BD1E, 0xEDED93ED3B7EC7D6,
147  0xCCCC17CC2EDB85E2, 0x424215422A578468, 0x98985A98B4C22D2C, 0xA4A4AAA4490E55ED,
148  0x2828A0285D885075, 0x5C5C6D5CDA31B886, 0xF8F8C7F8933FED6B, 0x8686228644A411C2
149 };
150 
151 //Whirlpool object identifier (1.0.10118.3.0.55)
152 const uint8_t whirlpoolOid[6] = {0x28, 0xCF, 0x06, 0x03, 0x00, 0x37};
153 
154 //Common interface for hash algorithms
156 {
157  "WHIRLPOOL",
158  whirlpoolOid,
159  sizeof(whirlpoolOid),
160  sizeof(WhirlpoolContext),
167 };
168 
169 
170 /**
171  * @brief Digest a message using Whirlpool
172  * @param[in] data Pointer to the message being hashed
173  * @param[in] length Length of the message
174  * @param[out] digest Pointer to the calculated digest
175  * @return Error code
176  **/
177 
178 error_t whirlpoolCompute(const void *data, size_t length, uint8_t *digest)
179 {
180  //Allocate a memory buffer to hold the Whirlpool context
182  //Failed to allocate memory?
183  if(context == NULL)
184  return ERROR_OUT_OF_MEMORY;
185 
186  //Initialize the Whirlpool context
187  whirlpoolInit(context);
188  //Digest the message
189  whirlpoolUpdate(context, data, length);
190  //Finalize the Whirlpool message digest
191  whirlpoolFinal(context, digest);
192 
193  //Free previously allocated memory
194  cryptoFreeMem(context);
195  //Successful processing
196  return NO_ERROR;
197 }
198 
199 
200 /**
201  * @brief Initialize Whirlpool message digest context
202  * @param[in] context Pointer to the Whirlpool context to initialize
203  **/
204 
206 {
207  uint_t i;
208 
209  //Set initial hash value
210  for(i = 0; i < 8; i++)
211  context->h[i] = 0;
212 
213  //Number of bytes in the buffer
214  context->size = 0;
215  //Total length of the message
216  context->totalSize = 0;
217 }
218 
219 
220 /**
221  * @brief Update the Whirlpool context with a portion of the message being hashed
222  * @param[in] context Pointer to the Whirlpool context
223  * @param[in] data Pointer to the buffer being hashed
224  * @param[in] length Length of the buffer
225  **/
226 
227 void whirlpoolUpdate(WhirlpoolContext *context, const void *data, size_t length)
228 {
229  size_t n;
230 
231  //Process the incoming data
232  while(length > 0)
233  {
234  //The buffer can hold at most 64 bytes
235  n = MIN(length, 64 - context->size);
236 
237  //Copy the data to the buffer
238  cryptoMemcpy(context->buffer + context->size, data, n);
239 
240  //Update the Whirlpool context
241  context->size += n;
242  context->totalSize += n;
243  //Advance the data pointer
244  data = (uint8_t *) data + n;
245  //Remaining bytes to process
246  length -= n;
247 
248  //Process message in 8-word blocks
249  if(context->size == 64)
250  {
251  //Transform the 8-word block
252  whirlpoolProcessBlock(context);
253  //Empty the buffer
254  context->size = 0;
255  }
256  }
257 }
258 
259 
260 /**
261  * @brief Finish the Whirlpool message digest
262  * @param[in] context Pointer to the Whirlpool context
263  * @param[out] digest Calculated digest (optional parameter)
264  **/
265 
266 void whirlpoolFinal(WhirlpoolContext *context, uint8_t *digest)
267 {
268  uint_t i;
269  size_t paddingSize;
270  uint64_t totalSize;
271 
272  //Length of the original message (before padding)
273  totalSize = context->totalSize * 8;
274 
275  //Pad the message so that its length is congruent to 32 modulo 64
276  if(context->size < 32)
277  paddingSize = 32 - context->size;
278  else
279  paddingSize = 64 + 32 - context->size;
280 
281  //Append padding
282  whirlpoolUpdate(context, padding, paddingSize);
283 
284  //Append the length of the original message
285  context->x[4] = 0;
286  context->x[5] = 0;
287  context->x[6] = 0;
288  context->x[7] = htobe64(totalSize);
289 
290  //Calculate the message digest
291  whirlpoolProcessBlock(context);
292 
293  //Convert from host byte order to big-endian byte order
294  for(i = 0; i < 8; i++)
295  context->h[i] = htobe64(context->h[i]);
296 
297  //Copy the resulting digest
298  if(digest != NULL)
299  cryptoMemcpy(digest, context->digest, WHIRLPOOL_DIGEST_SIZE);
300 }
301 
302 
303 /**
304  * @brief Process message in 16-word blocks
305  * @param[in] context Pointer to the Whirlpool context
306  **/
307 
309 {
310  uint_t i;
311 
312  uint64_t *x = context->x;
313  uint64_t *k = context->k;
314  uint64_t *l = context->l;
315  uint64_t *state = context->state;
316 
317  //Convert from big-endian byte order to host byte order
318  for(i = 0; i < 8; i++)
319  x[i] = betoh64(x[i]);
320 
321  k[0] = context->h[0];
322  k[1] = context->h[1];
323  k[2] = context->h[2];
324  k[3] = context->h[3];
325  k[4] = context->h[4];
326  k[5] = context->h[5];
327  k[6] = context->h[6];
328  k[7] = context->h[7];
329 
330  state[0] = x[0] ^ k[0];
331  state[1] = x[1] ^ k[1];
332  state[2] = x[2] ^ k[2];
333  state[3] = x[3] ^ k[3];
334  state[4] = x[4] ^ k[4];
335  state[5] = x[5] ^ k[5];
336  state[6] = x[6] ^ k[6];
337  state[7] = x[7] ^ k[7];
338 
339  //Iterate over all rounds
340  for(i = 0; i < 10; i++)
341  {
342  //Key schedule
343  RHO(l[0], k, 0, rc[i]);
344  RHO(l[1], k, 1, 0);
345  RHO(l[2], k, 2, 0);
346  RHO(l[3], k, 3, 0);
347  RHO(l[4], k, 4, 0);
348  RHO(l[5], k, 5, 0);
349  RHO(l[6], k, 6, 0);
350  RHO(l[7], k, 7, 0);
351 
352  k[0] = l[0];
353  k[1] = l[1];
354  k[2] = l[2];
355  k[3] = l[3];
356  k[4] = l[4];
357  k[5] = l[5];
358  k[6] = l[6];
359  k[7] = l[7];
360 
361  //Apply the round function
362  RHO(l[0], state, 0, k[0]);
363  RHO(l[1], state, 1, k[1]);
364  RHO(l[2], state, 2, k[2]);
365  RHO(l[3], state, 3, k[3]);
366  RHO(l[4], state, 4, k[4]);
367  RHO(l[5], state, 5, k[5]);
368  RHO(l[6], state, 6, k[6]);
369  RHO(l[7], state, 7, k[7]);
370 
371  state[0] = l[0];
372  state[1] = l[1];
373  state[2] = l[2];
374  state[3] = l[3];
375  state[4] = l[4];
376  state[5] = l[5];
377  state[6] = l[6];
378  state[7] = l[7];
379  }
380 
381  //Update the hash value
382  context->h[0] ^= state[0] ^ x[0];
383  context->h[1] ^= state[1] ^ x[1];
384  context->h[2] ^= state[2] ^ x[2];
385  context->h[3] ^= state[3] ^ x[3];
386  context->h[4] ^= state[4] ^ x[4];
387  context->h[5] ^= state[5] ^ x[5];
388  context->h[6] ^= state[6] ^ x[6];
389  context->h[7] ^= state[7] ^ x[7];
390 }
391 
392 #endif
uint8_t buffer[64]
Definition: whirlpool.h:64
Whirlpool algorithm context.
Definition: whirlpool.h:54
#define cryptoMemcpy(dest, src, length)
Definition: crypto.h:590
#define cryptoFreeMem(p)
Definition: crypto.h:578
Whirlpool hash function.
void whirlpoolUpdate(WhirlpoolContext *context, const void *data, size_t length)
Update the Whirlpool context with a portion of the message being hashed.
Definition: whirlpool.c:227
error_t(* HashAlgoCompute)(const void *data, size_t length, uint8_t *digest)
Definition: crypto.h:1020
#define cryptoAllocMem(size)
Definition: crypto.h:573
uint8_t digest[64]
Definition: whirlpool.h:59
General definitions for cryptographic algorithms.
const HashAlgo whirlpoolHashAlgo
Definition: whirlpool.c:155
uint64_t h[8]
Definition: whirlpool.h:58
void whirlpoolFinal(WhirlpoolContext *context, uint8_t *digest)
Finish the Whirlpool message digest.
Definition: whirlpool.c:266
uint32_t totalSize
error_t whirlpoolCompute(const void *data, size_t length, uint8_t *digest)
Digest a message using Whirlpool.
Definition: whirlpool.c:178
void whirlpoolProcessBlock(WhirlpoolContext *context)
Process message in 16-word blocks.
Definition: whirlpool.c:308
uint64_t l[8]
Definition: whirlpool.h:68
#define WHIRLPOOL_BLOCK_SIZE
Definition: whirlpool.h:36
uint64_t totalSize
Definition: whirlpool.h:72
void(* HashAlgoInit)(void *context)
Definition: crypto.h:1021
#define RHO(b, a, n, c)
Definition: whirlpool.c:45
uint64_t state[8]
Definition: whirlpool.h:69
uint64_t x[8]
Definition: whirlpool.h:63
#define MIN(a, b)
Definition: os_port.h:60
void(* HashAlgoUpdate)(void *context, const void *data, size_t length)
Definition: crypto.h:1022
Success.
Definition: error.h:42
error_t
Error codes.
Definition: error.h:40
#define WHIRLPOOL_DIGEST_SIZE
Definition: whirlpool.h:38
unsigned int uint_t
Definition: compiler_port.h:43
#define betoh64(value)
Definition: cpu_endian.h:429
#define htobe64(value)
Definition: cpu_endian.h:421
const uint8_t whirlpoolOid[6]
Definition: whirlpool.c:152
uint8_t data[]
Definition: dtls_misc.h:167
void whirlpoolInit(WhirlpoolContext *context)
Initialize Whirlpool message digest context.
Definition: whirlpool.c:205
uint8_t l
Definition: ndp.h:408
Common interface for hash algorithms.
Definition: crypto.h:1054
uint8_t length
Definition: dtls_misc.h:140
uint8_t n
uint64_t k[8]
Definition: whirlpool.h:67
void(* HashAlgoFinal)(void *context, uint8_t *digest)
Definition: crypto.h:1023