1 /* $OpenBSD: gost2814789.c,v 1.4 2015/02/10 09:46:30 miod Exp $ */
3 * Copyright (c) 2014 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
4 * Copyright (c) 2005-2006 Cryptocom LTD
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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
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/)"
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.
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.
32 * 6. Redistributions of any form whatsoever must retain the following
34 * "This product includes software developed by the OpenSSL Project
35 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
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 * ====================================================================
54 #include <openssl/opensslconf.h>
56 #ifndef OPENSSL_NO_GOST
57 #include <openssl/objects.h>
58 #include <openssl/gost.h>
60 #include "gost_locl.h"
62 static inline unsigned int
63 f(const GOST2814789_KEY
*c
, unsigned int x
)
65 return c
->k87
[(x
>>24) & 255] | c
->k65
[(x
>>16) & 255]|
66 c
->k43
[(x
>> 8) & 255] | c
->k21
[(x
) & 255];
70 Gost2814789_encrypt(const unsigned char *in
, unsigned char *out
,
71 const GOST2814789_KEY
*key
)
73 unsigned int n1
, n2
; /* As named in the GOST */
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]);
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]);
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]);
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]);
104 Gost2814789_decrypt(const unsigned char *in
, unsigned char *out
,
105 const GOST2814789_KEY
*key
)
107 unsigned int n1
, n2
; /* As named in the GOST */
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]);
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]);
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]);
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]);
138 Gost2814789_mac(const unsigned char *in
, unsigned char *mac
,
139 GOST2814789_KEY
*key
)
141 unsigned int n1
, n2
; /* As named in the GOST */
145 for (i
= 0; i
< 8; i
++)
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]);
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]);
169 Gost2814789_ecb_encrypt(const unsigned char *in
, unsigned char *out
,
170 GOST2814789_KEY
*key
, const int enc
)
172 if (key
->key_meshing
&& key
->count
== 1024) {
173 Gost2814789_cryptopro_key_mesh(key
);
178 Gost2814789_encrypt(in
, out
, key
);
180 Gost2814789_decrypt(in
, out
, key
);
184 Gost2814789_encrypt_mesh(unsigned char *iv
, GOST2814789_KEY
*key
)
186 if (key
->key_meshing
&& key
->count
== 1024) {
187 Gost2814789_cryptopro_key_mesh(key
);
188 Gost2814789_encrypt(iv
, iv
, key
);
191 Gost2814789_encrypt(iv
, iv
, key
);
196 Gost2814789_mac_mesh(const unsigned char *data
, unsigned char *mac
,
197 GOST2814789_KEY
*key
)
199 if (key
->key_meshing
&& key
->count
== 1024) {
200 Gost2814789_cryptopro_key_mesh(key
);
203 Gost2814789_mac(data
, mac
, key
);
208 Gost2814789_cfb64_encrypt(const unsigned char *in
, unsigned char *out
,
209 size_t len
, GOST2814789_KEY
*key
, unsigned char *ivec
, int *num
,
218 #if !defined(OPENSSL_SMALL_FOOTPRINT)
219 if (8 % sizeof(size_t) == 0) do { /* always true actually */
221 *(out
++) = ivec
[n
] ^= *(in
++);
225 #ifdef __STRICT_ALIGNMENT
226 if (((size_t)in
| (size_t)out
| (size_t)ivec
) %
231 Gost2814789_encrypt_mesh(ivec
, key
);
232 for (; n
< 8; n
+= sizeof(size_t)) {
233 *(size_t*)(out
+ n
) =
234 *(size_t*)(ivec
+ n
) ^=
243 Gost2814789_encrypt_mesh(ivec
, key
);
245 out
[n
] = ivec
[n
] ^= in
[n
];
252 /* the rest would be commonly eliminated by x86* compiler */
256 Gost2814789_encrypt_mesh(ivec
, key
);
258 out
[l
] = ivec
[n
] ^= in
[l
];
264 #if !defined(OPENSSL_SMALL_FOOTPRINT)
265 if (8 % sizeof(size_t) == 0) do { /* always true actually */
269 *(out
++) = ivec
[n
] ^ (c
= *(in
++));
274 #ifdef __STRICT_ALIGNMENT
275 if (((size_t)in
| (size_t)out
| (size_t)ivec
) %
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
;
293 Gost2814789_encrypt_mesh(ivec
, key
);
297 out
[n
] = ivec
[n
] ^ (c
= in
[n
]);
305 /* the rest would be commonly eliminated by x86* compiler */
311 Gost2814789_encrypt_mesh(ivec
, key
);
313 out
[l
] = ivec
[n
] ^ (c
= in
[l
]); ivec
[n
] = c
;
322 Gost2814789_cnt_next(unsigned char *ivec
, unsigned char *out
,
323 GOST2814789_KEY
*key
)
325 unsigned char *p
= ivec
, *p2
= ivec
;
326 unsigned int val
, val2
;
329 Gost2814789_encrypt(ivec
, ivec
, key
);
331 if (key
->key_meshing
&& key
->count
== 1024) {
332 Gost2814789_cryptopro_key_mesh(key
);
333 Gost2814789_encrypt(ivec
, ivec
, key
);
338 val2
= val
+ 0x01010101;
342 val2
= val
+ 0x01010104;
343 if (val
> val2
) /* overflow */
347 Gost2814789_encrypt(ivec
, out
, key
);
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
)
360 #if !defined(OPENSSL_SMALL_FOOTPRINT)
361 if (8 % sizeof(size_t) == 0) do { /* always true actually */
363 *(out
++) = *(in
++) ^ cnt_buf
[n
];
368 #ifdef __STRICT_ALIGNMENT
369 if (((size_t)in
| (size_t)out
| (size_t)ivec
) %
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
);
384 Gost2814789_cnt_next(ivec
, cnt_buf
, key
);
386 out
[n
] = in
[n
] ^ cnt_buf
[n
];
393 /* the rest would be commonly eliminated by x86* compiler */
397 Gost2814789_cnt_next(ivec
, cnt_buf
, key
);
398 out
[l
] = in
[l
] ^ cnt_buf
[n
];
407 GOST2814789IMIT_Init(GOST2814789IMIT_CTX
*c
, int nid
)
409 c
->Nl
= c
->Nh
= c
->num
= 0;
410 memset(c
->mac
, 0, 8);
411 return Gost2814789_set_sbox(&c
->cipher
, nid
);
415 GOST2814789IMIT_block_data_order(GOST2814789IMIT_CTX
*ctx
,
416 const unsigned char *p
, size_t num
)
420 for (i
= 0; i
< num
; i
++) {
421 Gost2814789_mac_mesh(p
, ctx
->mac
, &ctx
->cipher
);
426 #define DATA_ORDER_IS_LITTLE_ENDIAN
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
436 #include "md32_common.h"
439 GOST2814789IMIT_Final(unsigned char *md
, GOST2814789IMIT_CTX
*c
)
442 memset(c
->data
+ c
->num
, 0, 8 - c
->num
);
443 Gost2814789_mac_mesh(c
->data
, c
->mac
, &c
->cipher
);
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
);
449 memcpy(md
, c
->mac
, 4);
454 GOST2814789IMIT(const unsigned char *d
, size_t n
, unsigned char *md
, int nid
,
455 const unsigned char *key
, const unsigned char *iv
)
457 GOST2814789IMIT_CTX c
;
458 static unsigned char m
[GOST2814789IMIT_LENGTH
];
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
));