1 /* $OpenBSD: gost2814789.c,v 1.5 2015/09/10 15:56:25 jsing Exp $ */
2 /*
3  * Copyright (c) 2014 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
4  * Copyright (c) 2005-2006 Cryptocom LTD
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  *
18  * 3. All advertising materials mentioning features or use of this
19  *    software must display the following acknowledgment:
20  *    "This product includes software developed by the OpenSSL Project
21  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
22  *
23  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
24  *    endorse or promote products derived from this software without
25  *    prior written permission. For written permission, please contact
26  *    openssl-core@openssl.org.
27  *
28  * 5. Products derived from this software may not be called "OpenSSL"
29  *    nor may "OpenSSL" appear in their names without prior written
30  *    permission of the OpenSSL Project.
31  *
32  * 6. Redistributions of any form whatsoever must retain the following
33  *    acknowledgment:
34  *    "This product includes software developed by the OpenSSL Project
35  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
36  *
37  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
38  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
40  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
41  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
43  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
44  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
46  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
47  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
48  * OF THE POSSIBILITY OF SUCH DAMAGE.
49  * ====================================================================
50  */
51 
52 #include <string.h>
53 
54 #include <openssl/opensslconf.h>
55 
56 #ifndef OPENSSL_NO_GOST
57 #include <openssl/objects.h>
58 #include <openssl/gost.h>
59 
60 #include "gost_locl.h"
61 
62 static inline unsigned int
63 f(const GOST2814789_KEY *c, unsigned int x)
64 {
65 	return  c->k87[(x>>24) & 255] | c->k65[(x>>16) & 255]|
66 		c->k43[(x>> 8) & 255] | c->k21[(x    ) & 255];
67 }
68 
69 void
70 Gost2814789_encrypt(const unsigned char *in, unsigned char *out,
71     const GOST2814789_KEY *key)
72 {
73 	unsigned int n1, n2; /* As named in the GOST */
74 
75 	c2l(in, n1);
76 	c2l(in, n2);
77 
78 	/* Instead of swapping halves, swap names each round */
79 	n2 ^= f(key, n1 + key->key[0]); n1 ^= f(key, n2 + key->key[1]);
80 	n2 ^= f(key, n1 + key->key[2]); n1 ^= f(key, n2 + key->key[3]);
81 	n2 ^= f(key, n1 + key->key[4]); n1 ^= f(key, n2 + key->key[5]);
82 	n2 ^= f(key, n1 + key->key[6]); n1 ^= f(key, n2 + key->key[7]);
83 
84 	n2 ^= f(key, n1 + key->key[0]); n1 ^= f(key, n2 + key->key[1]);
85 	n2 ^= f(key, n1 + key->key[2]); n1 ^= f(key, n2 + key->key[3]);
86 	n2 ^= f(key, n1 + key->key[4]); n1 ^= f(key, n2 + key->key[5]);
87 	n2 ^= f(key, n1 + key->key[6]); n1 ^= f(key, n2 + key->key[7]);
88 
89 	n2 ^= f(key, n1 + key->key[0]); n1 ^= f(key, n2 + key->key[1]);
90 	n2 ^= f(key, n1 + key->key[2]); n1 ^= f(key, n2 + key->key[3]);
91 	n2 ^= f(key, n1 + key->key[4]); n1 ^= f(key, n2 + key->key[5]);
92 	n2 ^= f(key, n1 + key->key[6]); n1 ^= f(key, n2 + key->key[7]);
93 
94 	n2 ^= f(key, n1 + key->key[7]); n1 ^= f(key, n2 + key->key[6]);
95 	n2 ^= f(key, n1 + key->key[5]); n1 ^= f(key, n2 + key->key[4]);
96 	n2 ^= f(key, n1 + key->key[3]); n1 ^= f(key, n2 + key->key[2]);
97 	n2 ^= f(key, n1 + key->key[1]); n1 ^= f(key, n2 + key->key[0]);
98 
99 	l2c(n2, out);
100 	l2c(n1, out);
101 }
102 
103 void
104 Gost2814789_decrypt(const unsigned char *in, unsigned char *out,
105     const GOST2814789_KEY *key)
106 {
107 	unsigned int n1, n2; /* As named in the GOST */
108 
109 	c2l(in, n1);
110 	c2l(in, n2);
111 
112 	/* Instead of swapping halves, swap names each round */
113 	n2 ^= f(key, n1 + key->key[0]); n1 ^= f(key, n2 + key->key[1]);
114 	n2 ^= f(key, n1 + key->key[2]); n1 ^= f(key, n2 + key->key[3]);
115 	n2 ^= f(key, n1 + key->key[4]); n1 ^= f(key, n2 + key->key[5]);
116 	n2 ^= f(key, n1 + key->key[6]); n1 ^= f(key, n2 + key->key[7]);
117 
118 	n2 ^= f(key, n1 + key->key[7]); n1 ^= f(key, n2 + key->key[6]);
119 	n2 ^= f(key, n1 + key->key[5]); n1 ^= f(key, n2 + key->key[4]);
120 	n2 ^= f(key, n1 + key->key[3]); n1 ^= f(key, n2 + key->key[2]);
121 	n2 ^= f(key, n1 + key->key[1]); n1 ^= f(key, n2 + key->key[0]);
122 
123 	n2 ^= f(key, n1 + key->key[7]); n1 ^= f(key, n2 + key->key[6]);
124 	n2 ^= f(key, n1 + key->key[5]); n1 ^= f(key, n2 + key->key[4]);
125 	n2 ^= f(key, n1 + key->key[3]); n1 ^= f(key, n2 + key->key[2]);
126 	n2 ^= f(key, n1 + key->key[1]); n1 ^= f(key, n2 + key->key[0]);
127 
128 	n2 ^= f(key, n1 + key->key[7]); n1 ^= f(key, n2 + key->key[6]);
129 	n2 ^= f(key, n1 + key->key[5]); n1 ^= f(key, n2 + key->key[4]);
130 	n2 ^= f(key, n1 + key->key[3]); n1 ^= f(key, n2 + key->key[2]);
131 	n2 ^= f(key, n1 + key->key[1]); n1 ^= f(key, n2 + key->key[0]);
132 
133 	l2c(n2, out);
134 	l2c(n1, out);
135 }
136 
137 static void
138 Gost2814789_mac(const unsigned char *in, unsigned char *mac,
139     GOST2814789_KEY *key)
140 {
141 	unsigned int n1, n2; /* As named in the GOST */
142 	unsigned char *p;
143 	int i;
144 
145 	for (i = 0; i < 8; i++)
146 		mac[i] ^= in[i];
147 
148 	p = mac;
149 	c2l(p, n1);
150 	c2l(p, n2);
151 
152 	/* Instead of swapping halves, swap names each round */
153 	n2 ^= f(key, n1 + key->key[0]); n1 ^= f(key, n2 + key->key[1]);
154 	n2 ^= f(key, n1 + key->key[2]); n1 ^= f(key, n2 + key->key[3]);
155 	n2 ^= f(key, n1 + key->key[4]); n1 ^= f(key, n2 + key->key[5]);
156 	n2 ^= f(key, n1 + key->key[6]); n1 ^= f(key, n2 + key->key[7]);
157 
158 	n2 ^= f(key, n1 + key->key[0]); n1 ^= f(key, n2 + key->key[1]);
159 	n2 ^= f(key, n1 + key->key[2]); n1 ^= f(key, n2 + key->key[3]);
160 	n2 ^= f(key, n1 + key->key[4]); n1 ^= f(key, n2 + key->key[5]);
161 	n2 ^= f(key, n1 + key->key[6]); n1 ^= f(key, n2 + key->key[7]);
162 
163 	p = mac;
164 	l2c(n1, p);
165 	l2c(n2, p);
166 }
167 
168 void
169 Gost2814789_ecb_encrypt(const unsigned char *in, unsigned char *out,
170     GOST2814789_KEY *key, const int enc)
171 {
172 	if (key->key_meshing && key->count == 1024) {
173 		Gost2814789_cryptopro_key_mesh(key);
174 		key->count = 0;
175 	}
176 
177 	if (enc)
178 		Gost2814789_encrypt(in, out, key);
179 	else
180 		Gost2814789_decrypt(in, out, key);
181 }
182 
183 static inline void
184 Gost2814789_encrypt_mesh(unsigned char *iv, GOST2814789_KEY *key)
185 {
186 	if (key->key_meshing && key->count == 1024) {
187 		Gost2814789_cryptopro_key_mesh(key);
188 		Gost2814789_encrypt(iv, iv, key);
189 		key->count = 0;
190 	}
191 	Gost2814789_encrypt(iv, iv, key);
192 	key->count += 8;
193 }
194 
195 static inline void
196 Gost2814789_mac_mesh(const unsigned char *data, unsigned char *mac,
197     GOST2814789_KEY *key)
198 {
199 	if (key->key_meshing && key->count == 1024) {
200 		Gost2814789_cryptopro_key_mesh(key);
201 		key->count = 0;
202 	}
203 	Gost2814789_mac(data, mac, key);
204 	key->count += 8;
205 }
206 
207 void
208 Gost2814789_cfb64_encrypt(const unsigned char *in, unsigned char *out,
209     size_t len, GOST2814789_KEY *key, unsigned char *ivec, int *num,
210     const int enc)
211 {
212 	unsigned int n;
213 	size_t l = 0;
214 
215 	n = *num;
216 
217 	if (enc) {
218 #if !defined(OPENSSL_SMALL_FOOTPRINT)
219 		if (8 % sizeof(size_t) == 0) do { /* always true actually */
220 			while (n && len) {
221 				*(out++) = ivec[n] ^= *(in++);
222 				--len;
223 				n = (n + 1) % 8;
224 			}
225 #ifdef __STRICT_ALIGNMENT
226 			if (((size_t)in | (size_t)out | (size_t)ivec) %
227 			    sizeof(size_t) != 0)
228 				break;
229 #endif
230 			while (len >= 8) {
231 				Gost2814789_encrypt_mesh(ivec, key);
232 				for (; n < 8; n += sizeof(size_t)) {
233 					*(size_t*)(out + n) =
234 					*(size_t*)(ivec + n) ^=
235 					    *(size_t*)(in + n);
236 				}
237 				len -= 8;
238 				out += 8;
239 				in  += 8;
240 				n = 0;
241 			}
242 			if (len) {
243 				Gost2814789_encrypt_mesh(ivec, key);
244 				while (len--) {
245 					out[n] = ivec[n] ^= in[n];
246 					++n;
247 				}
248 			}
249 			*num = n;
250 			return;
251 		} while (0);
252 		/* the rest would be commonly eliminated by x86* compiler */
253 #endif
254 		while (l<len) {
255 			if (n == 0) {
256 				Gost2814789_encrypt_mesh(ivec, key);
257 			}
258 			out[l] = ivec[n] ^= in[l];
259 			++l;
260 			n = (n + 1) % 8;
261 		}
262 		*num = n;
263 	} else {
264 #if !defined(OPENSSL_SMALL_FOOTPRINT)
265 		if (8 % sizeof(size_t) == 0) do { /* always true actually */
266 			while (n && len) {
267 				unsigned char c;
268 
269 				*(out++) = ivec[n] ^ (c = *(in++));
270 				ivec[n] = c;
271 				--len;
272 				n = (n + 1) % 8;
273  			}
274 #ifdef __STRICT_ALIGNMENT
275 			if (((size_t)in | (size_t)out | (size_t)ivec) %
276 			    sizeof(size_t) != 0)
277 				break;
278 #endif
279 			while (len >= 8) {
280 				Gost2814789_encrypt_mesh(ivec, key);
281 				for (; n < 8; n += sizeof(size_t)) {
282 					size_t t = *(size_t*)(in + n);
283 					*(size_t*)(out + n) =
284 					    *(size_t*)(ivec + n) ^ t;
285 					*(size_t*)(ivec + n) = t;
286 				}
287 				len -= 8;
288 				out += 8;
289 				in  += 8;
290 				n = 0;
291 			}
292 			if (len) {
293 				Gost2814789_encrypt_mesh(ivec, key);
294 				while (len--) {
295 					unsigned char c;
296 
297 					out[n] = ivec[n] ^ (c = in[n]);
298 					ivec[n] = c;
299 					++n;
300 				}
301  			}
302 			*num = n;
303 			return;
304 		} while (0);
305 		/* the rest would be commonly eliminated by x86* compiler */
306 #endif
307 		while (l < len) {
308 			unsigned char c;
309 
310 			if (n == 0) {
311 				Gost2814789_encrypt_mesh(ivec, key);
312 			}
313 			out[l] = ivec[n] ^ (c = in[l]); ivec[n] = c;
314 			++l;
315 			n = (n + 1) % 8;
316 		}
317 		*num = n;
318 	}
319 }
320 
321 static inline void
322 Gost2814789_cnt_next(unsigned char *ivec, unsigned char *out,
323     GOST2814789_KEY *key)
324 {
325 	unsigned char *p = ivec, *p2 = ivec;
326 	unsigned int val, val2;
327 
328 	if (key->count == 0)
329 		Gost2814789_encrypt(ivec, ivec, key);
330 
331 	if (key->key_meshing && key->count == 1024) {
332 		Gost2814789_cryptopro_key_mesh(key);
333 		Gost2814789_encrypt(ivec, ivec, key);
334 		key->count = 0;
335 	}
336 
337 	c2l(p, val);
338 	val2 = val + 0x01010101;
339 	l2c(val2, p2);
340 
341 	c2l(p, val);
342 	val2 = val + 0x01010104;
343 	if (val > val2) /* overflow */
344 		val2++;
345 	l2c(val2, p2);
346 
347 	Gost2814789_encrypt(ivec, out, key);
348 	key->count += 8;
349 }
350 
351 void
352 Gost2814789_cnt_encrypt(const unsigned char *in, unsigned char *out, size_t len,
353     GOST2814789_KEY *key, unsigned char *ivec, unsigned char *cnt_buf, int *num)
354 {
355 	unsigned int n;
356 	size_t l = 0;
357 
358 	n = *num;
359 
360 #if !defined(OPENSSL_SMALL_FOOTPRINT)
361 	if (8 % sizeof(size_t) == 0) do { /* always true actually */
362 		while (n && len) {
363 			*(out++) = *(in++) ^ cnt_buf[n];
364 			--len;
365 			n = (n + 1) % 8;
366 		}
367 
368 #ifdef __STRICT_ALIGNMENT
369 		if (((size_t)in | (size_t)out | (size_t)ivec) %
370 		    sizeof(size_t) != 0)
371 			break;
372 #endif
373 		while (len >= 8) {
374 			Gost2814789_cnt_next(ivec, cnt_buf, key);
375 			for (; n < 8; n += sizeof(size_t))
376 				*(size_t *)(out + n) = *(size_t *)(in + n) ^
377 				    *(size_t *)(cnt_buf + n);
378 			len -= 8;
379 			out += 8;
380 			in  += 8;
381 			n = 0;
382 		}
383 		if (len) {
384 			Gost2814789_cnt_next(ivec, cnt_buf, key);
385 			while (len--) {
386 				out[n] = in[n] ^ cnt_buf[n];
387 				++n;
388 			}
389 		}
390 		*num = n;
391 		return;
392 	} while(0);
393 	/* the rest would be commonly eliminated by x86* compiler */
394 #endif
395 	while (l < len) {
396 		if (n==0)
397 			Gost2814789_cnt_next(ivec, cnt_buf, key);
398 		out[l] = in[l] ^ cnt_buf[n];
399 		++l;
400 		n = (n + 1) % 8;
401 	}
402 
403 	*num=n;
404 }
405 
406 int
407 GOST2814789IMIT_Init(GOST2814789IMIT_CTX *c, int nid)
408 {
409 	c->Nl = c->Nh = c->num = 0;
410 	memset(c->mac, 0, 8);
411 	return Gost2814789_set_sbox(&c->cipher, nid);
412 }
413 
414 static void
415 GOST2814789IMIT_block_data_order(GOST2814789IMIT_CTX *ctx,
416     const unsigned char *p, size_t num)
417 {
418 	int i;
419 
420 	for (i = 0; i < num; i++) {
421 		Gost2814789_mac_mesh(p, ctx->mac, &ctx->cipher);
422 		p += 8;
423 	}
424 }
425 
426 #define DATA_ORDER_IS_LITTLE_ENDIAN
427 
428 #define HASH_CBLOCK	GOST2814789IMIT_CBLOCK
429 #define HASH_LONG	GOST2814789IMIT_LONG
430 #define HASH_CTX	GOST2814789IMIT_CTX
431 #define HASH_UPDATE	GOST2814789IMIT_Update
432 #define HASH_TRANSFORM	GOST2814789IMIT_Transform
433 #define HASH_NO_FINAL	1
434 #define HASH_BLOCK_DATA_ORDER	GOST2814789IMIT_block_data_order
435 
436 #include "md32_common.h"
437 
438 int
439 GOST2814789IMIT_Final(unsigned char *md, GOST2814789IMIT_CTX *c)
440 {
441 	if (c->num) {
442 		memset(c->data + c->num, 0, 8 - c->num);
443 		Gost2814789_mac_mesh(c->data, c->mac, &c->cipher);
444 	}
445 	if (c->Nl <= 8 * 8 && c->Nl > 0 && c->Nh == 0) {
446 		memset(c->data, 0, 8);
447 		Gost2814789_mac_mesh(c->data, c->mac, &c->cipher);
448 	}
449 	memcpy(md, c->mac, 4);
450 	return 1;
451 }
452 
453 unsigned char *
454 GOST2814789IMIT(const unsigned char *d, size_t n, unsigned char *md, int nid,
455     const unsigned char *key, const unsigned char *iv)
456 {
457 	GOST2814789IMIT_CTX c;
458 	static unsigned char m[GOST2814789IMIT_LENGTH];
459 
460 	if (md == NULL)
461 		md = m;
462 	GOST2814789IMIT_Init(&c, nid);
463 	memcpy(c.mac, iv, 8);
464 	Gost2814789_set_key(&c.cipher, key, 256);
465 	GOST2814789IMIT_Update(&c, d, n);
466 	GOST2814789IMIT_Final(md, &c);
467 	explicit_bzero(&c, sizeof(c));
468 	return (md);
469 }
470 
471 #endif
472