GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libcrypto/gost/gost2814789.c Lines: 150 192 78.1 %
Date: 2017-11-07 Branches: 47 68 69.1 %

Line Branch Exec Source
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
1317095552
	return  c->k87[(x>>24) & 255] | c->k65[(x>>16) & 255]|
66
658547776
		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
15909204
	c2l(in, n1);
76
7954602
	c2l(in, n2);
77
78
	/* Instead of swapping halves, swap names each round */
79
7954602
	n2 ^= f(key, n1 + key->key[0]); n1 ^= f(key, n2 + key->key[1]);
80
7954602
	n2 ^= f(key, n1 + key->key[2]); n1 ^= f(key, n2 + key->key[3]);
81
7954602
	n2 ^= f(key, n1 + key->key[4]); n1 ^= f(key, n2 + key->key[5]);
82
7954602
	n2 ^= f(key, n1 + key->key[6]); n1 ^= f(key, n2 + key->key[7]);
83
84
7954602
	n2 ^= f(key, n1 + key->key[0]); n1 ^= f(key, n2 + key->key[1]);
85
7954602
	n2 ^= f(key, n1 + key->key[2]); n1 ^= f(key, n2 + key->key[3]);
86
7954602
	n2 ^= f(key, n1 + key->key[4]); n1 ^= f(key, n2 + key->key[5]);
87
7954602
	n2 ^= f(key, n1 + key->key[6]); n1 ^= f(key, n2 + key->key[7]);
88
89
7954602
	n2 ^= f(key, n1 + key->key[0]); n1 ^= f(key, n2 + key->key[1]);
90
7954602
	n2 ^= f(key, n1 + key->key[2]); n1 ^= f(key, n2 + key->key[3]);
91
7954602
	n2 ^= f(key, n1 + key->key[4]); n1 ^= f(key, n2 + key->key[5]);
92
7954602
	n2 ^= f(key, n1 + key->key[6]); n1 ^= f(key, n2 + key->key[7]);
93
94
7954602
	n2 ^= f(key, n1 + key->key[7]); n1 ^= f(key, n2 + key->key[6]);
95
7954602
	n2 ^= f(key, n1 + key->key[5]); n1 ^= f(key, n2 + key->key[4]);
96
7954602
	n2 ^= f(key, n1 + key->key[3]); n1 ^= f(key, n2 + key->key[2]);
97
7954602
	n2 ^= f(key, n1 + key->key[1]); n1 ^= f(key, n2 + key->key[0]);
98
99
7954602
	l2c(n2, out);
100
7954602
	l2c(n1, out);
101
7954602
}
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
737376
	c2l(in, n1);
110
368688
	c2l(in, n2);
111
112
	/* Instead of swapping halves, swap names each round */
113
368688
	n2 ^= f(key, n1 + key->key[0]); n1 ^= f(key, n2 + key->key[1]);
114
368688
	n2 ^= f(key, n1 + key->key[2]); n1 ^= f(key, n2 + key->key[3]);
115
368688
	n2 ^= f(key, n1 + key->key[4]); n1 ^= f(key, n2 + key->key[5]);
116
368688
	n2 ^= f(key, n1 + key->key[6]); n1 ^= f(key, n2 + key->key[7]);
117
118
368688
	n2 ^= f(key, n1 + key->key[7]); n1 ^= f(key, n2 + key->key[6]);
119
368688
	n2 ^= f(key, n1 + key->key[5]); n1 ^= f(key, n2 + key->key[4]);
120
368688
	n2 ^= f(key, n1 + key->key[3]); n1 ^= f(key, n2 + key->key[2]);
121
368688
	n2 ^= f(key, n1 + key->key[1]); n1 ^= f(key, n2 + key->key[0]);
122
123
368688
	n2 ^= f(key, n1 + key->key[7]); n1 ^= f(key, n2 + key->key[6]);
124
368688
	n2 ^= f(key, n1 + key->key[5]); n1 ^= f(key, n2 + key->key[4]);
125
368688
	n2 ^= f(key, n1 + key->key[3]); n1 ^= f(key, n2 + key->key[2]);
126
368688
	n2 ^= f(key, n1 + key->key[1]); n1 ^= f(key, n2 + key->key[0]);
127
128
368688
	n2 ^= f(key, n1 + key->key[7]); n1 ^= f(key, n2 + key->key[6]);
129
368688
	n2 ^= f(key, n1 + key->key[5]); n1 ^= f(key, n2 + key->key[4]);
130
368688
	n2 ^= f(key, n1 + key->key[3]); n1 ^= f(key, n2 + key->key[2]);
131
368688
	n2 ^= f(key, n1 + key->key[1]); n1 ^= f(key, n2 + key->key[0]);
132
133
368688
	l2c(n2, out);
134
368688
	l2c(n1, out);
135
368688
}
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
74727722
	for (i = 0; i < 8; i++)
146
31464304
		mac[i] ^= in[i];
147
148
	p = mac;
149
3933038
	c2l(p, n1);
150
3933038
	c2l(p, n2);
151
152
	/* Instead of swapping halves, swap names each round */
153
3933038
	n2 ^= f(key, n1 + key->key[0]); n1 ^= f(key, n2 + key->key[1]);
154
3933038
	n2 ^= f(key, n1 + key->key[2]); n1 ^= f(key, n2 + key->key[3]);
155
3933038
	n2 ^= f(key, n1 + key->key[4]); n1 ^= f(key, n2 + key->key[5]);
156
3933038
	n2 ^= f(key, n1 + key->key[6]); n1 ^= f(key, n2 + key->key[7]);
157
158
3933038
	n2 ^= f(key, n1 + key->key[0]); n1 ^= f(key, n2 + key->key[1]);
159
3933038
	n2 ^= f(key, n1 + key->key[2]); n1 ^= f(key, n2 + key->key[3]);
160
3933038
	n2 ^= f(key, n1 + key->key[4]); n1 ^= f(key, n2 + key->key[5]);
161
3933038
	n2 ^= f(key, n1 + key->key[6]); n1 ^= f(key, n2 + key->key[7]);
162
163
	p = mac;
164
3933038
	l2c(n1, p);
165
3933038
	l2c(n2, p);
166
3933038
}
167
168
void
169
Gost2814789_ecb_encrypt(const unsigned char *in, unsigned char *out,
170
    GOST2814789_KEY *key, const int enc)
171
{
172

72
	if (key->key_meshing && key->count == 1024) {
173
		Gost2814789_cryptopro_key_mesh(key);
174
		key->count = 0;
175
	}
176
177
30
	if (enc)
178
30
		Gost2814789_encrypt(in, out, key);
179
	else
180
		Gost2814789_decrypt(in, out, key);
181
30
}
182
183
static inline void
184
Gost2814789_encrypt_mesh(unsigned char *iv, GOST2814789_KEY *key)
185
{
186

11798928
	if (key->key_meshing && key->count == 1024) {
187
30726
		Gost2814789_cryptopro_key_mesh(key);
188
30726
		Gost2814789_encrypt(iv, iv, key);
189
30726
		key->count = 0;
190
30726
	}
191
3932976
	Gost2814789_encrypt(iv, iv, key);
192
3932976
	key->count += 8;
193
3932976
}
194
195
static inline void
196
Gost2814789_mac_mesh(const unsigned char *data, unsigned char *mac,
197
    GOST2814789_KEY *key)
198
{
199

11799114
	if (key->key_meshing && key->count == 1024) {
200
30720
		Gost2814789_cryptopro_key_mesh(key);
201
30720
		key->count = 0;
202
30720
	}
203
3933038
	Gost2814789_mac(data, mac, key);
204
3933038
	key->count += 8;
205
3933038
}
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
60
	n = *num;
216
217
30
	if (enc) {
218
#if !defined(OPENSSL_SMALL_FOOTPRINT)
219
		if (8 % sizeof(size_t) == 0) do { /* always true actually */
220
30
			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
7865946
			while (len >= 8) {
231
3932958
				Gost2814789_encrypt_mesh(ivec, key);
232
15731832
				for (; n < 8; n += sizeof(size_t)) {
233
3932958
					*(size_t*)(out + n) =
234
3932958
					*(size_t*)(ivec + n) ^=
235
3932958
					    *(size_t*)(in + n);
236
				}
237
3932958
				len -= 8;
238
3932958
				out += 8;
239
3932958
				in  += 8;
240
				n = 0;
241
			}
242
30
			if (len) {
243
18
				Gost2814789_encrypt_mesh(ivec, key);
244
180
				while (len--) {
245
72
					out[n] = ivec[n] ^= in[n];
246
72
					++n;
247
				}
248
			}
249
30
			*num = n;
250
30
			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
30
}
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
7865916
	if (key->count == 0)
329
18
		Gost2814789_encrypt(ivec, ivec, key);
330
331

7865916
	if (key->key_meshing && key->count == 1024) {
332
30726
		Gost2814789_cryptopro_key_mesh(key);
333
30726
		Gost2814789_encrypt(ivec, ivec, key);
334
30726
		key->count = 0;
335
30726
	}
336
337
3932958
	c2l(p, val);
338
3932958
	val2 = val + 0x01010101;
339
3932958
	l2c(val2, p2);
340
341
3932958
	c2l(p, val);
342
3932958
	val2 = val + 0x01010104;
343
3932958
	if (val > val2) /* overflow */
344
15348
		val2++;
345
3932958
	l2c(val2, p2);
346
347
3932958
	Gost2814789_encrypt(ivec, out, key);
348
3932958
	key->count += 8;
349
3932958
}
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
36
	n = *num;
359
360
#if !defined(OPENSSL_SMALL_FOOTPRINT)
361
	if (8 % sizeof(size_t) == 0) do { /* always true actually */
362
36
		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
7865922
		while (len >= 8) {
374
3932952
			Gost2814789_cnt_next(ivec, cnt_buf, key);
375
15731808
			for (; n < 8; n += sizeof(size_t))
376
7865904
				*(size_t *)(out + n) = *(size_t *)(in + n) ^
377
3932952
				    *(size_t *)(cnt_buf + n);
378
3932952
			len -= 8;
379
3932952
			out += 8;
380
3932952
			in  += 8;
381
			n = 0;
382
		}
383
18
		if (len) {
384
6
			Gost2814789_cnt_next(ivec, cnt_buf, key);
385
72
			while (len--) {
386
30
				out[n] = in[n] ^ cnt_buf[n];
387
30
				++n;
388
			}
389
		}
390
18
		*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
18
}
405
406
int
407
GOST2814789IMIT_Init(GOST2814789IMIT_CTX *c, int nid)
408
{
409
128
	c->Nl = c->Nh = c->num = 0;
410
64
	memset(c->mac, 0, 8);
411
64
	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
7866152
	for (i = 0; i < num; i++) {
421
3932998
		Gost2814789_mac_mesh(p, ctx->mac, &ctx->cipher);
422
3932998
		p += 8;
423
	}
424
52
}
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
116
	if (c->num) {
442
28
		memset(c->data + c->num, 0, 8 - c->num);
443
28
		Gost2814789_mac_mesh(c->data, c->mac, &c->cipher);
444
28
	}
445

88
	if (c->Nl <= 8 * 8 && c->Nl > 0 && c->Nh == 0) {
446
12
		memset(c->data, 0, 8);
447
12
		Gost2814789_mac_mesh(c->data, c->mac, &c->cipher);
448
12
	}
449
58
	memcpy(md, c->mac, 4);
450
58
	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