]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost89.c
Remove unset local buffer meshing. This removes valgrind errors.
[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 const byte ACPKM_D_const[] = {
246     0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
247     0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
248     0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
249     0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
250 };
251
252 /* Initialization of gost_ctx subst blocks*/
253 void kboxinit(gost_ctx * c, const gost_subst_block * b)
254 {
255     int i;
256
257     for (i = 0; i < 256; i++) {
258         c->k87[i] = (word32) (b->k8[i >> 4] << 4 | b->k7[i & 15]) << 24;
259         c->k65[i] = (b->k6[i >> 4] << 4 | b->k5[i & 15]) << 16;
260         c->k43[i] = (b->k4[i >> 4] << 4 | b->k3[i & 15]) << 8;
261         c->k21[i] = b->k2[i >> 4] << 4 | b->k1[i & 15];
262
263     }
264 }
265
266 /* Part of GOST 28147 algorithm moved into separate function */
267 static word32 f(gost_ctx * c, word32 x)
268 {
269     x = c->k87[x >> 24 & 255] | c->k65[x >> 16 & 255] |
270         c->k43[x >> 8 & 255] | c->k21[x & 255];
271     /* Rotate left 11 bits */
272     return x << 11 | x >> (32 - 11);
273 }
274
275 /* Low-level encryption routine - encrypts one 64 bit block*/
276 void gostcrypt(gost_ctx * c, const byte * in, byte * out)
277 {
278     register word32 n1, n2;     /* As named in the GOST */
279     n1 = in[0] | (in[1] << 8) | (in[2] << 16) | ((word32) in[3] << 24);
280     n2 = in[4] | (in[5] << 8) | (in[6] << 16) | ((word32) in[7] << 24);
281     /* Instead of swapping halves, swap names each round */
282
283     n2 ^= f(c, n1 + c->k[0]);
284     n1 ^= f(c, n2 + c->k[1]);
285     n2 ^= f(c, n1 + c->k[2]);
286     n1 ^= f(c, n2 + c->k[3]);
287     n2 ^= f(c, n1 + c->k[4]);
288     n1 ^= f(c, n2 + c->k[5]);
289     n2 ^= f(c, n1 + c->k[6]);
290     n1 ^= f(c, n2 + c->k[7]);
291
292     n2 ^= f(c, n1 + c->k[0]);
293     n1 ^= f(c, n2 + c->k[1]);
294     n2 ^= f(c, n1 + c->k[2]);
295     n1 ^= f(c, n2 + c->k[3]);
296     n2 ^= f(c, n1 + c->k[4]);
297     n1 ^= f(c, n2 + c->k[5]);
298     n2 ^= f(c, n1 + c->k[6]);
299     n1 ^= f(c, n2 + c->k[7]);
300
301     n2 ^= f(c, n1 + c->k[0]);
302     n1 ^= f(c, n2 + c->k[1]);
303     n2 ^= f(c, n1 + c->k[2]);
304     n1 ^= f(c, n2 + c->k[3]);
305     n2 ^= f(c, n1 + c->k[4]);
306     n1 ^= f(c, n2 + c->k[5]);
307     n2 ^= f(c, n1 + c->k[6]);
308     n1 ^= f(c, n2 + c->k[7]);
309
310     n2 ^= f(c, n1 + c->k[7]);
311     n1 ^= f(c, n2 + c->k[6]);
312     n2 ^= f(c, n1 + c->k[5]);
313     n1 ^= f(c, n2 + c->k[4]);
314     n2 ^= f(c, n1 + c->k[3]);
315     n1 ^= f(c, n2 + c->k[2]);
316     n2 ^= f(c, n1 + c->k[1]);
317     n1 ^= f(c, n2 + c->k[0]);
318
319     out[0] = (byte) (n2 & 0xff);
320     out[1] = (byte) ((n2 >> 8) & 0xff);
321     out[2] = (byte) ((n2 >> 16) & 0xff);
322     out[3] = (byte) (n2 >> 24);
323     out[4] = (byte) (n1 & 0xff);
324     out[5] = (byte) ((n1 >> 8) & 0xff);
325     out[6] = (byte) ((n1 >> 16) & 0xff);
326     out[7] = (byte) (n1 >> 24);
327 }
328
329 /* Low-level decryption routine. Decrypts one 64-bit block */
330 void gostdecrypt(gost_ctx * c, const byte * in, byte * out)
331 {
332     register word32 n1, n2;     /* As named in the GOST */
333     n1 = in[0] | (in[1] << 8) | (in[2] << 16) | ((word32) in[3] << 24);
334     n2 = in[4] | (in[5] << 8) | (in[6] << 16) | ((word32) in[7] << 24);
335
336     n2 ^= f(c, n1 + c->k[0]);
337     n1 ^= f(c, n2 + c->k[1]);
338     n2 ^= f(c, n1 + c->k[2]);
339     n1 ^= f(c, n2 + c->k[3]);
340     n2 ^= f(c, n1 + c->k[4]);
341     n1 ^= f(c, n2 + c->k[5]);
342     n2 ^= f(c, n1 + c->k[6]);
343     n1 ^= f(c, n2 + c->k[7]);
344
345     n2 ^= f(c, n1 + c->k[7]);
346     n1 ^= f(c, n2 + c->k[6]);
347     n2 ^= f(c, n1 + c->k[5]);
348     n1 ^= f(c, n2 + c->k[4]);
349     n2 ^= f(c, n1 + c->k[3]);
350     n1 ^= f(c, n2 + c->k[2]);
351     n2 ^= f(c, n1 + c->k[1]);
352     n1 ^= f(c, n2 + c->k[0]);
353
354     n2 ^= f(c, n1 + c->k[7]);
355     n1 ^= f(c, n2 + c->k[6]);
356     n2 ^= f(c, n1 + c->k[5]);
357     n1 ^= f(c, n2 + c->k[4]);
358     n2 ^= f(c, n1 + c->k[3]);
359     n1 ^= f(c, n2 + c->k[2]);
360     n2 ^= f(c, n1 + c->k[1]);
361     n1 ^= f(c, n2 + c->k[0]);
362
363     n2 ^= f(c, n1 + c->k[7]);
364     n1 ^= f(c, n2 + c->k[6]);
365     n2 ^= f(c, n1 + c->k[5]);
366     n1 ^= f(c, n2 + c->k[4]);
367     n2 ^= f(c, n1 + c->k[3]);
368     n1 ^= f(c, n2 + c->k[2]);
369     n2 ^= f(c, n1 + c->k[1]);
370     n1 ^= f(c, n2 + c->k[0]);
371
372     out[0] = (byte) (n2 & 0xff);
373     out[1] = (byte) ((n2 >> 8) & 0xff);
374     out[2] = (byte) ((n2 >> 16) & 0xff);
375     out[3] = (byte) (n2 >> 24);
376     out[4] = (byte) (n1 & 0xff);
377     out[5] = (byte) ((n1 >> 8) & 0xff);
378     out[6] = (byte) ((n1 >> 16) & 0xff);
379     out[7] = (byte) (n1 >> 24);
380 }
381
382 /* Encrypts several blocks in ECB mode */
383 void gost_enc(gost_ctx * c, const byte * clear, byte * cipher, int blocks)
384 {
385     int i;
386     for (i = 0; i < blocks; i++) {
387         gostcrypt(c, clear, cipher);
388         clear += 8;
389         cipher += 8;
390     }
391 }
392
393 /* Decrypts several blocks in ECB mode */
394 void gost_dec(gost_ctx * c, const byte * cipher, byte * clear, int blocks)
395 {
396     int i;
397     for (i = 0; i < blocks; i++) {
398         gostdecrypt(c, cipher, clear);
399         clear += 8;
400         cipher += 8;
401     }
402 }
403
404 /* Encrypts several full blocks in CFB mode using 8byte IV */
405 void gost_enc_cfb(gost_ctx * ctx, const byte * iv, const byte * clear,
406                   byte * cipher, int blocks)
407 {
408     byte cur_iv[8];
409     byte gamma[8];
410     int i, j;
411     const byte *in;
412     byte *out;
413     memcpy(cur_iv, iv, 8);
414     for (i = 0, in = clear, out = cipher; i < blocks; i++, in += 8, out += 8) {
415         gostcrypt(ctx, cur_iv, gamma);
416         for (j = 0; j < 8; j++) {
417             cur_iv[j] = out[j] = in[j] ^ gamma[j];
418         }
419     }
420 }
421
422 /* Decrypts several full blocks in CFB mode using 8byte IV */
423 void gost_dec_cfb(gost_ctx * ctx, const byte * iv, const byte * cipher,
424                   byte * clear, int blocks)
425 {
426     byte cur_iv[8];
427     byte gamma[8];
428     int i, j;
429     const byte *in;
430     byte *out;
431     memcpy(cur_iv, iv, 8);
432     for (i = 0, in = cipher, out = clear; i < blocks; i++, in += 8, out += 8) {
433         gostcrypt(ctx, cur_iv, gamma);
434         for (j = 0; j < 8; j++) {
435             out[j] = (cur_iv[j] = in[j]) ^ gamma[j];
436         }
437     }
438 }
439
440 /* Encrypts one block using specified key */
441 void gost_enc_with_key(gost_ctx * c, byte * key, byte * inblock,
442                        byte * outblock)
443 {
444     gost_key(c, key);
445     gostcrypt(c, inblock, outblock);
446 }
447
448 /* Set 256 bit gost89 key into context */
449 void gost_key(gost_ctx * c, const byte * k)
450 {
451     int i, j;
452     for (i = 0, j = 0; i < 8; i++, j += 4) {
453         c->k[i] =
454             k[j] | (k[j + 1] << 8) | (k[j + 2] << 16) | ((word32) k[j + 3] <<
455                                                          24);
456     }
457 }
458
459 /* Set 256 bit Magma key into context */
460 void magma_key(gost_ctx * c, const byte * k)
461 {
462     int i, j;
463     for (i = 0, j = 0; i < 8; i++, j += 4) {
464         c->k[i] =
465             k[j + 3] | (k[j + 2] << 8) | (k[j + 1] << 16) | ((word32) k[j] <<
466                                                              24);
467     }
468 }
469
470 /* Retrieve 256-bit gost89 key from context */
471 void gost_get_key(gost_ctx * c, byte * k)
472 {
473     int i, j;
474     for (i = 0, j = 0; i < 8; i++, j += 4) {
475         k[j] = (byte) (c->k[i] & 0xFF);
476         k[j + 1] = (byte) ((c->k[i] >> 8) & 0xFF);
477         k[j + 2] = (byte) ((c->k[i] >> 16) & 0xFF);
478         k[j + 3] = (byte) ((c->k[i] >> 24) & 0xFF);
479     }
480 }
481
482 /* Retrieve 256-bit magma key from context */
483 void magma_get_key(gost_ctx * c, byte * k)
484 {
485     int i, j;
486     for (i = 0, j = 0; i < 8; i++, j += 4) {
487         k[j + 3] = (byte) (c->k[i] & 0xFF);
488         k[j + 2] = (byte) ((c->k[i] >> 8) & 0xFF);
489         k[j + 1] = (byte) ((c->k[i] >> 16) & 0xFF);
490         k[j + 0] = (byte) ((c->k[i] >> 24) & 0xFF);
491     }
492 }
493
494 /* Initalize context. Provides default value for subst_block */
495 void gost_init(gost_ctx * c, const gost_subst_block * b)
496 {
497     if (!b) {
498         b = &GostR3411_94_TestParamSet;
499     }
500     kboxinit(c, b);
501 }
502
503 /* Cleans up key from context */
504 void gost_destroy(gost_ctx * c)
505 {
506     int i;
507     for (i = 0; i < 8; i++)
508         c->k[i] = 0;
509 }
510
511 /*
512  * Compute GOST 28147 mac block Parameters gost_ctx *c - context initalized
513  * with substitution blocks and key buffer - 8-byte mac state buffer block
514  * 8-byte block to process.
515  */
516 void mac_block(gost_ctx * c, byte * buffer, const byte * block)
517 {
518     register word32 n1, n2;     /* As named in the GOST */
519     int i;
520     for (i = 0; i < 8; i++) {
521         buffer[i] ^= block[i];
522     }
523     n1 = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | ((word32)
524                                                              buffer[3] << 24);
525     n2 = buffer[4] | (buffer[5] << 8) | (buffer[6] << 16) | ((word32)
526                                                              buffer[7] << 24);
527     /* Instead of swapping halves, swap names each round */
528
529     n2 ^= f(c, n1 + c->k[0]);
530     n1 ^= f(c, n2 + c->k[1]);
531     n2 ^= f(c, n1 + c->k[2]);
532     n1 ^= f(c, n2 + c->k[3]);
533     n2 ^= f(c, n1 + c->k[4]);
534     n1 ^= f(c, n2 + c->k[5]);
535     n2 ^= f(c, n1 + c->k[6]);
536     n1 ^= f(c, n2 + c->k[7]);
537
538     n2 ^= f(c, n1 + c->k[0]);
539     n1 ^= f(c, n2 + c->k[1]);
540     n2 ^= f(c, n1 + c->k[2]);
541     n1 ^= f(c, n2 + c->k[3]);
542     n2 ^= f(c, n1 + c->k[4]);
543     n1 ^= f(c, n2 + c->k[5]);
544     n2 ^= f(c, n1 + c->k[6]);
545     n1 ^= f(c, n2 + c->k[7]);
546
547     buffer[0] = (byte) (n1 & 0xff);
548     buffer[1] = (byte) ((n1 >> 8) & 0xff);
549     buffer[2] = (byte) ((n1 >> 16) & 0xff);
550     buffer[3] = (byte) (n1 >> 24);
551     buffer[4] = (byte) (n2 & 0xff);
552     buffer[5] = (byte) ((n2 >> 8) & 0xff);
553     buffer[6] = (byte) ((n2 >> 16) & 0xff);
554     buffer[7] = (byte) (n2 >> 24);
555 }
556
557 /* Get mac with specified number of bits from MAC state buffer */
558 void get_mac(byte * buffer, int nbits, byte * out)
559 {
560     int nbytes = nbits >> 3;
561     int rembits = nbits & 7;
562     int mask = rembits ? ((1 < rembits) - 1) : 0;
563     int i;
564     for (i = 0; i < nbytes; i++)
565         out[i] = buffer[i];
566     if (rembits)
567         out[i] = buffer[i] & mask;
568 }
569
570 /*
571  * Compute mac of specified length (in bits) from data. Context should be
572  * initialized with key and subst blocks
573  */
574 int gost_mac(gost_ctx * ctx, int mac_len, const unsigned char *data,
575              unsigned int data_len, unsigned char *mac)
576 {
577     byte buffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
578     byte buf2[8];
579     unsigned int i;
580     for (i = 0; i + 8 <= data_len; i += 8)
581         mac_block(ctx, buffer, data + i);
582     if (i < data_len) {
583         memset(buf2, 0, 8);
584         memcpy(buf2, data + i, data_len - i);
585         mac_block(ctx, buffer, buf2);
586         i += 8;
587     }
588     if (i == 8) {
589         memset(buf2, 0, 8);
590         mac_block(ctx, buffer, buf2);
591     }
592     get_mac(buffer, mac_len, mac);
593     return 1;
594 }
595
596 /* Compute MAC with non-zero IV. Used in some RFC 4357 algorithms */
597 int gost_mac_iv(gost_ctx * ctx, int mac_len, const unsigned char *iv,
598                 const unsigned char *data, unsigned int data_len,
599                 unsigned char *mac)
600 {
601     byte buffer[8];
602     byte buf2[8];
603     unsigned int i;
604     memcpy(buffer, iv, 8);
605     for (i = 0; i + 8 <= data_len; i += 8)
606         mac_block(ctx, buffer, data + i);
607     if (i < data_len) {
608         memset(buf2, 0, 8);
609         memcpy(buf2, data + i, data_len - i);
610         mac_block(ctx, buffer, buf2);
611         i += 8;
612     }
613     if (i == 8) {
614         memset(buf2, 0, 8);
615         mac_block(ctx, buffer, buf2);
616     }
617     get_mac(buffer, mac_len, mac);
618     return 1;
619 }
620
621 /* Implements key meshing algorithm by modifing ctx and IV in place */
622 void cryptopro_key_meshing(gost_ctx * ctx, unsigned char *iv)
623 {
624     unsigned char newkey[32];
625     /* Set static keymeshing key */
626     /* "Decrypt" key with keymeshing key */
627     gost_dec(ctx, CryptoProKeyMeshingKey, newkey, 4);
628     /* set new key */
629     gost_key(ctx, newkey);
630     /* Encrypt iv with new key */
631     if (iv != NULL ) {
632         unsigned char newiv[8];
633         gostcrypt(ctx, iv, newiv);
634         memcpy(iv, newiv, 8);
635     }
636 }
637
638 void acpkm_magma_key_meshing(gost_ctx * ctx)
639 {
640     unsigned char newkey[32];
641     int i, j;
642     unsigned char buf[8], keybuf[8];
643
644     for (i = 0; i < 4; i++) {
645         for (j = 0; j < 8; j++) {
646             buf[j] = ACPKM_D_const[8 * i + 7 - j];
647         }
648         gostcrypt(ctx, buf, keybuf);
649         memcpy(newkey + 8 * i, keybuf + 4, 4);
650         memcpy(newkey + 8 * i + 4, keybuf, 4);
651     }
652     /* set new key */
653     gost_key(ctx, newkey);
654 }