]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost89.c
Initial commit providing GOST 2012 algorithms.
[openssl-gost/engine.git] / 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 /* 1.2.643.7.1.2.5.1.1 */
212 gost_subst_block Gost28147_TC26ParamSetZ = {
213     {0x1, 0x7, 0xe, 0xd, 0x0, 0x5, 0x8, 0x3, 0x4, 0xf, 0xa, 0x6, 0x9, 0xc,
214      0xb, 0x2}
215     ,
216     {0x8, 0xe, 0x2, 0x5, 0x6, 0x9, 0x1, 0xc, 0xf, 0x4, 0xb, 0x0, 0xd, 0xa,
217      0x3, 0x7}
218     ,
219     {0x5, 0xd, 0xf, 0x6, 0x9, 0x2, 0xc, 0xa, 0xb, 0x7, 0x8, 0x1, 0x4, 0x3,
220      0xe, 0x0}
221     ,
222     {0x7, 0xf, 0x5, 0xa, 0x8, 0x1, 0x6, 0xd, 0x0, 0x9, 0x3, 0xe, 0xb, 0x4,
223      0x2, 0xc}
224     ,
225     {0xc, 0x8, 0x2, 0x1, 0xd, 0x4, 0xf, 0x6, 0x7, 0x0, 0xa, 0x5, 0x3, 0xe,
226      0x9, 0xb}
227     ,
228     {0xb, 0x3, 0x5, 0x8, 0x2, 0xf, 0xa, 0xd, 0xe, 0x1, 0x7, 0x4, 0xc, 0x9,
229      0x6, 0x0}
230     ,
231     {0x6, 0x8, 0x2, 0x3, 0x9, 0xa, 0x5, 0xc, 0x1, 0xe, 0x4, 0x7, 0xb, 0xd,
232      0x0, 0xf}
233     ,
234     {0xc, 0x4, 0x6, 0x2, 0xa, 0x5, 0xb, 0x9, 0xe, 0x8, 0xd, 0x7, 0x0, 0x3,
235      0xf, 0x1}
236 };
237
238 const byte CryptoProKeyMeshingKey[] = {
239     0x69, 0x00, 0x72, 0x22, 0x64, 0xC9, 0x04, 0x23,
240     0x8D, 0x3A, 0xDB, 0x96, 0x46, 0xE9, 0x2A, 0xC4,
241     0x18, 0xFE, 0xAC, 0x94, 0x00, 0xED, 0x07, 0x12,
242     0xC0, 0x86, 0xDC, 0xC2, 0xEF, 0x4C, 0xA9, 0x2B
243 };
244
245 /* Initialization of gost_ctx subst blocks*/
246 static void kboxinit(gost_ctx * c, const gost_subst_block * b)
247 {
248     int i;
249
250     for (i = 0; i < 256; i++) {
251         c->k87[i] = (word32) (b->k8[i >> 4] << 4 | b->k7[i & 15]) << 24;
252         c->k65[i] = (b->k6[i >> 4] << 4 | b->k5[i & 15]) << 16;
253         c->k43[i] = (b->k4[i >> 4] << 4 | b->k3[i & 15]) << 8;
254         c->k21[i] = b->k2[i >> 4] << 4 | b->k1[i & 15];
255
256     }
257 }
258
259 /* Part of GOST 28147 algorithm moved into separate function */
260 static word32 f(gost_ctx * c, word32 x)
261 {
262     x = c->k87[x >> 24 & 255] | c->k65[x >> 16 & 255] |
263         c->k43[x >> 8 & 255] | c->k21[x & 255];
264     /* Rotate left 11 bits */
265     return x << 11 | x >> (32 - 11);
266 }
267
268 /* Low-level encryption routine - encrypts one 64 bit block*/
269 void gostcrypt(gost_ctx * c, const byte * in, byte * out)
270 {
271     register word32 n1, n2;     /* As named in the GOST */
272     n1 = in[0] | (in[1] << 8) | (in[2] << 16) | ((word32) in[3] << 24);
273     n2 = in[4] | (in[5] << 8) | (in[6] << 16) | ((word32) in[7] << 24);
274     /* Instead of swapping halves, swap names each round */
275
276     n2 ^= f(c, n1 + c->k[0]);
277     n1 ^= f(c, n2 + c->k[1]);
278     n2 ^= f(c, n1 + c->k[2]);
279     n1 ^= f(c, n2 + c->k[3]);
280     n2 ^= f(c, n1 + c->k[4]);
281     n1 ^= f(c, n2 + c->k[5]);
282     n2 ^= f(c, n1 + c->k[6]);
283     n1 ^= f(c, n2 + c->k[7]);
284
285     n2 ^= f(c, n1 + c->k[0]);
286     n1 ^= f(c, n2 + c->k[1]);
287     n2 ^= f(c, n1 + c->k[2]);
288     n1 ^= f(c, n2 + c->k[3]);
289     n2 ^= f(c, n1 + c->k[4]);
290     n1 ^= f(c, n2 + c->k[5]);
291     n2 ^= f(c, n1 + c->k[6]);
292     n1 ^= f(c, n2 + c->k[7]);
293
294     n2 ^= f(c, n1 + c->k[0]);
295     n1 ^= f(c, n2 + c->k[1]);
296     n2 ^= f(c, n1 + c->k[2]);
297     n1 ^= f(c, n2 + c->k[3]);
298     n2 ^= f(c, n1 + c->k[4]);
299     n1 ^= f(c, n2 + c->k[5]);
300     n2 ^= f(c, n1 + c->k[6]);
301     n1 ^= f(c, n2 + c->k[7]);
302
303     n2 ^= f(c, n1 + c->k[7]);
304     n1 ^= f(c, n2 + c->k[6]);
305     n2 ^= f(c, n1 + c->k[5]);
306     n1 ^= f(c, n2 + c->k[4]);
307     n2 ^= f(c, n1 + c->k[3]);
308     n1 ^= f(c, n2 + c->k[2]);
309     n2 ^= f(c, n1 + c->k[1]);
310     n1 ^= f(c, n2 + c->k[0]);
311
312     out[0] = (byte) (n2 & 0xff);
313     out[1] = (byte) ((n2 >> 8) & 0xff);
314     out[2] = (byte) ((n2 >> 16) & 0xff);
315     out[3] = (byte) (n2 >> 24);
316     out[4] = (byte) (n1 & 0xff);
317     out[5] = (byte) ((n1 >> 8) & 0xff);
318     out[6] = (byte) ((n1 >> 16) & 0xff);
319     out[7] = (byte) (n1 >> 24);
320 }
321
322 /* Low-level decryption routine. Decrypts one 64-bit block */
323 void gostdecrypt(gost_ctx * c, const byte * in, byte * out)
324 {
325     register word32 n1, n2;     /* As named in the GOST */
326     n1 = in[0] | (in[1] << 8) | (in[2] << 16) | ((word32) in[3] << 24);
327     n2 = in[4] | (in[5] << 8) | (in[6] << 16) | ((word32) in[7] << 24);
328
329     n2 ^= f(c, n1 + c->k[0]);
330     n1 ^= f(c, n2 + c->k[1]);
331     n2 ^= f(c, n1 + c->k[2]);
332     n1 ^= f(c, n2 + c->k[3]);
333     n2 ^= f(c, n1 + c->k[4]);
334     n1 ^= f(c, n2 + c->k[5]);
335     n2 ^= f(c, n1 + c->k[6]);
336     n1 ^= f(c, n2 + c->k[7]);
337
338     n2 ^= f(c, n1 + c->k[7]);
339     n1 ^= f(c, n2 + c->k[6]);
340     n2 ^= f(c, n1 + c->k[5]);
341     n1 ^= f(c, n2 + c->k[4]);
342     n2 ^= f(c, n1 + c->k[3]);
343     n1 ^= f(c, n2 + c->k[2]);
344     n2 ^= f(c, n1 + c->k[1]);
345     n1 ^= f(c, n2 + c->k[0]);
346
347     n2 ^= f(c, n1 + c->k[7]);
348     n1 ^= f(c, n2 + c->k[6]);
349     n2 ^= f(c, n1 + c->k[5]);
350     n1 ^= f(c, n2 + c->k[4]);
351     n2 ^= f(c, n1 + c->k[3]);
352     n1 ^= f(c, n2 + c->k[2]);
353     n2 ^= f(c, n1 + c->k[1]);
354     n1 ^= f(c, n2 + c->k[0]);
355
356     n2 ^= f(c, n1 + c->k[7]);
357     n1 ^= f(c, n2 + c->k[6]);
358     n2 ^= f(c, n1 + c->k[5]);
359     n1 ^= f(c, n2 + c->k[4]);
360     n2 ^= f(c, n1 + c->k[3]);
361     n1 ^= f(c, n2 + c->k[2]);
362     n2 ^= f(c, n1 + c->k[1]);
363     n1 ^= f(c, n2 + c->k[0]);
364
365     out[0] = (byte) (n2 & 0xff);
366     out[1] = (byte) ((n2 >> 8) & 0xff);
367     out[2] = (byte) ((n2 >> 16) & 0xff);
368     out[3] = (byte) (n2 >> 24);
369     out[4] = (byte) (n1 & 0xff);
370     out[5] = (byte) ((n1 >> 8) & 0xff);
371     out[6] = (byte) ((n1 >> 16) & 0xff);
372     out[7] = (byte) (n1 >> 24);
373 }
374
375 /* Encrypts several blocks in ECB mode */
376 void gost_enc(gost_ctx * c, const byte * clear, byte * cipher, int blocks)
377 {
378     int i;
379     for (i = 0; i < blocks; i++) {
380         gostcrypt(c, clear, cipher);
381         clear += 8;
382         cipher += 8;
383     }
384 }
385
386 /* Decrypts several blocks in ECB mode */
387 void gost_dec(gost_ctx * c, const byte * cipher, byte * clear, int blocks)
388 {
389     int i;
390     for (i = 0; i < blocks; i++) {
391         gostdecrypt(c, cipher, clear);
392         clear += 8;
393         cipher += 8;
394     }
395 }
396
397 /* Encrypts several full blocks in CFB mode using 8byte IV */
398 void gost_enc_cfb(gost_ctx * ctx, const byte * iv, const byte * clear,
399                   byte * cipher, int blocks)
400 {
401     byte cur_iv[8];
402     byte gamma[8];
403     int i, j;
404     const byte *in;
405     byte *out;
406     memcpy(cur_iv, iv, 8);
407     for (i = 0, in = clear, out = cipher; i < blocks; i++, in += 8, out += 8) {
408         gostcrypt(ctx, cur_iv, gamma);
409         for (j = 0; j < 8; j++) {
410             cur_iv[j] = out[j] = in[j] ^ gamma[j];
411         }
412     }
413 }
414
415 /* Decrypts several full blocks in CFB mode using 8byte IV */
416 void gost_dec_cfb(gost_ctx * ctx, const byte * iv, const byte * cipher,
417                   byte * clear, int blocks)
418 {
419     byte cur_iv[8];
420     byte gamma[8];
421     int i, j;
422     const byte *in;
423     byte *out;
424     memcpy(cur_iv, iv, 8);
425     for (i = 0, in = cipher, out = clear; i < blocks; i++, in += 8, out += 8) {
426         gostcrypt(ctx, cur_iv, gamma);
427         for (j = 0; j < 8; j++) {
428             out[j] = (cur_iv[j] = in[j]) ^ gamma[j];
429         }
430     }
431 }
432
433 /* Encrypts one block using specified key */
434 void gost_enc_with_key(gost_ctx * c, byte * key, byte * inblock,
435                        byte * outblock)
436 {
437     gost_key(c, key);
438     gostcrypt(c, inblock, outblock);
439 }
440
441 /* Set 256 bit  key into context */
442 void gost_key(gost_ctx * c, const byte * k)
443 {
444     int i, j;
445     for (i = 0, j = 0; i < 8; i++, j += 4) {
446         c->k[i] =
447             k[j] | (k[j + 1] << 8) | (k[j + 2] << 16) | ((word32) k[j + 3] <<
448                                                          24);
449     }
450 }
451
452 /* Retrieve 256-bit key from context */
453 void gost_get_key(gost_ctx * c, byte * k)
454 {
455     int i, j;
456     for (i = 0, j = 0; i < 8; i++, j += 4) {
457         k[j] = (byte) (c->k[i] & 0xFF);
458         k[j + 1] = (byte) ((c->k[i] >> 8) & 0xFF);
459         k[j + 2] = (byte) ((c->k[i] >> 16) & 0xFF);
460         k[j + 3] = (byte) ((c->k[i] >> 24) & 0xFF);
461     }
462 }
463
464 /* Initalize context. Provides default value for subst_block */
465 void gost_init(gost_ctx * c, const gost_subst_block * b)
466 {
467     if (!b) {
468         b = &GostR3411_94_TestParamSet;
469     }
470     kboxinit(c, b);
471 }
472
473 /* Cleans up key from context */
474 void gost_destroy(gost_ctx * c)
475 {
476     int i;
477     for (i = 0; i < 8; i++)
478         c->k[i] = 0;
479 }
480
481 /*
482  * Compute GOST 28147 mac block Parameters gost_ctx *c - context initalized
483  * with substitution blocks and key buffer - 8-byte mac state buffer block
484  * 8-byte block to process.
485  */
486 void mac_block(gost_ctx * c, byte * buffer, const byte * block)
487 {
488     register word32 n1, n2;     /* As named in the GOST */
489     int i;
490     for (i = 0; i < 8; i++) {
491         buffer[i] ^= block[i];
492     }
493     n1 = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | ((word32)
494                                                              buffer[3] << 24);
495     n2 = buffer[4] | (buffer[5] << 8) | (buffer[6] << 16) | ((word32)
496                                                              buffer[7] << 24);
497     /* Instead of swapping halves, swap names each round */
498
499     n2 ^= f(c, n1 + c->k[0]);
500     n1 ^= f(c, n2 + c->k[1]);
501     n2 ^= f(c, n1 + c->k[2]);
502     n1 ^= f(c, n2 + c->k[3]);
503     n2 ^= f(c, n1 + c->k[4]);
504     n1 ^= f(c, n2 + c->k[5]);
505     n2 ^= f(c, n1 + c->k[6]);
506     n1 ^= f(c, n2 + c->k[7]);
507
508     n2 ^= f(c, n1 + c->k[0]);
509     n1 ^= f(c, n2 + c->k[1]);
510     n2 ^= f(c, n1 + c->k[2]);
511     n1 ^= f(c, n2 + c->k[3]);
512     n2 ^= f(c, n1 + c->k[4]);
513     n1 ^= f(c, n2 + c->k[5]);
514     n2 ^= f(c, n1 + c->k[6]);
515     n1 ^= f(c, n2 + c->k[7]);
516
517     buffer[0] = (byte) (n1 & 0xff);
518     buffer[1] = (byte) ((n1 >> 8) & 0xff);
519     buffer[2] = (byte) ((n1 >> 16) & 0xff);
520     buffer[3] = (byte) (n1 >> 24);
521     buffer[4] = (byte) (n2 & 0xff);
522     buffer[5] = (byte) ((n2 >> 8) & 0xff);
523     buffer[6] = (byte) ((n2 >> 16) & 0xff);
524     buffer[7] = (byte) (n2 >> 24);
525 }
526
527 /* Get mac with specified number of bits from MAC state buffer */
528 void get_mac(byte * buffer, int nbits, byte * out)
529 {
530     int nbytes = nbits >> 3;
531     int rembits = nbits & 7;
532     int mask = rembits ? ((1 < rembits) - 1) : 0;
533     int i;
534     for (i = 0; i < nbytes; i++)
535         out[i] = buffer[i];
536     if (rembits)
537         out[i] = buffer[i] & mask;
538 }
539
540 /*
541  * Compute mac of specified length (in bits) from data. Context should be
542  * initialized with key and subst blocks
543  */
544 int gost_mac(gost_ctx * ctx, int mac_len, const unsigned char *data,
545              unsigned int data_len, unsigned char *mac)
546 {
547     byte buffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
548     byte buf2[8];
549     unsigned int i;
550     for (i = 0; i + 8 <= data_len; i += 8)
551         mac_block(ctx, buffer, data + i);
552     if (i < data_len) {
553         memset(buf2, 0, 8);
554         memcpy(buf2, data + i, data_len - i);
555         mac_block(ctx, buffer, buf2);
556         i += 8;
557     }
558     if (i == 8) {
559         memset(buf2, 0, 8);
560         mac_block(ctx, buffer, buf2);
561     }
562     get_mac(buffer, mac_len, mac);
563     return 1;
564 }
565
566 /* Compute MAC with non-zero IV. Used in some RFC 4357 algorithms */
567 int gost_mac_iv(gost_ctx * ctx, int mac_len, const unsigned char *iv,
568                 const unsigned char *data, unsigned int data_len,
569                 unsigned char *mac)
570 {
571     byte buffer[8];
572     byte buf2[8];
573     unsigned int i;
574     memcpy(buffer, iv, 8);
575     for (i = 0; i + 8 <= data_len; i += 8)
576         mac_block(ctx, buffer, data + i);
577     if (i < data_len) {
578         memset(buf2, 0, 8);
579         memcpy(buf2, data + i, data_len - i);
580         mac_block(ctx, buffer, buf2);
581         i += 8;
582     }
583     if (i == 8) {
584         memset(buf2, 0, 8);
585         mac_block(ctx, buffer, buf2);
586     }
587     get_mac(buffer, mac_len, mac);
588     return 1;
589 }
590
591 /* Implements key meshing algorithm by modifing ctx and IV in place */
592 void cryptopro_key_meshing(gost_ctx * ctx, unsigned char *iv)
593 {
594     unsigned char newkey[32], newiv[8];
595     /* Set static keymeshing key */
596     /* "Decrypt" key with keymeshing key */
597     gost_dec(ctx, CryptoProKeyMeshingKey, newkey, 4);
598     /* set new key */
599     gost_key(ctx, newkey);
600     /* Encrypt iv with new key */
601     gostcrypt(ctx, iv, newiv);
602     memcpy(iv, newiv, 8);
603 }