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