gostr3411-94: Fix the iteration count for length filling loop.
[libgcrypt.git] / cipher / gostr3411-94.c
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 #define max(a, b) (((a) > (b)) ? (a) : (b))
35
36 typedef struct {
37   gcry_md_block_ctx_t bctx;
38   GOST28147_context hd;
39   union {
40     u32 h[8];
41     byte result[32];
42   };
43   u32 sigma[8];
44   u32 len;
45   int cryptopro;
46 } GOSTR3411_CONTEXT;
47
48 static unsigned int
49 transform (void *c, const unsigned char *data, size_t nblks);
50
51 static void
52 gost3411_init (void *context, unsigned int flags)
53 {
54   GOSTR3411_CONTEXT *hd = context;
55
56   (void)flags;
57
58   memset (&hd->hd, 0, sizeof(hd->hd));
59   memset (hd->h, 0, 32);
60   memset (hd->sigma, 0, 32);
61
62   hd->bctx.nblocks = 0;
63   hd->bctx.count = 0;
64   hd->bctx.blocksize = 32;
65   hd->bctx.bwrite = transform;
66   hd->cryptopro = 0;
67 }
68
69 static void
70 gost3411_cp_init (void *context, unsigned int flags)
71 {
72   GOSTR3411_CONTEXT *hd = context;
73   gost3411_init (context, flags);
74   hd->cryptopro = 1;
75 }
76
77 static void
78 do_p (u32 *p, u32 *u, u32 *v)
79 {
80   int k;
81   u32 t[8];
82
83   for (k = 0; k < 8; k++)
84     t[k] = u[k] ^ v[k];
85
86   for (k = 0; k < 4; k++)
87     {
88           p[k+0] = ((t[0] >> (8*k)) & 0xff) << 0 |
89                    ((t[2] >> (8*k)) & 0xff) << 8 |
90                    ((t[4] >> (8*k)) & 0xff) << 16 |
91                    ((t[6] >> (8*k)) & 0xff) << 24;
92           p[k+4] = ((t[1] >> (8*k)) & 0xff) << 0 |
93                    ((t[3] >> (8*k)) & 0xff) << 8 |
94                    ((t[5] >> (8*k)) & 0xff) << 16 |
95                    ((t[7] >> (8*k)) & 0xff) << 24;
96     }
97 }
98
99 static void
100 do_a (u32 *u)
101 {
102   u32 t[2];
103   int i;
104   memcpy(t, u, 2*4);
105   for (i = 0; i < 6; i++)
106     u[i] = u[i+2];
107   u[6] = u[0] ^ t[0];
108   u[7] = u[1] ^ t[1];
109 }
110 /* apply do_a twice: 1 2 3 4 -> 3 4 1^2 2^3 */
111 static void
112 do_a2 (u32 *u)
113 {
114   u32 t[4];
115   int i;
116   memcpy (t, u, 16);
117   memcpy (u, u + 4, 16);
118   for (i = 0; i < 2; i++)
119     {
120       u[4+i] = t[i] ^ t[i + 2];
121       u[6+i] = u[i] ^ t[i + 2];
122     }
123 }
124
125 static void
126 do_apply_c2 (u32 *u)
127 {
128   u[ 0] ^= 0xff00ff00;
129   u[ 1] ^= 0xff00ff00;
130   u[ 2] ^= 0x00ff00ff;
131   u[ 3] ^= 0x00ff00ff;
132   u[ 4] ^= 0x00ffff00;
133   u[ 5] ^= 0xff0000ff;
134   u[ 6] ^= 0x000000ff;
135   u[ 7] ^= 0xff00ffff;
136 }
137
138 #define do_chi_step12(e) \
139   e[6] ^= ((e[6] >> 16) ^ e[7] ^ (e[7] >> 16) ^ e[4] ^ (e[5] >>16)) & 0xffff;
140
141 #define do_chi_step13(e) \
142   e[6] ^= ((e[7] ^ (e[7] >> 16) ^ e[0] ^ (e[4] >> 16) ^ e[6]) & 0xffff) << 16;
143
144 #define do_chi_doublestep(e, i) \
145   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); \
146   e[i] ^= (e[i] << 16);
147
148 static void
149 do_chi_submix12 (u32 *e, u32 *x)
150 {
151   e[6] ^= x[0];
152   e[7] ^= x[1];
153   e[0] ^= x[2];
154   e[1] ^= x[3];
155   e[2] ^= x[4];
156   e[3] ^= x[5];
157   e[4] ^= x[6];
158   e[5] ^= x[7];
159 }
160
161 static void
162 do_chi_submix13 (u32 *e, u32 *x)
163 {
164   e[6] ^= (x[0] << 16) | (x[7] >> 16);
165   e[7] ^= (x[1] << 16) | (x[0] >> 16);
166   e[0] ^= (x[2] << 16) | (x[1] >> 16);
167   e[1] ^= (x[3] << 16) | (x[2] >> 16);
168   e[2] ^= (x[4] << 16) | (x[3] >> 16);
169   e[3] ^= (x[5] << 16) | (x[4] >> 16);
170   e[4] ^= (x[6] << 16) | (x[5] >> 16);
171   e[5] ^= (x[7] << 16) | (x[6] >> 16);
172 }
173
174 static void
175 do_add (u32 *s, u32 *a)
176 {
177   u32 carry = 0;
178   int i;
179
180   for (i = 0; i < 8; i++)
181     {
182       u32 op = carry + a[i];
183       s[i] += op;
184       carry = (a[i] > op) || (op > s[i]);
185     }
186 }
187
188 static unsigned int
189 do_hash_step (GOSTR3411_CONTEXT *hd, u32 *h, u32 *m)
190 {
191   u32 u[8], v[8];
192   u32 s[8];
193   u32 k[8];
194   unsigned int burn;
195   int i;
196
197   memcpy (u, h, 32);
198   memcpy (v, m, 32);
199
200   for (i = 0; i < 4; i++) {
201     do_p (k, u, v);
202
203     burn = _gcry_gost_enc_data (&hd->hd, k, &s[2*i], &s[2*i+1], h[2*i], h[2*i+1], hd->cryptopro);
204
205     do_a (u);
206     if (i == 1)
207       do_apply_c2 (u);
208     do_a2 (v);
209   }
210
211   for (i = 0; i < 5; i++)
212     {
213       do_chi_doublestep (s, 0);
214       do_chi_doublestep (s, 1);
215       do_chi_doublestep (s, 2);
216       do_chi_doublestep (s, 3);
217       do_chi_doublestep (s, 4);
218       /* That is in total 12 + 1 + 61 = 74 = 16 * 4 + 10 rounds */
219       if (i == 4)
220         break;
221       do_chi_doublestep (s, 5);
222       if (i == 0)
223         do_chi_submix12(s, m);
224       do_chi_step12 (s);
225       if (i == 0)
226         do_chi_submix13(s, h);
227       do_chi_step13 (s);
228       do_chi_doublestep (s, 7);
229     }
230
231   memcpy (h, s+5, 12);
232   memcpy (h+3, s, 20);
233
234   return /* burn_stack */ 4 * sizeof(void*) /* func call (ret addr + args) */ +
235                           4 * 32 + 2 * sizeof(int) /* stack */ +
236                           max(burn /* _gcry_gost_enc_one */,
237                               sizeof(void*) * 2 /* do_a2 call */ +
238                               16 + sizeof(int) /* do_a2 stack */ );
239 }
240
241 static unsigned int
242 transform_blk (void *ctx, const unsigned char *data)
243 {
244   GOSTR3411_CONTEXT *hd = ctx;
245   u32 m[8];
246   unsigned int burn;
247   int i;
248
249   for (i = 0; i < 8; i++)
250     m[i] = buf_get_le32(data + i*4);
251   burn = do_hash_step (hd, hd->h, m);
252   do_add (hd->sigma, m);
253
254   return /* burn_stack */ burn + 3 * sizeof(void*) + 32 + 2 * sizeof(void*);
255 }
256
257
258 static unsigned int
259 transform ( void *c, const unsigned char *data, size_t nblks )
260 {
261   unsigned int burn;
262
263   do
264     {
265       burn = transform_blk (c, data);
266       data += 32;
267     }
268   while (--nblks);
269
270   return burn;
271 }
272
273
274 /*
275    The routine finally terminates the computation and returns the
276    digest.  The handle is prepared for a new cycle, but adding bytes
277    to the handle will the destroy the returned buffer.  Returns: 32
278    bytes with the message the digest.  */
279 static void
280 gost3411_final (void *context)
281 {
282   GOSTR3411_CONTEXT *hd = context;
283   size_t padlen = 0;
284   u32 l[8];
285   int i;
286   MD_NBLOCKS_TYPE nblocks;
287
288   if (hd->bctx.count > 0)
289     {
290       padlen = 32 - hd->bctx.count;
291       memset (hd->bctx.buf + hd->bctx.count, 0, padlen);
292       hd->bctx.count += padlen;
293       _gcry_md_block_write (hd, NULL, 0); /* flush */;
294     }
295
296   if (hd->bctx.count != 0)
297     return; /* Something went wrong */
298
299   memset (l, 0, 32);
300
301   nblocks = hd->bctx.nblocks;
302   if (padlen)
303     {
304       nblocks --;
305       l[0] = 256 - padlen * 8;
306     }
307   l[0] |= nblocks << 8;
308   nblocks >>= 24;
309
310   for (i = 1; i < 8 && nblocks != 0; i++)
311     {
312       l[i] = nblocks;
313       nblocks >>= 24;
314     }
315
316   do_hash_step (hd, hd->h, l);
317   do_hash_step (hd, hd->h, hd->sigma);
318   for (i = 0; i < 8; i++)
319     hd->h[i] = le_bswap32(hd->h[i]);
320 }
321
322 static byte *
323 gost3411_read (void *context)
324 {
325   GOSTR3411_CONTEXT *hd = context;
326
327   return hd->result;
328 }
329
330 static unsigned char asn[6] = /* Object ID is 1.2.643.2.2.3 */
331   { 0x2a, 0x85, 0x03, 0x02, 0x02, 0x03 };
332
333 static gcry_md_oid_spec_t oid_spec_gostr3411[] =
334   {
335     /* iso.member-body.ru.rans.cryptopro.3 (gostR3411-94-with-gostR3410-2001) */
336     { "1.2.643.2.2.3" },
337     /* iso.member-body.ru.rans.cryptopro.9 (gostR3411-94) */
338     { "1.2.643.2.2.9" },
339     {NULL},
340   };
341
342 gcry_md_spec_t _gcry_digest_spec_gost3411_94 =
343   {
344     GCRY_MD_GOSTR3411_94, {0, 0},
345     "GOSTR3411_94", NULL, 0, NULL, 32,
346     gost3411_init, _gcry_md_block_write, gost3411_final, gost3411_read,
347     sizeof (GOSTR3411_CONTEXT)
348   };
349 gcry_md_spec_t _gcry_digest_spec_gost3411_cp =
350   {
351     GCRY_MD_GOSTR3411_CP, {0, 0},
352     "GOSTR3411_CP", asn, DIM (asn), oid_spec_gostr3411, 32,
353     gost3411_cp_init, _gcry_md_block_write, gost3411_final, gost3411_read,
354     sizeof (GOSTR3411_CONTEXT)
355   };