File Coverage

_edonr.c
Criterion Covered Total %
statement 73 113 64.6
branch 17 36 47.2
condition n/a
subroutine n/a
pod n/a
total 90 149 60.4


line stmt bran cond sub pod time code
1             /* edonr.c - an implementation of EDON-R 256/224/384/512 hash functions
2             *
3             * Copyright (c) 2011, Aleksey Kravchenko
4             *
5             * Permission to use, copy, modify, and/or distribute this software for any
6             * purpose with or without fee is hereby granted.
7             *
8             * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
9             * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10             * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11             * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12             * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13             * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14             * PERFORMANCE OF THIS SOFTWARE.
15             *
16             * This implementation is based on the article:
17             * D. Gligoroski, R. S. Odegard, M. Mihova, S. J. Knapskog, ...,
18             * Cryptographic Hash Function EDON-R - Submission to NIST, 2008
19             *
20             * EDON-R has been designed to be much more efficient than SHA-2
21             * cryptographic hash functions, offering the same or better security.
22             */
23              
24             #include
25             #include "byte_order.h"
26             #include "edonr.h"
27              
28             /**
29             * Initialize context before calculating hash.
30             *
31             * @param ctx context to initialize
32             */
33 2           void rhash_edonr256_init(edonr_ctx* ctx)
34             {
35             static const unsigned EDONR256_H0[16] = {
36             0x40414243, 0x44454647, 0x48494a4b, 0x4c4d4e4f, 0x50515253, 0x54555657,
37             0x58595a5b, 0x5c5d5e5f, 0x60616263, 0x64656667, 0x68696a6b, 0x6c6d6e6f,
38             0x70717273, 0x74757677, 0x78797a7b, 0x7c7d7e7f
39             };
40              
41             #if FULL_CTX_INITIALIZATION
42             memset(ctx, 0, sizeof(*ctx));
43             #else
44 2           ctx->length = 0;
45             #endif
46 2           ctx->digest_length = edonr256_hash_size;
47 2           memcpy(ctx->u.data256.hash, EDONR256_H0, sizeof(EDONR256_H0));
48 2           }
49              
50             /**
51             * Initialize context before calculating hash.
52             *
53             * @param ctx context to initialize
54             */
55 0           void rhash_edonr224_init(struct edonr_ctx* ctx)
56             {
57             static const unsigned EDONR224_H0[16] = {
58             0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f, 0x10111213, 0x14151617,
59             0x18191a1b, 0x1c1d1e1f, 0x20212223, 0x24252627, 0x28292a2b, 0x2c2d2e2f,
60             0x30313233, 0x24353637, 0x38393a3b, 0x3c3d3e3f
61             };
62              
63             #if FULL_CTX_INITIALIZATION
64             memset(ctx, 0, sizeof(*ctx));
65             #else
66 0           ctx->length = 0;
67             #endif
68 0           ctx->digest_length = edonr224_hash_size;
69 0           memcpy(ctx->u.data256.hash, EDONR224_H0, sizeof(EDONR224_H0));
70 0           }
71              
72             /**
73             * Initialize context before calculating hash.
74             *
75             * @param ctx context to initialize
76             */
77 2           void rhash_edonr512_init(edonr_ctx* ctx)
78             {
79             static const uint64_t EDONR512_H0[16] = {
80             I64(0x8081828384858687), I64(0x88898a8b8c8d8e8f), I64(0x9091929394959697),
81             I64(0x98999a9b9c9d9e9f), I64(0xa0a1a2a3a4a5a6a7), I64(0xa8a9aaabacadaeaf),
82             I64(0xb0b1b2b3b4b5b6b7), I64(0xb8b9babbbcbdbebf), I64(0xc0c1c2c3c4c5c6c7),
83             I64(0xc8c9cacbcccdcecf), I64(0xd0d1d2d3d4d5d6d7), I64(0xd8d9dadbdcdddedf),
84             I64(0xe0e1e2e3e4e5e6e7), I64(0xe8e9eaebecedeeef), I64(0xf0f1f2f3f4f5f6f7),
85             I64(0xf8f9fafbfcfdfeff)
86             };
87              
88             #if FULL_CTX_INITIALIZATION
89             memset(ctx, 0, sizeof(*ctx));
90             #else
91 2           ctx->length = 0;
92             #endif
93 2           ctx->digest_length = edonr512_hash_size;
94 2           memcpy(ctx->u.data512.hash, EDONR512_H0, sizeof(EDONR512_H0));
95 2           }
96              
97             /**
98             * Initialize context before calculating hash.
99             *
100             * @param ctx context to initialize
101             */
102 0           void rhash_edonr384_init(struct edonr_ctx* ctx)
103             {
104             static const uint64_t EDONR384_H0[16] = {
105             I64(0x0001020304050607), I64(0x08090a0b0c0d0e0f), I64(0x1011121314151617),
106             I64(0x18191a1b1c1d1e1f), I64(0x2021222324252627), I64(0x28292a2b2c2d2e2f),
107             I64(0x3031323324353637), I64(0x38393a3b3c3d3e3f), I64(0x4041424344454647),
108             I64(0x48494a4b4c4d4e4f), I64(0x5051525354555657), I64(0x58595a5b5c5d5e5f),
109             I64(0x6061626364656667), I64(0x68696a6b6c6d6e6f), I64(0x7071727374757677),
110             I64(0x78797a7b7c7d7e7f)
111             };
112              
113             #if FULL_CTX_INITIALIZATION
114             memset(ctx, 0, sizeof(*ctx));
115             #else
116 0           ctx->length = 0;
117             #endif
118 0           ctx->digest_length = edonr384_hash_size;
119 0           memcpy(ctx->u.data512.hash, EDONR384_H0, sizeof(EDONR384_H0));
120 0           }
121              
122             /* Q256 macro, taken from eBASH submission */
123             #define Q256(x0,x1,x2,x3,x4,x5,x6,x7,y0,y1,y2,y3,y4,y5,y6,y7,z0,z1,z2,z3,z4,z5,z6,z7) \
124             {\
125             /* The First Latin Square\
126             0 7 1 3 2 4 6 5\
127             4 1 7 6 3 0 5 2\
128             7 0 4 2 5 3 1 6\
129             1 4 0 5 6 2 7 3\
130             2 3 6 7 1 5 0 4\
131             5 2 3 1 7 6 4 0\
132             3 6 5 0 4 7 2 1\
133             6 5 2 4 0 1 3 7\
134             */\
135             t8 = x0 + x4; \
136             t9 = x1 + x7; \
137             t12 = t8 + t9; \
138             t10 = x2 + x3; \
139             t11 = x5 + x6; \
140             t13 = t10 + t11; \
141             t0 = 0xaaaaaaaa + t12 + x2; \
142             t1 = t12 + x3; \
143             t1 = ROTL32((t1), 5); \
144             t2 = t12 + x6; \
145             t2 = ROTL32((t2), 11); \
146             t3 = t13 + x7; \
147             t3 = ROTL32((t3), 13); \
148             t4 = x1 + t13; \
149             t4 = ROTL32((t4), 17); \
150             t5 = t8 + t10 + x5; \
151             t5 = ROTL32((t5), 19); \
152             t6 = x0 + t9 + t11; \
153             t6 = ROTL32((t6), 29); \
154             t7 = t13 + x4; \
155             t7 = ROTL32((t7), 31); \
156             \
157             t16 = t0 ^ t4; \
158             t17 = t1 ^ t7; \
159             t18 = t2 ^ t3; \
160             t19 = t5 ^ t6; \
161             t8 = t3 ^ t19; \
162             t9 = t2 ^ t19; \
163             t10 = t18 ^ t5; \
164             t11 = t16 ^ t1; \
165             t12 = t16 ^ t7; \
166             t13 = t17 ^ t6; \
167             t14 = t18 ^ t4; \
168             t15 = t0 ^ t17; \
169             \
170             /* The Second Orthogonal Latin Square\
171             0 4 2 3 1 6 5 7\
172             7 6 3 2 5 4 1 0\
173             5 3 1 6 0 2 7 4\
174             1 0 5 4 3 7 2 6\
175             2 1 0 7 4 5 6 3\
176             3 5 7 0 6 1 4 2\
177             4 7 6 1 2 0 3 5\
178             6 2 4 5 7 3 0 1\
179             */\
180             t16 = y0 + y1; \
181             t17 = y2 + y5; \
182             t20 = t16 + t17; \
183             t18 = y3 + y4; \
184             t22 = t16 + t18; \
185             t19 = y6 + y7; \
186             t21 = t18 + t19; \
187             t23 = t17 + t19; \
188             t0 = 0x55555555 + t20 + y7; \
189             t1 = t22 + y6; \
190             t1 = ROTL32((t1), 3); \
191             t2 = t20 + y3; \
192             t2 = ROTL32((t2), 7); \
193             t3 = y2 + t21; \
194             t3 = ROTL32((t3), 11); \
195             t4 = t22 + y5; \
196             t4 = ROTL32((t4), 17); \
197             t5 = t23 + y4; \
198             t5 = ROTL32((t5), 19); \
199             t6 = y1 + t23; \
200             t6 = ROTL32((t6), 23); \
201             t7 = y0 + t21; \
202             t7 = ROTL32((t7), 29); \
203             \
204             t16 = t0 ^ t1; \
205             t17 = t2 ^ t5; \
206             t18 = t3 ^ t4; \
207             t19 = t6 ^ t7; \
208             z5 = t8 + (t18 ^ t6); \
209             z6 = t9 + (t17 ^ t7); \
210             z7 = t10 + (t4 ^ t19); \
211             z0 = t11 + (t16 ^ t5); \
212             z1 = t12 + (t2 ^ t19); \
213             z2 = t13 + (t16 ^ t3); \
214             z3 = t14 + (t0 ^ t18); \
215             z4 = t15 + (t1 ^ t17); \
216             }
217              
218             /* Q512 macro, taken from eBASH submission */
219             #define Q512(x0,x1,x2,x3,x4,x5,x6,x7,y0,y1,y2,y3,y4,y5,y6,y7,z0,z1,z2,z3,z4,z5,z6,z7) \
220             {\
221             /* First Latin Square\
222             0 7 1 3 2 4 6 5\
223             4 1 7 6 3 0 5 2\
224             7 0 4 2 5 3 1 6\
225             1 4 0 5 6 2 7 3\
226             2 3 6 7 1 5 0 4\
227             5 2 3 1 7 6 4 0\
228             3 6 5 0 4 7 2 1\
229             6 5 2 4 0 1 3 7\
230             */\
231             t8 = x0 + x4; \
232             t9 = x1 + x7; \
233             t12 = t8 + t9; \
234             t10 = x2 + x3; \
235             t11 = x5 + x6; \
236             t13 = t10 + t11; \
237             t0 = I64(0xaaaaaaaaaaaaaaaa) + t12 + x2; \
238             t1 = t12 + x3; \
239             t1 = ROTL64((t1), 5); \
240             t2 = t12 + x6; \
241             t2 = ROTL64((t2),19); \
242             t3 = t13 + x7; \
243             t3 = ROTL64((t3),29); \
244             t4 = x1 + t13; \
245             t4 = ROTL64((t4),31); \
246             t5 = t8 + t10 + x5; \
247             t5 = ROTL64((t5),41); \
248             t6 = x0 + t9 + t11; \
249             t6 = ROTL64((t6),57); \
250             t7 = t13 + x4; \
251             t7 = ROTL64((t7),61); \
252             \
253             t16 = t0 ^ t4; \
254             t17 = t1 ^ t7; \
255             t18 = t2 ^ t3; \
256             t19 = t5 ^ t6; \
257             t8 = t3 ^ t19; \
258             t9 = t2 ^ t19; \
259             t10 = t18 ^ t5; \
260             t11 = t16 ^ t1; \
261             t12 = t16 ^ t7; \
262             t13 = t17 ^ t6; \
263             t14 = t18 ^ t4; \
264             t15 = t0 ^ t17; \
265             \
266             /* Second Orthogonal Latin Square\
267             0 4 2 3 1 6 5 7\
268             7 6 3 2 5 4 1 0\
269             5 3 1 6 0 2 7 4\
270             1 0 5 4 3 7 2 6\
271             2 1 0 7 4 5 6 3\
272             3 5 7 0 6 1 4 2\
273             4 7 6 1 2 0 3 5\
274             6 2 4 5 7 3 0 1\
275             */\
276             t16 = y0 + y1; \
277             t17 = y2 + y5; \
278             t20 = t16 + t17; \
279             t18 = y3 + y4; \
280             t22 = t16 + t18; \
281             t19 = y6 + y7; \
282             t21 = t18 + t19; \
283             t23 = t17 + t19; \
284             t0 = I64(0x5555555555555555) + t20 + y7; \
285             t1 = t22 + y6; \
286             t1 = ROTL64((t1), 3); \
287             t2 = t20 + y3; \
288             t2 = ROTL64((t2), 17); \
289             t3 = y2 + t21; \
290             t3 = ROTL64((t3), 23); \
291             t4 = t22 + y5; \
292             t4 = ROTL64((t4), 31); \
293             t5 = t23 + y4; \
294             t5 = ROTL64((t5), 37); \
295             t6 = y1 + t23; \
296             t6 = ROTL64((t6), 45); \
297             t7 = y0 + t21; \
298             t7 = ROTL64((t7), 59); \
299             \
300             t16 = t0 ^ t1; \
301             t17 = t2 ^ t5; \
302             t18 = t3 ^ t4; \
303             t19 = t6 ^ t7; \
304             z5 = t8 + (t18 ^ t6); \
305             z6 = t9 + (t17 ^ t7); \
306             z7 = t10 + (t4 ^ t19); \
307             z0 = t11 + (t16 ^ t5); \
308             z1 = t12 + (t2 ^ t19); \
309             z2 = t13 + (t16 ^ t3); \
310             z3 = t14 + (t0 ^ t18); \
311             z4 = t15 + (t1 ^ t17); \
312             }
313              
314             /**
315             * The core transformation. Process a 512-bit block.
316             *
317             * @param hash algorithm state
318             * @param block the message block to process
319             */
320 2           static void rhash_edonr256_process_block(unsigned hash[16], const unsigned* block, size_t count)
321             {
322 0           while (1) {
323             uint32_t t0, t1, t2, t3, t4, t5, t6, t7;
324             uint32_t t8, t9, t10, t11, t12, t13, t14, t15;
325             uint32_t t16, t17,t18, t19, t20, t21, t22, t23;
326             uint32_t p16, p17, p18, p19, p20, p21, p22, p23;
327             uint32_t p24, p25, p26, p27, p28, p29, p30, p31;
328              
329             /* First row of quasigroup e-transformations */
330 2           Q256(block[15], block[14], block[13], block[12], block[11], block[10], block[ 9], block[ 8],
331             block[ 0], block[ 1], block[ 2], block[ 3], block[ 4], block[ 5], block[ 6], block[ 7],
332             p16, p17, p18, p19, p20, p21, p22, p23);
333 2           Q256(p16, p17, p18, p19, p20, p21, p22, p23,
334             block[ 8], block[ 9], block[10], block[11], block[12], block[13], block[14], block[15],
335             p24, p25, p26, p27, p28, p29, p30, p31);
336              
337             /* Second row of quasigroup e-transformations */
338 2           Q256(hash[ 8], hash[ 9], hash[10], hash[11], hash[12], hash[13], hash[14], hash[15],
339             p16, p17, p18, p19, p20, p21, p22, p23,
340             p16, p17, p18, p19, p20, p21, p22, p23);
341 2           Q256(p16, p17, p18, p19, p20, p21, p22, p23,
342             p24, p25, p26, p27, p28, p29, p30, p31,
343             p24, p25, p26, p27, p28, p29, p30, p31);
344              
345             /* Third row of quasigroup e-transformations */
346 2           Q256(p16, p17, p18, p19, p20, p21, p22, p23,
347             hash[ 0], hash[ 1], hash[ 2], hash[ 3], hash[ 4], hash[ 5], hash[ 6], hash[ 7],
348             p16, p17, p18, p19, p20, p21, p22, p23);
349 2           Q256(p24, p25, p26, p27, p28, p29, p30, p31,
350             p16, p17, p18, p19, p20, p21, p22, p23,
351             p24, p25, p26, p27, p28, p29, p30, p31);
352              
353             /* Fourth row of quasigroup e-transformations */
354 2           Q256(block[ 7], block[ 6], block[ 5], block[ 4], block[ 3], block[ 2], block[ 1], block[ 0],
355             p16, p17, p18, p19, p20, p21, p22, p23,
356             hash[ 0], hash[ 1], hash[ 2], hash[ 3], hash[ 4], hash[ 5], hash[ 6], hash[ 7]);
357 2           Q256(hash[ 0], hash[ 1], hash[ 2], hash[ 3], hash[ 4], hash[ 5], hash[ 6], hash[ 7],
358             p24, p25, p26, p27, p28, p29, p30, p31,
359             hash[ 8], hash[ 9], hash[10], hash[11], hash[12], hash[13], hash[14], hash[15]);
360              
361 2 50         if (!--count) return;
362 0           block += edonr256_block_size / sizeof(unsigned);
363             };
364             }
365              
366             /**
367             * The core transformation. Process a 1024-bit block.
368             *
369             * @param hash algorithm state
370             * @param block the message block to process
371             */
372 2           static void rhash_edonr512_process_block(uint64_t hash[16], const uint64_t* block, size_t count)
373             {
374 0           while (1) {
375             uint64_t t0, t1, t2, t3, t4, t5, t6, t7;
376             uint64_t t8, t9, t10, t11, t12, t13, t14, t15;
377             uint64_t t16, t17,t18, t19, t20, t21, t22, t23;
378             uint64_t p16, p17, p18, p19, p20, p21, p22, p23;
379             uint64_t p24, p25, p26, p27, p28, p29, p30, p31;
380              
381             /* First row of quasigroup e-transformations */
382 2           Q512(block[15], block[14], block[13], block[12], block[11], block[10], block[ 9], block[ 8],
383             block[ 0], block[ 1], block[ 2], block[ 3], block[ 4], block[ 5], block[ 6], block[ 7],
384             p16, p17, p18, p19, p20, p21, p22, p23);
385 2           Q512(p16, p17, p18, p19, p20, p21, p22, p23,
386             block[ 8], block[ 9], block[10], block[11], block[12], block[13], block[14], block[15],
387             p24, p25, p26, p27, p28, p29, p30, p31);
388              
389             /* Second row of quasigroup e-transformations */
390 2           Q512(hash[ 8], hash[ 9], hash[10], hash[11], hash[12], hash[13], hash[14], hash[15],
391             p16, p17, p18, p19, p20, p21, p22, p23,
392             p16, p17, p18, p19, p20, p21, p22, p23);
393 2           Q512(p16, p17, p18, p19, p20, p21, p22, p23,
394             p24, p25, p26, p27, p28, p29, p30, p31,
395             p24, p25, p26, p27, p28, p29, p30, p31);
396              
397             /* Third row of quasigroup e-transformations */
398 2           Q512(p16, p17, p18, p19, p20, p21, p22, p23,
399             hash[ 0], hash[ 1], hash[ 2], hash[ 3], hash[ 4], hash[ 5], hash[ 6], hash[ 7],
400             p16, p17, p18, p19, p20, p21, p22, p23);
401 2           Q512(p24, p25, p26, p27, p28, p29, p30, p31,
402             p16, p17, p18, p19, p20, p21, p22, p23,
403             p24, p25, p26, p27, p28, p29, p30, p31);
404              
405             /* Fourth row of quasigroup e-transformations */
406 2           Q512(block[ 7], block[ 6], block[ 5], block[ 4], block[ 3], block[ 2], block[ 1], block[ 0],
407             p16, p17, p18, p19, p20, p21, p22, p23,
408             hash[ 0], hash[ 1], hash[ 2], hash[ 3], hash[ 4], hash[ 5], hash[ 6], hash[ 7]);
409 2           Q512(hash[ 0], hash[ 1], hash[ 2], hash[ 3], hash[ 4], hash[ 5], hash[ 6], hash[ 7],
410             p24, p25, p26, p27, p28, p29, p30, p31,
411             hash[ 8], hash[ 9], hash[10], hash[11], hash[12], hash[13], hash[14], hash[15]);
412              
413 2 50         if (!--count) return;
414 0           block += edonr512_block_size / sizeof(uint64_t);
415             };
416             }
417              
418             /**
419             * Calculate message hash.
420             * Can be called repeatedly with chunks of the message to be hashed.
421             *
422             * @param ctx the algorithm context containing current hashing state
423             * @param msg message chunk
424             * @param size length of the message chunk
425             */
426 2           void rhash_edonr256_update(edonr_ctx* ctx, const unsigned char* msg, size_t size)
427             {
428 2           size_t index = (size_t)ctx->length & 63;
429 2           ctx->length += size;
430              
431             /* fill partial block */
432 2 50         if (index) {
433 0           size_t left = edonr256_block_size - index;
434 0           le32_copy(ctx->u.data256.message, index, msg, (size < left ? size : left));
435 0 0         if (size < left) return;
436              
437             /* process partial block */
438 0           rhash_edonr256_process_block(ctx->u.data256.hash, ctx->u.data256.message, 1);
439 0           msg += left;
440 0           size -= left;
441             }
442              
443 2 50         if (size >= edonr256_block_size) {
444             #if defined(CPU_IA32) || defined(CPU_X64)
445             if (1)
446             #else
447             if (IS_LITTLE_ENDIAN && IS_ALIGNED_32(msg))
448             #endif
449             {
450             /* the most common case is processing a 32-bit aligned message
451             on a little-endian CPU without copying it */
452 0           size_t count = size / edonr256_block_size;
453 0           rhash_edonr256_process_block(ctx->u.data256.hash, (unsigned*)msg, count);
454 0           msg += edonr256_block_size * count;
455 0           size -= edonr256_block_size * count;
456             } else {
457             do {
458             le32_copy(ctx->u.data256.message, 0, msg, edonr256_block_size);
459             rhash_edonr256_process_block(ctx->u.data256.hash, ctx->u.data256.message, 1);
460             msg += edonr256_block_size;
461             size -= edonr256_block_size;
462             } while (size >= edonr256_block_size);
463             }
464             }
465              
466 2 50         if (size) {
467 2           le32_copy(ctx->u.data256.message, 0, msg, size); /* save leftovers */
468             }
469             }
470              
471             /**
472             * Store calculated hash into the given array.
473             *
474             * @param ctx the algorithm context containing current hashing state
475             * @param result calculated hash in binary form
476             */
477 2           void rhash_edonr256_final(edonr_ctx* ctx, unsigned char* result)
478             {
479 2           size_t index = ((unsigned)ctx->length & 63) >> 2;
480 2           unsigned shift = ((unsigned)ctx->length & 3) * 8;
481              
482             /* pad message and run for the last block */
483              
484             /* append the byte 0x80 to the message */
485 2           ctx->u.data256.message[index] &= ~(0xFFFFFFFFu << shift);
486 2           ctx->u.data256.message[index++] ^= 0x80u << shift;
487              
488             /* if no room left in the message to store 64-bit message length */
489 2 50         if (index > 14) {
490             /* then fill the rest with zeros and process it */
491 0 0         while (index < 16) {
492 0           ctx->u.data256.message[index++] = 0;
493             }
494 0           rhash_edonr256_process_block(ctx->u.data256.hash, ctx->u.data256.message, 1);
495 0           index = 0;
496             }
497 28 100         while (index < 14) {
498 26           ctx->u.data256.message[index++] = 0;
499             }
500             /* store message length in bits */
501 2           ctx->u.data256.message[14] = (unsigned)(ctx->length << 3);
502 2           ctx->u.data256.message[15] = (unsigned)(ctx->length >> 29);
503 2           rhash_edonr256_process_block(ctx->u.data256.hash, ctx->u.data256.message, 1);
504              
505 2 50         if (result) {
506             /* copy last bytes of intermidiate hash */
507 2 50         int off = (ctx->digest_length <= 256 ? 64 : 128) - ctx->digest_length;
508 2           le32_copy(result, 0, ((char*)ctx->u.data256.hash) + off, ctx->digest_length);
509             }
510 2           }
511              
512             /**
513             * Calculate message hash.
514             * Can be called repeatedly with chunks of the message to be hashed.
515             *
516             * @param ctx the algorithm context containing current hashing state
517             * @param msg message chunk
518             * @param size length of the message chunk
519             */
520 2           void rhash_edonr512_update(edonr_ctx* ctx, const unsigned char* msg, size_t size)
521             {
522 2           size_t index = (size_t)ctx->length & 127;
523 2           ctx->length += size;
524              
525             /* fill partial block */
526 2 50         if (index) {
527 0           size_t left = edonr512_block_size - index;
528 0           le64_copy(ctx->u.data512.message, index, msg, (size < left ? size : left));
529 0 0         if (size < left) return;
530              
531             /* process partial block */
532 0           rhash_edonr512_process_block(ctx->u.data512.hash, ctx->u.data512.message, 1);
533 0           msg += left;
534 0           size -= left;
535             }
536 2 50         if (size >= edonr512_block_size) {
537             #if defined(CPU_IA32) || defined(CPU_X64)
538             if (1)
539             #else
540             if (IS_LITTLE_ENDIAN && IS_ALIGNED_64(msg))
541             #endif
542             {
543             /* the most common case is processing a 64-bit aligned message
544             on a little-endian CPU without copying it */
545 0           size_t count = size / edonr512_block_size;
546 0           rhash_edonr512_process_block(ctx->u.data512.hash, (uint64_t*)msg, count);
547 0           msg += edonr512_block_size * count;
548 0           size -= edonr512_block_size * count;
549             } else {
550             do {
551             le64_copy(ctx->u.data512.message, 0, msg, edonr512_block_size);
552             rhash_edonr512_process_block(ctx->u.data512.hash, ctx->u.data512.message, 1);
553             msg += edonr512_block_size;
554             size -= edonr512_block_size;
555             } while (size >= edonr512_block_size);
556             }
557             }
558              
559 2 50         if (size) {
560 2           le64_copy(ctx->u.data512.message, 0, msg, size); /* save leftovers */
561             }
562             }
563              
564             /**
565             * Store calculated hash into the given array.
566             *
567             * @param ctx the algorithm context containing current hashing state
568             * @param result calculated hash in binary form
569             */
570 2           void rhash_edonr512_final(edonr_ctx* ctx, unsigned char* result)
571             {
572 2           size_t index = ((unsigned)ctx->length & 127) >> 3;
573 2           unsigned shift = ((unsigned)ctx->length & 7) * 8;
574              
575             /* pad message and run for the last block */
576              
577             /* append the byte 0x80 to the message */
578 2           ctx->u.data512.message[index] &= ~(I64(0xFFFFFFFFFFFFFFFF) << shift);
579 2           ctx->u.data512.message[index++] ^= I64(0x80) << shift;
580              
581             /* if no room left in the message to store 64-bit message length */
582 2 50         if (index == 16) {
583 0           rhash_edonr512_process_block(ctx->u.data512.hash, ctx->u.data512.message, 1);
584 0           index = 0;
585             }
586 30 100         while (index < 15) {
587 28           ctx->u.data512.message[index++] = 0;
588             }
589             /* store message length in bits */
590 2           ctx->u.data512.message[15] = ctx->length << 3;
591 2           rhash_edonr512_process_block(ctx->u.data512.hash, ctx->u.data512.message, 1);
592              
593 2 50         if (result) {
594             /* copy last bytes of intermidiate hash */
595 2           int off = edonr512_block_size - ctx->digest_length;
596 2           le64_copy(result, 0, ((char*)ctx->u.data512.hash) + off, ctx->digest_length);
597             }
598 2           }