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