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-2025 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 2.5.0
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 WHIRLPOOL_OID[6] = {0x28, 0xCF, 0x06, 0x03, 0x00, 0x37};
155 
156 //Common interface for hash algorithms
158 {
159  "Whirlpool",
161  sizeof(WHIRLPOOL_OID),
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 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
186  WhirlpoolContext *context;
187 #else
188  WhirlpoolContext context[1];
189 #endif
190 
191  //Check parameters
192  if(data == NULL && length != 0)
194 
195  if(digest == NULL)
197 
198 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
199  //Allocate a memory buffer to hold the Whirlpool context
200  context = cryptoAllocMem(sizeof(WhirlpoolContext));
201  //Failed to allocate memory?
202  if(context == NULL)
203  return ERROR_OUT_OF_MEMORY;
204 #endif
205 
206  //Initialize the Whirlpool context
207  whirlpoolInit(context);
208  //Digest the message
209  whirlpoolUpdate(context, data, length);
210  //Finalize the Whirlpool message digest
211  whirlpoolFinal(context, digest);
212 
213 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
214  //Free previously allocated memory
215  cryptoFreeMem(context);
216 #endif
217 
218  //Successful operation
219  return NO_ERROR;
220 }
221 
222 
223 /**
224  * @brief Initialize Whirlpool message digest context
225  * @param[in] context Pointer to the Whirlpool context to initialize
226  **/
227 
229 {
230  uint_t i;
231 
232  //Set initial hash value
233  for(i = 0; i < 8; i++)
234  {
235  context->h[i] = 0;
236  }
237 
238  //Number of bytes in the buffer
239  context->size = 0;
240  //Total length of the message
241  context->totalSize = 0;
242 }
243 
244 
245 /**
246  * @brief Update the Whirlpool context with a portion of the message being hashed
247  * @param[in] context Pointer to the Whirlpool context
248  * @param[in] data Pointer to the buffer being hashed
249  * @param[in] length Length of the buffer
250  **/
251 
252 void whirlpoolUpdate(WhirlpoolContext *context, const void *data, size_t length)
253 {
254  size_t n;
255 
256  //Process the incoming data
257  while(length > 0)
258  {
259  //The buffer can hold at most 64 bytes
260  n = MIN(length, 64 - context->size);
261 
262  //Copy the data to the buffer
263  osMemcpy(context->buffer + context->size, data, n);
264 
265  //Update the Whirlpool context
266  context->size += n;
267  context->totalSize += n;
268  //Advance the data pointer
269  data = (uint8_t *) data + n;
270  //Remaining bytes to process
271  length -= n;
272 
273  //Process message in 8-word blocks
274  if(context->size == 64)
275  {
276  //Transform the 8-word block
277  whirlpoolProcessBlock(context);
278  //Empty the buffer
279  context->size = 0;
280  }
281  }
282 }
283 
284 
285 /**
286  * @brief Finish the Whirlpool message digest
287  * @param[in] context Pointer to the Whirlpool context
288  * @param[out] digest Calculated digest
289  **/
290 
291 void whirlpoolFinal(WhirlpoolContext *context, uint8_t *digest)
292 {
293  uint_t i;
294  size_t paddingSize;
295  uint64_t totalSize;
296 
297  //Length of the original message (before padding)
298  totalSize = context->totalSize * 8;
299 
300  //Pad the message so that its length is congruent to 32 modulo 64
301  if(context->size < 32)
302  {
303  paddingSize = 32 - context->size;
304  }
305  else
306  {
307  paddingSize = 64 + 32 - context->size;
308  }
309 
310  //Append padding
311  whirlpoolUpdate(context, padding, paddingSize);
312 
313  //Append the length of the original message
314  for(i = 0; i < 32; i++)
315  {
316  context->buffer[63 - i] = totalSize & 0xFF;
317  totalSize >>= 8;
318  }
319 
320  //Calculate the message digest
321  whirlpoolProcessBlock(context);
322 
323  //Copy the resulting digest
324  for(i = 0; i < (WHIRLPOOL_DIGEST_SIZE / 8); i++)
325  {
326  STORE64BE(context->h[i], digest + i * 8);
327  }
328 }
329 
330 
331 /**
332  * @brief Process message in 16-word blocks
333  * @param[in] context Pointer to the Whirlpool context
334  **/
335 
337 {
338  uint_t i;
339 
340  uint64_t *x = context->x;
341  uint64_t *k = context->k;
342  uint64_t *l = context->l;
343  uint64_t *state = context->state;
344 
345  //Convert from big-endian byte order to host byte order
346  for(i = 0; i < 8; i++)
347  {
348  x[i] = LOAD64BE(context->buffer + i * 8);
349  }
350 
351  k[0] = context->h[0];
352  k[1] = context->h[1];
353  k[2] = context->h[2];
354  k[3] = context->h[3];
355  k[4] = context->h[4];
356  k[5] = context->h[5];
357  k[6] = context->h[6];
358  k[7] = context->h[7];
359 
360  state[0] = x[0] ^ k[0];
361  state[1] = x[1] ^ k[1];
362  state[2] = x[2] ^ k[2];
363  state[3] = x[3] ^ k[3];
364  state[4] = x[4] ^ k[4];
365  state[5] = x[5] ^ k[5];
366  state[6] = x[6] ^ k[6];
367  state[7] = x[7] ^ k[7];
368 
369  //Iterate over all rounds
370  for(i = 0; i < 10; i++)
371  {
372  //Key schedule
373  RHO(l[0], k, 0, rc[i]);
374  RHO(l[1], k, 1, 0);
375  RHO(l[2], k, 2, 0);
376  RHO(l[3], k, 3, 0);
377  RHO(l[4], k, 4, 0);
378  RHO(l[5], k, 5, 0);
379  RHO(l[6], k, 6, 0);
380  RHO(l[7], k, 7, 0);
381 
382  k[0] = l[0];
383  k[1] = l[1];
384  k[2] = l[2];
385  k[3] = l[3];
386  k[4] = l[4];
387  k[5] = l[5];
388  k[6] = l[6];
389  k[7] = l[7];
390 
391  //Apply the round function
392  RHO(l[0], state, 0, k[0]);
393  RHO(l[1], state, 1, k[1]);
394  RHO(l[2], state, 2, k[2]);
395  RHO(l[3], state, 3, k[3]);
396  RHO(l[4], state, 4, k[4]);
397  RHO(l[5], state, 5, k[5]);
398  RHO(l[6], state, 6, k[6]);
399  RHO(l[7], state, 7, k[7]);
400 
401  state[0] = l[0];
402  state[1] = l[1];
403  state[2] = l[2];
404  state[3] = l[3];
405  state[4] = l[4];
406  state[5] = l[5];
407  state[6] = l[6];
408  state[7] = l[7];
409  }
410 
411  //Update the hash value
412  context->h[0] ^= state[0] ^ x[0];
413  context->h[1] ^= state[1] ^ x[1];
414  context->h[2] ^= state[2] ^ x[2];
415  context->h[3] ^= state[3] ^ x[3];
416  context->h[4] ^= state[4] ^ x[4];
417  context->h[5] ^= state[5] ^ x[5];
418  context->h[6] ^= state[6] ^ x[6];
419  context->h[7] ^= state[7] ^ x[7];
420 }
421 
422 #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:252
uint64_t k[8]
Definition: whirlpool.h:65
#define WHIRLPOOL_MIN_PAD_SIZE
Definition: whirlpool.h:42
void(* HashAlgoInit)(void *context)
Definition: crypto.h:1027
const uint8_t WHIRLPOOL_OID[6]
Definition: whirlpool.c:154
#define WHIRLPOOL_BLOCK_SIZE
Definition: whirlpool.h:38
uint8_t x
Definition: lldp_ext_med.h:211
uint64_t h[8]
Definition: whirlpool.h:58
uint8_t t
Definition: lldp_ext_med.h:212
#define TRUE
Definition: os_port.h:50
#define RHO(b, a, n, c)
Definition: whirlpool.c:47
uint8_t data[]
Definition: ethernet.h:222
uint8_t buffer[64]
Definition: whirlpool.h:62
@ 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:336
void(* HashAlgoUpdate)(void *context, const void *data, size_t length)
Definition: crypto.h:1029
uint64_t totalSize
Definition: whirlpool.h:70
uint64_t l[8]
Definition: whirlpool.h:66
#define LOAD64BE(p)
Definition: cpu_endian.h:246
void whirlpoolInit(WhirlpoolContext *context)
Initialize Whirlpool message digest context.
Definition: whirlpool.c:228
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
#define osMemcpy(dest, src, length)
Definition: os_port.h:144
error_t
Error codes.
Definition: error.h:43
uint64_t x[8]
Definition: whirlpool.h:61
General definitions for cryptographic algorithms.
uint8_t length
Definition: tcp.h:375
#define MIN(a, b)
Definition: os_port.h:63
uint64_t state[8]
Definition: whirlpool.h:67
void whirlpoolFinal(WhirlpoolContext *context, uint8_t *digest)
Finish the Whirlpool message digest.
Definition: whirlpool.c:291
Whirlpool algorithm context.
Definition: whirlpool.h:57
void(* HashAlgoFinal)(void *context, uint8_t *digest)
Definition: crypto.h:1031
uint8_t l
Definition: ndp.h:412
#define STORE64BE(a, p)
Definition: cpu_endian.h:322
uint8_t n
#define cryptoFreeMem(p)
Definition: crypto.h:826
#define cryptoAllocMem(size)
Definition: crypto.h:821
Common interface for hash algorithms.
Definition: crypto.h:1082
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:57
#define WHIRLPOOL_DIGEST_SIZE
Definition: whirlpool.h:40
error_t(* HashAlgoCompute)(const void *data, size_t length, uint8_t *digest)
Definition: crypto.h:1024
@ NO_ERROR
Success.
Definition: error.h:44