1 /* $OpenBSD: gost2814789.c,v 1.7 2021/11/09 18:40:21 bcook 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 <endian.h>
53 #include <string.h>
54 
55 #include <openssl/opensslconf.h>
56 
57 #ifndef OPENSSL_NO_GOST
58 #include <openssl/objects.h>
59 #include <openssl/gost.h>
60 
61 #include "gost_locl.h"
62 
63 static inline unsigned int
64 f(const GOST2814789_KEY *c, unsigned int x)
65 {
66 	return  c->k87[(x>>24) & 255] | c->k65[(x>>16) & 255]|
67 		c->k43[(x>> 8) & 255] | c->k21[(x    ) & 255];
68 }
69 
70 void
71 Gost2814789_encrypt(const unsigned char *in, unsigned char *out,
72     const GOST2814789_KEY *key)
73 {
74 	unsigned int n1, n2; /* As named in the GOST */
75 
76 	c2l(in, n1);
77 	c2l(in, n2);
78 
79 	/* Instead of swapping halves, swap names each round */
80 	n2 ^= f(key, n1 + key->key[0]); n1 ^= f(key, n2 + key->key[1]);
81 	n2 ^= f(key, n1 + key->key[2]); n1 ^= f(key, n2 + key->key[3]);
82 	n2 ^= f(key, n1 + key->key[4]); n1 ^= f(key, n2 + key->key[5]);
83 	n2 ^= f(key, n1 + key->key[6]); n1 ^= f(key, n2 + key->key[7]);
84 
85 	n2 ^= f(key, n1 + key->key[0]); n1 ^= f(key, n2 + key->key[1]);
86 	n2 ^= f(key, n1 + key->key[2]); n1 ^= f(key, n2 + key->key[3]);
87 	n2 ^= f(key, n1 + key->key[4]); n1 ^= f(key, n2 + key->key[5]);
88 	n2 ^= f(key, n1 + key->key[6]); n1 ^= f(key, n2 + key->key[7]);
89 
90 	n2 ^= f(key, n1 + key->key[0]); n1 ^= f(key, n2 + key->key[1]);
91 	n2 ^= f(key, n1 + key->key[2]); n1 ^= f(key, n2 + key->key[3]);
92 	n2 ^= f(key, n1 + key->key[4]); n1 ^= f(key, n2 + key->key[5]);
93 	n2 ^= f(key, n1 + key->key[6]); n1 ^= f(key, n2 + key->key[7]);
94 
95 	n2 ^= f(key, n1 + key->key[7]); n1 ^= f(key, n2 + key->key[6]);
96 	n2 ^= f(key, n1 + key->key[5]); n1 ^= f(key, n2 + key->key[4]);
97 	n2 ^= f(key, n1 + key->key[3]); n1 ^= f(key, n2 + key->key[2]);
98 	n2 ^= f(key, n1 + key->key[1]); n1 ^= f(key, n2 + key->key[0]);
99 
100 	l2c(n2, out);
101 	l2c(n1, out);
102 }
103 
104 void
105 Gost2814789_decrypt(const unsigned char *in, unsigned char *out,
106     const GOST2814789_KEY *key)
107 {
108 	unsigned int n1, n2; /* As named in the GOST */
109 
110 	c2l(in, n1);
111 	c2l(in, n2);
112 
113 	/* Instead of swapping halves, swap names each round */
114 	n2 ^= f(key, n1 + key->key[0]); n1 ^= f(key, n2 + key->key[1]);
115 	n2 ^= f(key, n1 + key->key[2]); n1 ^= f(key, n2 + key->key[3]);
116 	n2 ^= f(key, n1 + key->key[4]); n1 ^= f(key, n2 + key->key[5]);
117 	n2 ^= f(key, n1 + key->key[6]); n1 ^= f(key, n2 + key->key[7]);
118 
119 	n2 ^= f(key, n1 + key->key[7]); n1 ^= f(key, n2 + key->key[6]);
120 	n2 ^= f(key, n1 + key->key[5]); n1 ^= f(key, n2 + key->key[4]);
121 	n2 ^= f(key, n1 + key->key[3]); n1 ^= f(key, n2 + key->key[2]);
122 	n2 ^= f(key, n1 + key->key[1]); n1 ^= f(key, n2 + key->key[0]);
123 
124 	n2 ^= f(key, n1 + key->key[7]); n1 ^= f(key, n2 + key->key[6]);
125 	n2 ^= f(key, n1 + key->key[5]); n1 ^= f(key, n2 + key->key[4]);
126 	n2 ^= f(key, n1 + key->key[3]); n1 ^= f(key, n2 + key->key[2]);
127 	n2 ^= f(key, n1 + key->key[1]); n1 ^= f(key, n2 + key->key[0]);
128 
129 	n2 ^= f(key, n1 + key->key[7]); n1 ^= f(key, n2 + key->key[6]);
130 	n2 ^= f(key, n1 + key->key[5]); n1 ^= f(key, n2 + key->key[4]);
131 	n2 ^= f(key, n1 + key->key[3]); n1 ^= f(key, n2 + key->key[2]);
132 	n2 ^= f(key, n1 + key->key[1]); n1 ^= f(key, n2 + key->key[0]);
133 
134 	l2c(n2, out);
135 	l2c(n1, out);
136 }
137 
138 static void
139 Gost2814789_mac(const unsigned char *in, unsigned char *mac,
140     GOST2814789_KEY *key)
141 {
142 	unsigned int n1, n2; /* As named in the GOST */
143 	unsigned char *p;
144 	int i;
145 
146 	for (i = 0; i < 8; i++)
147 		mac[i] ^= in[i];
148 
149 	p = mac;
150 	c2l(p, n1);
151 	c2l(p, n2);
152 
153 	/* Instead of swapping halves, swap names each round */
154 	n2 ^= f(key, n1 + key->key[0]); n1 ^= f(key, n2 + key->key[1]);
155 	n2 ^= f(key, n1 + key->key[2]); n1 ^= f(key, n2 + key->key[3]);
156 	n2 ^= f(key, n1 + key->key[4]); n1 ^= f(key, n2 + key->key[5]);
157 	n2 ^= f(key, n1 + key->key[6]); n1 ^= f(key, n2 + key->key[7]);
158 
159 	n2 ^= f(key, n1 + key->key[0]); n1 ^= f(key, n2 + key->key[1]);
160 	n2 ^= f(key, n1 + key->key[2]); n1 ^= f(key, n2 + key->key[3]);
161 	n2 ^= f(key, n1 + key->key[4]); n1 ^= f(key, n2 + key->key[5]);
162 	n2 ^= f(key, n1 + key->key[6]); n1 ^= f(key, n2 + key->key[7]);
163 
164 	p = mac;
165 	l2c(n1, p);
166 	l2c(n2, p);
167 }
168 
169 void
170 Gost2814789_ecb_encrypt(const unsigned char *in, unsigned char *out,
171     GOST2814789_KEY *key, const int enc)
172 {
173 	if (key->key_meshing && key->count == 1024) {
174 		Gost2814789_cryptopro_key_mesh(key);
175 		key->count = 0;
176 	}
177 
178 	if (enc)
179 		Gost2814789_encrypt(in, out, key);
180 	else
181 		Gost2814789_decrypt(in, out, key);
182 }
183 
184 static inline void
185 Gost2814789_encrypt_mesh(unsigned char *iv, GOST2814789_KEY *key)
186 {
187 	if (key->key_meshing && key->count == 1024) {
188 		Gost2814789_cryptopro_key_mesh(key);
189 		Gost2814789_encrypt(iv, iv, key);
190 		key->count = 0;
191 	}
192 	Gost2814789_encrypt(iv, iv, key);
193 	key->count += 8;
194 }
195 
196 static inline void
197 Gost2814789_mac_mesh(const unsigned char *data, unsigned char *mac,
198     GOST2814789_KEY *key)
199 {
200 	if (key->key_meshing && key->count == 1024) {
201 		Gost2814789_cryptopro_key_mesh(key);
202 		key->count = 0;
203 	}
204 	Gost2814789_mac(data, mac, key);
205 	key->count += 8;
206 }
207 
208 void
209 Gost2814789_cfb64_encrypt(const unsigned char *in, unsigned char *out,
210     size_t len, GOST2814789_KEY *key, unsigned char *ivec, int *num,
211     const int enc)
212 {
213 	unsigned int n;
214 	size_t l = 0;
215 
216 	n = *num;
217 
218 	if (enc) {
219 #if !defined(OPENSSL_SMALL_FOOTPRINT)
220 		if (8 % sizeof(size_t) == 0) do { /* always true actually */
221 			while (n && len) {
222 				*(out++) = ivec[n] ^= *(in++);
223 				--len;
224 				n = (n + 1) % 8;
225 			}
226 #ifdef __STRICT_ALIGNMENT
227 			if (((size_t)in | (size_t)out | (size_t)ivec) %
228 			    sizeof(size_t) != 0)
229 				break;
230 #endif
231 			while (len >= 8) {
232 				Gost2814789_encrypt_mesh(ivec, key);
233 				for (; n < 8; n += sizeof(size_t)) {
234 					*(size_t*)(out + n) =
235 					*(size_t*)(ivec + n) ^=
236 					    *(size_t*)(in + n);
237 				}
238 				len -= 8;
239 				out += 8;
240 				in  += 8;
241 				n = 0;
242 			}
243 			if (len) {
244 				Gost2814789_encrypt_mesh(ivec, key);
245 				while (len--) {
246 					out[n] = ivec[n] ^= in[n];
247 					++n;
248 				}
249 			}
250 			*num = n;
251 			return;
252 		} while (0);
253 		/* the rest would be commonly eliminated by x86* compiler */
254 #endif
255 		while (l<len) {
256 			if (n == 0) {
257 				Gost2814789_encrypt_mesh(ivec, key);
258 			}
259 			out[l] = ivec[n] ^= in[l];
260 			++l;
261 			n = (n + 1) % 8;
262 		}
263 		*num = n;
264 	} else {
265 #if !defined(OPENSSL_SMALL_FOOTPRINT)
266 		if (8 % sizeof(size_t) == 0) do { /* always true actually */
267 			while (n && len) {
268 				unsigned char c;
269 
270 				*(out++) = ivec[n] ^ (c = *(in++));
271 				ivec[n] = c;
272 				--len;
273 				n = (n + 1) % 8;
274  			}
275 #ifdef __STRICT_ALIGNMENT
276 			if (((size_t)in | (size_t)out | (size_t)ivec) %
277 			    sizeof(size_t) != 0)
278 				break;
279 #endif
280 			while (len >= 8) {
281 				Gost2814789_encrypt_mesh(ivec, key);
282 				for (; n < 8; n += sizeof(size_t)) {
283 					size_t t = *(size_t*)(in + n);
284 					*(size_t*)(out + n) =
285 					    *(size_t*)(ivec + n) ^ t;
286 					*(size_t*)(ivec + n) = t;
287 				}
288 				len -= 8;
289 				out += 8;
290 				in  += 8;
291 				n = 0;
292 			}
293 			if (len) {
294 				Gost2814789_encrypt_mesh(ivec, key);
295 				while (len--) {
296 					unsigned char c;
297 
298 					out[n] = ivec[n] ^ (c = in[n]);
299 					ivec[n] = c;
300 					++n;
301 				}
302  			}
303 			*num = n;
304 			return;
305 		} while (0);
306 		/* the rest would be commonly eliminated by x86* compiler */
307 #endif
308 		while (l < len) {
309 			unsigned char c;
310 
311 			if (n == 0) {
312 				Gost2814789_encrypt_mesh(ivec, key);
313 			}
314 			out[l] = ivec[n] ^ (c = in[l]); ivec[n] = c;
315 			++l;
316 			n = (n + 1) % 8;
317 		}
318 		*num = n;
319 	}
320 }
321 
322 static inline void
323 Gost2814789_cnt_next(unsigned char *ivec, unsigned char *out,
324     GOST2814789_KEY *key)
325 {
326 	unsigned char *p = ivec, *p2 = ivec;
327 	unsigned int val, val2;
328 
329 	if (key->count == 0)
330 		Gost2814789_encrypt(ivec, ivec, key);
331 
332 	if (key->key_meshing && key->count == 1024) {
333 		Gost2814789_cryptopro_key_mesh(key);
334 		Gost2814789_encrypt(ivec, ivec, key);
335 		key->count = 0;
336 	}
337 
338 	c2l(p, val);
339 	val2 = val + 0x01010101;
340 	l2c(val2, p2);
341 
342 	c2l(p, val);
343 	val2 = val + 0x01010104;
344 	if (val > val2) /* overflow */
345 		val2++;
346 	l2c(val2, p2);
347 
348 	Gost2814789_encrypt(ivec, out, key);
349 	key->count += 8;
350 }
351 
352 void
353 Gost2814789_cnt_encrypt(const unsigned char *in, unsigned char *out, size_t len,
354     GOST2814789_KEY *key, unsigned char *ivec, unsigned char *cnt_buf, int *num)
355 {
356 	unsigned int n;
357 	size_t l = 0;
358 
359 	n = *num;
360 
361 #if !defined(OPENSSL_SMALL_FOOTPRINT)
362 	if (8 % sizeof(size_t) == 0) do { /* always true actually */
363 		while (n && len) {
364 			*(out++) = *(in++) ^ cnt_buf[n];
365 			--len;
366 			n = (n + 1) % 8;
367 		}
368 
369 #ifdef __STRICT_ALIGNMENT
370 		if (((size_t)in | (size_t)out | (size_t)ivec) %
371 		    sizeof(size_t) != 0)
372 			break;
373 #endif
374 		while (len >= 8) {
375 			Gost2814789_cnt_next(ivec, cnt_buf, key);
376 			for (; n < 8; n += sizeof(size_t))
377 				*(size_t *)(out + n) = *(size_t *)(in + n) ^
378 				    *(size_t *)(cnt_buf + n);
379 			len -= 8;
380 			out += 8;
381 			in  += 8;
382 			n = 0;
383 		}
384 		if (len) {
385 			Gost2814789_cnt_next(ivec, cnt_buf, key);
386 			while (len--) {
387 				out[n] = in[n] ^ cnt_buf[n];
388 				++n;
389 			}
390 		}
391 		*num = n;
392 		return;
393 	} while(0);
394 	/* the rest would be commonly eliminated by x86* compiler */
395 #endif
396 	while (l < len) {
397 		if (n==0)
398 			Gost2814789_cnt_next(ivec, cnt_buf, key);
399 		out[l] = in[l] ^ cnt_buf[n];
400 		++l;
401 		n = (n + 1) % 8;
402 	}
403 
404 	*num=n;
405 }
406 
407 int
408 GOST2814789IMIT_Init(GOST2814789IMIT_CTX *c, int nid)
409 {
410 	c->Nl = c->Nh = c->num = 0;
411 	memset(c->mac, 0, 8);
412 	return Gost2814789_set_sbox(&c->cipher, nid);
413 }
414 
415 static void
416 GOST2814789IMIT_block_data_order(GOST2814789IMIT_CTX *ctx,
417     const unsigned char *p, size_t num)
418 {
419 	int i;
420 
421 	for (i = 0; i < num; i++) {
422 		Gost2814789_mac_mesh(p, ctx->mac, &ctx->cipher);
423 		p += 8;
424 	}
425 }
426 
427 #define DATA_ORDER_IS_LITTLE_ENDIAN
428 
429 #define HASH_CBLOCK	GOST2814789IMIT_CBLOCK
430 #define HASH_LONG	GOST2814789IMIT_LONG
431 #define HASH_CTX	GOST2814789IMIT_CTX
432 #define HASH_UPDATE	GOST2814789IMIT_Update
433 #define HASH_TRANSFORM	GOST2814789IMIT_Transform
434 #define HASH_NO_FINAL	1
435 #define HASH_BLOCK_DATA_ORDER	GOST2814789IMIT_block_data_order
436 
437 #include "md32_common.h"
438 
439 int
440 GOST2814789IMIT_Final(unsigned char *md, GOST2814789IMIT_CTX *c)
441 {
442 	if (c->num) {
443 		memset(c->data + c->num, 0, 8 - c->num);
444 		Gost2814789_mac_mesh(c->data, c->mac, &c->cipher);
445 	}
446 	if (c->Nl <= 8 * 8 && c->Nl > 0 && c->Nh == 0) {
447 		memset(c->data, 0, 8);
448 		Gost2814789_mac_mesh(c->data, c->mac, &c->cipher);
449 	}
450 	memcpy(md, c->mac, 4);
451 	return 1;
452 }
453 
454 unsigned char *
455 GOST2814789IMIT(const unsigned char *d, size_t n, unsigned char *md, int nid,
456     const unsigned char *key, const unsigned char *iv)
457 {
458 	GOST2814789IMIT_CTX c;
459 	static unsigned char m[GOST2814789IMIT_LENGTH];
460 
461 	if (md == NULL)
462 		md = m;
463 	GOST2814789IMIT_Init(&c, nid);
464 	memcpy(c.mac, iv, 8);
465 	Gost2814789_set_key(&c.cipher, key, 256);
466 	GOST2814789IMIT_Update(&c, d, n);
467 	GOST2814789IMIT_Final(md, &c);
468 	explicit_bzero(&c, sizeof(c));
469 	return (md);
470 }
471 
472 #endif
473