]>
Commit | Line | Data |
---|---|---|
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*/ | |
23 | gost_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 |
50 | gost_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 |
77 | gost_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 |
104 | gost_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 |
131 | gost_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 |
158 | gost_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 */ | |
185 | gost_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 | ||
211 | const 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 |
219 | static 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 |
233 | static 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 |
242 | void 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 |
296 | void 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 |
349 | void 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 |
360 | void 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 |
371 | void 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 |
389 | void 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 |
407 | void 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 |
415 | void 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 |
426 | void 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 |
438 | void 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 |
447 | void 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 | */ | |
459 | void 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 |
501 | void 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 | */ | |
517 | int 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 |
540 | int 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 |
565 | void 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 | } |