ReactOS 0.4.15-dev-7934-g1dc8d80
sha3.c
Go to the documentation of this file.
1/* @(#)sha3.c 1.4 15/12/27 2015 J. Schilling */
2#include <schily/mconfig.h>
3#ifndef lint
4static UConst char sccsid[] =
5 "@(#)sha3.c 1.4 15/12/27 2015 J. Schilling";
6#endif
7/*
8 * SHA3 hash code taken from
9 * https://github.com/rhash/RHash/tree/master/librhash
10 *
11 * Portions Copyright (c) 2015 J. Schilling
12 */
13
14/*
15 * sha3.c - an implementation of Secure Hash Algorithm 3 (Keccak).
16 * based on the
17 * The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011
18 * by Guido Bertoni, Joan Daemen, Michaƫl Peeters and Gilles Van Assche
19 *
20 * Copyright: 2013 Aleksey Kravchenko <rhash.admin@gmail.com>
21 *
22 * Permission is hereby granted, free of charge, to any person obtaining a
23 * copy of this software and associated documentation files (the "Software"),
24 * to deal in the Software without restriction, including without limitation
25 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
26 * and/or sell copies of the Software, and to permit persons to whom the
27 * Software is furnished to do so.
28 *
29 * This program is distributed in the hope that it will be useful, but
30 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
31 * or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk!
32 */
33
34#include <schily/assert.h>
35#include <schily/string.h>
36#include "byte_order.h"
37#include <schily/sha3.h>
38
39#ifdef HAVE_LONGLONG
40
41#if !defined(HAVE_MEMCPY) || !defined(HAVE_MEMSET)
42#include <schily/schily.h>
43#endif
44#if !defined(HAVE_MEMCPY) && !defined(memcpy)
45#define memcpy(s1, s2, n) movebytes(s2, s1, n)
46#endif
47#if !defined(HAVE_MEMSET) && !defined(memset)
48#define memset(s, c, n) fillbytes(s, n, c)
49#endif
50
51static void rhash_keccak_init __PR((sha3_ctx *ctx, unsigned bits));
52static void keccak_theta __PR((UInt64_t *A));
53static void keccak_pi __PR((UInt64_t *A));
54static void keccak_chi __PR((UInt64_t *A));
55static void rhash_sha3_permutation __PR((UInt64_t *state));
56static void rhash_sha3_process_block __PR((UInt64_t hash[25],
57 const UInt64_t *block,
58 size_t block_size));
59
60/*
61 * The Cygwin compile environment incorrectly implements #pragma weak.
62 * The weak symbols are only defined as local symbols making it impossible
63 * to use them from outside the scope of this source file.
64 * A platform that allows linking with global symbols has HAVE_LINK_WEAK
65 * defined.
66 */
67#if defined(HAVE_PRAGMA_WEAK) && defined(HAVE_LINK_WEAK)
68#pragma weak SHA3_224_Init = rhash_sha3_224_init
69#pragma weak SHA3_256_Init = rhash_sha3_256_init
70#pragma weak SHA3_384_Init = rhash_sha3_384_init
71#pragma weak SHA3_512_Init = rhash_sha3_512_init
72#pragma weak SHA3_Update = rhash_sha3_update
73#else
74
75void SHA3_224_Init __PR((SHA3_CTX *ctx));
76void SHA3_256_Init __PR((SHA3_CTX *ctx));
77void SHA3_384_Init __PR((SHA3_CTX *ctx));
78void SHA3_512_Init __PR((SHA3_CTX *ctx));
79void SHA3_Update __PR((SHA3_CTX *ctx,
80 const unsigned char *msg,
81 size_t size));
82
83void
84SHA3_224_Init(ctx)
85 SHA3_CTX *ctx;
86{
87 rhash_sha3_224_init(ctx);
88}
89
90void
91SHA3_256_Init(ctx)
92 SHA3_CTX *ctx;
93{
94 rhash_sha3_256_init(ctx);
95}
96
97void
98SHA3_384_Init(ctx)
99 SHA3_CTX *ctx;
100{
101 rhash_sha3_384_init(ctx);
102}
103
104void
105SHA3_512_Init(ctx)
106 SHA3_CTX *ctx;
107{
108 rhash_sha3_512_init(ctx);
109}
110
111void
112SHA3_Update(ctx, msg, size)
113 SHA3_CTX *ctx;
114 const unsigned char *msg;
115 size_t size;
116{
117 rhash_sha3_update(ctx, msg, size);
118}
119#endif /* defined(HAVE_PRAGMA_WEAK) && defined(HAVE_LINK_WEAK) */
120
121/* constants */
122#define NumberOfRounds 24
123
124/* SHA3 (Keccak) constants for 24 rounds */
125static UInt64_t keccak_round_constants[NumberOfRounds] = {
126 UI64(0x0000000000000001), UI64(0x0000000000008082),
127 UI64(0x800000000000808A), UI64(0x8000000080008000),
128 UI64(0x000000000000808B), UI64(0x0000000080000001),
129 UI64(0x8000000080008081), UI64(0x8000000000008009),
130 UI64(0x000000000000008A), UI64(0x0000000000000088),
131 UI64(0x0000000080008009), UI64(0x000000008000000A),
132 UI64(0x000000008000808B), UI64(0x800000000000008B),
133 UI64(0x8000000000008089), UI64(0x8000000000008003),
134 UI64(0x8000000000008002), UI64(0x8000000000000080),
135 UI64(0x000000000000800A), UI64(0x800000008000000A),
136 UI64(0x8000000080008081), UI64(0x8000000000008080),
137 UI64(0x0000000080000001), UI64(0x8000000080008008)
138};
139
140/* Initializing a sha3 context for given number of output bits */
141static void
142rhash_keccak_init(ctx, bits)
143 sha3_ctx *ctx;
144 unsigned bits;
145{
146 /* NB: The Keccak capacity parameter = bits * 2 */
147 unsigned rate = 1600 - bits * 2;
148
149 memset(ctx, 0, sizeof (sha3_ctx));
150 ctx->block_size = rate / 8;
151 assert(rate <= 1600 && (rate % 64) == 0);
152}
153
154/*
155 * Initialize context before calculating hash.
156 *
157 * @param ctx context to initialize
158 */
159void
160rhash_sha3_224_init(ctx)
161 sha3_ctx *ctx;
162{
163 rhash_keccak_init(ctx, 224);
164}
165
166/*
167 * Initialize context before calculating hash.
168 *
169 * @param ctx context to initialize
170 */
171void
172rhash_sha3_256_init(ctx)
173 sha3_ctx *ctx;
174{
175 rhash_keccak_init(ctx, 256);
176}
177
178/*
179 * Initialize context before calculating hash.
180 *
181 * @param ctx context to initialize
182 */
183void
184rhash_sha3_384_init(ctx)
185 sha3_ctx *ctx;
186{
187 rhash_keccak_init(ctx, 384);
188}
189
190/*
191 * Initialize context before calculating hash.
192 *
193 * @param ctx context to initialize
194 */
195void
196rhash_sha3_512_init(ctx)
197 sha3_ctx *ctx;
198{
199 rhash_keccak_init(ctx, 512);
200}
201
202/* Keccak theta() transformation */
203static void
204keccak_theta(A)
205 UInt64_t *A;
206{
207 unsigned int x;
208 UInt64_t C[5], D[5];
209
210 for (x = 0; x < 5; x++) {
211 C[x] = A[x] ^ A[x + 5] ^ A[x + 10] ^ A[x + 15] ^ A[x + 20];
212 }
213 D[0] = ROTL64(C[1], 1) ^ C[4];
214 D[1] = ROTL64(C[2], 1) ^ C[0];
215 D[2] = ROTL64(C[3], 1) ^ C[1];
216 D[3] = ROTL64(C[4], 1) ^ C[2];
217 D[4] = ROTL64(C[0], 1) ^ C[3];
218
219 for (x = 0; x < 5; x++) {
220 A[x] ^= D[x];
221 A[x + 5] ^= D[x];
222 A[x + 10] ^= D[x];
223 A[x + 15] ^= D[x];
224 A[x + 20] ^= D[x];
225 }
226}
227
228/* Keccak pi() transformation */
229static void
230keccak_pi(A)
231 UInt64_t *A;
232{
233 UInt64_t A1;
234 A1 = A[1];
235 A[ 1] = A[ 6];
236 A[ 6] = A[ 9];
237 A[ 9] = A[22];
238 A[22] = A[14];
239 A[14] = A[20];
240 A[20] = A[ 2];
241 A[ 2] = A[12];
242 A[12] = A[13];
243 A[13] = A[19];
244 A[19] = A[23];
245 A[23] = A[15];
246 A[15] = A[ 4];
247 A[ 4] = A[24];
248 A[24] = A[21];
249 A[21] = A[ 8];
250 A[ 8] = A[16];
251 A[16] = A[ 5];
252 A[ 5] = A[ 3];
253 A[ 3] = A[18];
254 A[18] = A[17];
255 A[17] = A[11];
256 A[11] = A[ 7];
257 A[ 7] = A[10];
258 A[10] = A1;
259 /* note: A[ 0] is left as is */
260}
261
262/* Keccak chi() transformation */
263static void
264keccak_chi(A)
265 UInt64_t *A;
266{
267 int i;
268 for (i = 0; i < 25; i += 5) {
269 UInt64_t A0 = A[0 + i], A1 = A[1 + i];
270 A[0 + i] ^= ~A1 & A[2 + i];
271 A[1 + i] ^= ~A[2 + i] & A[3 + i];
272 A[2 + i] ^= ~A[3 + i] & A[4 + i];
273 A[3 + i] ^= ~A[4 + i] & A0;
274 A[4 + i] ^= ~A0 & A1;
275 }
276}
277
278static void
279rhash_sha3_permutation(state)
280 UInt64_t *state;
281{
282 int round;
283 for (round = 0; round < NumberOfRounds; round++)
284 {
285 keccak_theta(state);
286
287 /* apply Keccak rho() transformation */
288 state[ 1] = ROTL64(state[ 1], 1);
289 state[ 2] = ROTL64(state[ 2], 62);
290 state[ 3] = ROTL64(state[ 3], 28);
291 state[ 4] = ROTL64(state[ 4], 27);
292 state[ 5] = ROTL64(state[ 5], 36);
293 state[ 6] = ROTL64(state[ 6], 44);
294 state[ 7] = ROTL64(state[ 7], 6);
295 state[ 8] = ROTL64(state[ 8], 55);
296 state[ 9] = ROTL64(state[ 9], 20);
297 state[10] = ROTL64(state[10], 3);
298 state[11] = ROTL64(state[11], 10);
299 state[12] = ROTL64(state[12], 43);
300 state[13] = ROTL64(state[13], 25);
301 state[14] = ROTL64(state[14], 39);
302 state[15] = ROTL64(state[15], 41);
303 state[16] = ROTL64(state[16], 45);
304 state[17] = ROTL64(state[17], 15);
305 state[18] = ROTL64(state[18], 21);
306 state[19] = ROTL64(state[19], 8);
307 state[20] = ROTL64(state[20], 18);
308 state[21] = ROTL64(state[21], 2);
309 state[22] = ROTL64(state[22], 61);
310 state[23] = ROTL64(state[23], 56);
311 state[24] = ROTL64(state[24], 14);
312
313 keccak_pi(state);
314 keccak_chi(state);
315
316 /* apply iota(state, round) */
317 *state ^= keccak_round_constants[round];
318 }
319}
320
321/*
322 * The core transformation. Process the specified block of data.
323 *
324 * @param hash the algorithm state
325 * @param block the message block to process
326 * @param block_size the size of the processed block in bytes
327 */
328static void
329rhash_sha3_process_block(hash, block, block_size)
330 UInt64_t hash[25];
331 const UInt64_t *block;
332 size_t block_size;
333{
334 /* expanded loop */
335 hash[ 0] ^= le2me_64(block[ 0]);
336 hash[ 1] ^= le2me_64(block[ 1]);
337 hash[ 2] ^= le2me_64(block[ 2]);
338 hash[ 3] ^= le2me_64(block[ 3]);
339 hash[ 4] ^= le2me_64(block[ 4]);
340 hash[ 5] ^= le2me_64(block[ 5]);
341 hash[ 6] ^= le2me_64(block[ 6]);
342 hash[ 7] ^= le2me_64(block[ 7]);
343 hash[ 8] ^= le2me_64(block[ 8]);
344 /* if not sha3-512 */
345 if (block_size > 72) {
346 hash[ 9] ^= le2me_64(block[ 9]);
347 hash[10] ^= le2me_64(block[10]);
348 hash[11] ^= le2me_64(block[11]);
349 hash[12] ^= le2me_64(block[12]);
350 /* if not sha3-384 */
351 if (block_size > 104) {
352 hash[13] ^= le2me_64(block[13]);
353 hash[14] ^= le2me_64(block[14]);
354 hash[15] ^= le2me_64(block[15]);
355 hash[16] ^= le2me_64(block[16]);
356 /* if not sha3-256 */
357 if (block_size > 136) {
358 hash[17] ^= le2me_64(block[17]);
359#ifdef FULL_SHA3_FAMILY_SUPPORT
360 /* if not sha3-224 */
361 if (block_size > 144) {
362 hash[18] ^= le2me_64(block[18]);
363 hash[19] ^= le2me_64(block[19]);
364 hash[20] ^= le2me_64(block[20]);
365 hash[21] ^= le2me_64(block[21]);
366 hash[22] ^= le2me_64(block[22]);
367 hash[23] ^= le2me_64(block[23]);
368 hash[24] ^= le2me_64(block[24]);
369 }
370#endif
371 }
372 }
373 }
374 /* make a permutation of the hash */
375 rhash_sha3_permutation(hash);
376}
377
378#define SHA3_FINALIZED 0x80000000
379
380/*
381 * Calculate message hash.
382 * Can be called repeatedly with chunks of the message to be hashed.
383 *
384 * @param ctx the algorithm context containing current hashing state
385 * @param msg message chunk
386 * @param size length of the message chunk
387 */
388void
389rhash_sha3_update(ctx, msg, size)
390 sha3_ctx *ctx;
391 const unsigned char *msg;
392 size_t size;
393{
394 size_t idx = (size_t)ctx->rest;
395 size_t block_size = (size_t)ctx->block_size;
396
397 if (ctx->rest & SHA3_FINALIZED)
398 return; /* too late for additional input */
399 ctx->rest = (unsigned)((ctx->rest + size) % block_size);
400
401 /* fill partial block */
402 if (idx) {
403 size_t left = block_size - idx;
404 memcpy((char *)ctx->message + idx, msg,
405 (size < left ? size : left));
406 if (size < left)
407 return;
408
409 /* process partial block */
410 rhash_sha3_process_block(ctx->hash, ctx->message, block_size);
411 msg += left;
412 size -= left;
413 }
414 while (size >= block_size) {
415 UInt64_t *aligned_message_block;
416 if (IS_ALIGNED_64(msg)) {
417 /*
418 * the most common case is processing of an already
419 * aligned message without copying it
420 */
421 aligned_message_block = (UInt64_t *)msg;
422 } else {
423 memcpy(ctx->message, msg, block_size);
424 aligned_message_block = ctx->message;
425 }
426
427 rhash_sha3_process_block(ctx->hash, aligned_message_block,
428 block_size);
429 msg += block_size;
430 size -= block_size;
431 }
432 if (size) {
433 memcpy(ctx->message, msg, size); /* save leftovers */
434 }
435}
436
437/*
438 * Store calculated hash into the given array.
439 *
440 * @param ctx the algorithm context containing current hashing state
441 * @param result calculated hash in binary form
442 */
443void
444rhash_sha3_final(ctx, result)
445 sha3_ctx *ctx;
446 unsigned char *result;
447{
448 size_t digest_length = 100 - ctx->block_size / 2;
449 const size_t block_size = ctx->block_size;
450
451 if (!(ctx->rest & SHA3_FINALIZED))
452 {
453 /* clear the rest of the data queue */
454 memset((char *)ctx->message + ctx->rest, 0,
455 block_size - ctx->rest);
456 ((char *)ctx->message)[ctx->rest] |= 0x06;
457 ((char *)ctx->message)[block_size - 1] |= 0x80;
458
459 /* process final block */
460 rhash_sha3_process_block(ctx->hash, ctx->message, block_size);
461 ctx->rest = SHA3_FINALIZED; /* mark context as finalized */
462 }
463
464 assert(block_size > digest_length);
465 if (result) me64_to_le_str(result, ctx->hash, digest_length);
466}
467
468void
469SHA3_Final(result, ctx)
471 SHA3_CTX *ctx;
472{
473 rhash_sha3_final(ctx, result);
474}
475
476#ifdef USE_KECCAK
477/*
478 * Store calculated hash into the given array.
479 *
480 * @param ctx the algorithm context containing current hashing state
481 * @param result calculated hash in binary form
482 */
483void
484rhash_keccak_final(sha3_ctx *ctx, unsigned char *result)
485{
486 size_t digest_length = 100 - ctx->block_size / 2;
487 const size_t block_size = ctx->block_size;
488
489 if (!(ctx->rest & SHA3_FINALIZED)) {
490 /* clear the rest of the data queue */
491 memset((char *)ctx->message + ctx->rest, 0,
492 block_size - ctx->rest);
493 ((char *)ctx->message)[ctx->rest] |= 0x01;
494 ((char *)ctx->message)[block_size - 1] |= 0x80;
495
496 /* process final block */
497 rhash_sha3_process_block(ctx->hash, ctx->message, block_size);
498 ctx->rest = SHA3_FINALIZED; /* mark context as finalized */
499 }
500
501 assert(block_size > digest_length);
502 if (result)
503 me64_to_le_str(result, ctx->hash, digest_length);
504}
505#endif /* USE_KECCAK */
506
507#endif /* HAVE_LONGLONG */
static int state
Definition: maze.c:121
#define msg(x)
Definition: auth_time.c:54
#define D(d)
Definition: builtin.c:4557
#define UI64(x)
Definition: byte_order.h:112
#define IS_ALIGNED_64(p)
Definition: byte_order.h:87
#define me64_to_le_str(to, from, length)
Definition: byte_order.h:200
#define le2me_64(x)
Definition: byte_order.h:193
#define ROTL64(qword, n)
Definition: byte_order.h:206
#define UConst
Definition: ccomdefs.h:72
Definition: ehthrow.cxx:93
Definition: terminate.cpp:24
unsigned int idx
Definition: utils.c:41
#define A(row, col)
#define assert(x)
Definition: debug.h:53
__kernel_size_t size_t
Definition: linux.h:237
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLsizeiptr size
Definition: glext.h:5919
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * bits
Definition: glext.h:10929
GLint left
Definition: glext.h:7726
GLuint64EXT * result
Definition: glext.h:11304
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define bits
Definition: infblock.c:15
static DWORD block_size(DWORD block)
Definition: jsutils.c:66
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static unsigned(__cdecl *hash_bstr)(bstr_t s)
#define round(x)
Definition: opentype.c:47
int rate
Definition: pcmconverter.c:97
#define __PR(a)
Definition: prototyp.h:106
#define memset(x, y, z)
Definition: compat.h:39
static UConst char sccsid[]
Definition: sha3.c:4
Definition: _hash_fun.h:40
#define A1
unsigned char UInt8_t
Definition: stdint.h:322
static unsigned int block
Definition: xmlmemory.c:101