]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost89.c
Finalized magma-cbc
[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 /* Set 256 bit  key into context */
453 void magma_key(gost_ctx * c, const byte * k)
454 {
455     int i, j;
456     for (i = 0, j = 0; i < 8; i++, j += 4) {
457         c->k[i] =
458             k[j+3] | (k[j + 2] << 8) | (k[j + 1] << 16) | ((word32) k[j] <<
459                                                          24);
460     }
461 }
462
463 /* Retrieve 256-bit key from context */
464 void gost_get_key(gost_ctx * c, byte * k)
465 {
466     int i, j;
467     for (i = 0, j = 0; i < 8; i++, j += 4) {
468         k[j] = (byte) (c->k[i] & 0xFF);
469         k[j + 1] = (byte) ((c->k[i] >> 8) & 0xFF);
470         k[j + 2] = (byte) ((c->k[i] >> 16) & 0xFF);
471         k[j + 3] = (byte) ((c->k[i] >> 24) & 0xFF);
472     }
473 }
474
475 /* Initalize context. Provides default value for subst_block */
476 void gost_init(gost_ctx * c, const gost_subst_block * b)
477 {
478     if (!b) {
479         b = &GostR3411_94_TestParamSet;
480     }
481     kboxinit(c, b);
482 }
483
484 /* Cleans up key from context */
485 void gost_destroy(gost_ctx * c)
486 {
487     int i;
488     for (i = 0; i < 8; i++)
489         c->k[i] = 0;
490 }
491
492 /*
493  * Compute GOST 28147 mac block Parameters gost_ctx *c - context initalized
494  * with substitution blocks and key buffer - 8-byte mac state buffer block
495  * 8-byte block to process.
496  */
497 void mac_block(gost_ctx * c, byte * buffer, const byte * block)
498 {
499     register word32 n1, n2;     /* As named in the GOST */
500     int i;
501     for (i = 0; i < 8; i++) {
502         buffer[i] ^= block[i];
503     }
504     n1 = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | ((word32)
505                                                              buffer[3] << 24);
506     n2 = buffer[4] | (buffer[5] << 8) | (buffer[6] << 16) | ((word32)
507                                                              buffer[7] << 24);
508     /* Instead of swapping halves, swap names each round */
509
510     n2 ^= f(c, n1 + c->k[0]);
511     n1 ^= f(c, n2 + c->k[1]);
512     n2 ^= f(c, n1 + c->k[2]);
513     n1 ^= f(c, n2 + c->k[3]);
514     n2 ^= f(c, n1 + c->k[4]);
515     n1 ^= f(c, n2 + c->k[5]);
516     n2 ^= f(c, n1 + c->k[6]);
517     n1 ^= f(c, n2 + c->k[7]);
518
519     n2 ^= f(c, n1 + c->k[0]);
520     n1 ^= f(c, n2 + c->k[1]);
521     n2 ^= f(c, n1 + c->k[2]);
522     n1 ^= f(c, n2 + c->k[3]);
523     n2 ^= f(c, n1 + c->k[4]);
524     n1 ^= f(c, n2 + c->k[5]);
525     n2 ^= f(c, n1 + c->k[6]);
526     n1 ^= f(c, n2 + c->k[7]);
527
528     buffer[0] = (byte) (n1 & 0xff);
529     buffer[1] = (byte) ((n1 >> 8) & 0xff);
530     buffer[2] = (byte) ((n1 >> 16) & 0xff);
531     buffer[3] = (byte) (n1 >> 24);
532     buffer[4] = (byte) (n2 & 0xff);
533     buffer[5] = (byte) ((n2 >> 8) & 0xff);
534     buffer[6] = (byte) ((n2 >> 16) & 0xff);
535     buffer[7] = (byte) (n2 >> 24);
536 }
537
538 /* Get mac with specified number of bits from MAC state buffer */
539 void get_mac(byte * buffer, int nbits, byte * out)
540 {
541     int nbytes = nbits >> 3;
542     int rembits = nbits & 7;
543     int mask = rembits ? ((1 < rembits) - 1) : 0;
544     int i;
545     for (i = 0; i < nbytes; i++)
546         out[i] = buffer[i];
547     if (rembits)
548         out[i] = buffer[i] & mask;
549 }
550
551 /*
552  * Compute mac of specified length (in bits) from data. Context should be
553  * initialized with key and subst blocks
554  */
555 int gost_mac(gost_ctx * ctx, int mac_len, const unsigned char *data,
556              unsigned int data_len, unsigned char *mac)
557 {
558     byte buffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
559     byte buf2[8];
560     unsigned int i;
561     for (i = 0; i + 8 <= data_len; i += 8)
562         mac_block(ctx, buffer, data + i);
563     if (i < data_len) {
564         memset(buf2, 0, 8);
565         memcpy(buf2, data + i, data_len - i);
566         mac_block(ctx, buffer, buf2);
567         i += 8;
568     }
569     if (i == 8) {
570         memset(buf2, 0, 8);
571         mac_block(ctx, buffer, buf2);
572     }
573     get_mac(buffer, mac_len, mac);
574     return 1;
575 }
576
577 /* Compute MAC with non-zero IV. Used in some RFC 4357 algorithms */
578 int gost_mac_iv(gost_ctx * ctx, int mac_len, const unsigned char *iv,
579                 const unsigned char *data, unsigned int data_len,
580                 unsigned char *mac)
581 {
582     byte buffer[8];
583     byte buf2[8];
584     unsigned int i;
585     memcpy(buffer, iv, 8);
586     for (i = 0; i + 8 <= data_len; i += 8)
587         mac_block(ctx, buffer, data + i);
588     if (i < data_len) {
589         memset(buf2, 0, 8);
590         memcpy(buf2, data + i, data_len - i);
591         mac_block(ctx, buffer, buf2);
592         i += 8;
593     }
594     if (i == 8) {
595         memset(buf2, 0, 8);
596         mac_block(ctx, buffer, buf2);
597     }
598     get_mac(buffer, mac_len, mac);
599     return 1;
600 }
601
602 /* Implements key meshing algorithm by modifing ctx and IV in place */
603 void cryptopro_key_meshing(gost_ctx * ctx, unsigned char *iv)
604 {
605     unsigned char newkey[32], newiv[8];
606     /* Set static keymeshing key */
607     /* "Decrypt" key with keymeshing key */
608     gost_dec(ctx, CryptoProKeyMeshingKey, newkey, 4);
609     /* set new key */
610     gost_key(ctx, newkey);
611     /* Encrypt iv with new key */
612     gostcrypt(ctx, iv, newiv);
613     memcpy(iv, newiv, 8);
614 }