GH365: Missing #ifdef rename.
[openssl.git] / 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] = (word32) (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) | ((word32) in[3] << 24);
246     n2 = in[4] | (in[5] << 8) | (in[6] << 16) | ((word32) 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) | ((word32) in[3] << 24);
300     n2 = in[4] | (in[5] << 8) | (in[6] << 16) | ((word32) 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) | ((word32) k[j + 3] <<
421                                                          24);
422     }
423 }
424
425 /* Retrieve 256-bit key from context */
426 void gost_get_key(gost_ctx * c, byte * k)
427 {
428     int i, j;
429     for (i = 0, j = 0; i < 8; i++, j += 4) {
430         k[j] = (byte) (c->k[i] & 0xFF);
431         k[j + 1] = (byte) ((c->k[i] >> 8) & 0xFF);
432         k[j + 2] = (byte) ((c->k[i] >> 16) & 0xFF);
433         k[j + 3] = (byte) ((c->k[i] >> 24) & 0xFF);
434     }
435 }
436
437 /* Initalize context. Provides default value for subst_block */
438 void gost_init(gost_ctx * c, const gost_subst_block * b)
439 {
440     if (!b) {
441         b = &GostR3411_94_TestParamSet;
442     }
443     kboxinit(c, b);
444 }
445
446 /* Cleans up key from context */
447 void gost_destroy(gost_ctx * c)
448 {
449     int i;
450     for (i = 0; i < 8; i++)
451         c->k[i] = 0;
452 }
453
454 /*
455  * Compute GOST 28147 mac block Parameters gost_ctx *c - context initalized
456  * with substitution blocks and key buffer - 8-byte mac state buffer block
457  * 8-byte block to process.
458  */
459 void mac_block(gost_ctx * c, byte * buffer, const byte * block)
460 {
461     register word32 n1, n2;     /* As named in the GOST */
462     int i;
463     for (i = 0; i < 8; i++) {
464         buffer[i] ^= block[i];
465     }
466     n1 = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | ((word32)
467                                                              buffer[3] << 24);
468     n2 = buffer[4] | (buffer[5] << 8) | (buffer[6] << 16) | ((word32)
469                                                              buffer[7] << 24);
470     /* Instead of swapping halves, swap names each round */
471
472     n2 ^= f(c, n1 + c->k[0]);
473     n1 ^= f(c, n2 + c->k[1]);
474     n2 ^= f(c, n1 + c->k[2]);
475     n1 ^= f(c, n2 + c->k[3]);
476     n2 ^= f(c, n1 + c->k[4]);
477     n1 ^= f(c, n2 + c->k[5]);
478     n2 ^= f(c, n1 + c->k[6]);
479     n1 ^= f(c, n2 + c->k[7]);
480
481     n2 ^= f(c, n1 + c->k[0]);
482     n1 ^= f(c, n2 + c->k[1]);
483     n2 ^= f(c, n1 + c->k[2]);
484     n1 ^= f(c, n2 + c->k[3]);
485     n2 ^= f(c, n1 + c->k[4]);
486     n1 ^= f(c, n2 + c->k[5]);
487     n2 ^= f(c, n1 + c->k[6]);
488     n1 ^= f(c, n2 + c->k[7]);
489
490     buffer[0] = (byte) (n1 & 0xff);
491     buffer[1] = (byte) ((n1 >> 8) & 0xff);
492     buffer[2] = (byte) ((n1 >> 16) & 0xff);
493     buffer[3] = (byte) (n1 >> 24);
494     buffer[4] = (byte) (n2 & 0xff);
495     buffer[5] = (byte) ((n2 >> 8) & 0xff);
496     buffer[6] = (byte) ((n2 >> 16) & 0xff);
497     buffer[7] = (byte) (n2 >> 24);
498 }
499
500 /* Get mac with specified number of bits from MAC state buffer */
501 void get_mac(byte * buffer, int nbits, byte * out)
502 {
503     int nbytes = nbits >> 3;
504     int rembits = nbits & 7;
505     int mask = rembits ? ((1 < rembits) - 1) : 0;
506     int i;
507     for (i = 0; i < nbytes; i++)
508         out[i] = buffer[i];
509     if (rembits)
510         out[i] = buffer[i] & mask;
511 }
512
513 /*
514  * Compute mac of specified length (in bits) from data. Context should be
515  * initialized with key and subst blocks
516  */
517 int gost_mac(gost_ctx * ctx, int mac_len, const unsigned char *data,
518              unsigned int data_len, unsigned char *mac)
519 {
520     byte buffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
521     byte buf2[8];
522     unsigned int i;
523     for (i = 0; i + 8 <= data_len; i += 8)
524         mac_block(ctx, buffer, data + i);
525     if (i < data_len) {
526         memset(buf2, 0, 8);
527         memcpy(buf2, data + i, data_len - i);
528         mac_block(ctx, buffer, buf2);
529         i += 8;
530     }
531     if (i == 8) {
532         memset(buf2, 0, 8);
533         mac_block(ctx, buffer, buf2);
534     }
535     get_mac(buffer, mac_len, mac);
536     return 1;
537 }
538
539 /* Compute MAC with non-zero IV. Used in some RFC 4357 algorithms */
540 int gost_mac_iv(gost_ctx * ctx, int mac_len, const unsigned char *iv,
541                 const unsigned char *data, unsigned int data_len,
542                 unsigned char *mac)
543 {
544     byte buffer[8];
545     byte buf2[8];
546     unsigned int i;
547     memcpy(buffer, iv, 8);
548     for (i = 0; i + 8 <= data_len; i += 8)
549         mac_block(ctx, buffer, data + i);
550     if (i < data_len) {
551         memset(buf2, 0, 8);
552         memcpy(buf2, data + i, data_len - i);
553         mac_block(ctx, buffer, buf2);
554         i += 8;
555     }
556     if (i == 8) {
557         memset(buf2, 0, 8);
558         mac_block(ctx, buffer, buf2);
559     }
560     get_mac(buffer, mac_len, mac);
561     return 1;
562 }
563
564 /* Implements key meshing algorithm by modifing ctx and IV in place */
565 void cryptopro_key_meshing(gost_ctx * ctx, unsigned char *iv)
566 {
567     unsigned char newkey[32], newiv[8];
568     /* Set static keymeshing key */
569     /* "Decrypt" key with keymeshing key */
570     gost_dec(ctx, CryptoProKeyMeshingKey, newkey, 4);
571     /* set new key */
572     gost_key(ctx, newkey);
573     /* Encrypt iv with new key */
574     gostcrypt(ctx, iv, newiv);
575     memcpy(iv, newiv, 8);
576 }