]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost89.c
modernize ctrl function for magma & kuznechik TLS usage
[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 void magma_master_key(gost_ctx *c, const byte *k) {
488     memcpy(c->master_key, k, sizeof(c->master_key));
489 }
490
491 /* Retrieve 256-bit gost89 key from context */
492 void gost_get_key(gost_ctx * c, byte * k)
493 {
494     int i, j;
495     for (i = 0, j = 0; i < 8; i++, j += 4) {
496         k[j] = (byte)((c->key[i] + c->mask[i]) & 0xFF);
497         k[j+1] = (byte)(((c->key[i] + c->mask[i]) >> 8 )& 0xFF);
498         k[j+2] = (byte)(((c->key[i] + c->mask[i]) >> 16) & 0xFF);
499         k[j+3] = (byte)(((c->key[i] + c->mask[i]) >> 24) & 0xFF);
500     }
501 }
502
503 /* Retrieve 256-bit magma key from context */
504 void magma_get_key(gost_ctx * c, byte * k)
505 {
506     int i, j;
507     for (i = 0, j = 0; i < 8; i++, j += 4) {
508         k[j + 3] = (byte) ((c->key[i] + c->mask[i]) & 0xFF);
509         k[j + 2] = (byte) (((c->key[i] + c->mask[i]) >> 8) & 0xFF);
510         k[j + 1] = (byte) (((c->key[i] + c->mask[i]) >> 16) & 0xFF);
511         k[j + 0] = (byte) (((c->key[i] + c->mask[i]) >> 24) & 0xFF);
512     }
513 }
514
515 /* Initalize context. Provides default value for subst_block */
516 void gost_init(gost_ctx * c, const gost_subst_block * b)
517 {
518     if (!b) {
519         b = &GostR3411_94_TestParamSet;
520     }
521     kboxinit(c, b);
522 }
523
524 /* Cleans up key from context */
525 void gost_destroy(gost_ctx * c)
526 {
527     OPENSSL_cleanse(c->master_key, sizeof(c->master_key));
528     OPENSSL_cleanse(c->key, sizeof(c->key));
529     OPENSSL_cleanse(c->mask, sizeof(c->mask));
530 }
531
532 /*
533  * Compute GOST 28147 mac block Parameters gost_ctx *c - context initalized
534  * with substitution blocks and key buffer - 8-byte mac state buffer block
535  * 8-byte block to process.
536  */
537 void mac_block(gost_ctx * c, byte * buffer, const byte * block)
538 {
539     register word32 n1, n2;     /* As named in the GOST */
540     int i;
541     for (i = 0; i < 8; i++) {
542         buffer[i] ^= block[i];
543     }
544     n1 = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | ((word32)
545                                                              buffer[3] << 24);
546     n2 = buffer[4] | (buffer[5] << 8) | (buffer[6] << 16) | ((word32)
547                                                              buffer[7] << 24);
548     /* Instead of swapping halves, swap names each round */
549
550     n2 ^= f(c, n1 + c->key[0] + c->mask[0]);
551     n1 ^= f(c, n2 + c->key[1] + c->mask[1]);
552     n2 ^= f(c, n1 + c->key[2] + c->mask[2]);
553     n1 ^= f(c, n2 + c->key[3] + c->mask[3]);
554     n2 ^= f(c, n1 + c->key[4] + c->mask[4]);
555     n1 ^= f(c, n2 + c->key[5] + c->mask[5]);
556     n2 ^= f(c, n1 + c->key[6] + c->mask[6]);
557     n1 ^= f(c, n2 + c->key[7] + c->mask[7]);
558
559     n2 ^= f(c, n1 + c->key[0] + c->mask[0]);
560     n1 ^= f(c, n2 + c->key[1] + c->mask[1]);
561     n2 ^= f(c, n1 + c->key[2] + c->mask[2]);
562     n1 ^= f(c, n2 + c->key[3] + c->mask[3]);
563     n2 ^= f(c, n1 + c->key[4] + c->mask[4]);
564     n1 ^= f(c, n2 + c->key[5] + c->mask[5]);
565     n2 ^= f(c, n1 + c->key[6] + c->mask[6]);
566     n1 ^= f(c, n2 + c->key[7] + c->mask[7]);
567
568     buffer[0] = (byte) (n1 & 0xff);
569     buffer[1] = (byte) ((n1 >> 8) & 0xff);
570     buffer[2] = (byte) ((n1 >> 16) & 0xff);
571     buffer[3] = (byte) (n1 >> 24);
572     buffer[4] = (byte) (n2 & 0xff);
573     buffer[5] = (byte) ((n2 >> 8) & 0xff);
574     buffer[6] = (byte) ((n2 >> 16) & 0xff);
575     buffer[7] = (byte) (n2 >> 24);
576 }
577
578 /* Get mac with specified number of bits from MAC state buffer */
579 void get_mac(byte * buffer, int nbits, byte * out)
580 {
581     int nbytes = nbits >> 3;
582     int rembits = nbits & 7;
583     int mask = rembits ? ((1 < rembits) - 1) : 0;
584     int i;
585     for (i = 0; i < nbytes; i++)
586         out[i] = buffer[i];
587     if (rembits)
588         out[i] = buffer[i] & mask;
589 }
590
591 /*
592  * Compute mac of specified length (in bits) from data. Context should be
593  * initialized with key and subst blocks
594  */
595 int gost_mac(gost_ctx * ctx, int mac_len, const unsigned char *data,
596              unsigned int data_len, unsigned char *mac)
597 {
598     byte buffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
599     byte buf2[8];
600     unsigned int i;
601     for (i = 0; i + 8 <= data_len; i += 8)
602         mac_block(ctx, buffer, data + i);
603     if (i < data_len) {
604         memset(buf2, 0, 8);
605         memcpy(buf2, data + i, data_len - i);
606         mac_block(ctx, buffer, buf2);
607         i += 8;
608     }
609     if (i == 8) {
610         memset(buf2, 0, 8);
611         mac_block(ctx, buffer, buf2);
612     }
613     get_mac(buffer, mac_len, mac);
614     return 1;
615 }
616
617 /* Compute MAC with non-zero IV. Used in some RFC 4357 algorithms */
618 int gost_mac_iv(gost_ctx * ctx, int mac_len, const unsigned char *iv,
619                 const unsigned char *data, unsigned int data_len,
620                 unsigned char *mac)
621 {
622     byte buffer[8];
623     byte buf2[8];
624     unsigned int i;
625     memcpy(buffer, iv, 8);
626     for (i = 0; i + 8 <= data_len; i += 8)
627         mac_block(ctx, buffer, data + i);
628     if (i < data_len) {
629         memset(buf2, 0, 8);
630         memcpy(buf2, data + i, data_len - i);
631         mac_block(ctx, buffer, buf2);
632         i += 8;
633     }
634     if (i == 8) {
635         memset(buf2, 0, 8);
636         mac_block(ctx, buffer, buf2);
637     }
638     get_mac(buffer, mac_len, mac);
639     return 1;
640 }
641
642 /* Implements key meshing algorithm by modifing ctx and IV in place */
643 void cryptopro_key_meshing(gost_ctx * ctx, unsigned char *iv)
644 {
645     unsigned char newkey[32];
646     /* Set static keymeshing key */
647     /* "Decrypt" key with keymeshing key */
648     gost_dec(ctx, CryptoProKeyMeshingKey, newkey, 4);
649     /* set new key */
650     gost_key(ctx, newkey);
651     OPENSSL_cleanse(newkey, sizeof(newkey));
652     /* Encrypt iv with new key */
653     if (iv != NULL ) {
654         unsigned char newiv[8];
655         gostcrypt(ctx, iv, newiv);
656         memcpy(iv, newiv, 8);
657         OPENSSL_cleanse(newiv, sizeof(newiv));
658     }
659 }
660
661 void acpkm_magma_key_meshing(gost_ctx * ctx)
662 {
663     unsigned char newkey[32];
664     int i, j;
665
666     for (i = 0; i < 4; i++) {
667         unsigned char buf[8], keybuf[8];
668         for (j = 0; j < 8; j++) {
669             buf[j] = ACPKM_D_const[8 * i + 7 - j];
670         }
671         gostcrypt(ctx, buf, keybuf);
672         memcpy(newkey + 8 * i, keybuf + 4, 4);
673         memcpy(newkey + 8 * i + 4, keybuf, 4);
674         OPENSSL_cleanse(keybuf, sizeof(keybuf));
675         OPENSSL_cleanse(buf, sizeof(buf));
676     }
677     /* set new key */
678     gost_key(ctx, newkey);
679     OPENSSL_cleanse(newkey, sizeof(newkey));
680 }