gost89.c revision 296341
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*/
23gost_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  */
50gost_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 */
77gost_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 */
104gost_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 */
131gost_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 */
158gost_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 */
185gost_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
211const 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*/
219static 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 */
233static 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*/
242void 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 */
296void 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 */
349void 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 */
360void 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 */
371void 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 */
389void 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 */
407void 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 */
415void 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 */
425void 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 */
437void 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 */
446void 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 */
458void 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 */
498void 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 */
514int 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 */
537int 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 */
562void 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}
574