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