]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost89.c
Destroy GOST key data with OPENSSL_cleanse()
[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 <openssl/crypto.h>
12 #include "gost89.h"
13 /*-
14    Substitution blocks from RFC 4357
15
16    Note: our implementation of gost 28147-89 algorithm
17    uses S-box matrix rotated 90 degrees counterclockwise, relative to
18    examples given in RFC.
19
20
21 */
22
23 /* Substitution blocks from test examples for GOST R 34.11-94*/
24 gost_subst_block GostR3411_94_TestParamSet = {
25     {0X1, 0XF, 0XD, 0X0, 0X5, 0X7, 0XA, 0X4, 0X9, 0X2, 0X3, 0XE, 0X6, 0XB,
26      0X8, 0XC}
27     ,
28     {0XD, 0XB, 0X4, 0X1, 0X3, 0XF, 0X5, 0X9, 0X0, 0XA, 0XE, 0X7, 0X6, 0X8,
29      0X2, 0XC}
30     ,
31     {0X4, 0XB, 0XA, 0X0, 0X7, 0X2, 0X1, 0XD, 0X3, 0X6, 0X8, 0X5, 0X9, 0XC,
32      0XF, 0XE}
33     ,
34     {0X6, 0XC, 0X7, 0X1, 0X5, 0XF, 0XD, 0X8, 0X4, 0XA, 0X9, 0XE, 0X0, 0X3,
35      0XB, 0X2}
36     ,
37     {0X7, 0XD, 0XA, 0X1, 0X0, 0X8, 0X9, 0XF, 0XE, 0X4, 0X6, 0XC, 0XB, 0X2,
38      0X5, 0X3}
39     ,
40     {0X5, 0X8, 0X1, 0XD, 0XA, 0X3, 0X4, 0X2, 0XE, 0XF, 0XC, 0X7, 0X6, 0X0,
41      0X9, 0XB}
42     ,
43     {0XE, 0XB, 0X4, 0XC, 0X6, 0XD, 0XF, 0XA, 0X2, 0X3, 0X8, 0X1, 0X0, 0X7,
44      0X5, 0X9}
45     ,
46     {0X4, 0XA, 0X9, 0X2, 0XD, 0X8, 0X0, 0XE, 0X6, 0XB, 0X1, 0XC, 0X7, 0XF,
47      0X5, 0X3}
48 };
49
50 /* Substitution blocks for hash function 1.2.643.2.9.1.6.1  */
51 gost_subst_block GostR3411_94_CryptoProParamSet = {
52     {0x1, 0x3, 0xA, 0x9, 0x5, 0xB, 0x4, 0xF, 0x8, 0x6, 0x7, 0xE, 0xD, 0x0,
53      0x2, 0xC}
54     ,
55     {0xD, 0xE, 0x4, 0x1, 0x7, 0x0, 0x5, 0xA, 0x3, 0xC, 0x8, 0xF, 0x6, 0x2,
56      0x9, 0xB}
57     ,
58     {0x7, 0x6, 0x2, 0x4, 0xD, 0x9, 0xF, 0x0, 0xA, 0x1, 0x5, 0xB, 0x8, 0xE,
59      0xC, 0x3}
60     ,
61     {0x7, 0x6, 0x4, 0xB, 0x9, 0xC, 0x2, 0xA, 0x1, 0x8, 0x0, 0xE, 0xF, 0xD,
62      0x3, 0x5}
63     ,
64     {0x4, 0xA, 0x7, 0xC, 0x0, 0xF, 0x2, 0x8, 0xE, 0x1, 0x6, 0x5, 0xD, 0xB,
65      0x9, 0x3}
66     ,
67     {0x7, 0xF, 0xC, 0xE, 0x9, 0x4, 0x1, 0x0, 0x3, 0xB, 0x5, 0x2, 0x6, 0xA,
68      0x8, 0xD}
69     ,
70     {0x5, 0xF, 0x4, 0x0, 0x2, 0xD, 0xB, 0x9, 0x1, 0x7, 0x6, 0x3, 0xC, 0xE,
71      0xA, 0x8}
72     ,
73     {0xA, 0x4, 0x5, 0x6, 0x8, 0x1, 0x3, 0x7, 0xD, 0xC, 0xE, 0x0, 0x9, 0x2,
74      0xB, 0xF}
75 };
76
77 /* Test paramset from GOST 28147 */
78 gost_subst_block Gost28147_TestParamSet = {
79     {0xC, 0x6, 0x5, 0x2, 0xB, 0x0, 0x9, 0xD, 0x3, 0xE, 0x7, 0xA, 0xF, 0x4,
80      0x1, 0x8}
81     ,
82     {0x9, 0xB, 0xC, 0x0, 0x3, 0x6, 0x7, 0x5, 0x4, 0x8, 0xE, 0xF, 0x1, 0xA,
83      0x2, 0xD}
84     ,
85     {0x8, 0xF, 0x6, 0xB, 0x1, 0x9, 0xC, 0x5, 0xD, 0x3, 0x7, 0xA, 0x0, 0xE,
86      0x2, 0x4}
87     ,
88     {0x3, 0xE, 0x5, 0x9, 0x6, 0x8, 0x0, 0xD, 0xA, 0xB, 0x7, 0xC, 0x2, 0x1,
89      0xF, 0x4}
90     ,
91     {0xE, 0x9, 0xB, 0x2, 0x5, 0xF, 0x7, 0x1, 0x0, 0xD, 0xC, 0x6, 0xA, 0x4,
92      0x3, 0x8}
93     ,
94     {0xD, 0x8, 0xE, 0xC, 0x7, 0x3, 0x9, 0xA, 0x1, 0x5, 0x2, 0x4, 0x6, 0xF,
95      0x0, 0xB}
96     ,
97     {0xC, 0x9, 0xF, 0xE, 0x8, 0x1, 0x3, 0xA, 0x2, 0x7, 0x4, 0xD, 0x6, 0x0,
98      0xB, 0x5}
99     ,
100     {0x4, 0x2, 0xF, 0x5, 0x9, 0x1, 0x0, 0x8, 0xE, 0x3, 0xB, 0xC, 0xD, 0x7,
101      0xA, 0x6}
102 };
103
104 /* 1.2.643.2.2.31.1 */
105 gost_subst_block Gost28147_CryptoProParamSetA = {
106     {0xB, 0xA, 0xF, 0x5, 0x0, 0xC, 0xE, 0x8, 0x6, 0x2, 0x3, 0x9, 0x1, 0x7,
107      0xD, 0x4}
108     ,
109     {0x1, 0xD, 0x2, 0x9, 0x7, 0xA, 0x6, 0x0, 0x8, 0xC, 0x4, 0x5, 0xF, 0x3,
110      0xB, 0xE}
111     ,
112     {0x3, 0xA, 0xD, 0xC, 0x1, 0x2, 0x0, 0xB, 0x7, 0x5, 0x9, 0x4, 0x8, 0xF,
113      0xE, 0x6}
114     ,
115     {0xB, 0x5, 0x1, 0x9, 0x8, 0xD, 0xF, 0x0, 0xE, 0x4, 0x2, 0x3, 0xC, 0x7,
116      0xA, 0x6}
117     ,
118     {0xE, 0x7, 0xA, 0xC, 0xD, 0x1, 0x3, 0x9, 0x0, 0x2, 0xB, 0x4, 0xF, 0x8,
119      0x5, 0x6}
120     ,
121     {0xE, 0x4, 0x6, 0x2, 0xB, 0x3, 0xD, 0x8, 0xC, 0xF, 0x5, 0xA, 0x0, 0x7,
122      0x1, 0x9}
123     ,
124     {0x3, 0x7, 0xE, 0x9, 0x8, 0xA, 0xF, 0x0, 0x5, 0x2, 0x6, 0xC, 0xB, 0x4,
125      0xD, 0x1}
126     ,
127     {0x9, 0x6, 0x3, 0x2, 0x8, 0xB, 0x1, 0x7, 0xA, 0x4, 0xE, 0xF, 0xC, 0x0,
128      0xD, 0x5}
129 };
130
131 /* 1.2.643.2.2.31.2 */
132 gost_subst_block Gost28147_CryptoProParamSetB = {
133     {0x0, 0x4, 0xB, 0xE, 0x8, 0x3, 0x7, 0x1, 0xA, 0x2, 0x9, 0x6, 0xF, 0xD,
134      0x5, 0xC}
135     ,
136     {0x5, 0x2, 0xA, 0xB, 0x9, 0x1, 0xC, 0x3, 0x7, 0x4, 0xD, 0x0, 0x6, 0xF,
137      0x8, 0xE}
138     ,
139     {0x8, 0x3, 0x2, 0x6, 0x4, 0xD, 0xE, 0xB, 0xC, 0x1, 0x7, 0xF, 0xA, 0x0,
140      0x9, 0x5}
141     ,
142     {0x2, 0x7, 0xC, 0xF, 0x9, 0x5, 0xA, 0xB, 0x1, 0x4, 0x0, 0xD, 0x6, 0x8,
143      0xE, 0x3}
144     ,
145     {0x7, 0x5, 0x0, 0xD, 0xB, 0x6, 0x1, 0x2, 0x3, 0xA, 0xC, 0xF, 0x4, 0xE,
146      0x9, 0x8}
147     ,
148     {0xE, 0xC, 0x0, 0xA, 0x9, 0x2, 0xD, 0xB, 0x7, 0x5, 0x8, 0xF, 0x3, 0x6,
149      0x1, 0x4}
150     ,
151     {0x0, 0x1, 0x2, 0xA, 0x4, 0xD, 0x5, 0xC, 0x9, 0x7, 0x3, 0xF, 0xB, 0x8,
152      0x6, 0xE}
153     ,
154     {0x8, 0x4, 0xB, 0x1, 0x3, 0x5, 0x0, 0x9, 0x2, 0xE, 0xA, 0xC, 0xD, 0x6,
155      0x7, 0xF}
156 };
157
158 /* 1.2.643.2.2.31.3 */
159 gost_subst_block Gost28147_CryptoProParamSetC = {
160     {0x7, 0x4, 0x0, 0x5, 0xA, 0x2, 0xF, 0xE, 0xC, 0x6, 0x1, 0xB, 0xD, 0x9,
161      0x3, 0x8}
162     ,
163     {0xA, 0x9, 0x6, 0x8, 0xD, 0xE, 0x2, 0x0, 0xF, 0x3, 0x5, 0xB, 0x4, 0x1,
164      0xC, 0x7}
165     ,
166     {0xC, 0x9, 0xB, 0x1, 0x8, 0xE, 0x2, 0x4, 0x7, 0x3, 0x6, 0x5, 0xA, 0x0,
167      0xF, 0xD}
168     ,
169     {0x8, 0xD, 0xB, 0x0, 0x4, 0x5, 0x1, 0x2, 0x9, 0x3, 0xC, 0xE, 0x6, 0xF,
170      0xA, 0x7}
171     ,
172     {0x3, 0x6, 0x0, 0x1, 0x5, 0xD, 0xA, 0x8, 0xB, 0x2, 0x9, 0x7, 0xE, 0xF,
173      0xC, 0x4}
174     ,
175     {0x8, 0x2, 0x5, 0x0, 0x4, 0x9, 0xF, 0xA, 0x3, 0x7, 0xC, 0xD, 0x6, 0xE,
176      0x1, 0xB}
177     ,
178     {0x0, 0x1, 0x7, 0xD, 0xB, 0x4, 0x5, 0x2, 0x8, 0xE, 0xF, 0xC, 0x9, 0xA,
179      0x6, 0x3}
180     ,
181     {0x1, 0xB, 0xC, 0x2, 0x9, 0xD, 0x0, 0xF, 0x4, 0x5, 0x8, 0xE, 0xA, 0x7,
182      0x6, 0x3}
183 };
184
185 /* 1.2.643.2.2.31.4 */
186 gost_subst_block Gost28147_CryptoProParamSetD = {
187     {0x1, 0xA, 0x6, 0x8, 0xF, 0xB, 0x0, 0x4, 0xC, 0x3, 0x5, 0x9, 0x7, 0xD,
188      0x2, 0xE}
189     ,
190     {0x3, 0x0, 0x6, 0xF, 0x1, 0xE, 0x9, 0x2, 0xD, 0x8, 0xC, 0x4, 0xB, 0xA,
191      0x5, 0x7}
192     ,
193     {0x8, 0x0, 0xF, 0x3, 0x2, 0x5, 0xE, 0xB, 0x1, 0xA, 0x4, 0x7, 0xC, 0x9,
194      0xD, 0x6}
195     ,
196     {0x0, 0xC, 0x8, 0x9, 0xD, 0x2, 0xA, 0xB, 0x7, 0x3, 0x6, 0x5, 0x4, 0xE,
197      0xF, 0x1}
198     ,
199     {0x1, 0x5, 0xE, 0xC, 0xA, 0x7, 0x0, 0xD, 0x6, 0x2, 0xB, 0x4, 0x9, 0x3,
200      0xF, 0x8}
201     ,
202     {0x1, 0xC, 0xB, 0x0, 0xF, 0xE, 0x6, 0x5, 0xA, 0xD, 0x4, 0x8, 0x9, 0x3,
203      0x7, 0x2}
204     ,
205     {0xB, 0x6, 0x3, 0x4, 0xC, 0xF, 0xE, 0x2, 0x7, 0xD, 0x8, 0x0, 0x5, 0xA,
206      0x9, 0x1}
207     ,
208     {0xF, 0xC, 0x2, 0xA, 0x6, 0x4, 0x5, 0x0, 0x7, 0x9, 0xE, 0xD, 0x1, 0xB,
209      0x8, 0x3}
210 };
211
212 /* 1.2.643.7.1.2.5.1.1 */
213 gost_subst_block Gost28147_TC26ParamSetZ = {
214     {0x1, 0x7, 0xe, 0xd, 0x0, 0x5, 0x8, 0x3, 0x4, 0xf, 0xa, 0x6, 0x9, 0xc,
215      0xb, 0x2}
216     ,
217     {0x8, 0xe, 0x2, 0x5, 0x6, 0x9, 0x1, 0xc, 0xf, 0x4, 0xb, 0x0, 0xd, 0xa,
218      0x3, 0x7}
219     ,
220     {0x5, 0xd, 0xf, 0x6, 0x9, 0x2, 0xc, 0xa, 0xb, 0x7, 0x8, 0x1, 0x4, 0x3,
221      0xe, 0x0}
222     ,
223     {0x7, 0xf, 0x5, 0xa, 0x8, 0x1, 0x6, 0xd, 0x0, 0x9, 0x3, 0xe, 0xb, 0x4,
224      0x2, 0xc}
225     ,
226     {0xc, 0x8, 0x2, 0x1, 0xd, 0x4, 0xf, 0x6, 0x7, 0x0, 0xa, 0x5, 0x3, 0xe,
227      0x9, 0xb}
228     ,
229     {0xb, 0x3, 0x5, 0x8, 0x2, 0xf, 0xa, 0xd, 0xe, 0x1, 0x7, 0x4, 0xc, 0x9,
230      0x6, 0x0}
231     ,
232     {0x6, 0x8, 0x2, 0x3, 0x9, 0xa, 0x5, 0xc, 0x1, 0xe, 0x4, 0x7, 0xb, 0xd,
233      0x0, 0xf}
234     ,
235     {0xc, 0x4, 0x6, 0x2, 0xa, 0x5, 0xb, 0x9, 0xe, 0x8, 0xd, 0x7, 0x0, 0x3,
236      0xf, 0x1}
237 };
238
239 const byte CryptoProKeyMeshingKey[] = {
240     0x69, 0x00, 0x72, 0x22, 0x64, 0xC9, 0x04, 0x23,
241     0x8D, 0x3A, 0xDB, 0x96, 0x46, 0xE9, 0x2A, 0xC4,
242     0x18, 0xFE, 0xAC, 0x94, 0x00, 0xED, 0x07, 0x12,
243     0xC0, 0x86, 0xDC, 0xC2, 0xEF, 0x4C, 0xA9, 0x2B
244 };
245
246 const byte ACPKM_D_const[] = {
247     0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
248     0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
249     0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
250     0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
251 };
252
253 /* Initialization of gost_ctx subst blocks*/
254 void kboxinit(gost_ctx * c, const gost_subst_block * b)
255 {
256     int i;
257
258     for (i = 0; i < 256; i++) {
259         c->k87[i] = (word32) (b->k8[i >> 4] << 4 | b->k7[i & 15]) << 24;
260         c->k65[i] = (b->k6[i >> 4] << 4 | b->k5[i & 15]) << 16;
261         c->k43[i] = (b->k4[i >> 4] << 4 | b->k3[i & 15]) << 8;
262         c->k21[i] = b->k2[i >> 4] << 4 | b->k1[i & 15];
263
264     }
265 }
266
267 /* Part of GOST 28147 algorithm moved into separate function */
268 static word32 f(gost_ctx * c, word32 x)
269 {
270     x = c->k87[x >> 24 & 255] | c->k65[x >> 16 & 255] |
271         c->k43[x >> 8 & 255] | c->k21[x & 255];
272     /* Rotate left 11 bits */
273     return x << 11 | x >> (32 - 11);
274 }
275
276 /* Low-level encryption routine - encrypts one 64 bit block*/
277 void gostcrypt(gost_ctx * c, const byte * in, byte * out)
278 {
279     register word32 n1, n2;     /* As named in the GOST */
280     n1 = in[0] | (in[1] << 8) | (in[2] << 16) | ((word32) in[3] << 24);
281     n2 = in[4] | (in[5] << 8) | (in[6] << 16) | ((word32) in[7] << 24);
282     /* Instead of swapping halves, swap names each round */
283
284     n2 ^= f(c, n1 + c->k[0]);
285     n1 ^= f(c, n2 + c->k[1]);
286     n2 ^= f(c, n1 + c->k[2]);
287     n1 ^= f(c, n2 + c->k[3]);
288     n2 ^= f(c, n1 + c->k[4]);
289     n1 ^= f(c, n2 + c->k[5]);
290     n2 ^= f(c, n1 + c->k[6]);
291     n1 ^= f(c, n2 + c->k[7]);
292
293     n2 ^= f(c, n1 + c->k[0]);
294     n1 ^= f(c, n2 + c->k[1]);
295     n2 ^= f(c, n1 + c->k[2]);
296     n1 ^= f(c, n2 + c->k[3]);
297     n2 ^= f(c, n1 + c->k[4]);
298     n1 ^= f(c, n2 + c->k[5]);
299     n2 ^= f(c, n1 + c->k[6]);
300     n1 ^= f(c, n2 + c->k[7]);
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     out[0] = (byte) (n2 & 0xff);
321     out[1] = (byte) ((n2 >> 8) & 0xff);
322     out[2] = (byte) ((n2 >> 16) & 0xff);
323     out[3] = (byte) (n2 >> 24);
324     out[4] = (byte) (n1 & 0xff);
325     out[5] = (byte) ((n1 >> 8) & 0xff);
326     out[6] = (byte) ((n1 >> 16) & 0xff);
327     out[7] = (byte) (n1 >> 24);
328 }
329
330 /* Low-level decryption routine. Decrypts one 64-bit block */
331 void gostdecrypt(gost_ctx * c, const byte * in, byte * out)
332 {
333     register word32 n1, n2;     /* As named in the GOST */
334     n1 = in[0] | (in[1] << 8) | (in[2] << 16) | ((word32) in[3] << 24);
335     n2 = in[4] | (in[5] << 8) | (in[6] << 16) | ((word32) in[7] << 24);
336
337     n2 ^= f(c, n1 + c->k[0]);
338     n1 ^= f(c, n2 + c->k[1]);
339     n2 ^= f(c, n1 + c->k[2]);
340     n1 ^= f(c, n2 + c->k[3]);
341     n2 ^= f(c, n1 + c->k[4]);
342     n1 ^= f(c, n2 + c->k[5]);
343     n2 ^= f(c, n1 + c->k[6]);
344     n1 ^= f(c, n2 + c->k[7]);
345
346     n2 ^= f(c, n1 + c->k[7]);
347     n1 ^= f(c, n2 + c->k[6]);
348     n2 ^= f(c, n1 + c->k[5]);
349     n1 ^= f(c, n2 + c->k[4]);
350     n2 ^= f(c, n1 + c->k[3]);
351     n1 ^= f(c, n2 + c->k[2]);
352     n2 ^= f(c, n1 + c->k[1]);
353     n1 ^= f(c, n2 + c->k[0]);
354
355     n2 ^= f(c, n1 + c->k[7]);
356     n1 ^= f(c, n2 + c->k[6]);
357     n2 ^= f(c, n1 + c->k[5]);
358     n1 ^= f(c, n2 + c->k[4]);
359     n2 ^= f(c, n1 + c->k[3]);
360     n1 ^= f(c, n2 + c->k[2]);
361     n2 ^= f(c, n1 + c->k[1]);
362     n1 ^= f(c, n2 + c->k[0]);
363
364     n2 ^= f(c, n1 + c->k[7]);
365     n1 ^= f(c, n2 + c->k[6]);
366     n2 ^= f(c, n1 + c->k[5]);
367     n1 ^= f(c, n2 + c->k[4]);
368     n2 ^= f(c, n1 + c->k[3]);
369     n1 ^= f(c, n2 + c->k[2]);
370     n2 ^= f(c, n1 + c->k[1]);
371     n1 ^= f(c, n2 + c->k[0]);
372
373     out[0] = (byte) (n2 & 0xff);
374     out[1] = (byte) ((n2 >> 8) & 0xff);
375     out[2] = (byte) ((n2 >> 16) & 0xff);
376     out[3] = (byte) (n2 >> 24);
377     out[4] = (byte) (n1 & 0xff);
378     out[5] = (byte) ((n1 >> 8) & 0xff);
379     out[6] = (byte) ((n1 >> 16) & 0xff);
380     out[7] = (byte) (n1 >> 24);
381 }
382
383 /* Encrypts several blocks in ECB mode */
384 void gost_enc(gost_ctx * c, const byte * clear, byte * cipher, int blocks)
385 {
386     int i;
387     for (i = 0; i < blocks; i++) {
388         gostcrypt(c, clear, cipher);
389         clear += 8;
390         cipher += 8;
391     }
392 }
393
394 /* Decrypts several blocks in ECB mode */
395 void gost_dec(gost_ctx * c, const byte * cipher, byte * clear, int blocks)
396 {
397     int i;
398     for (i = 0; i < blocks; i++) {
399         gostdecrypt(c, cipher, clear);
400         clear += 8;
401         cipher += 8;
402     }
403 }
404
405 /* Encrypts several full blocks in CFB mode using 8byte IV */
406 void gost_enc_cfb(gost_ctx * ctx, const byte * iv, const byte * clear,
407                   byte * cipher, int blocks)
408 {
409     byte cur_iv[8];
410     byte gamma[8];
411     int i, j;
412     const byte *in;
413     byte *out;
414     memcpy(cur_iv, iv, 8);
415     for (i = 0, in = clear, out = cipher; i < blocks; i++, in += 8, out += 8) {
416         gostcrypt(ctx, cur_iv, gamma);
417         for (j = 0; j < 8; j++) {
418             cur_iv[j] = out[j] = in[j] ^ gamma[j];
419         }
420     }
421 }
422
423 /* Decrypts several full blocks in CFB mode using 8byte IV */
424 void gost_dec_cfb(gost_ctx * ctx, const byte * iv, const byte * cipher,
425                   byte * clear, int blocks)
426 {
427     byte cur_iv[8];
428     byte gamma[8];
429     int i, j;
430     const byte *in;
431     byte *out;
432     memcpy(cur_iv, iv, 8);
433     for (i = 0, in = cipher, out = clear; i < blocks; i++, in += 8, out += 8) {
434         gostcrypt(ctx, cur_iv, gamma);
435         for (j = 0; j < 8; j++) {
436             out[j] = (cur_iv[j] = in[j]) ^ gamma[j];
437         }
438     }
439 }
440
441 /* Encrypts one block using specified key */
442 void gost_enc_with_key(gost_ctx * c, byte * key, byte * inblock,
443                        byte * outblock)
444 {
445     gost_key(c, key);
446     gostcrypt(c, inblock, outblock);
447 }
448
449 /* Set 256 bit gost89 key into context */
450 void gost_key(gost_ctx * c, const byte * k)
451 {
452     int i, j;
453     for (i = 0, j = 0; i < 8; i++, j += 4) {
454         c->k[i] =
455             k[j] | (k[j + 1] << 8) | (k[j + 2] << 16) | ((word32) k[j + 3] <<
456                                                          24);
457     }
458 }
459
460 /* Set 256 bit Magma key into context */
461 void magma_key(gost_ctx * c, const byte * k)
462 {
463     int i, j;
464     for (i = 0, j = 0; i < 8; i++, j += 4) {
465         c->k[i] =
466             k[j + 3] | (k[j + 2] << 8) | (k[j + 1] << 16) | ((word32) k[j] <<
467                                                              24);
468     }
469 }
470
471 /* Retrieve 256-bit gost89 key from context */
472 void gost_get_key(gost_ctx * c, byte * k)
473 {
474     int i, j;
475     for (i = 0, j = 0; i < 8; i++, j += 4) {
476         k[j] = (byte) (c->k[i] & 0xFF);
477         k[j + 1] = (byte) ((c->k[i] >> 8) & 0xFF);
478         k[j + 2] = (byte) ((c->k[i] >> 16) & 0xFF);
479         k[j + 3] = (byte) ((c->k[i] >> 24) & 0xFF);
480     }
481 }
482
483 /* Retrieve 256-bit magma key from context */
484 void magma_get_key(gost_ctx * c, byte * k)
485 {
486     int i, j;
487     for (i = 0, j = 0; i < 8; i++, j += 4) {
488         k[j + 3] = (byte) (c->k[i] & 0xFF);
489         k[j + 2] = (byte) ((c->k[i] >> 8) & 0xFF);
490         k[j + 1] = (byte) ((c->k[i] >> 16) & 0xFF);
491         k[j + 0] = (byte) ((c->k[i] >> 24) & 0xFF);
492     }
493 }
494
495 /* Initalize context. Provides default value for subst_block */
496 void gost_init(gost_ctx * c, const gost_subst_block * b)
497 {
498     if (!b) {
499         b = &GostR3411_94_TestParamSet;
500     }
501     kboxinit(c, b);
502 }
503
504 /* Cleans up key from context */
505 void gost_destroy(gost_ctx * c)
506 {
507     OPENSSL_cleanse(c->k, sizeof(c->k));
508 }
509
510 /*
511  * Compute GOST 28147 mac block Parameters gost_ctx *c - context initalized
512  * with substitution blocks and key buffer - 8-byte mac state buffer block
513  * 8-byte block to process.
514  */
515 void mac_block(gost_ctx * c, byte * buffer, const byte * block)
516 {
517     register word32 n1, n2;     /* As named in the GOST */
518     int i;
519     for (i = 0; i < 8; i++) {
520         buffer[i] ^= block[i];
521     }
522     n1 = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | ((word32)
523                                                              buffer[3] << 24);
524     n2 = buffer[4] | (buffer[5] << 8) | (buffer[6] << 16) | ((word32)
525                                                              buffer[7] << 24);
526     /* Instead of swapping halves, swap names each round */
527
528     n2 ^= f(c, n1 + c->k[0]);
529     n1 ^= f(c, n2 + c->k[1]);
530     n2 ^= f(c, n1 + c->k[2]);
531     n1 ^= f(c, n2 + c->k[3]);
532     n2 ^= f(c, n1 + c->k[4]);
533     n1 ^= f(c, n2 + c->k[5]);
534     n2 ^= f(c, n1 + c->k[6]);
535     n1 ^= f(c, n2 + c->k[7]);
536
537     n2 ^= f(c, n1 + c->k[0]);
538     n1 ^= f(c, n2 + c->k[1]);
539     n2 ^= f(c, n1 + c->k[2]);
540     n1 ^= f(c, n2 + c->k[3]);
541     n2 ^= f(c, n1 + c->k[4]);
542     n1 ^= f(c, n2 + c->k[5]);
543     n2 ^= f(c, n1 + c->k[6]);
544     n1 ^= f(c, n2 + c->k[7]);
545
546     buffer[0] = (byte) (n1 & 0xff);
547     buffer[1] = (byte) ((n1 >> 8) & 0xff);
548     buffer[2] = (byte) ((n1 >> 16) & 0xff);
549     buffer[3] = (byte) (n1 >> 24);
550     buffer[4] = (byte) (n2 & 0xff);
551     buffer[5] = (byte) ((n2 >> 8) & 0xff);
552     buffer[6] = (byte) ((n2 >> 16) & 0xff);
553     buffer[7] = (byte) (n2 >> 24);
554 }
555
556 /* Get mac with specified number of bits from MAC state buffer */
557 void get_mac(byte * buffer, int nbits, byte * out)
558 {
559     int nbytes = nbits >> 3;
560     int rembits = nbits & 7;
561     int mask = rembits ? ((1 < rembits) - 1) : 0;
562     int i;
563     for (i = 0; i < nbytes; i++)
564         out[i] = buffer[i];
565     if (rembits)
566         out[i] = buffer[i] & mask;
567 }
568
569 /*
570  * Compute mac of specified length (in bits) from data. Context should be
571  * initialized with key and subst blocks
572  */
573 int gost_mac(gost_ctx * ctx, int mac_len, const unsigned char *data,
574              unsigned int data_len, unsigned char *mac)
575 {
576     byte buffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
577     byte buf2[8];
578     unsigned int i;
579     for (i = 0; i + 8 <= data_len; i += 8)
580         mac_block(ctx, buffer, data + i);
581     if (i < data_len) {
582         memset(buf2, 0, 8);
583         memcpy(buf2, data + i, data_len - i);
584         mac_block(ctx, buffer, buf2);
585         i += 8;
586     }
587     if (i == 8) {
588         memset(buf2, 0, 8);
589         mac_block(ctx, buffer, buf2);
590     }
591     get_mac(buffer, mac_len, mac);
592     return 1;
593 }
594
595 /* Compute MAC with non-zero IV. Used in some RFC 4357 algorithms */
596 int gost_mac_iv(gost_ctx * ctx, int mac_len, const unsigned char *iv,
597                 const unsigned char *data, unsigned int data_len,
598                 unsigned char *mac)
599 {
600     byte buffer[8];
601     byte buf2[8];
602     unsigned int i;
603     memcpy(buffer, iv, 8);
604     for (i = 0; i + 8 <= data_len; i += 8)
605         mac_block(ctx, buffer, data + i);
606     if (i < data_len) {
607         memset(buf2, 0, 8);
608         memcpy(buf2, data + i, data_len - i);
609         mac_block(ctx, buffer, buf2);
610         i += 8;
611     }
612     if (i == 8) {
613         memset(buf2, 0, 8);
614         mac_block(ctx, buffer, buf2);
615     }
616     get_mac(buffer, mac_len, mac);
617     return 1;
618 }
619
620 /* Implements key meshing algorithm by modifing ctx and IV in place */
621 void cryptopro_key_meshing(gost_ctx * ctx, unsigned char *iv)
622 {
623     unsigned char newkey[32];
624     /* Set static keymeshing key */
625     /* "Decrypt" key with keymeshing key */
626     gost_dec(ctx, CryptoProKeyMeshingKey, newkey, 4);
627     /* set new key */
628     gost_key(ctx, newkey);
629     OPENSSL_cleanse(newkey, sizeof(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         OPENSSL_cleanse(newiv, sizeof(newiv));
636     }
637 }
638
639 void acpkm_magma_key_meshing(gost_ctx * ctx)
640 {
641     unsigned char newkey[32];
642     int i, j;
643
644     for (i = 0; i < 4; i++) {
645         unsigned char buf[8], keybuf[8];
646         for (j = 0; j < 8; j++) {
647             buf[j] = ACPKM_D_const[8 * i + 7 - j];
648         }
649         gostcrypt(ctx, buf, keybuf);
650         memcpy(newkey + 8 * i, keybuf + 4, 4);
651         memcpy(newkey + 8 * i + 4, keybuf, 4);
652         OPENSSL_cleanse(keybuf, sizeof(keybuf));
653         OPENSSL_cleanse(buf, sizeof(buf));
654     }
655     /* set new key */
656     gost_key(ctx, newkey);
657     OPENSSL_cleanse(newkey, sizeof(newkey));
658 }