OSDN Git Service

new repo
[bytom/vapor.git] / mining / tensority / cgo_algorithm / lib / sha3-allInOne.h
1 /* sha3-allInOne.h */
2 #ifndef RHASH_SHA3_H
3 #define RHASH_SHA3_H
4 #include "ustd.h"
5
6 #ifdef __cplusplus
7 extern "C" {
8 #endif
9
10 #define sha3_224_hash_size  28
11 #define sha3_256_hash_size  32
12 #define sha3_384_hash_size  48
13 #define sha3_512_hash_size  64
14 #define sha3_max_permutation_size 25
15 #define sha3_max_rate_in_qwords 24
16
17 /**
18  * SHA3 Algorithm context.
19  */
20 typedef struct sha3_ctx
21 {
22         /* 1600 bits algorithm hashing state */
23         uint64_t hash[sha3_max_permutation_size];
24         /* 1536-bit buffer for leftovers */
25         uint64_t message[sha3_max_rate_in_qwords];
26         /* count of bytes in the message[] buffer */
27         unsigned rest;
28         /* size of a message block processed at once */
29         unsigned block_size;
30 } sha3_ctx;
31
32 /* methods for calculating the hash function */
33
34 // void rhash_sha3_224_init(sha3_ctx *ctx);
35 // void rhash_sha3_256_init(sha3_ctx *ctx);
36 // void rhash_sha3_384_init(sha3_ctx *ctx);
37 // void rhash_sha3_512_init(sha3_ctx *ctx);
38 // void rhash_sha3_update(sha3_ctx *ctx, const unsigned char* msg, size_t size);
39 // void rhash_sha3_final(sha3_ctx *ctx, unsigned char* result);
40
41 #ifdef USE_KECCAK
42 #define rhash_keccak_224_init rhash_sha3_224_init
43 #define rhash_keccak_256_init rhash_sha3_256_init
44 #define rhash_keccak_384_init rhash_sha3_384_init
45 #define rhash_keccak_512_init rhash_sha3_512_init
46 #define rhash_keccak_update rhash_sha3_update
47 inline void rhash_keccak_final(sha3_ctx *ctx, unsigned char* result);
48 #endif
49
50 #ifdef __cplusplus
51 } /* extern "C" */
52 #endif /* __cplusplus */
53
54
55
56 // Adpated from sha3.c
57 /*--------------------------------------------------------------------------*/
58 /* sha3.c - an implementation of Secure Hash Algorithm 3 (Keccak).
59  * based on the
60  * The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011
61  * by Guido Bertoni, Joan Daemen, MichaĆ«l Peeters and Gilles Van Assche
62  *
63  * Copyright: 2013 Aleksey Kravchenko <rhash.admin@gmail.com>
64  *
65  * Permission is hereby granted,  free of charge,  to any person  obtaining a
66  * copy of this software and associated documentation files (the "Software"),
67  * to deal in the Software without restriction,  including without limitation
68  * the rights to  use, copy, modify,  merge, publish, distribute, sublicense,
69  * and/or sell copies  of  the Software,  and to permit  persons  to whom the
70  * Software is furnished to do so.
71  *
72  * This program  is  distributed  in  the  hope  that it will be useful,  but
73  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
74  * or FITNESS FOR A PARTICULAR PURPOSE.  Use this program  at  your own risk!
75  */
76
77 #include <assert.h>
78 #include <string.h>
79 #include "byte_order-allInOne.h"
80
81 /* constants */
82 #define NumberOfRounds 24
83
84 /* SHA3 (Keccak) constants for 24 rounds */
85 static uint64_t keccak_round_constants[NumberOfRounds] = {
86     I64(0x0000000000000001), I64(0x0000000000008082), I64(0x800000000000808A), I64(0x8000000080008000),
87     I64(0x000000000000808B), I64(0x0000000080000001), I64(0x8000000080008081), I64(0x8000000000008009),
88     I64(0x000000000000008A), I64(0x0000000000000088), I64(0x0000000080008009), I64(0x000000008000000A),
89     I64(0x000000008000808B), I64(0x800000000000008B), I64(0x8000000000008089), I64(0x8000000000008003),
90     I64(0x8000000000008002), I64(0x8000000000000080), I64(0x000000000000800A), I64(0x800000008000000A),
91     I64(0x8000000080008081), I64(0x8000000000008080), I64(0x0000000080000001), I64(0x8000000080008008)
92 };
93
94 /* Initializing a sha3 context for given number of output bits */
95 inline void rhash_keccak_init(sha3_ctx *ctx, unsigned bits)
96 {
97     /* NB: The Keccak capacity parameter = bits * 2 */
98     unsigned rate = 1600 - bits * 2;
99
100     memset(ctx, 0, sizeof(sha3_ctx));
101     ctx->block_size = rate / 8;
102     assert(rate <= 1600 && (rate % 64) == 0);
103 }
104
105 /**
106  * Initialize context before calculating hash.
107  *
108  * @param ctx context to initialize
109  */
110 inline void rhash_sha3_224_init(sha3_ctx *ctx)
111 {
112     rhash_keccak_init(ctx, 224);
113 }
114
115 /**
116  * Initialize context before calculating hash.
117  *
118  * @param ctx context to initialize
119  */
120 inline void rhash_sha3_256_init(sha3_ctx *ctx)
121 {
122     rhash_keccak_init(ctx, 256);
123 }
124
125 /**
126  * Initialize context before calculating hash.
127  *
128  * @param ctx context to initialize
129  */
130 inline void rhash_sha3_384_init(sha3_ctx *ctx)
131 {
132     rhash_keccak_init(ctx, 384);
133 }
134
135 /**
136  * Initialize context before calculating hash.
137  *
138  * @param ctx context to initialize
139  */
140 inline void rhash_sha3_512_init(sha3_ctx *ctx)
141 {
142     rhash_keccak_init(ctx, 512);
143 }
144
145 /* Keccak theta() transformation */
146 inline void keccak_theta(uint64_t *A)
147 {
148     unsigned int x;
149     uint64_t C[5], D[5];
150
151     for (x = 0; x < 5; x++) {
152         C[x] = A[x] ^ A[x + 5] ^ A[x + 10] ^ A[x + 15] ^ A[x + 20];
153     }
154     D[0] = ROTL64(C[1], 1) ^ C[4];
155     D[1] = ROTL64(C[2], 1) ^ C[0];
156     D[2] = ROTL64(C[3], 1) ^ C[1];
157     D[3] = ROTL64(C[4], 1) ^ C[2];
158     D[4] = ROTL64(C[0], 1) ^ C[3];
159
160     for (x = 0; x < 5; x++) {
161         A[x]      ^= D[x];
162         A[x + 5]  ^= D[x];
163         A[x + 10] ^= D[x];
164         A[x + 15] ^= D[x];
165         A[x + 20] ^= D[x];
166     }
167 }
168
169 /* Keccak pi() transformation */
170 inline void keccak_pi(uint64_t *A)
171 {
172     uint64_t A1;
173     A1 = A[1];
174     A[ 1] = A[ 6];
175     A[ 6] = A[ 9];
176     A[ 9] = A[22];
177     A[22] = A[14];
178     A[14] = A[20];
179     A[20] = A[ 2];
180     A[ 2] = A[12];
181     A[12] = A[13];
182     A[13] = A[19];
183     A[19] = A[23];
184     A[23] = A[15];
185     A[15] = A[ 4];
186     A[ 4] = A[24];
187     A[24] = A[21];
188     A[21] = A[ 8];
189     A[ 8] = A[16];
190     A[16] = A[ 5];
191     A[ 5] = A[ 3];
192     A[ 3] = A[18];
193     A[18] = A[17];
194     A[17] = A[11];
195     A[11] = A[ 7];
196     A[ 7] = A[10];
197     A[10] = A1;
198     /* note: A[ 0] is left as is */
199 }
200
201 /* Keccak chi() transformation */
202 inline void keccak_chi(uint64_t *A)
203 {
204     int i;
205     for (i = 0; i < 25; i += 5) {
206         uint64_t A0 = A[0 + i], A1 = A[1 + i];
207         A[0 + i] ^= ~A1 & A[2 + i];
208         A[1 + i] ^= ~A[2 + i] & A[3 + i];
209         A[2 + i] ^= ~A[3 + i] & A[4 + i];
210         A[3 + i] ^= ~A[4 + i] & A0;
211         A[4 + i] ^= ~A0 & A1;
212     }
213 }
214
215 inline void rhash_sha3_permutation(uint64_t *state)
216 {
217     int round;
218     for (round = 0; round < NumberOfRounds; round++)
219     {
220         keccak_theta(state);
221
222         /* apply Keccak rho() transformation */
223         state[ 1] = ROTL64(state[ 1],  1);
224         state[ 2] = ROTL64(state[ 2], 62);
225         state[ 3] = ROTL64(state[ 3], 28);
226         state[ 4] = ROTL64(state[ 4], 27);
227         state[ 5] = ROTL64(state[ 5], 36);
228         state[ 6] = ROTL64(state[ 6], 44);
229         state[ 7] = ROTL64(state[ 7],  6);
230         state[ 8] = ROTL64(state[ 8], 55);
231         state[ 9] = ROTL64(state[ 9], 20);
232         state[10] = ROTL64(state[10],  3);
233         state[11] = ROTL64(state[11], 10);
234         state[12] = ROTL64(state[12], 43);
235         state[13] = ROTL64(state[13], 25);
236         state[14] = ROTL64(state[14], 39);
237         state[15] = ROTL64(state[15], 41);
238         state[16] = ROTL64(state[16], 45);
239         state[17] = ROTL64(state[17], 15);
240         state[18] = ROTL64(state[18], 21);
241         state[19] = ROTL64(state[19],  8);
242         state[20] = ROTL64(state[20], 18);
243         state[21] = ROTL64(state[21],  2);
244         state[22] = ROTL64(state[22], 61);
245         state[23] = ROTL64(state[23], 56);
246         state[24] = ROTL64(state[24], 14);
247
248         keccak_pi(state);
249         keccak_chi(state);
250
251         /* apply iota(state, round) */
252         *state ^= keccak_round_constants[round];
253     }
254 }
255
256 /**
257  * The core transformation. Process the specified block of data.
258  *
259  * @param hash the algorithm state
260  * @param block the message block to process
261  * @param block_size the size of the processed block in bytes
262  */
263 inline void rhash_sha3_process_block(uint64_t hash[25], const uint64_t *block, size_t block_size)
264 {
265     /* expanded loop */
266     hash[ 0] ^= le2me_64(block[ 0]);
267     hash[ 1] ^= le2me_64(block[ 1]);
268     hash[ 2] ^= le2me_64(block[ 2]);
269     hash[ 3] ^= le2me_64(block[ 3]);
270     hash[ 4] ^= le2me_64(block[ 4]);
271     hash[ 5] ^= le2me_64(block[ 5]);
272     hash[ 6] ^= le2me_64(block[ 6]);
273     hash[ 7] ^= le2me_64(block[ 7]);
274     hash[ 8] ^= le2me_64(block[ 8]);
275     /* if not sha3-512 */
276     if (block_size > 72) {
277         hash[ 9] ^= le2me_64(block[ 9]);
278         hash[10] ^= le2me_64(block[10]);
279         hash[11] ^= le2me_64(block[11]);
280         hash[12] ^= le2me_64(block[12]);
281         /* if not sha3-384 */
282         if (block_size > 104) {
283             hash[13] ^= le2me_64(block[13]);
284             hash[14] ^= le2me_64(block[14]);
285             hash[15] ^= le2me_64(block[15]);
286             hash[16] ^= le2me_64(block[16]);
287             /* if not sha3-256 */
288             if (block_size > 136) {
289                 hash[17] ^= le2me_64(block[17]);
290 #ifdef FULL_SHA3_FAMILY_SUPPORT
291                 /* if not sha3-224 */
292                 if (block_size > 144) {
293                     hash[18] ^= le2me_64(block[18]);
294                     hash[19] ^= le2me_64(block[19]);
295                     hash[20] ^= le2me_64(block[20]);
296                     hash[21] ^= le2me_64(block[21]);
297                     hash[22] ^= le2me_64(block[22]);
298                     hash[23] ^= le2me_64(block[23]);
299                     hash[24] ^= le2me_64(block[24]);
300                 }
301 #endif
302             }
303         }
304     }
305     /* make a permutation of the hash */
306     rhash_sha3_permutation(hash);
307 }
308
309 #define SHA3_FINALIZED 0x80000000
310
311 /**
312  * Calculate message hash.
313  * Can be called repeatedly with chunks of the message to be hashed.
314  *
315  * @param ctx the algorithm context containing current hashing state
316  * @param msg message chunk
317  * @param size length of the message chunk
318  */
319 inline void rhash_sha3_update(sha3_ctx *ctx, const unsigned char *msg, size_t size)
320 {
321     size_t index = (size_t)ctx->rest;
322     size_t block_size = (size_t)ctx->block_size;
323
324     if (ctx->rest & SHA3_FINALIZED) return; /* too late for additional input */
325     ctx->rest = (unsigned)((ctx->rest + size) % block_size);
326
327     /* fill partial block */
328     if (index) {
329         size_t left = block_size - index;
330         memcpy((char*)ctx->message + index, msg, (size < left ? size : left));
331         if (size < left) return;
332
333         /* process partial block */
334         rhash_sha3_process_block(ctx->hash, ctx->message, block_size);
335         msg  += left;
336         size -= left;
337     }
338     while (size >= block_size) {
339         uint64_t* aligned_message_block;
340         if (IS_ALIGNED_64(msg)) {
341             /* the most common case is processing of an already aligned message
342             without copying it */
343             aligned_message_block = (uint64_t*)msg;
344         } else {
345             memcpy(ctx->message, msg, block_size);
346             aligned_message_block = ctx->message;
347         }
348
349         rhash_sha3_process_block(ctx->hash, aligned_message_block, block_size);
350         msg  += block_size;
351         size -= block_size;
352     }
353     if (size) {
354         memcpy(ctx->message, msg, size); /* save leftovers */
355     }
356 }
357
358 /**
359  * Store calculated hash into the given array.
360  *
361  * @param ctx the algorithm context containing current hashing state
362  * @param result calculated hash in binary form
363  */
364 inline void rhash_sha3_final(sha3_ctx *ctx, unsigned char* result)
365 {
366     size_t digest_length = 100 - ctx->block_size / 2;
367     const size_t block_size = ctx->block_size;
368
369     if (!(ctx->rest & SHA3_FINALIZED))
370     {
371         /* clear the rest of the data queue */
372         memset((char*)ctx->message + ctx->rest, 0, block_size - ctx->rest);
373         ((char*)ctx->message)[ctx->rest] |= 0x06;
374         ((char*)ctx->message)[block_size - 1] |= 0x80;
375
376         /* process final block */
377         rhash_sha3_process_block(ctx->hash, ctx->message, block_size);
378         ctx->rest = SHA3_FINALIZED; /* mark context as finalized */
379     }
380
381     assert(block_size > digest_length);
382     if (result) me64_to_le_str(result, ctx->hash, digest_length);
383 }
384
385 #ifdef USE_KECCAK
386 /**
387 * Store calculated hash into the given array.
388 *
389 * @param ctx the algorithm context containing current hashing state
390 * @param result calculated hash in binary form
391 */
392 inline void rhash_keccak_final(sha3_ctx *ctx, unsigned char* result)
393 {
394     size_t digest_length = 100 - ctx->block_size / 2;
395     const size_t block_size = ctx->block_size;
396
397     if (!(ctx->rest & SHA3_FINALIZED))
398     {
399         /* clear the rest of the data queue */
400         memset((char*)ctx->message + ctx->rest, 0, block_size - ctx->rest);
401         ((char*)ctx->message)[ctx->rest] |= 0x01;
402         ((char*)ctx->message)[block_size - 1] |= 0x80;
403
404         /* process final block */
405         rhash_sha3_process_block(ctx->hash, ctx->message, block_size);
406         ctx->rest = SHA3_FINALIZED; /* mark context as finalized */
407     }
408
409     assert(block_size > digest_length);
410     if (result) me64_to_le_str(result, ctx->hash, digest_length);
411 }
412 #endif /* USE_KECCAK */
413
414
415
416 #endif /* RHASH_SHA3_H */