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