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] = (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 */
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) | ((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 */
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) | ((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 */
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) | ((word32) k[j + 3] <<
421                                                         24);
422    }
423}
424
425/* Retrieve 256-bit key from context */
426void 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 */
438void 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 */
447void 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 */
459void 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 */
501void 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 */
517int 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 */
540int 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 */
565void 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}
577