Coverage Report

Created: 2026-03-12 06:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Utilities/cmlibrhash/librhash/sha3.c
Line
Count
Source
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 <rhash.admin@gmail.com>
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
0
#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
0
{
41
  /* NB: The Keccak capacity parameter = bits * 2 */
42
0
  unsigned rate = 1600 - bits * 2;
43
44
0
  memset(ctx, 0, sizeof(sha3_ctx));
45
0
  ctx->block_size = rate / 8;
46
0
  assert(rate <= 1600 && (rate % 64) == 0);
47
0
}
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
0
{
56
0
  rhash_keccak_init(ctx, 224);
57
0
}
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
0
{
66
0
  rhash_keccak_init(ctx, 256);
67
0
}
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
0
{
76
0
  rhash_keccak_init(ctx, 384);
77
0
}
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
0
{
86
0
  rhash_keccak_init(ctx, 512);
87
0
}
88
89
0
#define XORED_A(i) A[(i)] ^ A[(i) + 5] ^ A[(i) + 10] ^ A[(i) + 15] ^ A[(i) + 20]
90
#define THETA_STEP(i) \
91
0
  A[(i)]      ^= D[(i)]; \
92
0
  A[(i) + 5]  ^= D[(i)]; \
93
0
  A[(i) + 10] ^= D[(i)]; \
94
0
  A[(i) + 15] ^= D[(i)]; \
95
0
  A[(i) + 20] ^= D[(i)] \
96
97
/* Keccak theta() transformation */
98
static void keccak_theta(uint64_t* A)
99
0
{
100
0
  uint64_t D[5];
101
0
  D[0] = ROTL64(XORED_A(1), 1) ^ XORED_A(4);
102
0
  D[1] = ROTL64(XORED_A(2), 1) ^ XORED_A(0);
103
0
  D[2] = ROTL64(XORED_A(3), 1) ^ XORED_A(1);
104
0
  D[3] = ROTL64(XORED_A(4), 1) ^ XORED_A(2);
105
0
  D[4] = ROTL64(XORED_A(0), 1) ^ XORED_A(3);
106
0
  THETA_STEP(0);
107
0
  THETA_STEP(1);
108
0
  THETA_STEP(2);
109
0
  THETA_STEP(3);
110
0
  THETA_STEP(4);
111
0
}
112
113
/* Keccak pi() transformation */
114
static void keccak_pi(uint64_t* A)
115
0
{
116
0
  uint64_t A1;
117
0
  A1 = A[1];
118
0
  A[ 1] = A[ 6];
119
0
  A[ 6] = A[ 9];
120
0
  A[ 9] = A[22];
121
0
  A[22] = A[14];
122
0
  A[14] = A[20];
123
0
  A[20] = A[ 2];
124
0
  A[ 2] = A[12];
125
0
  A[12] = A[13];
126
0
  A[13] = A[19];
127
0
  A[19] = A[23];
128
0
  A[23] = A[15];
129
0
  A[15] = A[ 4];
130
0
  A[ 4] = A[24];
131
0
  A[24] = A[21];
132
0
  A[21] = A[ 8];
133
0
  A[ 8] = A[16];
134
0
  A[16] = A[ 5];
135
0
  A[ 5] = A[ 3];
136
0
  A[ 3] = A[18];
137
0
  A[18] = A[17];
138
0
  A[17] = A[11];
139
0
  A[11] = A[ 7];
140
0
  A[ 7] = A[10];
141
0
  A[10] = A1;
142
  /* note: A[ 0] is left as is */
143
0
}
144
145
#define CHI_STEP(i) \
146
0
  A0 = A[0 + (i)]; \
147
0
  A1 = A[1 + (i)]; \
148
0
  A[0 + (i)] ^= ~A1 & A[2 + (i)]; \
149
0
  A[1 + (i)] ^= ~A[2 + (i)] & A[3 + (i)]; \
150
0
  A[2 + (i)] ^= ~A[3 + (i)] & A[4 + (i)]; \
151
0
  A[3 + (i)] ^= ~A[4 + (i)] & A0; \
152
0
  A[4 + (i)] ^= ~A0 & A1 \
153
154
/* Keccak chi() transformation */
155
static void keccak_chi(uint64_t* A)
156
0
{
157
0
  uint64_t A0, A1;
158
0
  CHI_STEP(0);
159
0
  CHI_STEP(5);
160
0
  CHI_STEP(10);
161
0
  CHI_STEP(15);
162
0
  CHI_STEP(20);
163
0
}
164
165
static void rhash_sha3_permutation(uint64_t* state)
166
0
{
167
0
  int round;
168
0
  for (round = 0; round < NumberOfRounds; round++)
169
0
  {
170
0
    keccak_theta(state);
171
172
    /* apply Keccak rho() transformation */
173
0
    state[ 1] = ROTL64(state[ 1],  1);
174
0
    state[ 2] = ROTL64(state[ 2], 62);
175
0
    state[ 3] = ROTL64(state[ 3], 28);
176
0
    state[ 4] = ROTL64(state[ 4], 27);
177
0
    state[ 5] = ROTL64(state[ 5], 36);
178
0
    state[ 6] = ROTL64(state[ 6], 44);
179
0
    state[ 7] = ROTL64(state[ 7],  6);
180
0
    state[ 8] = ROTL64(state[ 8], 55);
181
0
    state[ 9] = ROTL64(state[ 9], 20);
182
0
    state[10] = ROTL64(state[10],  3);
183
0
    state[11] = ROTL64(state[11], 10);
184
0
    state[12] = ROTL64(state[12], 43);
185
0
    state[13] = ROTL64(state[13], 25);
186
0
    state[14] = ROTL64(state[14], 39);
187
0
    state[15] = ROTL64(state[15], 41);
188
0
    state[16] = ROTL64(state[16], 45);
189
0
    state[17] = ROTL64(state[17], 15);
190
0
    state[18] = ROTL64(state[18], 21);
191
0
    state[19] = ROTL64(state[19],  8);
192
0
    state[20] = ROTL64(state[20], 18);
193
0
    state[21] = ROTL64(state[21],  2);
194
0
    state[22] = ROTL64(state[22], 61);
195
0
    state[23] = ROTL64(state[23], 56);
196
0
    state[24] = ROTL64(state[24], 14);
197
198
0
    keccak_pi(state);
199
0
    keccak_chi(state);
200
201
    /* apply iota(state, round) */
202
0
    *state ^= keccak_round_constants[round];
203
0
  }
204
0
}
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
0
{
215
  /* expanded loop */
216
0
  hash[ 0] ^= le2me_64(block[ 0]);
217
0
  hash[ 1] ^= le2me_64(block[ 1]);
218
0
  hash[ 2] ^= le2me_64(block[ 2]);
219
0
  hash[ 3] ^= le2me_64(block[ 3]);
220
0
  hash[ 4] ^= le2me_64(block[ 4]);
221
0
  hash[ 5] ^= le2me_64(block[ 5]);
222
0
  hash[ 6] ^= le2me_64(block[ 6]);
223
0
  hash[ 7] ^= le2me_64(block[ 7]);
224
0
  hash[ 8] ^= le2me_64(block[ 8]);
225
  /* if not sha3-512 */
226
0
  if (block_size > 72) {
227
0
    hash[ 9] ^= le2me_64(block[ 9]);
228
0
    hash[10] ^= le2me_64(block[10]);
229
0
    hash[11] ^= le2me_64(block[11]);
230
0
    hash[12] ^= le2me_64(block[12]);
231
    /* if not sha3-384 */
232
0
    if (block_size > 104) {
233
0
      hash[13] ^= le2me_64(block[13]);
234
0
      hash[14] ^= le2me_64(block[14]);
235
0
      hash[15] ^= le2me_64(block[15]);
236
0
      hash[16] ^= le2me_64(block[16]);
237
      /* if not sha3-256 */
238
0
      if (block_size > 136) {
239
0
        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
0
      }
253
0
    }
254
0
  }
255
  /* make a permutation of the hash */
256
0
  rhash_sha3_permutation(hash);
257
0
}
258
259
0
#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
0
{
271
0
  size_t index = (size_t)ctx->rest;
272
0
  size_t block_size = (size_t)ctx->block_size;
273
274
0
  if (ctx->rest & SHA3_FINALIZED) return; /* too late for additional input */
275
0
  ctx->rest = (unsigned)((ctx->rest + size) % block_size);
276
277
  /* fill partial block */
278
0
  if (index) {
279
0
    size_t left = block_size - index;
280
0
    memcpy((char*)ctx->message + index, msg, (size < left ? size : left));
281
0
    if (size < left) return;
282
283
    /* process partial block */
284
0
    rhash_sha3_process_block(ctx->hash, ctx->message, block_size);
285
0
    msg  += left;
286
0
    size -= left;
287
0
  }
288
0
  while (size >= block_size) {
289
0
    uint64_t* aligned_message_block;
290
0
    if (IS_ALIGNED_64(msg)) {
291
      /* the most common case is processing of an already aligned message
292
      without copying it */
293
0
      aligned_message_block = (uint64_t*)msg;
294
0
    } else {
295
0
      memcpy(ctx->message, msg, block_size);
296
0
      aligned_message_block = ctx->message;
297
0
    }
298
299
0
    rhash_sha3_process_block(ctx->hash, aligned_message_block, block_size);
300
0
    msg  += block_size;
301
0
    size -= block_size;
302
0
  }
303
0
  if (size) {
304
0
    memcpy(ctx->message, msg, size); /* save leftovers */
305
0
  }
306
0
}
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
0
{
316
0
  size_t digest_length = 100 - ctx->block_size / 2;
317
0
  const size_t block_size = ctx->block_size;
318
319
0
  if (!(ctx->rest & SHA3_FINALIZED))
320
0
  {
321
    /* clear the rest of the data queue */
322
0
    memset((char*)ctx->message + ctx->rest, 0, block_size - ctx->rest);
323
0
    ((char*)ctx->message)[ctx->rest] |= 0x06;
324
0
    ((char*)ctx->message)[block_size - 1] |= 0x80;
325
326
    /* process final block */
327
0
    rhash_sha3_process_block(ctx->hash, ctx->message, block_size);
328
0
    ctx->rest = SHA3_FINALIZED; /* mark context as finalized */
329
0
  }
330
331
0
  assert(block_size > digest_length);
332
0
  if (result) me64_to_le_str(result, ctx->hash, digest_length);
333
0
}
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 */