Coverage Report

Created: 2023-03-26 07:33

/src/nettle/gosthash94.c
Line
Count
Source (jump to first uncovered line)
1
/* gosthash94.c - an implementation of GOST Hash Function
2
 *
3
 * based on the Russian Standard GOST R 34.11-94.
4
 * English description in RFC 5831.
5
 * See also RFC 4357.
6
 *
7
 * Copyright: 2009-2012 Aleksey Kravchenko <rhash.admin@gmail.com>
8
 * Copyright: 2019 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
9
 *
10
 * Permission is hereby granted, free of charge, to any person obtaining a
11
 * copy of this software and associated documentation files (the
12
 * "Software"), to deal in the Software without restriction, including
13
 * without limitation the rights to use, copy, modify, merge, publish,
14
 * distribute, sublicense, and/or sell copies of the Software, and to
15
 * permit persons to whom the Software is furnished to do so, subject to
16
 * the following conditions:
17
 *
18
 * The above copyright notice and this permission notice shall be included
19
 * in all copies or substantial portions of the Software.
20
 *
21
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
25
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
 */
29
30
/*
31
 * Ported to nettle by Nikos Mavrogiannopoulos.
32
 */
33
34
#if HAVE_CONFIG_H
35
#include "config.h"
36
#endif
37
38
#include <assert.h>
39
#include <string.h>
40
41
#include "macros.h"
42
#include "nettle-write.h"
43
#include "gosthash94.h"
44
#include "gost28147-internal.h"
45
46
/**
47
 * Initialize algorithm context before calculating hash
48
 * with test parameters set.
49
 *
50
 * @param ctx context to initalize
51
 */
52
void
53
gosthash94_init (struct gosthash94_ctx *ctx)
54
0
{
55
0
    memset (ctx, 0, sizeof (struct gosthash94_ctx));
56
0
}
57
58
/**
59
 * The core transformation. Process a 512-bit block.
60
 *
61
 * @param hash intermediate message hash
62
 * @param block the message block to process
63
 */
64
static void
65
gost_block_compress (struct gosthash94_ctx *ctx, const uint32_t *block,
66
         const uint32_t sbox[4][256])
67
0
{
68
0
    unsigned i;
69
0
    uint32_t key[8], u[8], v[8], w[8], s[8];
70
71
    /* u := hash, v := <256-bit message block> */
72
0
    memcpy (u, ctx->hash, sizeof (u));
73
0
    memcpy (v, block, sizeof (v));
74
75
    /* w := u xor v */
76
0
    w[0] = u[0] ^ v[0], w[1] = u[1] ^ v[1];
77
0
    w[2] = u[2] ^ v[2], w[3] = u[3] ^ v[3];
78
0
    w[4] = u[4] ^ v[4], w[5] = u[5] ^ v[5];
79
0
    w[6] = u[6] ^ v[6], w[7] = u[7] ^ v[7];
80
81
    /* calculate keys, encrypt hash and store result to the s[] array */
82
0
    for (i = 0;; i += 2)
83
0
      {
84
          /* key generation: key_i := P(w) */
85
0
          key[0] =
86
0
              (w[0] & 0x000000ff) | ((w[2] & 0x000000ff) << 8) |
87
0
              ((w[4] & 0x000000ff) << 16) | ((w[6] & 0x000000ff) << 24);
88
0
          key[1] =
89
0
              ((w[0] & 0x0000ff00) >> 8) | (w[2] & 0x0000ff00) |
90
0
              ((w[4] & 0x0000ff00) << 8) | ((w[6] & 0x0000ff00) << 16);
91
0
          key[2] =
92
0
              ((w[0] & 0x00ff0000) >> 16) | ((w[2] & 0x00ff0000) >> 8) |
93
0
              (w[4] & 0x00ff0000) | ((w[6] & 0x00ff0000) << 8);
94
0
          key[3] =
95
0
              ((w[0] & 0xff000000) >> 24) | ((w[2] & 0xff000000) >> 16) |
96
0
              ((w[4] & 0xff000000) >> 8) | (w[6] & 0xff000000);
97
0
          key[4] =
98
0
              (w[1] & 0x000000ff) | ((w[3] & 0x000000ff) << 8) |
99
0
              ((w[5] & 0x000000ff) << 16) | ((w[7] & 0x000000ff) << 24);
100
0
          key[5] =
101
0
              ((w[1] & 0x0000ff00) >> 8) | (w[3] & 0x0000ff00) |
102
0
              ((w[5] & 0x0000ff00) << 8) | ((w[7] & 0x0000ff00) << 16);
103
0
          key[6] =
104
0
              ((w[1] & 0x00ff0000) >> 16) | ((w[3] & 0x00ff0000) >> 8) |
105
0
              (w[5] & 0x00ff0000) | ((w[7] & 0x00ff0000) << 8);
106
0
          key[7] =
107
0
              ((w[1] & 0xff000000) >> 24) | ((w[3] & 0xff000000) >> 16) |
108
0
              ((w[5] & 0xff000000) >> 8) | (w[7] & 0xff000000);
109
110
          /* encryption: s_i := E_{key_i} (h_i) */
111
0
          _nettle_gost28147_encrypt_block (key, sbox, &ctx->hash[i], &s[i]);
112
113
0
          if (i == 0)
114
0
            {
115
                /* w:= A(u) ^ A^2(v) */
116
0
                w[0] = u[2] ^ v[4], w[1] = u[3] ^ v[5];
117
0
                w[2] = u[4] ^ v[6], w[3] = u[5] ^ v[7];
118
0
                w[4] = u[6] ^ (v[0] ^= v[2]);
119
0
                w[5] = u[7] ^ (v[1] ^= v[3]);
120
0
                w[6] = (u[0] ^= u[2]) ^ (v[2] ^= v[4]);
121
0
                w[7] = (u[1] ^= u[3]) ^ (v[3] ^= v[5]);
122
0
            }
123
0
          else if ((i & 2) != 0)
124
0
            {
125
0
                if (i == 6)
126
0
                    break;
127
128
                /* w := A^2(u) xor A^4(v) xor C_3; u := A(u) xor C_3 */
129
                /* C_3=0xff00ffff000000ffff0000ff00ffff0000ff00ff00ff00ffff00ff00ff00ff00 */
130
0
                u[2] ^= u[4] ^ 0x000000ff;
131
0
                u[3] ^= u[5] ^ 0xff00ffff;
132
0
                u[4] ^= 0xff00ff00;
133
0
                u[5] ^= 0xff00ff00;
134
0
                u[6] ^= 0x00ff00ff;
135
0
                u[7] ^= 0x00ff00ff;
136
0
                u[0] ^= 0x00ffff00;
137
0
                u[1] ^= 0xff0000ff;
138
139
0
                w[0] = u[4] ^ v[0];
140
0
                w[2] = u[6] ^ v[2];
141
0
                w[4] = u[0] ^ (v[4] ^= v[6]);
142
0
                w[6] = u[2] ^ (v[6] ^= v[0]);
143
0
                w[1] = u[5] ^ v[1];
144
0
                w[3] = u[7] ^ v[3];
145
0
                w[5] = u[1] ^ (v[5] ^= v[7]);
146
0
                w[7] = u[3] ^ (v[7] ^= v[1]);
147
0
            }
148
0
          else
149
0
            {
150
                /* i==4 here */
151
                /* w:= A( A^2(u) xor C_3 ) xor A^6(v) */
152
0
                w[0] = u[6] ^ v[4], w[1] = u[7] ^ v[5];
153
0
                w[2] = u[0] ^ v[6], w[3] = u[1] ^ v[7];
154
0
                w[4] = u[2] ^ (v[0] ^= v[2]);
155
0
                w[5] = u[3] ^ (v[1] ^= v[3]);
156
0
                w[6] = (u[4] ^= u[6]) ^ (v[2] ^= v[4]);
157
0
                w[7] = (u[5] ^= u[7]) ^ (v[3] ^= v[5]);
158
0
            }
159
0
      }
160
161
    /* step hash function: x(block, hash) := psi^61(hash xor psi(block xor psi^12(S))) */
162
163
    /* 12 rounds of the LFSR and xor in <message block> */
164
0
    u[0] = block[0] ^ s[6];
165
0
    u[1] = block[1] ^ s[7];
166
0
    u[2] =
167
0
        block[2] ^ (s[0] << 16) ^ (s[0] >> 16) ^ (s[0] & 0xffff) ^ (s[1] &
168
0
                                                                    0xffff)
169
0
        ^ (s[1] >> 16) ^ (s[2] << 16) ^ s[6] ^ (s[6] << 16) ^ (s[7] &
170
0
                                                               0xffff0000)
171
0
        ^ (s[7] >> 16);
172
0
    u[3] =
173
0
        block[3] ^ (s[0] & 0xffff) ^ (s[0] << 16) ^ (s[1] & 0xffff) ^ (s[1]
174
0
                                                                       <<
175
0
                                                                       16)
176
0
        ^ (s[1] >> 16) ^ (s[2] << 16) ^ (s[2] >> 16) ^ (s[3] << 16) ^ s[6]
177
0
        ^ (s[6] << 16) ^ (s[6] >> 16) ^ (s[7] & 0xffff) ^ (s[7] << 16) ^
178
0
        (s[7] >> 16);
179
0
    u[4] =
180
0
        block[4] ^ (s[0] & 0xffff0000) ^ (s[0] << 16) ^ (s[0] >> 16) ^
181
0
        (s[1] & 0xffff0000) ^ (s[1] >> 16) ^ (s[2] << 16) ^ (s[2] >> 16) ^
182
0
        (s[3] << 16) ^ (s[3] >> 16) ^ (s[4] << 16) ^ (s[6] << 16) ^ (s[6]
183
0
                                                                     >> 16)
184
0
        ^ (s[7] & 0xffff) ^ (s[7] << 16) ^ (s[7] >> 16);
185
0
    u[5] =
186
0
        block[5] ^ (s[0] << 16) ^ (s[0] >> 16) ^ (s[0] & 0xffff0000) ^
187
0
        (s[1] & 0xffff) ^ s[2] ^ (s[2] >> 16) ^ (s[3] << 16) ^ (s[3] >> 16)
188
0
        ^ (s[4] << 16) ^ (s[4] >> 16) ^ (s[5] << 16) ^ (s[6] << 16) ^ (s[6]
189
0
                                                                       >>
190
0
                                                                       16)
191
0
        ^ (s[7] & 0xffff0000) ^ (s[7] << 16) ^ (s[7] >> 16);
192
0
    u[6] =
193
0
        block[6] ^ s[0] ^ (s[1] >> 16) ^ (s[2] << 16) ^ s[3] ^ (s[3] >> 16)
194
0
        ^ (s[4] << 16) ^ (s[4] >> 16) ^ (s[5] << 16) ^ (s[5] >> 16) ^ s[6]
195
0
        ^ (s[6] << 16) ^ (s[6] >> 16) ^ (s[7] << 16);
196
0
    u[7] =
197
0
        block[7] ^ (s[0] & 0xffff0000) ^ (s[0] << 16) ^ (s[1] & 0xffff) ^
198
0
        (s[1] << 16) ^ (s[2] >> 16) ^ (s[3] << 16) ^ s[4] ^ (s[4] >> 16) ^
199
0
        (s[5] << 16) ^ (s[5] >> 16) ^ (s[6] >> 16) ^ (s[7] & 0xffff) ^
200
0
        (s[7] << 16) ^ (s[7] >> 16);
201
202
    /* 1 round of the LFSR (a mixing transformation) and xor with <hash> */
203
0
    v[0] = ctx->hash[0] ^ (u[1] << 16) ^ (u[0] >> 16);
204
0
    v[1] = ctx->hash[1] ^ (u[2] << 16) ^ (u[1] >> 16);
205
0
    v[2] = ctx->hash[2] ^ (u[3] << 16) ^ (u[2] >> 16);
206
0
    v[3] = ctx->hash[3] ^ (u[4] << 16) ^ (u[3] >> 16);
207
0
    v[4] = ctx->hash[4] ^ (u[5] << 16) ^ (u[4] >> 16);
208
0
    v[5] = ctx->hash[5] ^ (u[6] << 16) ^ (u[5] >> 16);
209
0
    v[6] = ctx->hash[6] ^ (u[7] << 16) ^ (u[6] >> 16);
210
0
    v[7] =
211
0
        ctx->
212
0
        hash[7] ^ (u[0] & 0xffff0000) ^ (u[0] << 16) ^ (u[1] & 0xffff0000)
213
0
        ^ (u[1] << 16) ^ (u[6] << 16) ^ (u[7] & 0xffff0000) ^ (u[7] >> 16);
214
215
    /* 61 rounds of LFSR, mixing up hash */
216
0
    ctx->hash[0] = (v[0] & 0xffff0000) ^ (v[0] << 16) ^ (v[0] >> 16) ^
217
0
        (v[1] >> 16) ^ (v[1] & 0xffff0000) ^ (v[2] << 16) ^
218
0
        (v[3] >> 16) ^ (v[4] << 16) ^ (v[5] >> 16) ^ v[5] ^
219
0
        (v[6] >> 16) ^ (v[7] << 16) ^ (v[7] >> 16) ^ (v[7] & 0xffff);
220
0
    ctx->hash[1] = (v[0] << 16) ^ (v[0] >> 16) ^ (v[0] & 0xffff0000) ^
221
0
        (v[1] & 0xffff) ^ v[2] ^ (v[2] >> 16) ^ (v[3] << 16) ^
222
0
        (v[4] >> 16) ^ (v[5] << 16) ^ (v[6] << 16) ^ v[6] ^
223
0
        (v[7] & 0xffff0000) ^ (v[7] >> 16);
224
0
    ctx->hash[2] = (v[0] & 0xffff) ^ (v[0] << 16) ^ (v[1] << 16) ^
225
0
        (v[1] >> 16) ^ (v[1] & 0xffff0000) ^ (v[2] << 16) ^ (v[3] >> 16) ^
226
0
        v[3] ^ (v[4] << 16) ^ (v[5] >> 16) ^ v[6] ^ (v[6] >> 16) ^
227
0
        (v[7] & 0xffff) ^ (v[7] << 16) ^ (v[7] >> 16);
228
0
    ctx->hash[3] = (v[0] << 16) ^ (v[0] >> 16) ^ (v[0] & 0xffff0000) ^
229
0
        (v[1] & 0xffff0000) ^ (v[1] >> 16) ^ (v[2] << 16) ^
230
0
        (v[2] >> 16) ^ v[2] ^ (v[3] << 16) ^ (v[4] >> 16) ^ v[4] ^
231
0
        (v[5] << 16) ^ (v[6] << 16) ^ (v[7] & 0xffff) ^ (v[7] >> 16);
232
0
    ctx->hash[4] =
233
0
        (v[0] >> 16) ^ (v[1] << 16) ^ v[1] ^ (v[2] >> 16) ^ v[2] ^ (v[3] <<
234
0
                                                                    16) ^
235
0
        (v[3] >> 16) ^ v[3] ^ (v[4] << 16) ^ (v[5] >> 16) ^ v[5] ^ (v[6] <<
236
0
                                                                    16) ^
237
0
        (v[6] >> 16) ^ (v[7] << 16);
238
0
    ctx->hash[5] =
239
0
        (v[0] << 16) ^ (v[0] & 0xffff0000) ^ (v[1] << 16) ^ (v[1] >> 16) ^
240
0
        (v[1] & 0xffff0000) ^ (v[2] << 16) ^ v[2] ^ (v[3] >> 16) ^ v[3] ^
241
0
        (v[4] << 16) ^ (v[4] >> 16) ^ v[4] ^ (v[5] << 16) ^ (v[6] << 16) ^
242
0
        (v[6] >> 16) ^ v[6] ^ (v[7] << 16) ^ (v[7] >> 16) ^ (v[7] &
243
0
                                                             0xffff0000);
244
0
    ctx->hash[6] =
245
0
        v[0] ^ v[2] ^ (v[2] >> 16) ^ v[3] ^ (v[3] << 16) ^ v[4] ^ (v[4] >>
246
0
                                                                   16) ^
247
0
        (v[5] << 16) ^ (v[5] >> 16) ^ v[5] ^ (v[6] << 16) ^ (v[6] >> 16) ^
248
0
        v[6] ^ (v[7] << 16) ^ v[7];
249
0
    ctx->hash[7] =
250
0
        v[0] ^ (v[0] >> 16) ^ (v[1] << 16) ^ (v[1] >> 16) ^ (v[2] << 16) ^
251
0
        (v[3] >> 16) ^ v[3] ^ (v[4] << 16) ^ v[4] ^ (v[5] >> 16) ^ v[5] ^
252
0
        (v[6] << 16) ^ (v[6] >> 16) ^ (v[7] << 16) ^ v[7];
253
0
}
254
255
/**
256
 * This function calculates hash value by 256-bit blocks.
257
 * It updates 256-bit check sum as follows:
258
 *    *(uint256_t)(ctx->sum) += *(uint256_t*)block;
259
 * and then updates intermediate hash value ctx->hash 
260
 * by calling gost_block_compress().
261
 *
262
 * @param ctx algorithm context
263
 * @param block the 256-bit message block to process
264
 */
265
static void
266
gost_compute_sum_and_hash (struct gosthash94_ctx *ctx, const uint8_t *block,
267
         const uint32_t sbox[4][256])
268
0
{
269
0
    uint32_t block_le[8];
270
0
    unsigned i, carry;
271
272
    /* compute the 256-bit sum */
273
0
    for (i = carry = 0; i < 8; i++, block += 4)
274
0
      {
275
0
    block_le[i] = LE_READ_UINT32(block);
276
0
          ctx->sum[i] += carry;
277
0
    carry = (ctx->sum[i] < carry);
278
0
          ctx->sum[i] += block_le[i];
279
0
          carry += (ctx->sum[i] < block_le[i]);
280
0
      }
281
282
    /* update message hash */
283
0
    gost_block_compress (ctx, block_le, sbox);
284
0
}
285
286
0
#define COMPRESS(ctx, block) gost_compute_sum_and_hash((ctx), (block), sbox);
287
288
/**
289
 * Calculate message hash.
290
 * Can be called repeatedly with chunks of the message to be hashed.
291
 *
292
 * @param ctx the algorithm context containing current hashing state
293
 * @param msg message chunk
294
 * @param size length of the message chunk
295
 */
296
static void
297
gosthash94_update_int (struct gosthash94_ctx *ctx,
298
           size_t length, const uint8_t *msg,
299
           const uint32_t sbox[4][256])
300
0
{
301
0
    MD_UPDATE(ctx, length, msg, COMPRESS, ctx->count++);
302
0
}
303
304
/**
305
 * Calculate message hash.
306
 * Can be called repeatedly with chunks of the message to be hashed.
307
 *
308
 * @param ctx the algorithm context containing current hashing state
309
 * @param msg message chunk
310
 * @param size length of the message chunk
311
 */
312
void
313
gosthash94_update (struct gosthash94_ctx *ctx,
314
       size_t length, const uint8_t *msg)
315
0
{
316
0
  gosthash94_update_int (ctx, length, msg,
317
0
       _nettle_gost28147_param_test_3411.sbox);
318
0
}
319
320
/**
321
 * Calculate message hash.
322
 * Can be called repeatedly with chunks of the message to be hashed.
323
 *
324
 * @param ctx the algorithm context containing current hashing state
325
 * @param msg message chunk
326
 * @param size length of the message chunk
327
 */
328
void
329
gosthash94cp_update (struct gosthash94_ctx *ctx,
330
         size_t length, const uint8_t *msg)
331
0
{
332
0
  gosthash94_update_int (ctx, length, msg,
333
0
       _nettle_gost28147_param_CryptoPro_3411.sbox);
334
0
}
335
336
/**
337
 * Finish hashing and store message digest into given array.
338
 *
339
 * @param ctx the algorithm context containing current hashing state
340
 * @param result calculated hash in binary form
341
 */
342
static void
343
gosthash94_write_digest (struct gosthash94_ctx *ctx,
344
       size_t length, uint8_t *result,
345
       const uint32_t sbox[4][256])
346
0
{
347
0
    uint32_t msg32[GOSTHASH94_BLOCK_SIZE / 4];
348
349
0
    assert(length <= GOSTHASH94_DIGEST_SIZE);
350
351
    /* pad the last block with zeroes and hash it */
352
0
    if (ctx->index > 0)
353
0
      {
354
0
          memset (ctx->block + ctx->index, 0, GOSTHASH94_BLOCK_SIZE - ctx->index);
355
0
          gost_compute_sum_and_hash (ctx, ctx->block, sbox);
356
0
      }
357
358
    /* hash the message length and the sum */
359
0
    msg32[0] = (ctx->count << 8) | (ctx->index << 3);
360
0
    msg32[1] = ctx->count >> 24;
361
0
    memset (msg32 + 2, 0, sizeof (uint32_t) * 6);
362
363
0
    gost_block_compress (ctx, msg32, sbox);
364
0
    gost_block_compress (ctx, ctx->sum, sbox);
365
366
    /* convert hash state to result bytes */
367
0
    _nettle_write_le32(length, result, ctx->hash);
368
0
    gosthash94_init (ctx);
369
0
}
370
371
void
372
gosthash94_digest (struct gosthash94_ctx *ctx,
373
       size_t length, uint8_t *result)
374
0
{
375
0
  gosthash94_write_digest (ctx, length, result,
376
0
         _nettle_gost28147_param_test_3411.sbox);
377
0
}
378
379
void
380
gosthash94cp_digest (struct gosthash94_ctx *ctx,
381
         size_t length, uint8_t *result)
382
0
{
383
0
  gosthash94_write_digest (ctx, length, result,
384
0
         _nettle_gost28147_param_CryptoPro_3411.sbox);
385
0
}