Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Kitware
GitHub Repository: Kitware/CMake
Path: blob/master/Utilities/cmlibrhash/librhash/sha3.c
3150 views
1
/* sha3.c - an implementation of Secure Hash Algorithm 3 (Keccak).
2
* based on the
3
* The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011
4
* by Guido Bertoni, Joan Daemen, Michaƫl Peeters and Gilles Van Assche
5
*
6
* Copyright (c) 2013, Aleksey Kravchenko <[email protected]>
7
*
8
* Permission to use, copy, modify, and/or distribute this software for any
9
* purpose with or without fee is hereby granted.
10
*
11
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17
* PERFORMANCE OF THIS SOFTWARE.
18
*/
19
20
#include <assert.h>
21
#include <string.h>
22
#include "byte_order.h"
23
#include "sha3.h"
24
25
/* constants */
26
#define NumberOfRounds 24
27
28
/* SHA3 (Keccak) constants for 24 rounds */
29
static uint64_t keccak_round_constants[NumberOfRounds] = {
30
I64(0x0000000000000001), I64(0x0000000000008082), I64(0x800000000000808A), I64(0x8000000080008000),
31
I64(0x000000000000808B), I64(0x0000000080000001), I64(0x8000000080008081), I64(0x8000000000008009),
32
I64(0x000000000000008A), I64(0x0000000000000088), I64(0x0000000080008009), I64(0x000000008000000A),
33
I64(0x000000008000808B), I64(0x800000000000008B), I64(0x8000000000008089), I64(0x8000000000008003),
34
I64(0x8000000000008002), I64(0x8000000000000080), I64(0x000000000000800A), I64(0x800000008000000A),
35
I64(0x8000000080008081), I64(0x8000000000008080), I64(0x0000000080000001), I64(0x8000000080008008)
36
};
37
38
/* Initializing a sha3 context for given number of output bits */
39
static void rhash_keccak_init(sha3_ctx* ctx, unsigned bits)
40
{
41
/* NB: The Keccak capacity parameter = bits * 2 */
42
unsigned rate = 1600 - bits * 2;
43
44
memset(ctx, 0, sizeof(sha3_ctx));
45
ctx->block_size = rate / 8;
46
assert(rate <= 1600 && (rate % 64) == 0);
47
}
48
49
/**
50
* Initialize context before calculating hash.
51
*
52
* @param ctx context to initialize
53
*/
54
void rhash_sha3_224_init(sha3_ctx* ctx)
55
{
56
rhash_keccak_init(ctx, 224);
57
}
58
59
/**
60
* Initialize context before calculating hash.
61
*
62
* @param ctx context to initialize
63
*/
64
void rhash_sha3_256_init(sha3_ctx* ctx)
65
{
66
rhash_keccak_init(ctx, 256);
67
}
68
69
/**
70
* Initialize context before calculating hash.
71
*
72
* @param ctx context to initialize
73
*/
74
void rhash_sha3_384_init(sha3_ctx* ctx)
75
{
76
rhash_keccak_init(ctx, 384);
77
}
78
79
/**
80
* Initialize context before calculating hash.
81
*
82
* @param ctx context to initialize
83
*/
84
void rhash_sha3_512_init(sha3_ctx* ctx)
85
{
86
rhash_keccak_init(ctx, 512);
87
}
88
89
#define XORED_A(i) A[(i)] ^ A[(i) + 5] ^ A[(i) + 10] ^ A[(i) + 15] ^ A[(i) + 20]
90
#define THETA_STEP(i) \
91
A[(i)] ^= D[(i)]; \
92
A[(i) + 5] ^= D[(i)]; \
93
A[(i) + 10] ^= D[(i)]; \
94
A[(i) + 15] ^= D[(i)]; \
95
A[(i) + 20] ^= D[(i)] \
96
97
/* Keccak theta() transformation */
98
static void keccak_theta(uint64_t* A)
99
{
100
uint64_t D[5];
101
D[0] = ROTL64(XORED_A(1), 1) ^ XORED_A(4);
102
D[1] = ROTL64(XORED_A(2), 1) ^ XORED_A(0);
103
D[2] = ROTL64(XORED_A(3), 1) ^ XORED_A(1);
104
D[3] = ROTL64(XORED_A(4), 1) ^ XORED_A(2);
105
D[4] = ROTL64(XORED_A(0), 1) ^ XORED_A(3);
106
THETA_STEP(0);
107
THETA_STEP(1);
108
THETA_STEP(2);
109
THETA_STEP(3);
110
THETA_STEP(4);
111
}
112
113
/* Keccak pi() transformation */
114
static void keccak_pi(uint64_t* A)
115
{
116
uint64_t A1;
117
A1 = A[1];
118
A[ 1] = A[ 6];
119
A[ 6] = A[ 9];
120
A[ 9] = A[22];
121
A[22] = A[14];
122
A[14] = A[20];
123
A[20] = A[ 2];
124
A[ 2] = A[12];
125
A[12] = A[13];
126
A[13] = A[19];
127
A[19] = A[23];
128
A[23] = A[15];
129
A[15] = A[ 4];
130
A[ 4] = A[24];
131
A[24] = A[21];
132
A[21] = A[ 8];
133
A[ 8] = A[16];
134
A[16] = A[ 5];
135
A[ 5] = A[ 3];
136
A[ 3] = A[18];
137
A[18] = A[17];
138
A[17] = A[11];
139
A[11] = A[ 7];
140
A[ 7] = A[10];
141
A[10] = A1;
142
/* note: A[ 0] is left as is */
143
}
144
145
#define CHI_STEP(i) \
146
A0 = A[0 + (i)]; \
147
A1 = A[1 + (i)]; \
148
A[0 + (i)] ^= ~A1 & A[2 + (i)]; \
149
A[1 + (i)] ^= ~A[2 + (i)] & A[3 + (i)]; \
150
A[2 + (i)] ^= ~A[3 + (i)] & A[4 + (i)]; \
151
A[3 + (i)] ^= ~A[4 + (i)] & A0; \
152
A[4 + (i)] ^= ~A0 & A1 \
153
154
/* Keccak chi() transformation */
155
static void keccak_chi(uint64_t* A)
156
{
157
uint64_t A0, A1;
158
CHI_STEP(0);
159
CHI_STEP(5);
160
CHI_STEP(10);
161
CHI_STEP(15);
162
CHI_STEP(20);
163
}
164
165
static void rhash_sha3_permutation(uint64_t* state)
166
{
167
int round;
168
for (round = 0; round < NumberOfRounds; round++)
169
{
170
keccak_theta(state);
171
172
/* apply Keccak rho() transformation */
173
state[ 1] = ROTL64(state[ 1], 1);
174
state[ 2] = ROTL64(state[ 2], 62);
175
state[ 3] = ROTL64(state[ 3], 28);
176
state[ 4] = ROTL64(state[ 4], 27);
177
state[ 5] = ROTL64(state[ 5], 36);
178
state[ 6] = ROTL64(state[ 6], 44);
179
state[ 7] = ROTL64(state[ 7], 6);
180
state[ 8] = ROTL64(state[ 8], 55);
181
state[ 9] = ROTL64(state[ 9], 20);
182
state[10] = ROTL64(state[10], 3);
183
state[11] = ROTL64(state[11], 10);
184
state[12] = ROTL64(state[12], 43);
185
state[13] = ROTL64(state[13], 25);
186
state[14] = ROTL64(state[14], 39);
187
state[15] = ROTL64(state[15], 41);
188
state[16] = ROTL64(state[16], 45);
189
state[17] = ROTL64(state[17], 15);
190
state[18] = ROTL64(state[18], 21);
191
state[19] = ROTL64(state[19], 8);
192
state[20] = ROTL64(state[20], 18);
193
state[21] = ROTL64(state[21], 2);
194
state[22] = ROTL64(state[22], 61);
195
state[23] = ROTL64(state[23], 56);
196
state[24] = ROTL64(state[24], 14);
197
198
keccak_pi(state);
199
keccak_chi(state);
200
201
/* apply iota(state, round) */
202
*state ^= keccak_round_constants[round];
203
}
204
}
205
206
/**
207
* The core transformation. Process the specified block of data.
208
*
209
* @param hash the algorithm state
210
* @param block the message block to process
211
* @param block_size the size of the processed block in bytes
212
*/
213
static void rhash_sha3_process_block(uint64_t hash[25], const uint64_t* block, size_t block_size)
214
{
215
/* expanded loop */
216
hash[ 0] ^= le2me_64(block[ 0]);
217
hash[ 1] ^= le2me_64(block[ 1]);
218
hash[ 2] ^= le2me_64(block[ 2]);
219
hash[ 3] ^= le2me_64(block[ 3]);
220
hash[ 4] ^= le2me_64(block[ 4]);
221
hash[ 5] ^= le2me_64(block[ 5]);
222
hash[ 6] ^= le2me_64(block[ 6]);
223
hash[ 7] ^= le2me_64(block[ 7]);
224
hash[ 8] ^= le2me_64(block[ 8]);
225
/* if not sha3-512 */
226
if (block_size > 72) {
227
hash[ 9] ^= le2me_64(block[ 9]);
228
hash[10] ^= le2me_64(block[10]);
229
hash[11] ^= le2me_64(block[11]);
230
hash[12] ^= le2me_64(block[12]);
231
/* if not sha3-384 */
232
if (block_size > 104) {
233
hash[13] ^= le2me_64(block[13]);
234
hash[14] ^= le2me_64(block[14]);
235
hash[15] ^= le2me_64(block[15]);
236
hash[16] ^= le2me_64(block[16]);
237
/* if not sha3-256 */
238
if (block_size > 136) {
239
hash[17] ^= le2me_64(block[17]);
240
#ifdef FULL_SHA3_FAMILY_SUPPORT
241
/* if not sha3-224 */
242
if (block_size > 144) {
243
hash[18] ^= le2me_64(block[18]);
244
hash[19] ^= le2me_64(block[19]);
245
hash[20] ^= le2me_64(block[20]);
246
hash[21] ^= le2me_64(block[21]);
247
hash[22] ^= le2me_64(block[22]);
248
hash[23] ^= le2me_64(block[23]);
249
hash[24] ^= le2me_64(block[24]);
250
}
251
#endif
252
}
253
}
254
}
255
/* make a permutation of the hash */
256
rhash_sha3_permutation(hash);
257
}
258
259
#define SHA3_FINALIZED 0x80000000
260
261
/**
262
* Calculate message hash.
263
* Can be called repeatedly with chunks of the message to be hashed.
264
*
265
* @param ctx the algorithm context containing current hashing state
266
* @param msg message chunk
267
* @param size length of the message chunk
268
*/
269
void rhash_sha3_update(sha3_ctx* ctx, const unsigned char* msg, size_t size)
270
{
271
size_t index = (size_t)ctx->rest;
272
size_t block_size = (size_t)ctx->block_size;
273
274
if (ctx->rest & SHA3_FINALIZED) return; /* too late for additional input */
275
ctx->rest = (unsigned)((ctx->rest + size) % block_size);
276
277
/* fill partial block */
278
if (index) {
279
size_t left = block_size - index;
280
memcpy((char*)ctx->message + index, msg, (size < left ? size : left));
281
if (size < left) return;
282
283
/* process partial block */
284
rhash_sha3_process_block(ctx->hash, ctx->message, block_size);
285
msg += left;
286
size -= left;
287
}
288
while (size >= block_size) {
289
uint64_t* aligned_message_block;
290
if (IS_ALIGNED_64(msg)) {
291
/* the most common case is processing of an already aligned message
292
without copying it */
293
aligned_message_block = (uint64_t*)msg;
294
} else {
295
memcpy(ctx->message, msg, block_size);
296
aligned_message_block = ctx->message;
297
}
298
299
rhash_sha3_process_block(ctx->hash, aligned_message_block, block_size);
300
msg += block_size;
301
size -= block_size;
302
}
303
if (size) {
304
memcpy(ctx->message, msg, size); /* save leftovers */
305
}
306
}
307
308
/**
309
* Store calculated hash into the given array.
310
*
311
* @param ctx the algorithm context containing current hashing state
312
* @param result calculated hash in binary form
313
*/
314
void rhash_sha3_final(sha3_ctx* ctx, unsigned char* result)
315
{
316
size_t digest_length = 100 - ctx->block_size / 2;
317
const size_t block_size = ctx->block_size;
318
319
if (!(ctx->rest & SHA3_FINALIZED))
320
{
321
/* clear the rest of the data queue */
322
memset((char*)ctx->message + ctx->rest, 0, block_size - ctx->rest);
323
((char*)ctx->message)[ctx->rest] |= 0x06;
324
((char*)ctx->message)[block_size - 1] |= 0x80;
325
326
/* process final block */
327
rhash_sha3_process_block(ctx->hash, ctx->message, block_size);
328
ctx->rest = SHA3_FINALIZED; /* mark context as finalized */
329
}
330
331
assert(block_size > digest_length);
332
if (result) me64_to_le_str(result, ctx->hash, digest_length);
333
}
334
335
#ifdef USE_KECCAK
336
/**
337
* Store calculated hash into the given array.
338
*
339
* @param ctx the algorithm context containing current hashing state
340
* @param result calculated hash in binary form
341
*/
342
void rhash_keccak_final(sha3_ctx* ctx, unsigned char* result)
343
{
344
size_t digest_length = 100 - ctx->block_size / 2;
345
const size_t block_size = ctx->block_size;
346
347
if (!(ctx->rest & SHA3_FINALIZED))
348
{
349
/* clear the rest of the data queue */
350
memset((char*)ctx->message + ctx->rest, 0, block_size - ctx->rest);
351
((char*)ctx->message)[ctx->rest] |= 0x01;
352
((char*)ctx->message)[block_size - 1] |= 0x80;
353
354
/* process final block */
355
rhash_sha3_process_block(ctx->hash, ctx->message, block_size);
356
ctx->rest = SHA3_FINALIZED; /* mark context as finalized */
357
}
358
359
assert(block_size > digest_length);
360
if (result) me64_to_le_str(result, ctx->hash, digest_length);
361
}
362
#endif /* USE_KECCAK */
363
364