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