1/********************************************************************** 2 * gost89.c * 3 * Copyright (c) 2005-2006 Cryptocom LTD * 4 * This file is distributed under the same license as OpenSSL * 5 * * 6 * Implementation of GOST 28147-89 encryption algorithm * 7 * No OpenSSL libraries required to compile and use * 8 * this code * 9 **********************************************************************/ 10#include <string.h> 11#include "gost89.h" 12/*- 13 Substitution blocks from RFC 4357 14 15 Note: our implementation of gost 28147-89 algorithm 16 uses S-box matrix rotated 90 degrees counterclockwise, relative to 17 examples given in RFC. 18 19 20*/ 21 22/* Substitution blocks from test examples for GOST R 34.11-94*/ 23gost_subst_block GostR3411_94_TestParamSet = { 24 {0X1, 0XF, 0XD, 0X0, 0X5, 0X7, 0XA, 0X4, 0X9, 0X2, 0X3, 0XE, 0X6, 0XB, 25 0X8, 0XC} 26 , 27 {0XD, 0XB, 0X4, 0X1, 0X3, 0XF, 0X5, 0X9, 0X0, 0XA, 0XE, 0X7, 0X6, 0X8, 28 0X2, 0XC} 29 , 30 {0X4, 0XB, 0XA, 0X0, 0X7, 0X2, 0X1, 0XD, 0X3, 0X6, 0X8, 0X5, 0X9, 0XC, 31 0XF, 0XE} 32 , 33 {0X6, 0XC, 0X7, 0X1, 0X5, 0XF, 0XD, 0X8, 0X4, 0XA, 0X9, 0XE, 0X0, 0X3, 34 0XB, 0X2} 35 , 36 {0X7, 0XD, 0XA, 0X1, 0X0, 0X8, 0X9, 0XF, 0XE, 0X4, 0X6, 0XC, 0XB, 0X2, 37 0X5, 0X3} 38 , 39 {0X5, 0X8, 0X1, 0XD, 0XA, 0X3, 0X4, 0X2, 0XE, 0XF, 0XC, 0X7, 0X6, 0X0, 40 0X9, 0XB} 41 , 42 {0XE, 0XB, 0X4, 0XC, 0X6, 0XD, 0XF, 0XA, 0X2, 0X3, 0X8, 0X1, 0X0, 0X7, 43 0X5, 0X9} 44 , 45 {0X4, 0XA, 0X9, 0X2, 0XD, 0X8, 0X0, 0XE, 0X6, 0XB, 0X1, 0XC, 0X7, 0XF, 46 0X5, 0X3} 47}; 48 49/* Substitution blocks for hash function 1.2.643.2.9.1.6.1 */ 50gost_subst_block GostR3411_94_CryptoProParamSet = { 51 {0x1, 0x3, 0xA, 0x9, 0x5, 0xB, 0x4, 0xF, 0x8, 0x6, 0x7, 0xE, 0xD, 0x0, 52 0x2, 0xC} 53 , 54 {0xD, 0xE, 0x4, 0x1, 0x7, 0x0, 0x5, 0xA, 0x3, 0xC, 0x8, 0xF, 0x6, 0x2, 55 0x9, 0xB} 56 , 57 {0x7, 0x6, 0x2, 0x4, 0xD, 0x9, 0xF, 0x0, 0xA, 0x1, 0x5, 0xB, 0x8, 0xE, 58 0xC, 0x3} 59 , 60 {0x7, 0x6, 0x4, 0xB, 0x9, 0xC, 0x2, 0xA, 0x1, 0x8, 0x0, 0xE, 0xF, 0xD, 61 0x3, 0x5} 62 , 63 {0x4, 0xA, 0x7, 0xC, 0x0, 0xF, 0x2, 0x8, 0xE, 0x1, 0x6, 0x5, 0xD, 0xB, 64 0x9, 0x3} 65 , 66 {0x7, 0xF, 0xC, 0xE, 0x9, 0x4, 0x1, 0x0, 0x3, 0xB, 0x5, 0x2, 0x6, 0xA, 67 0x8, 0xD} 68 , 69 {0x5, 0xF, 0x4, 0x0, 0x2, 0xD, 0xB, 0x9, 0x1, 0x7, 0x6, 0x3, 0xC, 0xE, 70 0xA, 0x8} 71 , 72 {0xA, 0x4, 0x5, 0x6, 0x8, 0x1, 0x3, 0x7, 0xD, 0xC, 0xE, 0x0, 0x9, 0x2, 73 0xB, 0xF} 74}; 75 76/* Test paramset from GOST 28147 */ 77gost_subst_block Gost28147_TestParamSet = { 78 {0xC, 0x6, 0x5, 0x2, 0xB, 0x0, 0x9, 0xD, 0x3, 0xE, 0x7, 0xA, 0xF, 0x4, 79 0x1, 0x8} 80 , 81 {0x9, 0xB, 0xC, 0x0, 0x3, 0x6, 0x7, 0x5, 0x4, 0x8, 0xE, 0xF, 0x1, 0xA, 82 0x2, 0xD} 83 , 84 {0x8, 0xF, 0x6, 0xB, 0x1, 0x9, 0xC, 0x5, 0xD, 0x3, 0x7, 0xA, 0x0, 0xE, 85 0x2, 0x4} 86 , 87 {0x3, 0xE, 0x5, 0x9, 0x6, 0x8, 0x0, 0xD, 0xA, 0xB, 0x7, 0xC, 0x2, 0x1, 88 0xF, 0x4} 89 , 90 {0xE, 0x9, 0xB, 0x2, 0x5, 0xF, 0x7, 0x1, 0x0, 0xD, 0xC, 0x6, 0xA, 0x4, 91 0x3, 0x8} 92 , 93 {0xD, 0x8, 0xE, 0xC, 0x7, 0x3, 0x9, 0xA, 0x1, 0x5, 0x2, 0x4, 0x6, 0xF, 94 0x0, 0xB} 95 , 96 {0xC, 0x9, 0xF, 0xE, 0x8, 0x1, 0x3, 0xA, 0x2, 0x7, 0x4, 0xD, 0x6, 0x0, 97 0xB, 0x5} 98 , 99 {0x4, 0x2, 0xF, 0x5, 0x9, 0x1, 0x0, 0x8, 0xE, 0x3, 0xB, 0xC, 0xD, 0x7, 100 0xA, 0x6} 101}; 102 103/* 1.2.643.2.2.31.1 */ 104gost_subst_block Gost28147_CryptoProParamSetA = { 105 {0xB, 0xA, 0xF, 0x5, 0x0, 0xC, 0xE, 0x8, 0x6, 0x2, 0x3, 0x9, 0x1, 0x7, 106 0xD, 0x4} 107 , 108 {0x1, 0xD, 0x2, 0x9, 0x7, 0xA, 0x6, 0x0, 0x8, 0xC, 0x4, 0x5, 0xF, 0x3, 109 0xB, 0xE} 110 , 111 {0x3, 0xA, 0xD, 0xC, 0x1, 0x2, 0x0, 0xB, 0x7, 0x5, 0x9, 0x4, 0x8, 0xF, 112 0xE, 0x6} 113 , 114 {0xB, 0x5, 0x1, 0x9, 0x8, 0xD, 0xF, 0x0, 0xE, 0x4, 0x2, 0x3, 0xC, 0x7, 115 0xA, 0x6} 116 , 117 {0xE, 0x7, 0xA, 0xC, 0xD, 0x1, 0x3, 0x9, 0x0, 0x2, 0xB, 0x4, 0xF, 0x8, 118 0x5, 0x6} 119 , 120 {0xE, 0x4, 0x6, 0x2, 0xB, 0x3, 0xD, 0x8, 0xC, 0xF, 0x5, 0xA, 0x0, 0x7, 121 0x1, 0x9} 122 , 123 {0x3, 0x7, 0xE, 0x9, 0x8, 0xA, 0xF, 0x0, 0x5, 0x2, 0x6, 0xC, 0xB, 0x4, 124 0xD, 0x1} 125 , 126 {0x9, 0x6, 0x3, 0x2, 0x8, 0xB, 0x1, 0x7, 0xA, 0x4, 0xE, 0xF, 0xC, 0x0, 127 0xD, 0x5} 128}; 129 130/* 1.2.643.2.2.31.2 */ 131gost_subst_block Gost28147_CryptoProParamSetB = { 132 {0x0, 0x4, 0xB, 0xE, 0x8, 0x3, 0x7, 0x1, 0xA, 0x2, 0x9, 0x6, 0xF, 0xD, 133 0x5, 0xC} 134 , 135 {0x5, 0x2, 0xA, 0xB, 0x9, 0x1, 0xC, 0x3, 0x7, 0x4, 0xD, 0x0, 0x6, 0xF, 136 0x8, 0xE} 137 , 138 {0x8, 0x3, 0x2, 0x6, 0x4, 0xD, 0xE, 0xB, 0xC, 0x1, 0x7, 0xF, 0xA, 0x0, 139 0x9, 0x5} 140 , 141 {0x2, 0x7, 0xC, 0xF, 0x9, 0x5, 0xA, 0xB, 0x1, 0x4, 0x0, 0xD, 0x6, 0x8, 142 0xE, 0x3} 143 , 144 {0x7, 0x5, 0x0, 0xD, 0xB, 0x6, 0x1, 0x2, 0x3, 0xA, 0xC, 0xF, 0x4, 0xE, 145 0x9, 0x8} 146 , 147 {0xE, 0xC, 0x0, 0xA, 0x9, 0x2, 0xD, 0xB, 0x7, 0x5, 0x8, 0xF, 0x3, 0x6, 148 0x1, 0x4} 149 , 150 {0x0, 0x1, 0x2, 0xA, 0x4, 0xD, 0x5, 0xC, 0x9, 0x7, 0x3, 0xF, 0xB, 0x8, 151 0x6, 0xE} 152 , 153 {0x8, 0x4, 0xB, 0x1, 0x3, 0x5, 0x0, 0x9, 0x2, 0xE, 0xA, 0xC, 0xD, 0x6, 154 0x7, 0xF} 155}; 156 157/* 1.2.643.2.2.31.3 */ 158gost_subst_block Gost28147_CryptoProParamSetC = { 159 {0x7, 0x4, 0x0, 0x5, 0xA, 0x2, 0xF, 0xE, 0xC, 0x6, 0x1, 0xB, 0xD, 0x9, 160 0x3, 0x8} 161 , 162 {0xA, 0x9, 0x6, 0x8, 0xD, 0xE, 0x2, 0x0, 0xF, 0x3, 0x5, 0xB, 0x4, 0x1, 163 0xC, 0x7} 164 , 165 {0xC, 0x9, 0xB, 0x1, 0x8, 0xE, 0x2, 0x4, 0x7, 0x3, 0x6, 0x5, 0xA, 0x0, 166 0xF, 0xD} 167 , 168 {0x8, 0xD, 0xB, 0x0, 0x4, 0x5, 0x1, 0x2, 0x9, 0x3, 0xC, 0xE, 0x6, 0xF, 169 0xA, 0x7} 170 , 171 {0x3, 0x6, 0x0, 0x1, 0x5, 0xD, 0xA, 0x8, 0xB, 0x2, 0x9, 0x7, 0xE, 0xF, 172 0xC, 0x4} 173 , 174 {0x8, 0x2, 0x5, 0x0, 0x4, 0x9, 0xF, 0xA, 0x3, 0x7, 0xC, 0xD, 0x6, 0xE, 175 0x1, 0xB} 176 , 177 {0x0, 0x1, 0x7, 0xD, 0xB, 0x4, 0x5, 0x2, 0x8, 0xE, 0xF, 0xC, 0x9, 0xA, 178 0x6, 0x3} 179 , 180 {0x1, 0xB, 0xC, 0x2, 0x9, 0xD, 0x0, 0xF, 0x4, 0x5, 0x8, 0xE, 0xA, 0x7, 181 0x6, 0x3} 182}; 183 184/* 1.2.643.2.2.31.4 */ 185gost_subst_block Gost28147_CryptoProParamSetD = { 186 {0x1, 0xA, 0x6, 0x8, 0xF, 0xB, 0x0, 0x4, 0xC, 0x3, 0x5, 0x9, 0x7, 0xD, 187 0x2, 0xE} 188 , 189 {0x3, 0x0, 0x6, 0xF, 0x1, 0xE, 0x9, 0x2, 0xD, 0x8, 0xC, 0x4, 0xB, 0xA, 190 0x5, 0x7} 191 , 192 {0x8, 0x0, 0xF, 0x3, 0x2, 0x5, 0xE, 0xB, 0x1, 0xA, 0x4, 0x7, 0xC, 0x9, 193 0xD, 0x6} 194 , 195 {0x0, 0xC, 0x8, 0x9, 0xD, 0x2, 0xA, 0xB, 0x7, 0x3, 0x6, 0x5, 0x4, 0xE, 196 0xF, 0x1} 197 , 198 {0x1, 0x5, 0xE, 0xC, 0xA, 0x7, 0x0, 0xD, 0x6, 0x2, 0xB, 0x4, 0x9, 0x3, 199 0xF, 0x8} 200 , 201 {0x1, 0xC, 0xB, 0x0, 0xF, 0xE, 0x6, 0x5, 0xA, 0xD, 0x4, 0x8, 0x9, 0x3, 202 0x7, 0x2} 203 , 204 {0xB, 0x6, 0x3, 0x4, 0xC, 0xF, 0xE, 0x2, 0x7, 0xD, 0x8, 0x0, 0x5, 0xA, 205 0x9, 0x1} 206 , 207 {0xF, 0xC, 0x2, 0xA, 0x6, 0x4, 0x5, 0x0, 0x7, 0x9, 0xE, 0xD, 0x1, 0xB, 208 0x8, 0x3} 209}; 210 211const byte CryptoProKeyMeshingKey[] = { 212 0x69, 0x00, 0x72, 0x22, 0x64, 0xC9, 0x04, 0x23, 213 0x8D, 0x3A, 0xDB, 0x96, 0x46, 0xE9, 0x2A, 0xC4, 214 0x18, 0xFE, 0xAC, 0x94, 0x00, 0xED, 0x07, 0x12, 215 0xC0, 0x86, 0xDC, 0xC2, 0xEF, 0x4C, 0xA9, 0x2B 216}; 217 218/* Initialization of gost_ctx subst blocks*/ 219static void kboxinit(gost_ctx * c, const gost_subst_block * b) 220{ 221 int i; 222 223 for (i = 0; i < 256; i++) { 224 c->k87[i] = (word32) (b->k8[i >> 4] << 4 | b->k7[i & 15]) << 24; 225 c->k65[i] = (b->k6[i >> 4] << 4 | b->k5[i & 15]) << 16; 226 c->k43[i] = (b->k4[i >> 4] << 4 | b->k3[i & 15]) << 8; 227 c->k21[i] = b->k2[i >> 4] << 4 | b->k1[i & 15]; 228 229 } 230} 231 232/* Part of GOST 28147 algorithm moved into separate function */ 233static word32 f(gost_ctx * c, word32 x) 234{ 235 x = c->k87[x >> 24 & 255] | c->k65[x >> 16 & 255] | 236 c->k43[x >> 8 & 255] | c->k21[x & 255]; 237 /* Rotate left 11 bits */ 238 return x << 11 | x >> (32 - 11); 239} 240 241/* Low-level encryption routine - encrypts one 64 bit block*/ 242void gostcrypt(gost_ctx * c, const byte * in, byte * out) 243{ 244 register word32 n1, n2; /* As named in the GOST */ 245 n1 = in[0] | (in[1] << 8) | (in[2] << 16) | ((word32) in[3] << 24); 246 n2 = in[4] | (in[5] << 8) | (in[6] << 16) | ((word32) in[7] << 24); 247 /* Instead of swapping halves, swap names each round */ 248 249 n2 ^= f(c, n1 + c->k[0]); 250 n1 ^= f(c, n2 + c->k[1]); 251 n2 ^= f(c, n1 + c->k[2]); 252 n1 ^= f(c, n2 + c->k[3]); 253 n2 ^= f(c, n1 + c->k[4]); 254 n1 ^= f(c, n2 + c->k[5]); 255 n2 ^= f(c, n1 + c->k[6]); 256 n1 ^= f(c, n2 + c->k[7]); 257 258 n2 ^= f(c, n1 + c->k[0]); 259 n1 ^= f(c, n2 + c->k[1]); 260 n2 ^= f(c, n1 + c->k[2]); 261 n1 ^= f(c, n2 + c->k[3]); 262 n2 ^= f(c, n1 + c->k[4]); 263 n1 ^= f(c, n2 + c->k[5]); 264 n2 ^= f(c, n1 + c->k[6]); 265 n1 ^= f(c, n2 + c->k[7]); 266 267 n2 ^= f(c, n1 + c->k[0]); 268 n1 ^= f(c, n2 + c->k[1]); 269 n2 ^= f(c, n1 + c->k[2]); 270 n1 ^= f(c, n2 + c->k[3]); 271 n2 ^= f(c, n1 + c->k[4]); 272 n1 ^= f(c, n2 + c->k[5]); 273 n2 ^= f(c, n1 + c->k[6]); 274 n1 ^= f(c, n2 + c->k[7]); 275 276 n2 ^= f(c, n1 + c->k[7]); 277 n1 ^= f(c, n2 + c->k[6]); 278 n2 ^= f(c, n1 + c->k[5]); 279 n1 ^= f(c, n2 + c->k[4]); 280 n2 ^= f(c, n1 + c->k[3]); 281 n1 ^= f(c, n2 + c->k[2]); 282 n2 ^= f(c, n1 + c->k[1]); 283 n1 ^= f(c, n2 + c->k[0]); 284 285 out[0] = (byte) (n2 & 0xff); 286 out[1] = (byte) ((n2 >> 8) & 0xff); 287 out[2] = (byte) ((n2 >> 16) & 0xff); 288 out[3] = (byte) (n2 >> 24); 289 out[4] = (byte) (n1 & 0xff); 290 out[5] = (byte) ((n1 >> 8) & 0xff); 291 out[6] = (byte) ((n1 >> 16) & 0xff); 292 out[7] = (byte) (n1 >> 24); 293} 294 295/* Low-level decryption routine. Decrypts one 64-bit block */ 296void gostdecrypt(gost_ctx * c, const byte * in, byte * out) 297{ 298 register word32 n1, n2; /* As named in the GOST */ 299 n1 = in[0] | (in[1] << 8) | (in[2] << 16) | ((word32) in[3] << 24); 300 n2 = in[4] | (in[5] << 8) | (in[6] << 16) | ((word32) in[7] << 24); 301 302 n2 ^= f(c, n1 + c->k[0]); 303 n1 ^= f(c, n2 + c->k[1]); 304 n2 ^= f(c, n1 + c->k[2]); 305 n1 ^= f(c, n2 + c->k[3]); 306 n2 ^= f(c, n1 + c->k[4]); 307 n1 ^= f(c, n2 + c->k[5]); 308 n2 ^= f(c, n1 + c->k[6]); 309 n1 ^= f(c, n2 + c->k[7]); 310 311 n2 ^= f(c, n1 + c->k[7]); 312 n1 ^= f(c, n2 + c->k[6]); 313 n2 ^= f(c, n1 + c->k[5]); 314 n1 ^= f(c, n2 + c->k[4]); 315 n2 ^= f(c, n1 + c->k[3]); 316 n1 ^= f(c, n2 + c->k[2]); 317 n2 ^= f(c, n1 + c->k[1]); 318 n1 ^= f(c, n2 + c->k[0]); 319 320 n2 ^= f(c, n1 + c->k[7]); 321 n1 ^= f(c, n2 + c->k[6]); 322 n2 ^= f(c, n1 + c->k[5]); 323 n1 ^= f(c, n2 + c->k[4]); 324 n2 ^= f(c, n1 + c->k[3]); 325 n1 ^= f(c, n2 + c->k[2]); 326 n2 ^= f(c, n1 + c->k[1]); 327 n1 ^= f(c, n2 + c->k[0]); 328 329 n2 ^= f(c, n1 + c->k[7]); 330 n1 ^= f(c, n2 + c->k[6]); 331 n2 ^= f(c, n1 + c->k[5]); 332 n1 ^= f(c, n2 + c->k[4]); 333 n2 ^= f(c, n1 + c->k[3]); 334 n1 ^= f(c, n2 + c->k[2]); 335 n2 ^= f(c, n1 + c->k[1]); 336 n1 ^= f(c, n2 + c->k[0]); 337 338 out[0] = (byte) (n2 & 0xff); 339 out[1] = (byte) ((n2 >> 8) & 0xff); 340 out[2] = (byte) ((n2 >> 16) & 0xff); 341 out[3] = (byte) (n2 >> 24); 342 out[4] = (byte) (n1 & 0xff); 343 out[5] = (byte) ((n1 >> 8) & 0xff); 344 out[6] = (byte) ((n1 >> 16) & 0xff); 345 out[7] = (byte) (n1 >> 24); 346} 347 348/* Encrypts several blocks in ECB mode */ 349void gost_enc(gost_ctx * c, const byte * clear, byte * cipher, int blocks) 350{ 351 int i; 352 for (i = 0; i < blocks; i++) { 353 gostcrypt(c, clear, cipher); 354 clear += 8; 355 cipher += 8; 356 } 357} 358 359/* Decrypts several blocks in ECB mode */ 360void gost_dec(gost_ctx * c, const byte * cipher, byte * clear, int blocks) 361{ 362 int i; 363 for (i = 0; i < blocks; i++) { 364 gostdecrypt(c, cipher, clear); 365 clear += 8; 366 cipher += 8; 367 } 368} 369 370/* Encrypts several full blocks in CFB mode using 8byte IV */ 371void gost_enc_cfb(gost_ctx * ctx, const byte * iv, const byte * clear, 372 byte * cipher, int blocks) 373{ 374 byte cur_iv[8]; 375 byte gamma[8]; 376 int i, j; 377 const byte *in; 378 byte *out; 379 memcpy(cur_iv, iv, 8); 380 for (i = 0, in = clear, out = cipher; i < blocks; i++, in += 8, out += 8) { 381 gostcrypt(ctx, cur_iv, gamma); 382 for (j = 0; j < 8; j++) { 383 cur_iv[j] = out[j] = in[j] ^ gamma[j]; 384 } 385 } 386} 387 388/* Decrypts several full blocks in CFB mode using 8byte IV */ 389void gost_dec_cfb(gost_ctx * ctx, const byte * iv, const byte * cipher, 390 byte * clear, int blocks) 391{ 392 byte cur_iv[8]; 393 byte gamma[8]; 394 int i, j; 395 const byte *in; 396 byte *out; 397 memcpy(cur_iv, iv, 8); 398 for (i = 0, in = cipher, out = clear; i < blocks; i++, in += 8, out += 8) { 399 gostcrypt(ctx, cur_iv, gamma); 400 for (j = 0; j < 8; j++) { 401 out[j] = (cur_iv[j] = in[j]) ^ gamma[j]; 402 } 403 } 404} 405 406/* Encrypts one block using specified key */ 407void gost_enc_with_key(gost_ctx * c, byte * key, byte * inblock, 408 byte * outblock) 409{ 410 gost_key(c, key); 411 gostcrypt(c, inblock, outblock); 412} 413 414/* Set 256 bit key into context */ 415void gost_key(gost_ctx * c, const byte * k) 416{ 417 int i, j; 418 for (i = 0, j = 0; i < 8; i++, j += 4) { 419 c->k[i] = 420 k[j] | (k[j + 1] << 8) | (k[j + 2] << 16) | ((word32) k[j + 3] << 421 24); 422 } 423} 424 425/* Retrieve 256-bit key from context */ 426void gost_get_key(gost_ctx * c, byte * k) 427{ 428 int i, j; 429 for (i = 0, j = 0; i < 8; i++, j += 4) { 430 k[j] = (byte) (c->k[i] & 0xFF); 431 k[j + 1] = (byte) ((c->k[i] >> 8) & 0xFF); 432 k[j + 2] = (byte) ((c->k[i] >> 16) & 0xFF); 433 k[j + 3] = (byte) ((c->k[i] >> 24) & 0xFF); 434 } 435} 436 437/* Initalize context. Provides default value for subst_block */ 438void gost_init(gost_ctx * c, const gost_subst_block * b) 439{ 440 if (!b) { 441 b = &GostR3411_94_TestParamSet; 442 } 443 kboxinit(c, b); 444} 445 446/* Cleans up key from context */ 447void gost_destroy(gost_ctx * c) 448{ 449 int i; 450 for (i = 0; i < 8; i++) 451 c->k[i] = 0; 452} 453 454/* 455 * Compute GOST 28147 mac block Parameters gost_ctx *c - context initalized 456 * with substitution blocks and key buffer - 8-byte mac state buffer block 457 * 8-byte block to process. 458 */ 459void mac_block(gost_ctx * c, byte * buffer, const byte * block) 460{ 461 register word32 n1, n2; /* As named in the GOST */ 462 int i; 463 for (i = 0; i < 8; i++) { 464 buffer[i] ^= block[i]; 465 } 466 n1 = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | ((word32) 467 buffer[3] << 24); 468 n2 = buffer[4] | (buffer[5] << 8) | (buffer[6] << 16) | ((word32) 469 buffer[7] << 24); 470 /* Instead of swapping halves, swap names each round */ 471 472 n2 ^= f(c, n1 + c->k[0]); 473 n1 ^= f(c, n2 + c->k[1]); 474 n2 ^= f(c, n1 + c->k[2]); 475 n1 ^= f(c, n2 + c->k[3]); 476 n2 ^= f(c, n1 + c->k[4]); 477 n1 ^= f(c, n2 + c->k[5]); 478 n2 ^= f(c, n1 + c->k[6]); 479 n1 ^= f(c, n2 + c->k[7]); 480 481 n2 ^= f(c, n1 + c->k[0]); 482 n1 ^= f(c, n2 + c->k[1]); 483 n2 ^= f(c, n1 + c->k[2]); 484 n1 ^= f(c, n2 + c->k[3]); 485 n2 ^= f(c, n1 + c->k[4]); 486 n1 ^= f(c, n2 + c->k[5]); 487 n2 ^= f(c, n1 + c->k[6]); 488 n1 ^= f(c, n2 + c->k[7]); 489 490 buffer[0] = (byte) (n1 & 0xff); 491 buffer[1] = (byte) ((n1 >> 8) & 0xff); 492 buffer[2] = (byte) ((n1 >> 16) & 0xff); 493 buffer[3] = (byte) (n1 >> 24); 494 buffer[4] = (byte) (n2 & 0xff); 495 buffer[5] = (byte) ((n2 >> 8) & 0xff); 496 buffer[6] = (byte) ((n2 >> 16) & 0xff); 497 buffer[7] = (byte) (n2 >> 24); 498} 499 500/* Get mac with specified number of bits from MAC state buffer */ 501void get_mac(byte * buffer, int nbits, byte * out) 502{ 503 int nbytes = nbits >> 3; 504 int rembits = nbits & 7; 505 int mask = rembits ? ((1 < rembits) - 1) : 0; 506 int i; 507 for (i = 0; i < nbytes; i++) 508 out[i] = buffer[i]; 509 if (rembits) 510 out[i] = buffer[i] & mask; 511} 512 513/* 514 * Compute mac of specified length (in bits) from data. Context should be 515 * initialized with key and subst blocks 516 */ 517int gost_mac(gost_ctx * ctx, int mac_len, const unsigned char *data, 518 unsigned int data_len, unsigned char *mac) 519{ 520 byte buffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 521 byte buf2[8]; 522 unsigned int i; 523 for (i = 0; i + 8 <= data_len; i += 8) 524 mac_block(ctx, buffer, data + i); 525 if (i < data_len) { 526 memset(buf2, 0, 8); 527 memcpy(buf2, data + i, data_len - i); 528 mac_block(ctx, buffer, buf2); 529 i += 8; 530 } 531 if (i == 8) { 532 memset(buf2, 0, 8); 533 mac_block(ctx, buffer, buf2); 534 } 535 get_mac(buffer, mac_len, mac); 536 return 1; 537} 538 539/* Compute MAC with non-zero IV. Used in some RFC 4357 algorithms */ 540int gost_mac_iv(gost_ctx * ctx, int mac_len, const unsigned char *iv, 541 const unsigned char *data, unsigned int data_len, 542 unsigned char *mac) 543{ 544 byte buffer[8]; 545 byte buf2[8]; 546 unsigned int i; 547 memcpy(buffer, iv, 8); 548 for (i = 0; i + 8 <= data_len; i += 8) 549 mac_block(ctx, buffer, data + i); 550 if (i < data_len) { 551 memset(buf2, 0, 8); 552 memcpy(buf2, data + i, data_len - i); 553 mac_block(ctx, buffer, buf2); 554 i += 8; 555 } 556 if (i == 8) { 557 memset(buf2, 0, 8); 558 mac_block(ctx, buffer, buf2); 559 } 560 get_mac(buffer, mac_len, mac); 561 return 1; 562} 563 564/* Implements key meshing algorithm by modifing ctx and IV in place */ 565void cryptopro_key_meshing(gost_ctx * ctx, unsigned char *iv) 566{ 567 unsigned char newkey[32], newiv[8]; 568 /* Set static keymeshing key */ 569 /* "Decrypt" key with keymeshing key */ 570 gost_dec(ctx, CryptoProKeyMeshingKey, newkey, 4); 571 /* set new key */ 572 gost_key(ctx, newkey); 573 /* Encrypt iv with new key */ 574 gostcrypt(ctx, iv, newiv); 575 memcpy(iv, newiv, 8); 576} 577