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