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