Merge branch 'vendor/OPENSSL'
[dragonfly.git] / crypto / openssl / engines / ccgost / gost89.c
1 /**********************************************************************
2  *                        gost89.c                                    *
3  *             Copyright (c) 2005-2006 Cryptocom LTD                  *
4  *         This file is distributed under the same license as OpenSSL *
5  *                                                                    *
6  *          Implementation of GOST 28147-89 encryption algorithm      *
7  *            No OpenSSL libraries required to compile and use        *
8  *                              this code                             *
9  **********************************************************************/
10 #include <string.h>
11 #include "gost89.h"
12 /*-
13    Substitution blocks from RFC 4357
14
15    Note: our implementation of gost 28147-89 algorithm
16    uses S-box matrix rotated 90 degrees counterclockwise, relative to
17    examples given in RFC.
18
19
20 */
21
22 /* Substitution blocks from test examples for GOST R 34.11-94*/
23 gost_subst_block GostR3411_94_TestParamSet = {
24     {0X1, 0XF, 0XD, 0X0, 0X5, 0X7, 0XA, 0X4, 0X9, 0X2, 0X3, 0XE, 0X6, 0XB,
25      0X8, 0XC}
26     ,
27     {0XD, 0XB, 0X4, 0X1, 0X3, 0XF, 0X5, 0X9, 0X0, 0XA, 0XE, 0X7, 0X6, 0X8,
28      0X2, 0XC}
29     ,
30     {0X4, 0XB, 0XA, 0X0, 0X7, 0X2, 0X1, 0XD, 0X3, 0X6, 0X8, 0X5, 0X9, 0XC,
31      0XF, 0XE}
32     ,
33     {0X6, 0XC, 0X7, 0X1, 0X5, 0XF, 0XD, 0X8, 0X4, 0XA, 0X9, 0XE, 0X0, 0X3,
34      0XB, 0X2}
35     ,
36     {0X7, 0XD, 0XA, 0X1, 0X0, 0X8, 0X9, 0XF, 0XE, 0X4, 0X6, 0XC, 0XB, 0X2,
37      0X5, 0X3}
38     ,
39     {0X5, 0X8, 0X1, 0XD, 0XA, 0X3, 0X4, 0X2, 0XE, 0XF, 0XC, 0X7, 0X6, 0X0,
40      0X9, 0XB}
41     ,
42     {0XE, 0XB, 0X4, 0XC, 0X6, 0XD, 0XF, 0XA, 0X2, 0X3, 0X8, 0X1, 0X0, 0X7,
43      0X5, 0X9}
44     ,
45     {0X4, 0XA, 0X9, 0X2, 0XD, 0X8, 0X0, 0XE, 0X6, 0XB, 0X1, 0XC, 0X7, 0XF,
46      0X5, 0X3}
47 };
48
49 /* Substitution blocks for hash function 1.2.643.2.9.1.6.1  */
50 gost_subst_block GostR3411_94_CryptoProParamSet = {
51     {0x1, 0x3, 0xA, 0x9, 0x5, 0xB, 0x4, 0xF, 0x8, 0x6, 0x7, 0xE, 0xD, 0x0,
52      0x2, 0xC}
53     ,
54     {0xD, 0xE, 0x4, 0x1, 0x7, 0x0, 0x5, 0xA, 0x3, 0xC, 0x8, 0xF, 0x6, 0x2,
55      0x9, 0xB}
56     ,
57     {0x7, 0x6, 0x2, 0x4, 0xD, 0x9, 0xF, 0x0, 0xA, 0x1, 0x5, 0xB, 0x8, 0xE,
58      0xC, 0x3}
59     ,
60     {0x7, 0x6, 0x4, 0xB, 0x9, 0xC, 0x2, 0xA, 0x1, 0x8, 0x0, 0xE, 0xF, 0xD,
61      0x3, 0x5}
62     ,
63     {0x4, 0xA, 0x7, 0xC, 0x0, 0xF, 0x2, 0x8, 0xE, 0x1, 0x6, 0x5, 0xD, 0xB,
64      0x9, 0x3}
65     ,
66     {0x7, 0xF, 0xC, 0xE, 0x9, 0x4, 0x1, 0x0, 0x3, 0xB, 0x5, 0x2, 0x6, 0xA,
67      0x8, 0xD}
68     ,
69     {0x5, 0xF, 0x4, 0x0, 0x2, 0xD, 0xB, 0x9, 0x1, 0x7, 0x6, 0x3, 0xC, 0xE,
70      0xA, 0x8}
71     ,
72     {0xA, 0x4, 0x5, 0x6, 0x8, 0x1, 0x3, 0x7, 0xD, 0xC, 0xE, 0x0, 0x9, 0x2,
73      0xB, 0xF}
74 };
75
76 /* Test paramset from GOST 28147 */
77 gost_subst_block Gost28147_TestParamSet = {
78     {0xC, 0x6, 0x5, 0x2, 0xB, 0x0, 0x9, 0xD, 0x3, 0xE, 0x7, 0xA, 0xF, 0x4,
79      0x1, 0x8}
80     ,
81     {0x9, 0xB, 0xC, 0x0, 0x3, 0x6, 0x7, 0x5, 0x4, 0x8, 0xE, 0xF, 0x1, 0xA,
82      0x2, 0xD}
83     ,
84     {0x8, 0xF, 0x6, 0xB, 0x1, 0x9, 0xC, 0x5, 0xD, 0x3, 0x7, 0xA, 0x0, 0xE,
85      0x2, 0x4}
86     ,
87     {0x3, 0xE, 0x5, 0x9, 0x6, 0x8, 0x0, 0xD, 0xA, 0xB, 0x7, 0xC, 0x2, 0x1,
88      0xF, 0x4}
89     ,
90     {0xE, 0x9, 0xB, 0x2, 0x5, 0xF, 0x7, 0x1, 0x0, 0xD, 0xC, 0x6, 0xA, 0x4,
91      0x3, 0x8}
92     ,
93     {0xD, 0x8, 0xE, 0xC, 0x7, 0x3, 0x9, 0xA, 0x1, 0x5, 0x2, 0x4, 0x6, 0xF,
94      0x0, 0xB}
95     ,
96     {0xC, 0x9, 0xF, 0xE, 0x8, 0x1, 0x3, 0xA, 0x2, 0x7, 0x4, 0xD, 0x6, 0x0,
97      0xB, 0x5}
98     ,
99     {0x4, 0x2, 0xF, 0x5, 0x9, 0x1, 0x0, 0x8, 0xE, 0x3, 0xB, 0xC, 0xD, 0x7,
100      0xA, 0x6}
101 };
102
103 /* 1.2.643.2.2.31.1 */
104 gost_subst_block Gost28147_CryptoProParamSetA = {
105     {0xB, 0xA, 0xF, 0x5, 0x0, 0xC, 0xE, 0x8, 0x6, 0x2, 0x3, 0x9, 0x1, 0x7,
106      0xD, 0x4}
107     ,
108     {0x1, 0xD, 0x2, 0x9, 0x7, 0xA, 0x6, 0x0, 0x8, 0xC, 0x4, 0x5, 0xF, 0x3,
109      0xB, 0xE}
110     ,
111     {0x3, 0xA, 0xD, 0xC, 0x1, 0x2, 0x0, 0xB, 0x7, 0x5, 0x9, 0x4, 0x8, 0xF,
112      0xE, 0x6}
113     ,
114     {0xB, 0x5, 0x1, 0x9, 0x8, 0xD, 0xF, 0x0, 0xE, 0x4, 0x2, 0x3, 0xC, 0x7,
115      0xA, 0x6}
116     ,
117     {0xE, 0x7, 0xA, 0xC, 0xD, 0x1, 0x3, 0x9, 0x0, 0x2, 0xB, 0x4, 0xF, 0x8,
118      0x5, 0x6}
119     ,
120     {0xE, 0x4, 0x6, 0x2, 0xB, 0x3, 0xD, 0x8, 0xC, 0xF, 0x5, 0xA, 0x0, 0x7,
121      0x1, 0x9}
122     ,
123     {0x3, 0x7, 0xE, 0x9, 0x8, 0xA, 0xF, 0x0, 0x5, 0x2, 0x6, 0xC, 0xB, 0x4,
124      0xD, 0x1}
125     ,
126     {0x9, 0x6, 0x3, 0x2, 0x8, 0xB, 0x1, 0x7, 0xA, 0x4, 0xE, 0xF, 0xC, 0x0,
127      0xD, 0x5}
128 };
129
130 /* 1.2.643.2.2.31.2 */
131 gost_subst_block Gost28147_CryptoProParamSetB = {
132     {0x0, 0x4, 0xB, 0xE, 0x8, 0x3, 0x7, 0x1, 0xA, 0x2, 0x9, 0x6, 0xF, 0xD,
133      0x5, 0xC}
134     ,
135     {0x5, 0x2, 0xA, 0xB, 0x9, 0x1, 0xC, 0x3, 0x7, 0x4, 0xD, 0x0, 0x6, 0xF,
136      0x8, 0xE}
137     ,
138     {0x8, 0x3, 0x2, 0x6, 0x4, 0xD, 0xE, 0xB, 0xC, 0x1, 0x7, 0xF, 0xA, 0x0,
139      0x9, 0x5}
140     ,
141     {0x2, 0x7, 0xC, 0xF, 0x9, 0x5, 0xA, 0xB, 0x1, 0x4, 0x0, 0xD, 0x6, 0x8,
142      0xE, 0x3}
143     ,
144     {0x7, 0x5, 0x0, 0xD, 0xB, 0x6, 0x1, 0x2, 0x3, 0xA, 0xC, 0xF, 0x4, 0xE,
145      0x9, 0x8}
146     ,
147     {0xE, 0xC, 0x0, 0xA, 0x9, 0x2, 0xD, 0xB, 0x7, 0x5, 0x8, 0xF, 0x3, 0x6,
148      0x1, 0x4}
149     ,
150     {0x0, 0x1, 0x2, 0xA, 0x4, 0xD, 0x5, 0xC, 0x9, 0x7, 0x3, 0xF, 0xB, 0x8,
151      0x6, 0xE}
152     ,
153     {0x8, 0x4, 0xB, 0x1, 0x3, 0x5, 0x0, 0x9, 0x2, 0xE, 0xA, 0xC, 0xD, 0x6,
154      0x7, 0xF}
155 };
156
157 /* 1.2.643.2.2.31.3 */
158 gost_subst_block Gost28147_CryptoProParamSetC = {
159     {0x7, 0x4, 0x0, 0x5, 0xA, 0x2, 0xF, 0xE, 0xC, 0x6, 0x1, 0xB, 0xD, 0x9,
160      0x3, 0x8}
161     ,
162     {0xA, 0x9, 0x6, 0x8, 0xD, 0xE, 0x2, 0x0, 0xF, 0x3, 0x5, 0xB, 0x4, 0x1,
163      0xC, 0x7}
164     ,
165     {0xC, 0x9, 0xB, 0x1, 0x8, 0xE, 0x2, 0x4, 0x7, 0x3, 0x6, 0x5, 0xA, 0x0,
166      0xF, 0xD}
167     ,
168     {0x8, 0xD, 0xB, 0x0, 0x4, 0x5, 0x1, 0x2, 0x9, 0x3, 0xC, 0xE, 0x6, 0xF,
169      0xA, 0x7}
170     ,
171     {0x3, 0x6, 0x0, 0x1, 0x5, 0xD, 0xA, 0x8, 0xB, 0x2, 0x9, 0x7, 0xE, 0xF,
172      0xC, 0x4}
173     ,
174     {0x8, 0x2, 0x5, 0x0, 0x4, 0x9, 0xF, 0xA, 0x3, 0x7, 0xC, 0xD, 0x6, 0xE,
175      0x1, 0xB}
176     ,
177     {0x0, 0x1, 0x7, 0xD, 0xB, 0x4, 0x5, 0x2, 0x8, 0xE, 0xF, 0xC, 0x9, 0xA,
178      0x6, 0x3}
179     ,
180     {0x1, 0xB, 0xC, 0x2, 0x9, 0xD, 0x0, 0xF, 0x4, 0x5, 0x8, 0xE, 0xA, 0x7,
181      0x6, 0x3}
182 };
183
184 /* 1.2.643.2.2.31.4 */
185 gost_subst_block Gost28147_CryptoProParamSetD = {
186     {0x1, 0xA, 0x6, 0x8, 0xF, 0xB, 0x0, 0x4, 0xC, 0x3, 0x5, 0x9, 0x7, 0xD,
187      0x2, 0xE}
188     ,
189     {0x3, 0x0, 0x6, 0xF, 0x1, 0xE, 0x9, 0x2, 0xD, 0x8, 0xC, 0x4, 0xB, 0xA,
190      0x5, 0x7}
191     ,
192     {0x8, 0x0, 0xF, 0x3, 0x2, 0x5, 0xE, 0xB, 0x1, 0xA, 0x4, 0x7, 0xC, 0x9,
193      0xD, 0x6}
194     ,
195     {0x0, 0xC, 0x8, 0x9, 0xD, 0x2, 0xA, 0xB, 0x7, 0x3, 0x6, 0x5, 0x4, 0xE,
196      0xF, 0x1}
197     ,
198     {0x1, 0x5, 0xE, 0xC, 0xA, 0x7, 0x0, 0xD, 0x6, 0x2, 0xB, 0x4, 0x9, 0x3,
199      0xF, 0x8}
200     ,
201     {0x1, 0xC, 0xB, 0x0, 0xF, 0xE, 0x6, 0x5, 0xA, 0xD, 0x4, 0x8, 0x9, 0x3,
202      0x7, 0x2}
203     ,
204     {0xB, 0x6, 0x3, 0x4, 0xC, 0xF, 0xE, 0x2, 0x7, 0xD, 0x8, 0x0, 0x5, 0xA,
205      0x9, 0x1}
206     ,
207     {0xF, 0xC, 0x2, 0xA, 0x6, 0x4, 0x5, 0x0, 0x7, 0x9, 0xE, 0xD, 0x1, 0xB,
208      0x8, 0x3}
209 };
210
211 const byte CryptoProKeyMeshingKey[] = {
212     0x69, 0x00, 0x72, 0x22, 0x64, 0xC9, 0x04, 0x23,
213     0x8D, 0x3A, 0xDB, 0x96, 0x46, 0xE9, 0x2A, 0xC4,
214     0x18, 0xFE, 0xAC, 0x94, 0x00, 0xED, 0x07, 0x12,
215     0xC0, 0x86, 0xDC, 0xC2, 0xEF, 0x4C, 0xA9, 0x2B
216 };
217
218 /* Initialization of gost_ctx subst blocks*/
219 static void kboxinit(gost_ctx * c, const gost_subst_block * b)
220 {
221     int i;
222
223     for (i = 0; i < 256; i++) {
224         c->k87[i] = (b->k8[i >> 4] << 4 | b->k7[i & 15]) << 24;
225         c->k65[i] = (b->k6[i >> 4] << 4 | b->k5[i & 15]) << 16;
226         c->k43[i] = (b->k4[i >> 4] << 4 | b->k3[i & 15]) << 8;
227         c->k21[i] = b->k2[i >> 4] << 4 | b->k1[i & 15];
228
229     }
230 }
231
232 /* Part of GOST 28147 algorithm moved into separate function */
233 static word32 f(gost_ctx * c, word32 x)
234 {
235     x = c->k87[x >> 24 & 255] | c->k65[x >> 16 & 255] |
236         c->k43[x >> 8 & 255] | c->k21[x & 255];
237     /* Rotate left 11 bits */
238     return x << 11 | x >> (32 - 11);
239 }
240
241 /* Low-level encryption routine - encrypts one 64 bit block*/
242 void gostcrypt(gost_ctx * c, const byte * in, byte * out)
243 {
244     register word32 n1, n2;     /* As named in the GOST */
245     n1 = in[0] | (in[1] << 8) | (in[2] << 16) | (in[3] << 24);
246     n2 = in[4] | (in[5] << 8) | (in[6] << 16) | (in[7] << 24);
247     /* Instead of swapping halves, swap names each round */
248
249     n2 ^= f(c, n1 + c->k[0]);
250     n1 ^= f(c, n2 + c->k[1]);
251     n2 ^= f(c, n1 + c->k[2]);
252     n1 ^= f(c, n2 + c->k[3]);
253     n2 ^= f(c, n1 + c->k[4]);
254     n1 ^= f(c, n2 + c->k[5]);
255     n2 ^= f(c, n1 + c->k[6]);
256     n1 ^= f(c, n2 + c->k[7]);
257
258     n2 ^= f(c, n1 + c->k[0]);
259     n1 ^= f(c, n2 + c->k[1]);
260     n2 ^= f(c, n1 + c->k[2]);
261     n1 ^= f(c, n2 + c->k[3]);
262     n2 ^= f(c, n1 + c->k[4]);
263     n1 ^= f(c, n2 + c->k[5]);
264     n2 ^= f(c, n1 + c->k[6]);
265     n1 ^= f(c, n2 + c->k[7]);
266
267     n2 ^= f(c, n1 + c->k[0]);
268     n1 ^= f(c, n2 + c->k[1]);
269     n2 ^= f(c, n1 + c->k[2]);
270     n1 ^= f(c, n2 + c->k[3]);
271     n2 ^= f(c, n1 + c->k[4]);
272     n1 ^= f(c, n2 + c->k[5]);
273     n2 ^= f(c, n1 + c->k[6]);
274     n1 ^= f(c, n2 + c->k[7]);
275
276     n2 ^= f(c, n1 + c->k[7]);
277     n1 ^= f(c, n2 + c->k[6]);
278     n2 ^= f(c, n1 + c->k[5]);
279     n1 ^= f(c, n2 + c->k[4]);
280     n2 ^= f(c, n1 + c->k[3]);
281     n1 ^= f(c, n2 + c->k[2]);
282     n2 ^= f(c, n1 + c->k[1]);
283     n1 ^= f(c, n2 + c->k[0]);
284
285     out[0] = (byte) (n2 & 0xff);
286     out[1] = (byte) ((n2 >> 8) & 0xff);
287     out[2] = (byte) ((n2 >> 16) & 0xff);
288     out[3] = (byte) (n2 >> 24);
289     out[4] = (byte) (n1 & 0xff);
290     out[5] = (byte) ((n1 >> 8) & 0xff);
291     out[6] = (byte) ((n1 >> 16) & 0xff);
292     out[7] = (byte) (n1 >> 24);
293 }
294
295 /* Low-level decryption routine. Decrypts one 64-bit block */
296 void gostdecrypt(gost_ctx * c, const byte * in, byte * out)
297 {
298     register word32 n1, n2;     /* As named in the GOST */
299     n1 = in[0] | (in[1] << 8) | (in[2] << 16) | (in[3] << 24);
300     n2 = in[4] | (in[5] << 8) | (in[6] << 16) | (in[7] << 24);
301
302     n2 ^= f(c, n1 + c->k[0]);
303     n1 ^= f(c, n2 + c->k[1]);
304     n2 ^= f(c, n1 + c->k[2]);
305     n1 ^= f(c, n2 + c->k[3]);
306     n2 ^= f(c, n1 + c->k[4]);
307     n1 ^= f(c, n2 + c->k[5]);
308     n2 ^= f(c, n1 + c->k[6]);
309     n1 ^= f(c, n2 + c->k[7]);
310
311     n2 ^= f(c, n1 + c->k[7]);
312     n1 ^= f(c, n2 + c->k[6]);
313     n2 ^= f(c, n1 + c->k[5]);
314     n1 ^= f(c, n2 + c->k[4]);
315     n2 ^= f(c, n1 + c->k[3]);
316     n1 ^= f(c, n2 + c->k[2]);
317     n2 ^= f(c, n1 + c->k[1]);
318     n1 ^= f(c, n2 + c->k[0]);
319
320     n2 ^= f(c, n1 + c->k[7]);
321     n1 ^= f(c, n2 + c->k[6]);
322     n2 ^= f(c, n1 + c->k[5]);
323     n1 ^= f(c, n2 + c->k[4]);
324     n2 ^= f(c, n1 + c->k[3]);
325     n1 ^= f(c, n2 + c->k[2]);
326     n2 ^= f(c, n1 + c->k[1]);
327     n1 ^= f(c, n2 + c->k[0]);
328
329     n2 ^= f(c, n1 + c->k[7]);
330     n1 ^= f(c, n2 + c->k[6]);
331     n2 ^= f(c, n1 + c->k[5]);
332     n1 ^= f(c, n2 + c->k[4]);
333     n2 ^= f(c, n1 + c->k[3]);
334     n1 ^= f(c, n2 + c->k[2]);
335     n2 ^= f(c, n1 + c->k[1]);
336     n1 ^= f(c, n2 + c->k[0]);
337
338     out[0] = (byte) (n2 & 0xff);
339     out[1] = (byte) ((n2 >> 8) & 0xff);
340     out[2] = (byte) ((n2 >> 16) & 0xff);
341     out[3] = (byte) (n2 >> 24);
342     out[4] = (byte) (n1 & 0xff);
343     out[5] = (byte) ((n1 >> 8) & 0xff);
344     out[6] = (byte) ((n1 >> 16) & 0xff);
345     out[7] = (byte) (n1 >> 24);
346 }
347
348 /* Encrypts several blocks in ECB mode */
349 void gost_enc(gost_ctx * c, const byte * clear, byte * cipher, int blocks)
350 {
351     int i;
352     for (i = 0; i < blocks; i++) {
353         gostcrypt(c, clear, cipher);
354         clear += 8;
355         cipher += 8;
356     }
357 }
358
359 /* Decrypts several blocks in ECB mode */
360 void gost_dec(gost_ctx * c, const byte * cipher, byte * clear, int blocks)
361 {
362     int i;
363     for (i = 0; i < blocks; i++) {
364         gostdecrypt(c, cipher, clear);
365         clear += 8;
366         cipher += 8;
367     }
368 }
369
370 /* Encrypts several full blocks in CFB mode using 8byte IV */
371 void gost_enc_cfb(gost_ctx * ctx, const byte * iv, const byte * clear,
372                   byte * cipher, int blocks)
373 {
374     byte cur_iv[8];
375     byte gamma[8];
376     int i, j;
377     const byte *in;
378     byte *out;
379     memcpy(cur_iv, iv, 8);
380     for (i = 0, in = clear, out = cipher; i < blocks; i++, in += 8, out += 8) {
381         gostcrypt(ctx, cur_iv, gamma);
382         for (j = 0; j < 8; j++) {
383             cur_iv[j] = out[j] = in[j] ^ gamma[j];
384         }
385     }
386 }
387
388 /* Decrypts several full blocks in CFB mode using 8byte IV */
389 void gost_dec_cfb(gost_ctx * ctx, const byte * iv, const byte * cipher,
390                   byte * clear, int blocks)
391 {
392     byte cur_iv[8];
393     byte gamma[8];
394     int i, j;
395     const byte *in;
396     byte *out;
397     memcpy(cur_iv, iv, 8);
398     for (i = 0, in = cipher, out = clear; i < blocks; i++, in += 8, out += 8) {
399         gostcrypt(ctx, cur_iv, gamma);
400         for (j = 0; j < 8; j++) {
401             out[j] = (cur_iv[j] = in[j]) ^ gamma[j];
402         }
403     }
404 }
405
406 /* Encrypts one block using specified key */
407 void gost_enc_with_key(gost_ctx * c, byte * key, byte * inblock,
408                        byte * outblock)
409 {
410     gost_key(c, key);
411     gostcrypt(c, inblock, outblock);
412 }
413
414 /* Set 256 bit  key into context */
415 void gost_key(gost_ctx * c, const byte * k)
416 {
417     int i, j;
418     for (i = 0, j = 0; i < 8; i++, j += 4) {
419         c->k[i] =
420             k[j] | (k[j + 1] << 8) | (k[j + 2] << 16) | (k[j + 3] << 24);
421     }
422 }
423
424 /* Retrieve 256-bit key from context */
425 void gost_get_key(gost_ctx * c, byte * k)
426 {
427     int i, j;
428     for (i = 0, j = 0; i < 8; i++, j += 4) {
429         k[j] = (byte) (c->k[i] & 0xFF);
430         k[j + 1] = (byte) ((c->k[i] >> 8) & 0xFF);
431         k[j + 2] = (byte) ((c->k[i] >> 16) & 0xFF);
432         k[j + 3] = (byte) ((c->k[i] >> 24) & 0xFF);
433     }
434 }
435
436 /* Initalize context. Provides default value for subst_block */
437 void gost_init(gost_ctx * c, const gost_subst_block * b)
438 {
439     if (!b) {
440         b = &GostR3411_94_TestParamSet;
441     }
442     kboxinit(c, b);
443 }
444
445 /* Cleans up key from context */
446 void gost_destroy(gost_ctx * c)
447 {
448     int i;
449     for (i = 0; i < 8; i++)
450         c->k[i] = 0;
451 }
452
453 /*
454  * Compute GOST 28147 mac block Parameters gost_ctx *c - context initalized
455  * with substitution blocks and key buffer - 8-byte mac state buffer block
456  * 8-byte block to process.
457  */
458 void mac_block(gost_ctx * c, byte * buffer, const byte * block)
459 {
460     register word32 n1, n2;     /* As named in the GOST */
461     int i;
462     for (i = 0; i < 8; i++) {
463         buffer[i] ^= block[i];
464     }
465     n1 = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
466     n2 = buffer[4] | (buffer[5] << 8) | (buffer[6] << 16) | (buffer[7] << 24);
467     /* Instead of swapping halves, swap names each round */
468
469     n2 ^= f(c, n1 + c->k[0]);
470     n1 ^= f(c, n2 + c->k[1]);
471     n2 ^= f(c, n1 + c->k[2]);
472     n1 ^= f(c, n2 + c->k[3]);
473     n2 ^= f(c, n1 + c->k[4]);
474     n1 ^= f(c, n2 + c->k[5]);
475     n2 ^= f(c, n1 + c->k[6]);
476     n1 ^= f(c, n2 + c->k[7]);
477
478     n2 ^= f(c, n1 + c->k[0]);
479     n1 ^= f(c, n2 + c->k[1]);
480     n2 ^= f(c, n1 + c->k[2]);
481     n1 ^= f(c, n2 + c->k[3]);
482     n2 ^= f(c, n1 + c->k[4]);
483     n1 ^= f(c, n2 + c->k[5]);
484     n2 ^= f(c, n1 + c->k[6]);
485     n1 ^= f(c, n2 + c->k[7]);
486
487     buffer[0] = (byte) (n1 & 0xff);
488     buffer[1] = (byte) ((n1 >> 8) & 0xff);
489     buffer[2] = (byte) ((n1 >> 16) & 0xff);
490     buffer[3] = (byte) (n1 >> 24);
491     buffer[4] = (byte) (n2 & 0xff);
492     buffer[5] = (byte) ((n2 >> 8) & 0xff);
493     buffer[6] = (byte) ((n2 >> 16) & 0xff);
494     buffer[7] = (byte) (n2 >> 24);
495 }
496
497 /* Get mac with specified number of bits from MAC state buffer */
498 void get_mac(byte * buffer, int nbits, byte * out)
499 {
500     int nbytes = nbits >> 3;
501     int rembits = nbits & 7;
502     int mask = rembits ? ((1 < rembits) - 1) : 0;
503     int i;
504     for (i = 0; i < nbytes; i++)
505         out[i] = buffer[i];
506     if (rembits)
507         out[i] = buffer[i] & mask;
508 }
509
510 /*
511  * Compute mac of specified length (in bits) from data. Context should be
512  * initialized with key and subst blocks
513  */
514 int gost_mac(gost_ctx * ctx, int mac_len, const unsigned char *data,
515              unsigned int data_len, unsigned char *mac)
516 {
517     byte buffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
518     byte buf2[8];
519     unsigned int i;
520     for (i = 0; i + 8 <= data_len; i += 8)
521         mac_block(ctx, buffer, data + i);
522     if (i < data_len) {
523         memset(buf2, 0, 8);
524         memcpy(buf2, data + i, data_len - i);
525         mac_block(ctx, buffer, buf2);
526         i += 8;
527     }
528     if (i == 8) {
529         memset(buf2, 0, 8);
530         mac_block(ctx, buffer, buf2);
531     }
532     get_mac(buffer, mac_len, mac);
533     return 1;
534 }
535
536 /* Compute MAC with non-zero IV. Used in some RFC 4357 algorithms */
537 int gost_mac_iv(gost_ctx * ctx, int mac_len, const unsigned char *iv,
538                 const unsigned char *data, unsigned int data_len,
539                 unsigned char *mac)
540 {
541     byte buffer[8];
542     byte buf2[8];
543     unsigned int i;
544     memcpy(buffer, iv, 8);
545     for (i = 0; i + 8 <= data_len; i += 8)
546         mac_block(ctx, buffer, data + i);
547     if (i < data_len) {
548         memset(buf2, 0, 8);
549         memcpy(buf2, data + i, data_len - i);
550         mac_block(ctx, buffer, buf2);
551         i += 8;
552     }
553     if (i == 8) {
554         memset(buf2, 0, 8);
555         mac_block(ctx, buffer, buf2);
556     }
557     get_mac(buffer, mac_len, mac);
558     return 1;
559 }
560
561 /* Implements key meshing algorithm by modifing ctx and IV in place */
562 void cryptopro_key_meshing(gost_ctx * ctx, unsigned char *iv)
563 {
564     unsigned char newkey[32], newiv[8];
565     /* Set static keymeshing key */
566     /* "Decrypt" key with keymeshing key */
567     gost_dec(ctx, CryptoProKeyMeshingKey, newkey, 4);
568     /* set new key */
569     gost_key(ctx, newkey);
570     /* Encrypt iv with new key */
571     gostcrypt(ctx, iv, newiv);
572     memcpy(iv, newiv, 8);
573 }