Coverage Report

Created: 2024-11-21 07:03

/src/libgcrypt/cipher/gostr3411-94.c
Line
Count
Source (jump to first uncovered line)
1
/* gostr3411-94.c - GOST R 34.11-94 hash function
2
 * Copyright (C) 2012 Free Software Foundation, Inc.
3
 *
4
 * This file is part of Libgcrypt.
5
 *
6
 * Libgcrypt is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU Lesser General Public License as
8
 * published by the Free Software Foundation; either version 2.1 of
9
 * the License, or (at your option) any later version.
10
 *
11
 * Libgcrypt is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
18
 */
19
20
21
#include <config.h>
22
#include <stdio.h>
23
#include <stdlib.h>
24
#include <string.h>
25
26
#include "g10lib.h"
27
#include "bithelp.h"
28
#include "bufhelp.h"
29
#include "cipher.h"
30
#include "hash-common.h"
31
32
#include "gost.h"
33
34
500k
#define max(a, b) (((a) > (b)) ? (a) : (b))
35
36
typedef struct {
37
  gcry_md_block_ctx_t bctx;
38
  union {
39
    u32 h[8];
40
    byte result[32];
41
  };
42
  u32 sigma[8];
43
  u32 len;
44
  int cryptopro;
45
} GOSTR3411_CONTEXT;
46
47
static unsigned int
48
transform (void *c, const unsigned char *data, size_t nblks);
49
50
static void
51
gost3411_init (void *context, unsigned int flags)
52
605
{
53
605
  GOSTR3411_CONTEXT *hd = context;
54
55
605
  (void)flags;
56
57
605
  memset (hd->h, 0, 32);
58
605
  memset (hd->sigma, 0, 32);
59
60
605
  hd->bctx.nblocks = 0;
61
605
  hd->bctx.count = 0;
62
605
  hd->bctx.blocksize_shift = _gcry_ctz(32);
63
605
  hd->bctx.bwrite = transform;
64
605
  hd->cryptopro = 0;
65
605
}
66
67
static void
68
gost3411_cp_init (void *context, unsigned int flags)
69
605
{
70
605
  GOSTR3411_CONTEXT *hd = context;
71
605
  gost3411_init (context, flags);
72
605
  hd->cryptopro = 1;
73
605
}
74
75
static void
76
do_p (u32 *p, u32 *u, u32 *v)
77
2.00M
{
78
2.00M
  int k;
79
2.00M
  u32 t[8];
80
81
18.0M
  for (k = 0; k < 8; k++)
82
16.0M
    t[k] = u[k] ^ v[k];
83
84
2.00M
  k = 0;
85
2.00M
  p[k+0] = ((t[0] >> (8*k)) & 0xff) << 0 |
86
2.00M
           ((t[2] >> (8*k)) & 0xff) << 8 |
87
2.00M
           ((t[4] >> (8*k)) & 0xff) << 16 |
88
2.00M
           ((t[6] >> (8*k)) & 0xff) << 24;
89
2.00M
  p[k+4] = ((t[1] >> (8*k)) & 0xff) << 0 |
90
2.00M
           ((t[3] >> (8*k)) & 0xff) << 8 |
91
2.00M
           ((t[5] >> (8*k)) & 0xff) << 16 |
92
2.00M
           ((t[7] >> (8*k)) & 0xff) << 24;
93
94
2.00M
  k = 1;
95
2.00M
  p[k+0] = ((t[0] >> (8*k)) & 0xff) << 0 |
96
2.00M
           ((t[2] >> (8*k)) & 0xff) << 8 |
97
2.00M
           ((t[4] >> (8*k)) & 0xff) << 16 |
98
2.00M
           ((t[6] >> (8*k)) & 0xff) << 24;
99
2.00M
  p[k+4] = ((t[1] >> (8*k)) & 0xff) << 0 |
100
2.00M
           ((t[3] >> (8*k)) & 0xff) << 8 |
101
2.00M
           ((t[5] >> (8*k)) & 0xff) << 16 |
102
2.00M
           ((t[7] >> (8*k)) & 0xff) << 24;
103
104
2.00M
  k = 2;
105
2.00M
  p[k+0] = ((t[0] >> (8*k)) & 0xff) << 0 |
106
2.00M
           ((t[2] >> (8*k)) & 0xff) << 8 |
107
2.00M
           ((t[4] >> (8*k)) & 0xff) << 16 |
108
2.00M
           ((t[6] >> (8*k)) & 0xff) << 24;
109
2.00M
  p[k+4] = ((t[1] >> (8*k)) & 0xff) << 0 |
110
2.00M
           ((t[3] >> (8*k)) & 0xff) << 8 |
111
2.00M
           ((t[5] >> (8*k)) & 0xff) << 16 |
112
2.00M
           ((t[7] >> (8*k)) & 0xff) << 24;
113
114
2.00M
  k = 3;
115
2.00M
  p[k+0] = ((t[0] >> (8*k)) & 0xff) << 0 |
116
2.00M
           ((t[2] >> (8*k)) & 0xff) << 8 |
117
2.00M
           ((t[4] >> (8*k)) & 0xff) << 16 |
118
2.00M
           ((t[6] >> (8*k)) & 0xff) << 24;
119
2.00M
  p[k+4] = ((t[1] >> (8*k)) & 0xff) << 0 |
120
2.00M
           ((t[3] >> (8*k)) & 0xff) << 8 |
121
2.00M
           ((t[5] >> (8*k)) & 0xff) << 16 |
122
2.00M
           ((t[7] >> (8*k)) & 0xff) << 24;
123
2.00M
}
124
125
static void
126
do_a (u32 *u)
127
2.00M
{
128
2.00M
  u32 t[2];
129
2.00M
  int i;
130
2.00M
  memcpy(t, u, 2*4);
131
14.0M
  for (i = 0; i < 6; i++)
132
12.0M
    u[i] = u[i+2];
133
2.00M
  u[6] = u[0] ^ t[0];
134
2.00M
  u[7] = u[1] ^ t[1];
135
2.00M
}
136
/* apply do_a twice: 1 2 3 4 -> 3 4 1^2 2^3 */
137
static void
138
do_a2 (u32 *u)
139
2.00M
{
140
2.00M
  u32 t[4];
141
2.00M
  int i;
142
2.00M
  memcpy (t, u, 16);
143
2.00M
  memcpy (u, u + 4, 16);
144
6.00M
  for (i = 0; i < 2; i++)
145
4.00M
    {
146
4.00M
      u[4+i] = t[i] ^ t[i + 2];
147
4.00M
      u[6+i] = u[i] ^ t[i + 2];
148
4.00M
    }
149
2.00M
}
150
151
static void
152
do_apply_c2 (u32 *u)
153
500k
{
154
500k
  u[ 0] ^= 0xff00ff00;
155
500k
  u[ 1] ^= 0xff00ff00;
156
500k
  u[ 2] ^= 0x00ff00ff;
157
500k
  u[ 3] ^= 0x00ff00ff;
158
500k
  u[ 4] ^= 0x00ffff00;
159
500k
  u[ 5] ^= 0xff0000ff;
160
500k
  u[ 6] ^= 0x000000ff;
161
500k
  u[ 7] ^= 0xff00ffff;
162
500k
}
163
164
#define do_chi_step12(e) \
165
2.00M
  e[6] ^= ((e[6] >> 16) ^ e[7] ^ (e[7] >> 16) ^ e[4] ^ (e[5] >>16)) & 0xffff;
166
167
#define do_chi_step13(e) \
168
2.00M
  e[6] ^= ((e[7] ^ (e[7] >> 16) ^ e[0] ^ (e[4] >> 16) ^ e[6]) & 0xffff) << 16;
169
170
#define do_chi_doublestep(e, i) \
171
16.5M
  e[i] ^= (e[i] >> 16) ^ (e[(i+1)%8] << 16) ^ e[(i+1)%8] ^ (e[(i+1)%8] >> 16) ^ (e[(i+2)%8] << 16) ^ e[(i+6)%8] ^ (e[(i+7)%8] >> 16); \
172
16.5M
  e[i] ^= (e[i] << 16);
173
174
static void
175
do_chi_submix12 (u32 *e, u32 *x)
176
500k
{
177
500k
  e[6] ^= x[0];
178
500k
  e[7] ^= x[1];
179
500k
  e[0] ^= x[2];
180
500k
  e[1] ^= x[3];
181
500k
  e[2] ^= x[4];
182
500k
  e[3] ^= x[5];
183
500k
  e[4] ^= x[6];
184
500k
  e[5] ^= x[7];
185
500k
}
186
187
static void
188
do_chi_submix13 (u32 *e, u32 *x)
189
500k
{
190
500k
  e[6] ^= (x[0] << 16) | (x[7] >> 16);
191
500k
  e[7] ^= (x[1] << 16) | (x[0] >> 16);
192
500k
  e[0] ^= (x[2] << 16) | (x[1] >> 16);
193
500k
  e[1] ^= (x[3] << 16) | (x[2] >> 16);
194
500k
  e[2] ^= (x[4] << 16) | (x[3] >> 16);
195
500k
  e[3] ^= (x[5] << 16) | (x[4] >> 16);
196
500k
  e[4] ^= (x[6] << 16) | (x[5] >> 16);
197
500k
  e[5] ^= (x[7] << 16) | (x[6] >> 16);
198
500k
}
199
200
static void
201
do_add (u32 *s, u32 *a)
202
488k
{
203
488k
  u32 carry = 0;
204
488k
  int i;
205
206
4.39M
  for (i = 0; i < 8; i++)
207
3.90M
    {
208
3.90M
      u32 op = carry + a[i];
209
3.90M
      s[i] += op;
210
3.90M
      carry = (a[i] > op) || (op > s[i]);
211
3.90M
    }
212
488k
}
213
214
static unsigned int
215
do_hash_step (GOSTR3411_CONTEXT *hd, u32 *h, u32 *m)
216
500k
{
217
500k
  u32 u[8], v[8];
218
500k
  u32 s[8];
219
500k
  u32 k[8];
220
500k
  unsigned int burn;
221
500k
  int i;
222
223
500k
  memcpy (u, h, 32);
224
500k
  memcpy (v, m, 32);
225
226
2.50M
  for (i = 0; i < 4; i++) {
227
2.00M
    do_p (k, u, v);
228
229
2.00M
    burn = _gcry_gost_enc_data (k, &s[2*i], &s[2*i+1], h[2*i], h[2*i+1], hd->cryptopro);
230
231
2.00M
    do_a (u);
232
2.00M
    if (i == 1)
233
500k
      do_apply_c2 (u);
234
2.00M
    do_a2 (v);
235
2.00M
  }
236
237
2.50M
  for (i = 0; i < 5; i++)
238
2.50M
    {
239
2.50M
      do_chi_doublestep (s, 0);
240
2.50M
      do_chi_doublestep (s, 1);
241
2.50M
      do_chi_doublestep (s, 2);
242
2.50M
      do_chi_doublestep (s, 3);
243
2.50M
      do_chi_doublestep (s, 4);
244
      /* That is in total 12 + 1 + 61 = 74 = 16 * 4 + 10 rounds */
245
2.50M
      if (i == 4)
246
500k
        break;
247
2.00M
      do_chi_doublestep (s, 5);
248
2.00M
      if (i == 0)
249
500k
        do_chi_submix12(s, m);
250
2.00M
      do_chi_step12 (s);
251
2.00M
      if (i == 0)
252
500k
        do_chi_submix13(s, h);
253
2.00M
      do_chi_step13 (s);
254
2.00M
      do_chi_doublestep (s, 7);
255
2.00M
    }
256
257
500k
  memcpy (h, s+5, 12);
258
500k
  memcpy (h+3, s, 20);
259
260
500k
  return /* burn_stack */ 4 * sizeof(void*) /* func call (ret addr + args) */ +
261
500k
                          4 * 32 + 2 * sizeof(int) /* stack */ +
262
500k
                          max(burn /* _gcry_gost_enc_one */,
263
500k
                              sizeof(void*) * 2 /* do_a2 call */ +
264
500k
                              16 + sizeof(int) /* do_a2 stack */ );
265
500k
}
266
267
static unsigned int
268
transform_blk (void *ctx, const unsigned char *data)
269
488k
{
270
488k
  GOSTR3411_CONTEXT *hd = ctx;
271
488k
  u32 m[8];
272
488k
  unsigned int burn;
273
488k
  int i;
274
275
4.39M
  for (i = 0; i < 8; i++)
276
3.90M
    m[i] = buf_get_le32(data + i*4);
277
488k
  burn = do_hash_step (hd, hd->h, m);
278
488k
  do_add (hd->sigma, m);
279
280
488k
  return /* burn_stack */ burn + 3 * sizeof(void*) + 32 + 2 * sizeof(void*);
281
488k
}
282
283
284
static unsigned int
285
transform ( void *c, const unsigned char *data, size_t nblks )
286
11.3k
{
287
11.3k
  unsigned int burn;
288
289
11.3k
  do
290
488k
    {
291
488k
      burn = transform_blk (c, data);
292
488k
      data += 32;
293
488k
    }
294
488k
  while (--nblks);
295
296
11.3k
  return burn;
297
11.3k
}
298
299
300
/*
301
   The routine finally terminates the computation and returns the
302
   digest.  The handle is prepared for a new cycle, but adding bytes
303
   to the handle will the destroy the returned buffer.  Returns: 32
304
   bytes with the message the digest.  */
305
static void
306
gost3411_final (void *context)
307
5.92k
{
308
5.92k
  GOSTR3411_CONTEXT *hd = context;
309
5.92k
  size_t padlen = 0;
310
5.92k
  u32 l[8];
311
5.92k
  int i;
312
5.92k
  MD_NBLOCKS_TYPE nblocks;
313
314
5.92k
  if (hd->bctx.count > 0)
315
2.53k
    {
316
2.53k
      padlen = 32 - hd->bctx.count;
317
2.53k
      memset (hd->bctx.buf + hd->bctx.count, 0, padlen);
318
2.53k
      hd->bctx.count += padlen;
319
2.53k
      _gcry_md_block_write (hd, NULL, 0); /* flush */;
320
2.53k
    }
321
322
5.92k
  if (hd->bctx.count != 0)
323
0
    return; /* Something went wrong */
324
325
5.92k
  memset (l, 0, 32);
326
327
5.92k
  nblocks = hd->bctx.nblocks;
328
5.92k
  if (padlen)
329
2.53k
    {
330
2.53k
      nblocks --;
331
2.53k
      l[0] = 256 - padlen * 8;
332
2.53k
    }
333
5.92k
  l[0] |= nblocks << 8;
334
5.92k
  nblocks >>= 24;
335
336
5.92k
  for (i = 1; i < 8 && nblocks != 0; i++)
337
0
    {
338
0
      l[i] = nblocks;
339
0
      nblocks >>= 24;
340
0
    }
341
342
5.92k
  do_hash_step (hd, hd->h, l);
343
5.92k
  do_hash_step (hd, hd->h, hd->sigma);
344
53.2k
  for (i = 0; i < 8; i++)
345
47.3k
    hd->h[i] = le_bswap32(hd->h[i]);
346
5.92k
}
347
348
static byte *
349
gost3411_read (void *context)
350
5.92k
{
351
5.92k
  GOSTR3411_CONTEXT *hd = context;
352
353
5.92k
  return hd->result;
354
5.92k
}
355
356
static const unsigned char asn[6] = /* Object ID is 1.2.643.2.2.3 */
357
  { 0x2a, 0x85, 0x03, 0x02, 0x02, 0x03 };
358
359
static const gcry_md_oid_spec_t oid_spec_gostr3411[] =
360
  {
361
    /* iso.member-body.ru.rans.cryptopro.3 (gostR3411-94-with-gostR3410-2001) */
362
    { "1.2.643.2.2.3" },
363
    /* iso.member-body.ru.rans.cryptopro.9 (gostR3411-94) */
364
    { "1.2.643.2.2.9" },
365
    {NULL},
366
  };
367
368
const gcry_md_spec_t _gcry_digest_spec_gost3411_94 =
369
  {
370
    GCRY_MD_GOSTR3411_94, {0, 0},
371
    "GOSTR3411_94", NULL, 0, NULL, 32,
372
    gost3411_init, _gcry_md_block_write, gost3411_final, gost3411_read, NULL,
373
    NULL,
374
    sizeof (GOSTR3411_CONTEXT)
375
  };
376
const gcry_md_spec_t _gcry_digest_spec_gost3411_cp =
377
  {
378
    GCRY_MD_GOSTR3411_CP, {0, 0},
379
    "GOSTR3411_CP", asn, DIM (asn), oid_spec_gostr3411, 32,
380
    gost3411_cp_init, _gcry_md_block_write, gost3411_final, gost3411_read, NULL,
381
    NULL,
382
    sizeof (GOSTR3411_CONTEXT)
383
  };