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