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