/src/openssl/engines/ccgost/gost89.c
Line | Count | Source (jump to first uncovered line) |
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 "gost89.h" |
12 | | /*- |
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 |
17 | | examples given in RFC. |
18 | | |
19 | | |
20 | | */ |
21 | | |
22 | | /* Substitution blocks from test examples for GOST R 34.11-94*/ |
23 | | gost_subst_block GostR3411_94_TestParamSet = { |
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 | | |
49 | | /* Substitution blocks for hash function 1.2.643.2.9.1.6.1 */ |
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 | | }; |
75 | | |
76 | | /* Test paramset from GOST 28147 */ |
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 | | }; |
102 | | |
103 | | /* 1.2.643.2.2.31.1 */ |
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 | | |
130 | | /* 1.2.643.2.2.31.2 */ |
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 | | |
157 | | /* 1.2.643.2.2.31.3 */ |
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 | | |
218 | | /* Initialization of gost_ctx subst blocks*/ |
219 | | static void kboxinit(gost_ctx * c, const gost_subst_block * b) |
220 | 0 | { |
221 | 0 | int i; |
222 | |
|
223 | 0 | for (i = 0; i < 256; i++) { |
224 | 0 | c->k87[i] = (word32) (b->k8[i >> 4] << 4 | b->k7[i & 15]) << 24; |
225 | 0 | c->k65[i] = (b->k6[i >> 4] << 4 | b->k5[i & 15]) << 16; |
226 | 0 | c->k43[i] = (b->k4[i >> 4] << 4 | b->k3[i & 15]) << 8; |
227 | 0 | c->k21[i] = b->k2[i >> 4] << 4 | b->k1[i & 15]; |
228 | |
|
229 | 0 | } |
230 | 0 | } |
231 | | |
232 | | /* Part of GOST 28147 algorithm moved into separate function */ |
233 | | static word32 f(gost_ctx * c, word32 x) |
234 | 0 | { |
235 | 0 | x = c->k87[x >> 24 & 255] | c->k65[x >> 16 & 255] | |
236 | 0 | c->k43[x >> 8 & 255] | c->k21[x & 255]; |
237 | | /* Rotate left 11 bits */ |
238 | 0 | return x << 11 | x >> (32 - 11); |
239 | 0 | } |
240 | | |
241 | | /* Low-level encryption routine - encrypts one 64 bit block*/ |
242 | | void gostcrypt(gost_ctx * c, const byte * in, byte * out) |
243 | 0 | { |
244 | 0 | register word32 n1, n2; /* As named in the GOST */ |
245 | 0 | n1 = in[0] | (in[1] << 8) | (in[2] << 16) | ((word32) in[3] << 24); |
246 | 0 | n2 = in[4] | (in[5] << 8) | (in[6] << 16) | ((word32) in[7] << 24); |
247 | | /* Instead of swapping halves, swap names each round */ |
248 | |
|
249 | 0 | n2 ^= f(c, n1 + c->k[0]); |
250 | 0 | n1 ^= f(c, n2 + c->k[1]); |
251 | 0 | n2 ^= f(c, n1 + c->k[2]); |
252 | 0 | n1 ^= f(c, n2 + c->k[3]); |
253 | 0 | n2 ^= f(c, n1 + c->k[4]); |
254 | 0 | n1 ^= f(c, n2 + c->k[5]); |
255 | 0 | n2 ^= f(c, n1 + c->k[6]); |
256 | 0 | n1 ^= f(c, n2 + c->k[7]); |
257 | |
|
258 | 0 | n2 ^= f(c, n1 + c->k[0]); |
259 | 0 | n1 ^= f(c, n2 + c->k[1]); |
260 | 0 | n2 ^= f(c, n1 + c->k[2]); |
261 | 0 | n1 ^= f(c, n2 + c->k[3]); |
262 | 0 | n2 ^= f(c, n1 + c->k[4]); |
263 | 0 | n1 ^= f(c, n2 + c->k[5]); |
264 | 0 | n2 ^= f(c, n1 + c->k[6]); |
265 | 0 | n1 ^= f(c, n2 + c->k[7]); |
266 | |
|
267 | 0 | n2 ^= f(c, n1 + c->k[0]); |
268 | 0 | n1 ^= f(c, n2 + c->k[1]); |
269 | 0 | n2 ^= f(c, n1 + c->k[2]); |
270 | 0 | n1 ^= f(c, n2 + c->k[3]); |
271 | 0 | n2 ^= f(c, n1 + c->k[4]); |
272 | 0 | n1 ^= f(c, n2 + c->k[5]); |
273 | 0 | n2 ^= f(c, n1 + c->k[6]); |
274 | 0 | n1 ^= f(c, n2 + c->k[7]); |
275 | |
|
276 | 0 | n2 ^= f(c, n1 + c->k[7]); |
277 | 0 | n1 ^= f(c, n2 + c->k[6]); |
278 | 0 | n2 ^= f(c, n1 + c->k[5]); |
279 | 0 | n1 ^= f(c, n2 + c->k[4]); |
280 | 0 | n2 ^= f(c, n1 + c->k[3]); |
281 | 0 | n1 ^= f(c, n2 + c->k[2]); |
282 | 0 | n2 ^= f(c, n1 + c->k[1]); |
283 | 0 | n1 ^= f(c, n2 + c->k[0]); |
284 | |
|
285 | 0 | out[0] = (byte) (n2 & 0xff); |
286 | 0 | out[1] = (byte) ((n2 >> 8) & 0xff); |
287 | 0 | out[2] = (byte) ((n2 >> 16) & 0xff); |
288 | 0 | out[3] = (byte) (n2 >> 24); |
289 | 0 | out[4] = (byte) (n1 & 0xff); |
290 | 0 | out[5] = (byte) ((n1 >> 8) & 0xff); |
291 | 0 | out[6] = (byte) ((n1 >> 16) & 0xff); |
292 | 0 | out[7] = (byte) (n1 >> 24); |
293 | 0 | } |
294 | | |
295 | | /* Low-level decryption routine. Decrypts one 64-bit block */ |
296 | | void gostdecrypt(gost_ctx * c, const byte * in, byte * out) |
297 | 0 | { |
298 | 0 | register word32 n1, n2; /* As named in the GOST */ |
299 | 0 | n1 = in[0] | (in[1] << 8) | (in[2] << 16) | ((word32) in[3] << 24); |
300 | 0 | n2 = in[4] | (in[5] << 8) | (in[6] << 16) | ((word32) in[7] << 24); |
301 | |
|
302 | 0 | n2 ^= f(c, n1 + c->k[0]); |
303 | 0 | n1 ^= f(c, n2 + c->k[1]); |
304 | 0 | n2 ^= f(c, n1 + c->k[2]); |
305 | 0 | n1 ^= f(c, n2 + c->k[3]); |
306 | 0 | n2 ^= f(c, n1 + c->k[4]); |
307 | 0 | n1 ^= f(c, n2 + c->k[5]); |
308 | 0 | n2 ^= f(c, n1 + c->k[6]); |
309 | 0 | n1 ^= f(c, n2 + c->k[7]); |
310 | |
|
311 | 0 | n2 ^= f(c, n1 + c->k[7]); |
312 | 0 | n1 ^= f(c, n2 + c->k[6]); |
313 | 0 | n2 ^= f(c, n1 + c->k[5]); |
314 | 0 | n1 ^= f(c, n2 + c->k[4]); |
315 | 0 | n2 ^= f(c, n1 + c->k[3]); |
316 | 0 | n1 ^= f(c, n2 + c->k[2]); |
317 | 0 | n2 ^= f(c, n1 + c->k[1]); |
318 | 0 | n1 ^= f(c, n2 + c->k[0]); |
319 | |
|
320 | 0 | n2 ^= f(c, n1 + c->k[7]); |
321 | 0 | n1 ^= f(c, n2 + c->k[6]); |
322 | 0 | n2 ^= f(c, n1 + c->k[5]); |
323 | 0 | n1 ^= f(c, n2 + c->k[4]); |
324 | 0 | n2 ^= f(c, n1 + c->k[3]); |
325 | 0 | n1 ^= f(c, n2 + c->k[2]); |
326 | 0 | n2 ^= f(c, n1 + c->k[1]); |
327 | 0 | n1 ^= f(c, n2 + c->k[0]); |
328 | |
|
329 | 0 | n2 ^= f(c, n1 + c->k[7]); |
330 | 0 | n1 ^= f(c, n2 + c->k[6]); |
331 | 0 | n2 ^= f(c, n1 + c->k[5]); |
332 | 0 | n1 ^= f(c, n2 + c->k[4]); |
333 | 0 | n2 ^= f(c, n1 + c->k[3]); |
334 | 0 | n1 ^= f(c, n2 + c->k[2]); |
335 | 0 | n2 ^= f(c, n1 + c->k[1]); |
336 | 0 | n1 ^= f(c, n2 + c->k[0]); |
337 | |
|
338 | 0 | out[0] = (byte) (n2 & 0xff); |
339 | 0 | out[1] = (byte) ((n2 >> 8) & 0xff); |
340 | 0 | out[2] = (byte) ((n2 >> 16) & 0xff); |
341 | 0 | out[3] = (byte) (n2 >> 24); |
342 | 0 | out[4] = (byte) (n1 & 0xff); |
343 | 0 | out[5] = (byte) ((n1 >> 8) & 0xff); |
344 | 0 | out[6] = (byte) ((n1 >> 16) & 0xff); |
345 | 0 | out[7] = (byte) (n1 >> 24); |
346 | 0 | } |
347 | | |
348 | | /* Encrypts several blocks in ECB mode */ |
349 | | void gost_enc(gost_ctx * c, const byte * clear, byte * cipher, int blocks) |
350 | 0 | { |
351 | 0 | int i; |
352 | 0 | for (i = 0; i < blocks; i++) { |
353 | 0 | gostcrypt(c, clear, cipher); |
354 | 0 | clear += 8; |
355 | 0 | cipher += 8; |
356 | 0 | } |
357 | 0 | } |
358 | | |
359 | | /* Decrypts several blocks in ECB mode */ |
360 | | void gost_dec(gost_ctx * c, const byte * cipher, byte * clear, int blocks) |
361 | 0 | { |
362 | 0 | int i; |
363 | 0 | for (i = 0; i < blocks; i++) { |
364 | 0 | gostdecrypt(c, cipher, clear); |
365 | 0 | clear += 8; |
366 | 0 | cipher += 8; |
367 | 0 | } |
368 | 0 | } |
369 | | |
370 | | /* Encrypts several full blocks in CFB mode using 8byte IV */ |
371 | | void gost_enc_cfb(gost_ctx * ctx, const byte * iv, const byte * clear, |
372 | | byte * cipher, int blocks) |
373 | 0 | { |
374 | 0 | byte cur_iv[8]; |
375 | 0 | byte gamma[8]; |
376 | 0 | int i, j; |
377 | 0 | const byte *in; |
378 | 0 | byte *out; |
379 | 0 | memcpy(cur_iv, iv, 8); |
380 | 0 | for (i = 0, in = clear, out = cipher; i < blocks; i++, in += 8, out += 8) { |
381 | 0 | gostcrypt(ctx, cur_iv, gamma); |
382 | 0 | for (j = 0; j < 8; j++) { |
383 | 0 | cur_iv[j] = out[j] = in[j] ^ gamma[j]; |
384 | 0 | } |
385 | 0 | } |
386 | 0 | } |
387 | | |
388 | | /* Decrypts several full blocks in CFB mode using 8byte IV */ |
389 | | void gost_dec_cfb(gost_ctx * ctx, const byte * iv, const byte * cipher, |
390 | | byte * clear, int blocks) |
391 | 0 | { |
392 | 0 | byte cur_iv[8]; |
393 | 0 | byte gamma[8]; |
394 | 0 | int i, j; |
395 | 0 | const byte *in; |
396 | 0 | byte *out; |
397 | 0 | memcpy(cur_iv, iv, 8); |
398 | 0 | for (i = 0, in = cipher, out = clear; i < blocks; i++, in += 8, out += 8) { |
399 | 0 | gostcrypt(ctx, cur_iv, gamma); |
400 | 0 | for (j = 0; j < 8; j++) { |
401 | 0 | out[j] = (cur_iv[j] = in[j]) ^ gamma[j]; |
402 | 0 | } |
403 | 0 | } |
404 | 0 | } |
405 | | |
406 | | /* Encrypts one block using specified key */ |
407 | | void gost_enc_with_key(gost_ctx * c, byte * key, byte * inblock, |
408 | | byte * outblock) |
409 | 0 | { |
410 | 0 | gost_key(c, key); |
411 | 0 | gostcrypt(c, inblock, outblock); |
412 | 0 | } |
413 | | |
414 | | /* Set 256 bit key into context */ |
415 | | void gost_key(gost_ctx * c, const byte * k) |
416 | 0 | { |
417 | 0 | int i, j; |
418 | 0 | for (i = 0, j = 0; i < 8; i++, j += 4) { |
419 | 0 | c->k[i] = |
420 | 0 | k[j] | (k[j + 1] << 8) | (k[j + 2] << 16) | ((word32) k[j + 3] << |
421 | 0 | 24); |
422 | 0 | } |
423 | 0 | } |
424 | | |
425 | | /* Retrieve 256-bit key from context */ |
426 | | void gost_get_key(gost_ctx * c, byte * k) |
427 | 0 | { |
428 | 0 | int i, j; |
429 | 0 | for (i = 0, j = 0; i < 8; i++, j += 4) { |
430 | 0 | k[j] = (byte) (c->k[i] & 0xFF); |
431 | 0 | k[j + 1] = (byte) ((c->k[i] >> 8) & 0xFF); |
432 | 0 | k[j + 2] = (byte) ((c->k[i] >> 16) & 0xFF); |
433 | 0 | k[j + 3] = (byte) ((c->k[i] >> 24) & 0xFF); |
434 | 0 | } |
435 | 0 | } |
436 | | |
437 | | /* Initalize context. Provides default value for subst_block */ |
438 | | void gost_init(gost_ctx * c, const gost_subst_block * b) |
439 | 0 | { |
440 | 0 | if (!b) { |
441 | 0 | b = &GostR3411_94_TestParamSet; |
442 | 0 | } |
443 | 0 | kboxinit(c, b); |
444 | 0 | } |
445 | | |
446 | | /* Cleans up key from context */ |
447 | | void gost_destroy(gost_ctx * c) |
448 | 0 | { |
449 | 0 | int i; |
450 | 0 | for (i = 0; i < 8; i++) |
451 | 0 | c->k[i] = 0; |
452 | 0 | } |
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 | 0 | { |
461 | 0 | register word32 n1, n2; /* As named in the GOST */ |
462 | 0 | int i; |
463 | 0 | for (i = 0; i < 8; i++) { |
464 | 0 | buffer[i] ^= block[i]; |
465 | 0 | } |
466 | 0 | n1 = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | ((word32) |
467 | 0 | buffer[3] << 24); |
468 | 0 | n2 = buffer[4] | (buffer[5] << 8) | (buffer[6] << 16) | ((word32) |
469 | 0 | buffer[7] << 24); |
470 | | /* Instead of swapping halves, swap names each round */ |
471 | |
|
472 | 0 | n2 ^= f(c, n1 + c->k[0]); |
473 | 0 | n1 ^= f(c, n2 + c->k[1]); |
474 | 0 | n2 ^= f(c, n1 + c->k[2]); |
475 | 0 | n1 ^= f(c, n2 + c->k[3]); |
476 | 0 | n2 ^= f(c, n1 + c->k[4]); |
477 | 0 | n1 ^= f(c, n2 + c->k[5]); |
478 | 0 | n2 ^= f(c, n1 + c->k[6]); |
479 | 0 | n1 ^= f(c, n2 + c->k[7]); |
480 | |
|
481 | 0 | n2 ^= f(c, n1 + c->k[0]); |
482 | 0 | n1 ^= f(c, n2 + c->k[1]); |
483 | 0 | n2 ^= f(c, n1 + c->k[2]); |
484 | 0 | n1 ^= f(c, n2 + c->k[3]); |
485 | 0 | n2 ^= f(c, n1 + c->k[4]); |
486 | 0 | n1 ^= f(c, n2 + c->k[5]); |
487 | 0 | n2 ^= f(c, n1 + c->k[6]); |
488 | 0 | n1 ^= f(c, n2 + c->k[7]); |
489 | |
|
490 | 0 | buffer[0] = (byte) (n1 & 0xff); |
491 | 0 | buffer[1] = (byte) ((n1 >> 8) & 0xff); |
492 | 0 | buffer[2] = (byte) ((n1 >> 16) & 0xff); |
493 | 0 | buffer[3] = (byte) (n1 >> 24); |
494 | 0 | buffer[4] = (byte) (n2 & 0xff); |
495 | 0 | buffer[5] = (byte) ((n2 >> 8) & 0xff); |
496 | 0 | buffer[6] = (byte) ((n2 >> 16) & 0xff); |
497 | 0 | buffer[7] = (byte) (n2 >> 24); |
498 | 0 | } |
499 | | |
500 | | /* Get mac with specified number of bits from MAC state buffer */ |
501 | | void get_mac(byte * buffer, int nbits, byte * out) |
502 | 0 | { |
503 | 0 | int nbytes = nbits >> 3; |
504 | 0 | int rembits = nbits & 7; |
505 | 0 | int mask = rembits ? ((1 < rembits) - 1) : 0; |
506 | 0 | int i; |
507 | 0 | for (i = 0; i < nbytes; i++) |
508 | 0 | out[i] = buffer[i]; |
509 | 0 | if (rembits) |
510 | 0 | out[i] = buffer[i] & mask; |
511 | 0 | } |
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 | 0 | { |
520 | 0 | byte buffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; |
521 | 0 | byte buf2[8]; |
522 | 0 | unsigned int i; |
523 | 0 | for (i = 0; i + 8 <= data_len; i += 8) |
524 | 0 | mac_block(ctx, buffer, data + i); |
525 | 0 | if (i < data_len) { |
526 | 0 | memset(buf2, 0, 8); |
527 | 0 | memcpy(buf2, data + i, data_len - i); |
528 | 0 | mac_block(ctx, buffer, buf2); |
529 | 0 | i += 8; |
530 | 0 | } |
531 | 0 | if (i == 8) { |
532 | 0 | memset(buf2, 0, 8); |
533 | 0 | mac_block(ctx, buffer, buf2); |
534 | 0 | } |
535 | 0 | get_mac(buffer, mac_len, mac); |
536 | 0 | return 1; |
537 | 0 | } |
538 | | |
539 | | /* Compute MAC with non-zero IV. Used in some RFC 4357 algorithms */ |
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 | 0 | { |
544 | 0 | byte buffer[8]; |
545 | 0 | byte buf2[8]; |
546 | 0 | unsigned int i; |
547 | 0 | memcpy(buffer, iv, 8); |
548 | 0 | for (i = 0; i + 8 <= data_len; i += 8) |
549 | 0 | mac_block(ctx, buffer, data + i); |
550 | 0 | if (i < data_len) { |
551 | 0 | memset(buf2, 0, 8); |
552 | 0 | memcpy(buf2, data + i, data_len - i); |
553 | 0 | mac_block(ctx, buffer, buf2); |
554 | 0 | i += 8; |
555 | 0 | } |
556 | 0 | if (i == 8) { |
557 | 0 | memset(buf2, 0, 8); |
558 | 0 | mac_block(ctx, buffer, buf2); |
559 | 0 | } |
560 | 0 | get_mac(buffer, mac_len, mac); |
561 | 0 | return 1; |
562 | 0 | } |
563 | | |
564 | | /* Implements key meshing algorithm by modifing ctx and IV in place */ |
565 | | void cryptopro_key_meshing(gost_ctx * ctx, unsigned char *iv) |
566 | 0 | { |
567 | 0 | unsigned char newkey[32], newiv[8]; |
568 | | /* Set static keymeshing key */ |
569 | | /* "Decrypt" key with keymeshing key */ |
570 | 0 | gost_dec(ctx, CryptoProKeyMeshingKey, newkey, 4); |
571 | | /* set new key */ |
572 | 0 | gost_key(ctx, newkey); |
573 | | /* Encrypt iv with new key */ |
574 | 0 | gostcrypt(ctx, iv, newiv); |
575 | 0 | memcpy(iv, newiv, 8); |
576 | 0 | } |