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