pubkey: Re-map all depreccated RSA algo numbers.
[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 "cipher.h"
29 #include "hash-common.h"
30
31 #include "gost.h"
32
33 #define max(a, b) (((a) > (b)) ? (a) : (b))
34
35 typedef struct {
36   gcry_md_block_ctx_t bctx;
37   GOST28147_context hd;
38   byte h[32];
39   byte sigma[32];
40   u32 len;
41 } GOSTR3411_CONTEXT;
42
43 static unsigned int
44 transform (void *c, const unsigned char *data, size_t nblks);
45
46 static void
47 gost3411_init (void *context, unsigned int flags)
48 {
49   GOSTR3411_CONTEXT *hd = context;
50
51   (void)flags;
52
53   memset (&hd->hd, 0, sizeof(hd->hd));
54   memset (hd->h, 0, 32);
55   memset (hd->sigma, 0, 32);
56
57   hd->bctx.nblocks = 0;
58   hd->bctx.count = 0;
59   hd->bctx.blocksize = 32;
60   hd->bctx.bwrite = transform;
61 }
62
63 static void
64 do_p (unsigned char *p, unsigned char *u, unsigned char *v)
65 {
66   int i, k;
67   for (k = 0; k < 8; k++)
68     {
69       for (i = 0; i < 4; i++)
70         {
71           p[i + 4 * k] = u[8 * i + k] ^ v[8 * i + k];
72         }
73     }
74 }
75
76 static void
77 do_a (unsigned char *u)
78 {
79   unsigned char temp[8];
80   int i;
81   memcpy (temp, u, 8);
82   memmove (u, u+8, 24);
83   for (i = 0; i < 8; i++)
84     {
85       u[24 + i] = u[i] ^ temp[i];
86     }
87 }
88 /* apply do_a twice: 1 2 3 4 -> 3 4 1^2 2^3 */
89 static void
90 do_a2 (unsigned char *u)
91 {
92   unsigned char temp[16];
93   int i;
94   memcpy (temp, u, 16);
95   memcpy (u, u + 16, 16);
96   for (i = 0; i < 8; i++)
97     {
98       u[16 + i] = temp[i] ^ temp[8 + i];
99       u[24 + i] =    u[i] ^ temp[8 + i];
100     }
101 }
102
103 static void
104 do_apply_c2 (unsigned char *u)
105 {
106   u[ 1] ^= 0xff;
107   u[ 3] ^= 0xff;
108   u[ 5] ^= 0xff;
109   u[ 7] ^= 0xff;
110
111   u[ 8] ^= 0xff;
112   u[10] ^= 0xff;
113   u[12] ^= 0xff;
114   u[14] ^= 0xff;
115
116   u[17] ^= 0xff;
117   u[18] ^= 0xff;
118   u[20] ^= 0xff;
119   u[23] ^= 0xff;
120
121   u[24] ^= 0xff;
122   u[28] ^= 0xff;
123   u[29] ^= 0xff;
124   u[31] ^= 0xff;
125 }
126
127 #define do_phi_step(e, i) \
128   e[(0 + 2*i) % 32] ^= e[(2 + 2*i) % 32] ^ e[(4 + 2*i) % 32] ^ e[(6 + 2*i) % 32] ^ e[(24 + 2*i) % 32] ^ e[(30 + 2*i) % 32]; \
129   e[(1 + 2*i) % 32] ^= e[(3 + 2*i) % 32] ^ e[(5 + 2*i) % 32] ^ e[(7 + 2*i) % 32] ^ e[(25 + 2*i) % 32] ^ e[(31 + 2*i) % 32];
130
131 static void
132 do_phi_submix (unsigned char *e, unsigned char *x, int round)
133 {
134   int i;
135   round *= 2;
136   for (i = 0; i < 32; i++)
137     {
138       e[(i + round) % 32] ^= x[i];
139     }
140 }
141
142 static void
143 do_add (unsigned char *s, unsigned char *a)
144 {
145   unsigned temp = 0;
146   int i;
147
148   for (i = 0; i < 32; i++)
149     {
150       temp = s[i] + a[i] + (temp >> 8);
151       s[i] = temp & 0xff;
152     }
153 }
154
155 static unsigned int
156 do_hash_step (GOST28147_context *hd, unsigned char *h, unsigned char *m)
157 {
158   unsigned char u[32], v[32], s[32];
159   unsigned char k[32];
160   unsigned int burn;
161   int i;
162
163   memcpy (u, h, 32);
164   memcpy (v, m, 32);
165
166   for (i = 0; i < 4; i++) {
167     do_p (k, u, v);
168
169     burn = _gcry_gost_enc_one (hd, k, s + i*8, h + i*8);
170
171     do_a (u);
172     if (i == 1)
173       do_apply_c2 (u);
174     do_a2 (v);
175   }
176
177   for (i = 0; i < 5; i++)
178     {
179       do_phi_step (s, 0);
180       do_phi_step (s, 1);
181       do_phi_step (s, 2);
182       do_phi_step (s, 3);
183       do_phi_step (s, 4);
184       do_phi_step (s, 5);
185       do_phi_step (s, 6);
186       do_phi_step (s, 7);
187       do_phi_step (s, 8);
188       do_phi_step (s, 9);
189       /* That is in total 12 + 1 + 61 = 74 = 16 * 4 + 10 rounds */
190       if (i == 4)
191         break;
192       do_phi_step (s, 10);
193       do_phi_step (s, 11);
194       if (i == 0)
195         do_phi_submix(s, m, 12);
196       do_phi_step (s, 12);
197       if (i == 0)
198         do_phi_submix(s, h, 13);
199       do_phi_step (s, 13);
200       do_phi_step (s, 14);
201       do_phi_step (s, 15);
202     }
203
204   memcpy (h, s+20, 12);
205   memcpy (h+12, s, 20);
206
207   return /* burn_stack */ 4 * sizeof(void*) /* func call (ret addr + args) */ +
208                           4 * 32 + 2 * sizeof(int) /* stack */ +
209                           max(burn /* _gcry_gost_enc_one */,
210                               sizeof(void*) * 2 /* do_a2 call */ +
211                               16 + sizeof(int) /* do_a2 stack */ );
212 }
213
214
215 static unsigned int
216 transform_blk (void *ctx, const unsigned char *data)
217 {
218   GOSTR3411_CONTEXT *hd = ctx;
219   byte m[32];
220   unsigned int burn;
221
222   memcpy (m, data, 32);
223   burn = do_hash_step (&hd->hd, hd->h, m);
224   do_add (hd->sigma, m);
225
226   return /* burn_stack */ burn + 3 * sizeof(void*) + 32 + 2 * sizeof(void*);
227 }
228
229
230 static unsigned int
231 transform ( void *c, const unsigned char *data, size_t nblks )
232 {
233   unsigned int burn;
234
235   do
236     {
237       burn = transform_blk (c, data);
238       data += 32;
239     }
240   while (--nblks);
241
242   return burn;
243 }
244
245
246 /*
247    The routine finally terminates the computation and returns the
248    digest.  The handle is prepared for a new cycle, but adding bytes
249    to the handle will the destroy the returned buffer.  Returns: 32
250    bytes with the message the digest.  */
251 static void
252 gost3411_final (void *context)
253 {
254   GOSTR3411_CONTEXT *hd = context;
255   size_t padlen = 0;
256   byte l[32];
257   int i;
258   u32 nblocks;
259
260   if (hd->bctx.count > 0)
261     {
262       padlen = 32 - hd->bctx.count;
263       memset (hd->bctx.buf + hd->bctx.count, 0, padlen);
264       hd->bctx.count += padlen;
265       _gcry_md_block_write (hd, NULL, 0); /* flush */;
266     }
267
268   if (hd->bctx.count != 0)
269     return; /* Something went wrong */
270
271   memset (l, 0, 32);
272
273   nblocks = hd->bctx.nblocks;
274   if (padlen)
275     {
276       nblocks --;
277       l[0] = 256 - padlen * 8;
278     }
279
280   for (i = 1; i < 32 && nblocks != 0; i++)
281     {
282       l[i] = nblocks % 256;
283       nblocks /= 256;
284     }
285
286   do_hash_step (&hd->hd, hd->h, l);
287   do_hash_step (&hd->hd, hd->h, hd->sigma);
288 }
289
290 static byte *
291 gost3411_read (void *context)
292 {
293   GOSTR3411_CONTEXT *hd = context;
294
295   return hd->h;
296 }
297 gcry_md_spec_t _gcry_digest_spec_gost3411_94 =
298   {
299     GCRY_MD_GOSTR3411_94, {0, 0},
300     "GOSTR3411_94", NULL, 0, NULL, 32,
301     gost3411_init, _gcry_md_block_write, gost3411_final, gost3411_read,
302     sizeof (GOSTR3411_CONTEXT)
303   };