1238384Sjkim/********************************************************************** 2238384Sjkim * gost89.c * 3238384Sjkim * Copyright (c) 2005-2006 Cryptocom LTD * 4238384Sjkim * This file is distributed under the same license as OpenSSL * 5238384Sjkim * * 6238384Sjkim * Implementation of GOST 28147-89 encryption algorithm * 7238384Sjkim * No OpenSSL libraries required to compile and use * 8238384Sjkim * this code * 9280304Sjkim **********************************************************************/ 10238384Sjkim#include <string.h> 11238384Sjkim#include "gost89.h" 12280304Sjkim/*- 13280304Sjkim Substitution blocks from RFC 4357 14280304Sjkim 15280304Sjkim Note: our implementation of gost 28147-89 algorithm 16280304Sjkim uses S-box matrix rotated 90 degrees counterclockwise, relative to 17238384Sjkim examples given in RFC. 18238384Sjkim 19280304Sjkim 20238384Sjkim*/ 21238384Sjkim 22238384Sjkim/* Substitution blocks from test examples for GOST R 34.11-94*/ 23238384Sjkimgost_subst_block GostR3411_94_TestParamSet = { 24280304Sjkim {0X1, 0XF, 0XD, 0X0, 0X5, 0X7, 0XA, 0X4, 0X9, 0X2, 0X3, 0XE, 0X6, 0XB, 25280304Sjkim 0X8, 0XC} 26280304Sjkim , 27280304Sjkim {0XD, 0XB, 0X4, 0X1, 0X3, 0XF, 0X5, 0X9, 0X0, 0XA, 0XE, 0X7, 0X6, 0X8, 28280304Sjkim 0X2, 0XC} 29280304Sjkim , 30280304Sjkim {0X4, 0XB, 0XA, 0X0, 0X7, 0X2, 0X1, 0XD, 0X3, 0X6, 0X8, 0X5, 0X9, 0XC, 31280304Sjkim 0XF, 0XE} 32280304Sjkim , 33280304Sjkim {0X6, 0XC, 0X7, 0X1, 0X5, 0XF, 0XD, 0X8, 0X4, 0XA, 0X9, 0XE, 0X0, 0X3, 34280304Sjkim 0XB, 0X2} 35280304Sjkim , 36280304Sjkim {0X7, 0XD, 0XA, 0X1, 0X0, 0X8, 0X9, 0XF, 0XE, 0X4, 0X6, 0XC, 0XB, 0X2, 37280304Sjkim 0X5, 0X3} 38280304Sjkim , 39280304Sjkim {0X5, 0X8, 0X1, 0XD, 0XA, 0X3, 0X4, 0X2, 0XE, 0XF, 0XC, 0X7, 0X6, 0X0, 40280304Sjkim 0X9, 0XB} 41280304Sjkim , 42280304Sjkim {0XE, 0XB, 0X4, 0XC, 0X6, 0XD, 0XF, 0XA, 0X2, 0X3, 0X8, 0X1, 0X0, 0X7, 43280304Sjkim 0X5, 0X9} 44280304Sjkim , 45280304Sjkim {0X4, 0XA, 0X9, 0X2, 0XD, 0X8, 0X0, 0XE, 0X6, 0XB, 0X1, 0XC, 0X7, 0XF, 46280304Sjkim 0X5, 0X3} 47280304Sjkim}; 48280304Sjkim 49238384Sjkim/* Substitution blocks for hash function 1.2.643.2.9.1.6.1 */ 50280304Sjkimgost_subst_block GostR3411_94_CryptoProParamSet = { 51280304Sjkim {0x1, 0x3, 0xA, 0x9, 0x5, 0xB, 0x4, 0xF, 0x8, 0x6, 0x7, 0xE, 0xD, 0x0, 52280304Sjkim 0x2, 0xC} 53280304Sjkim , 54280304Sjkim {0xD, 0xE, 0x4, 0x1, 0x7, 0x0, 0x5, 0xA, 0x3, 0xC, 0x8, 0xF, 0x6, 0x2, 55280304Sjkim 0x9, 0xB} 56280304Sjkim , 57280304Sjkim {0x7, 0x6, 0x2, 0x4, 0xD, 0x9, 0xF, 0x0, 0xA, 0x1, 0x5, 0xB, 0x8, 0xE, 58280304Sjkim 0xC, 0x3} 59280304Sjkim , 60280304Sjkim {0x7, 0x6, 0x4, 0xB, 0x9, 0xC, 0x2, 0xA, 0x1, 0x8, 0x0, 0xE, 0xF, 0xD, 61280304Sjkim 0x3, 0x5} 62280304Sjkim , 63280304Sjkim {0x4, 0xA, 0x7, 0xC, 0x0, 0xF, 0x2, 0x8, 0xE, 0x1, 0x6, 0x5, 0xD, 0xB, 64280304Sjkim 0x9, 0x3} 65280304Sjkim , 66280304Sjkim {0x7, 0xF, 0xC, 0xE, 0x9, 0x4, 0x1, 0x0, 0x3, 0xB, 0x5, 0x2, 0x6, 0xA, 67280304Sjkim 0x8, 0xD} 68280304Sjkim , 69280304Sjkim {0x5, 0xF, 0x4, 0x0, 0x2, 0xD, 0xB, 0x9, 0x1, 0x7, 0x6, 0x3, 0xC, 0xE, 70280304Sjkim 0xA, 0x8} 71280304Sjkim , 72280304Sjkim {0xA, 0x4, 0x5, 0x6, 0x8, 0x1, 0x3, 0x7, 0xD, 0xC, 0xE, 0x0, 0x9, 0x2, 73280304Sjkim 0xB, 0xF} 74280304Sjkim}; 75238384Sjkim 76238384Sjkim/* Test paramset from GOST 28147 */ 77280304Sjkimgost_subst_block Gost28147_TestParamSet = { 78280304Sjkim {0xC, 0x6, 0x5, 0x2, 0xB, 0x0, 0x9, 0xD, 0x3, 0xE, 0x7, 0xA, 0xF, 0x4, 79280304Sjkim 0x1, 0x8} 80280304Sjkim , 81280304Sjkim {0x9, 0xB, 0xC, 0x0, 0x3, 0x6, 0x7, 0x5, 0x4, 0x8, 0xE, 0xF, 0x1, 0xA, 82280304Sjkim 0x2, 0xD} 83280304Sjkim , 84280304Sjkim {0x8, 0xF, 0x6, 0xB, 0x1, 0x9, 0xC, 0x5, 0xD, 0x3, 0x7, 0xA, 0x0, 0xE, 85280304Sjkim 0x2, 0x4} 86280304Sjkim , 87280304Sjkim {0x3, 0xE, 0x5, 0x9, 0x6, 0x8, 0x0, 0xD, 0xA, 0xB, 0x7, 0xC, 0x2, 0x1, 88280304Sjkim 0xF, 0x4} 89280304Sjkim , 90280304Sjkim {0xE, 0x9, 0xB, 0x2, 0x5, 0xF, 0x7, 0x1, 0x0, 0xD, 0xC, 0x6, 0xA, 0x4, 91280304Sjkim 0x3, 0x8} 92280304Sjkim , 93280304Sjkim {0xD, 0x8, 0xE, 0xC, 0x7, 0x3, 0x9, 0xA, 0x1, 0x5, 0x2, 0x4, 0x6, 0xF, 94280304Sjkim 0x0, 0xB} 95280304Sjkim , 96280304Sjkim {0xC, 0x9, 0xF, 0xE, 0x8, 0x1, 0x3, 0xA, 0x2, 0x7, 0x4, 0xD, 0x6, 0x0, 97280304Sjkim 0xB, 0x5} 98280304Sjkim , 99280304Sjkim {0x4, 0x2, 0xF, 0x5, 0x9, 0x1, 0x0, 0x8, 0xE, 0x3, 0xB, 0xC, 0xD, 0x7, 100280304Sjkim 0xA, 0x6} 101280304Sjkim}; 102238384Sjkim 103280304Sjkim/* 1.2.643.2.2.31.1 */ 104280304Sjkimgost_subst_block Gost28147_CryptoProParamSetA = { 105280304Sjkim {0xB, 0xA, 0xF, 0x5, 0x0, 0xC, 0xE, 0x8, 0x6, 0x2, 0x3, 0x9, 0x1, 0x7, 106280304Sjkim 0xD, 0x4} 107280304Sjkim , 108280304Sjkim {0x1, 0xD, 0x2, 0x9, 0x7, 0xA, 0x6, 0x0, 0x8, 0xC, 0x4, 0x5, 0xF, 0x3, 109280304Sjkim 0xB, 0xE} 110280304Sjkim , 111280304Sjkim {0x3, 0xA, 0xD, 0xC, 0x1, 0x2, 0x0, 0xB, 0x7, 0x5, 0x9, 0x4, 0x8, 0xF, 112280304Sjkim 0xE, 0x6} 113280304Sjkim , 114280304Sjkim {0xB, 0x5, 0x1, 0x9, 0x8, 0xD, 0xF, 0x0, 0xE, 0x4, 0x2, 0x3, 0xC, 0x7, 115280304Sjkim 0xA, 0x6} 116280304Sjkim , 117280304Sjkim {0xE, 0x7, 0xA, 0xC, 0xD, 0x1, 0x3, 0x9, 0x0, 0x2, 0xB, 0x4, 0xF, 0x8, 118280304Sjkim 0x5, 0x6} 119280304Sjkim , 120280304Sjkim {0xE, 0x4, 0x6, 0x2, 0xB, 0x3, 0xD, 0x8, 0xC, 0xF, 0x5, 0xA, 0x0, 0x7, 121280304Sjkim 0x1, 0x9} 122280304Sjkim , 123280304Sjkim {0x3, 0x7, 0xE, 0x9, 0x8, 0xA, 0xF, 0x0, 0x5, 0x2, 0x6, 0xC, 0xB, 0x4, 124280304Sjkim 0xD, 0x1} 125280304Sjkim , 126280304Sjkim {0x9, 0x6, 0x3, 0x2, 0x8, 0xB, 0x1, 0x7, 0xA, 0x4, 0xE, 0xF, 0xC, 0x0, 127280304Sjkim 0xD, 0x5} 128280304Sjkim}; 129238384Sjkim 130280304Sjkim/* 1.2.643.2.2.31.2 */ 131280304Sjkimgost_subst_block Gost28147_CryptoProParamSetB = { 132280304Sjkim {0x0, 0x4, 0xB, 0xE, 0x8, 0x3, 0x7, 0x1, 0xA, 0x2, 0x9, 0x6, 0xF, 0xD, 133280304Sjkim 0x5, 0xC} 134280304Sjkim , 135280304Sjkim {0x5, 0x2, 0xA, 0xB, 0x9, 0x1, 0xC, 0x3, 0x7, 0x4, 0xD, 0x0, 0x6, 0xF, 136280304Sjkim 0x8, 0xE} 137280304Sjkim , 138280304Sjkim {0x8, 0x3, 0x2, 0x6, 0x4, 0xD, 0xE, 0xB, 0xC, 0x1, 0x7, 0xF, 0xA, 0x0, 139280304Sjkim 0x9, 0x5} 140280304Sjkim , 141280304Sjkim {0x2, 0x7, 0xC, 0xF, 0x9, 0x5, 0xA, 0xB, 0x1, 0x4, 0x0, 0xD, 0x6, 0x8, 142280304Sjkim 0xE, 0x3} 143280304Sjkim , 144280304Sjkim {0x7, 0x5, 0x0, 0xD, 0xB, 0x6, 0x1, 0x2, 0x3, 0xA, 0xC, 0xF, 0x4, 0xE, 145280304Sjkim 0x9, 0x8} 146280304Sjkim , 147280304Sjkim {0xE, 0xC, 0x0, 0xA, 0x9, 0x2, 0xD, 0xB, 0x7, 0x5, 0x8, 0xF, 0x3, 0x6, 148280304Sjkim 0x1, 0x4} 149280304Sjkim , 150280304Sjkim {0x0, 0x1, 0x2, 0xA, 0x4, 0xD, 0x5, 0xC, 0x9, 0x7, 0x3, 0xF, 0xB, 0x8, 151280304Sjkim 0x6, 0xE} 152280304Sjkim , 153280304Sjkim {0x8, 0x4, 0xB, 0x1, 0x3, 0x5, 0x0, 0x9, 0x2, 0xE, 0xA, 0xC, 0xD, 0x6, 154280304Sjkim 0x7, 0xF} 155280304Sjkim}; 156238384Sjkim 157238384Sjkim/* 1.2.643.2.2.31.3 */ 158280304Sjkimgost_subst_block Gost28147_CryptoProParamSetC = { 159280304Sjkim {0x7, 0x4, 0x0, 0x5, 0xA, 0x2, 0xF, 0xE, 0xC, 0x6, 0x1, 0xB, 0xD, 0x9, 160280304Sjkim 0x3, 0x8} 161280304Sjkim , 162280304Sjkim {0xA, 0x9, 0x6, 0x8, 0xD, 0xE, 0x2, 0x0, 0xF, 0x3, 0x5, 0xB, 0x4, 0x1, 163280304Sjkim 0xC, 0x7} 164280304Sjkim , 165280304Sjkim {0xC, 0x9, 0xB, 0x1, 0x8, 0xE, 0x2, 0x4, 0x7, 0x3, 0x6, 0x5, 0xA, 0x0, 166280304Sjkim 0xF, 0xD} 167280304Sjkim , 168280304Sjkim {0x8, 0xD, 0xB, 0x0, 0x4, 0x5, 0x1, 0x2, 0x9, 0x3, 0xC, 0xE, 0x6, 0xF, 169280304Sjkim 0xA, 0x7} 170280304Sjkim , 171280304Sjkim {0x3, 0x6, 0x0, 0x1, 0x5, 0xD, 0xA, 0x8, 0xB, 0x2, 0x9, 0x7, 0xE, 0xF, 172280304Sjkim 0xC, 0x4} 173280304Sjkim , 174280304Sjkim {0x8, 0x2, 0x5, 0x0, 0x4, 0x9, 0xF, 0xA, 0x3, 0x7, 0xC, 0xD, 0x6, 0xE, 175280304Sjkim 0x1, 0xB} 176280304Sjkim , 177280304Sjkim {0x0, 0x1, 0x7, 0xD, 0xB, 0x4, 0x5, 0x2, 0x8, 0xE, 0xF, 0xC, 0x9, 0xA, 178280304Sjkim 0x6, 0x3} 179280304Sjkim , 180280304Sjkim {0x1, 0xB, 0xC, 0x2, 0x9, 0xD, 0x0, 0xF, 0x4, 0x5, 0x8, 0xE, 0xA, 0x7, 181280304Sjkim 0x6, 0x3} 182280304Sjkim}; 183238384Sjkim 184280304Sjkim/* 1.2.643.2.2.31.4 */ 185280304Sjkimgost_subst_block Gost28147_CryptoProParamSetD = { 186280304Sjkim {0x1, 0xA, 0x6, 0x8, 0xF, 0xB, 0x0, 0x4, 0xC, 0x3, 0x5, 0x9, 0x7, 0xD, 187280304Sjkim 0x2, 0xE} 188280304Sjkim , 189280304Sjkim {0x3, 0x0, 0x6, 0xF, 0x1, 0xE, 0x9, 0x2, 0xD, 0x8, 0xC, 0x4, 0xB, 0xA, 190280304Sjkim 0x5, 0x7} 191280304Sjkim , 192280304Sjkim {0x8, 0x0, 0xF, 0x3, 0x2, 0x5, 0xE, 0xB, 0x1, 0xA, 0x4, 0x7, 0xC, 0x9, 193280304Sjkim 0xD, 0x6} 194280304Sjkim , 195280304Sjkim {0x0, 0xC, 0x8, 0x9, 0xD, 0x2, 0xA, 0xB, 0x7, 0x3, 0x6, 0x5, 0x4, 0xE, 196280304Sjkim 0xF, 0x1} 197280304Sjkim , 198280304Sjkim {0x1, 0x5, 0xE, 0xC, 0xA, 0x7, 0x0, 0xD, 0x6, 0x2, 0xB, 0x4, 0x9, 0x3, 199280304Sjkim 0xF, 0x8} 200280304Sjkim , 201280304Sjkim {0x1, 0xC, 0xB, 0x0, 0xF, 0xE, 0x6, 0x5, 0xA, 0xD, 0x4, 0x8, 0x9, 0x3, 202280304Sjkim 0x7, 0x2} 203280304Sjkim , 204280304Sjkim {0xB, 0x6, 0x3, 0x4, 0xC, 0xF, 0xE, 0x2, 0x7, 0xD, 0x8, 0x0, 0x5, 0xA, 205280304Sjkim 0x9, 0x1} 206280304Sjkim , 207280304Sjkim {0xF, 0xC, 0x2, 0xA, 0x6, 0x4, 0x5, 0x0, 0x7, 0x9, 0xE, 0xD, 0x1, 0xB, 208280304Sjkim 0x8, 0x3} 209280304Sjkim}; 210238384Sjkim 211280304Sjkimconst byte CryptoProKeyMeshingKey[] = { 212280304Sjkim 0x69, 0x00, 0x72, 0x22, 0x64, 0xC9, 0x04, 0x23, 213280304Sjkim 0x8D, 0x3A, 0xDB, 0x96, 0x46, 0xE9, 0x2A, 0xC4, 214280304Sjkim 0x18, 0xFE, 0xAC, 0x94, 0x00, 0xED, 0x07, 0x12, 215280304Sjkim 0xC0, 0x86, 0xDC, 0xC2, 0xEF, 0x4C, 0xA9, 0x2B 216280304Sjkim}; 217238384Sjkim 218238384Sjkim/* Initialization of gost_ctx subst blocks*/ 219280304Sjkimstatic void kboxinit(gost_ctx * c, const gost_subst_block * b) 220280304Sjkim{ 221280304Sjkim int i; 222238384Sjkim 223280304Sjkim for (i = 0; i < 256; i++) { 224280304Sjkim c->k87[i] = (b->k8[i >> 4] << 4 | b->k7[i & 15]) << 24; 225280304Sjkim c->k65[i] = (b->k6[i >> 4] << 4 | b->k5[i & 15]) << 16; 226280304Sjkim c->k43[i] = (b->k4[i >> 4] << 4 | b->k3[i & 15]) << 8; 227280304Sjkim c->k21[i] = b->k2[i >> 4] << 4 | b->k1[i & 15]; 228238384Sjkim 229280304Sjkim } 230280304Sjkim} 231280304Sjkim 232238384Sjkim/* Part of GOST 28147 algorithm moved into separate function */ 233280304Sjkimstatic word32 f(gost_ctx * c, word32 x) 234280304Sjkim{ 235280304Sjkim x = c->k87[x >> 24 & 255] | c->k65[x >> 16 & 255] | 236280304Sjkim c->k43[x >> 8 & 255] | c->k21[x & 255]; 237280304Sjkim /* Rotate left 11 bits */ 238280304Sjkim return x << 11 | x >> (32 - 11); 239280304Sjkim} 240280304Sjkim 241238384Sjkim/* Low-level encryption routine - encrypts one 64 bit block*/ 242280304Sjkimvoid gostcrypt(gost_ctx * c, const byte * in, byte * out) 243280304Sjkim{ 244280304Sjkim register word32 n1, n2; /* As named in the GOST */ 245280304Sjkim n1 = in[0] | (in[1] << 8) | (in[2] << 16) | (in[3] << 24); 246280304Sjkim n2 = in[4] | (in[5] << 8) | (in[6] << 16) | (in[7] << 24); 247280304Sjkim /* Instead of swapping halves, swap names each round */ 248280304Sjkim 249280304Sjkim n2 ^= f(c, n1 + c->k[0]); 250280304Sjkim n1 ^= f(c, n2 + c->k[1]); 251280304Sjkim n2 ^= f(c, n1 + c->k[2]); 252280304Sjkim n1 ^= f(c, n2 + c->k[3]); 253280304Sjkim n2 ^= f(c, n1 + c->k[4]); 254280304Sjkim n1 ^= f(c, n2 + c->k[5]); 255280304Sjkim n2 ^= f(c, n1 + c->k[6]); 256280304Sjkim n1 ^= f(c, n2 + c->k[7]); 257280304Sjkim 258280304Sjkim n2 ^= f(c, n1 + c->k[0]); 259280304Sjkim n1 ^= f(c, n2 + c->k[1]); 260280304Sjkim n2 ^= f(c, n1 + c->k[2]); 261280304Sjkim n1 ^= f(c, n2 + c->k[3]); 262280304Sjkim n2 ^= f(c, n1 + c->k[4]); 263280304Sjkim n1 ^= f(c, n2 + c->k[5]); 264280304Sjkim n2 ^= f(c, n1 + c->k[6]); 265280304Sjkim n1 ^= f(c, n2 + c->k[7]); 266280304Sjkim 267280304Sjkim n2 ^= f(c, n1 + c->k[0]); 268280304Sjkim n1 ^= f(c, n2 + c->k[1]); 269280304Sjkim n2 ^= f(c, n1 + c->k[2]); 270280304Sjkim n1 ^= f(c, n2 + c->k[3]); 271280304Sjkim n2 ^= f(c, n1 + c->k[4]); 272280304Sjkim n1 ^= f(c, n2 + c->k[5]); 273280304Sjkim n2 ^= f(c, n1 + c->k[6]); 274280304Sjkim n1 ^= f(c, n2 + c->k[7]); 275280304Sjkim 276280304Sjkim n2 ^= f(c, n1 + c->k[7]); 277280304Sjkim n1 ^= f(c, n2 + c->k[6]); 278280304Sjkim n2 ^= f(c, n1 + c->k[5]); 279280304Sjkim n1 ^= f(c, n2 + c->k[4]); 280280304Sjkim n2 ^= f(c, n1 + c->k[3]); 281280304Sjkim n1 ^= f(c, n2 + c->k[2]); 282280304Sjkim n2 ^= f(c, n1 + c->k[1]); 283280304Sjkim n1 ^= f(c, n2 + c->k[0]); 284280304Sjkim 285280304Sjkim out[0] = (byte) (n2 & 0xff); 286280304Sjkim out[1] = (byte) ((n2 >> 8) & 0xff); 287280304Sjkim out[2] = (byte) ((n2 >> 16) & 0xff); 288280304Sjkim out[3] = (byte) (n2 >> 24); 289280304Sjkim out[4] = (byte) (n1 & 0xff); 290280304Sjkim out[5] = (byte) ((n1 >> 8) & 0xff); 291280304Sjkim out[6] = (byte) ((n1 >> 16) & 0xff); 292280304Sjkim out[7] = (byte) (n1 >> 24); 293280304Sjkim} 294280304Sjkim 295238384Sjkim/* Low-level decryption routine. Decrypts one 64-bit block */ 296280304Sjkimvoid gostdecrypt(gost_ctx * c, const byte * in, byte * out) 297280304Sjkim{ 298280304Sjkim register word32 n1, n2; /* As named in the GOST */ 299280304Sjkim n1 = in[0] | (in[1] << 8) | (in[2] << 16) | (in[3] << 24); 300280304Sjkim n2 = in[4] | (in[5] << 8) | (in[6] << 16) | (in[7] << 24); 301238384Sjkim 302280304Sjkim n2 ^= f(c, n1 + c->k[0]); 303280304Sjkim n1 ^= f(c, n2 + c->k[1]); 304280304Sjkim n2 ^= f(c, n1 + c->k[2]); 305280304Sjkim n1 ^= f(c, n2 + c->k[3]); 306280304Sjkim n2 ^= f(c, n1 + c->k[4]); 307280304Sjkim n1 ^= f(c, n2 + c->k[5]); 308280304Sjkim n2 ^= f(c, n1 + c->k[6]); 309280304Sjkim n1 ^= f(c, n2 + c->k[7]); 310238384Sjkim 311280304Sjkim n2 ^= f(c, n1 + c->k[7]); 312280304Sjkim n1 ^= f(c, n2 + c->k[6]); 313280304Sjkim n2 ^= f(c, n1 + c->k[5]); 314280304Sjkim n1 ^= f(c, n2 + c->k[4]); 315280304Sjkim n2 ^= f(c, n1 + c->k[3]); 316280304Sjkim n1 ^= f(c, n2 + c->k[2]); 317280304Sjkim n2 ^= f(c, n1 + c->k[1]); 318280304Sjkim n1 ^= f(c, n2 + c->k[0]); 319280304Sjkim 320280304Sjkim n2 ^= f(c, n1 + c->k[7]); 321280304Sjkim n1 ^= f(c, n2 + c->k[6]); 322280304Sjkim n2 ^= f(c, n1 + c->k[5]); 323280304Sjkim n1 ^= f(c, n2 + c->k[4]); 324280304Sjkim n2 ^= f(c, n1 + c->k[3]); 325280304Sjkim n1 ^= f(c, n2 + c->k[2]); 326280304Sjkim n2 ^= f(c, n1 + c->k[1]); 327280304Sjkim n1 ^= f(c, n2 + c->k[0]); 328280304Sjkim 329280304Sjkim n2 ^= f(c, n1 + c->k[7]); 330280304Sjkim n1 ^= f(c, n2 + c->k[6]); 331280304Sjkim n2 ^= f(c, n1 + c->k[5]); 332280304Sjkim n1 ^= f(c, n2 + c->k[4]); 333280304Sjkim n2 ^= f(c, n1 + c->k[3]); 334280304Sjkim n1 ^= f(c, n2 + c->k[2]); 335280304Sjkim n2 ^= f(c, n1 + c->k[1]); 336280304Sjkim n1 ^= f(c, n2 + c->k[0]); 337280304Sjkim 338280304Sjkim out[0] = (byte) (n2 & 0xff); 339280304Sjkim out[1] = (byte) ((n2 >> 8) & 0xff); 340280304Sjkim out[2] = (byte) ((n2 >> 16) & 0xff); 341280304Sjkim out[3] = (byte) (n2 >> 24); 342280304Sjkim out[4] = (byte) (n1 & 0xff); 343280304Sjkim out[5] = (byte) ((n1 >> 8) & 0xff); 344280304Sjkim out[6] = (byte) ((n1 >> 16) & 0xff); 345280304Sjkim out[7] = (byte) (n1 >> 24); 346280304Sjkim} 347280304Sjkim 348238384Sjkim/* Encrypts several blocks in ECB mode */ 349280304Sjkimvoid gost_enc(gost_ctx * c, const byte * clear, byte * cipher, int blocks) 350280304Sjkim{ 351280304Sjkim int i; 352280304Sjkim for (i = 0; i < blocks; i++) { 353280304Sjkim gostcrypt(c, clear, cipher); 354280304Sjkim clear += 8; 355280304Sjkim cipher += 8; 356280304Sjkim } 357280304Sjkim} 358280304Sjkim 359238384Sjkim/* Decrypts several blocks in ECB mode */ 360280304Sjkimvoid gost_dec(gost_ctx * c, const byte * cipher, byte * clear, int blocks) 361280304Sjkim{ 362280304Sjkim int i; 363280304Sjkim for (i = 0; i < blocks; i++) { 364280304Sjkim gostdecrypt(c, cipher, clear); 365280304Sjkim clear += 8; 366280304Sjkim cipher += 8; 367280304Sjkim } 368280304Sjkim} 369238384Sjkim 370238384Sjkim/* Encrypts several full blocks in CFB mode using 8byte IV */ 371280304Sjkimvoid gost_enc_cfb(gost_ctx * ctx, const byte * iv, const byte * clear, 372280304Sjkim byte * cipher, int blocks) 373280304Sjkim{ 374280304Sjkim byte cur_iv[8]; 375280304Sjkim byte gamma[8]; 376280304Sjkim int i, j; 377280304Sjkim const byte *in; 378280304Sjkim byte *out; 379280304Sjkim memcpy(cur_iv, iv, 8); 380280304Sjkim for (i = 0, in = clear, out = cipher; i < blocks; i++, in += 8, out += 8) { 381280304Sjkim gostcrypt(ctx, cur_iv, gamma); 382280304Sjkim for (j = 0; j < 8; j++) { 383280304Sjkim cur_iv[j] = out[j] = in[j] ^ gamma[j]; 384280304Sjkim } 385280304Sjkim } 386280304Sjkim} 387280304Sjkim 388238384Sjkim/* Decrypts several full blocks in CFB mode using 8byte IV */ 389280304Sjkimvoid gost_dec_cfb(gost_ctx * ctx, const byte * iv, const byte * cipher, 390280304Sjkim byte * clear, int blocks) 391280304Sjkim{ 392280304Sjkim byte cur_iv[8]; 393280304Sjkim byte gamma[8]; 394280304Sjkim int i, j; 395280304Sjkim const byte *in; 396280304Sjkim byte *out; 397280304Sjkim memcpy(cur_iv, iv, 8); 398280304Sjkim for (i = 0, in = cipher, out = clear; i < blocks; i++, in += 8, out += 8) { 399280304Sjkim gostcrypt(ctx, cur_iv, gamma); 400280304Sjkim for (j = 0; j < 8; j++) { 401280304Sjkim out[j] = (cur_iv[j] = in[j]) ^ gamma[j]; 402280304Sjkim } 403280304Sjkim } 404280304Sjkim} 405238384Sjkim 406238384Sjkim/* Encrypts one block using specified key */ 407280304Sjkimvoid gost_enc_with_key(gost_ctx * c, byte * key, byte * inblock, 408280304Sjkim byte * outblock) 409280304Sjkim{ 410280304Sjkim gost_key(c, key); 411280304Sjkim gostcrypt(c, inblock, outblock); 412280304Sjkim} 413238384Sjkim 414238384Sjkim/* Set 256 bit key into context */ 415280304Sjkimvoid gost_key(gost_ctx * c, const byte * k) 416280304Sjkim{ 417280304Sjkim int i, j; 418280304Sjkim for (i = 0, j = 0; i < 8; i++, j += 4) { 419280304Sjkim c->k[i] = 420280304Sjkim k[j] | (k[j + 1] << 8) | (k[j + 2] << 16) | (k[j + 3] << 24); 421280304Sjkim } 422280304Sjkim} 423238384Sjkim 424238384Sjkim/* Retrieve 256-bit key from context */ 425280304Sjkimvoid gost_get_key(gost_ctx * c, byte * k) 426280304Sjkim{ 427280304Sjkim int i, j; 428280304Sjkim for (i = 0, j = 0; i < 8; i++, j += 4) { 429280304Sjkim k[j] = (byte) (c->k[i] & 0xFF); 430280304Sjkim k[j + 1] = (byte) ((c->k[i] >> 8) & 0xFF); 431280304Sjkim k[j + 2] = (byte) ((c->k[i] >> 16) & 0xFF); 432280304Sjkim k[j + 3] = (byte) ((c->k[i] >> 24) & 0xFF); 433280304Sjkim } 434280304Sjkim} 435238384Sjkim 436238384Sjkim/* Initalize context. Provides default value for subst_block */ 437280304Sjkimvoid gost_init(gost_ctx * c, const gost_subst_block * b) 438280304Sjkim{ 439280304Sjkim if (!b) { 440280304Sjkim b = &GostR3411_94_TestParamSet; 441280304Sjkim } 442280304Sjkim kboxinit(c, b); 443280304Sjkim} 444238384Sjkim 445238384Sjkim/* Cleans up key from context */ 446280304Sjkimvoid gost_destroy(gost_ctx * c) 447280304Sjkim{ 448280304Sjkim int i; 449280304Sjkim for (i = 0; i < 8; i++) 450280304Sjkim c->k[i] = 0; 451280304Sjkim} 452238384Sjkim 453280304Sjkim/* 454280304Sjkim * Compute GOST 28147 mac block Parameters gost_ctx *c - context initalized 455280304Sjkim * with substitution blocks and key buffer - 8-byte mac state buffer block 456280304Sjkim * 8-byte block to process. 457280304Sjkim */ 458280304Sjkimvoid mac_block(gost_ctx * c, byte * buffer, const byte * block) 459280304Sjkim{ 460280304Sjkim register word32 n1, n2; /* As named in the GOST */ 461280304Sjkim int i; 462280304Sjkim for (i = 0; i < 8; i++) { 463280304Sjkim buffer[i] ^= block[i]; 464280304Sjkim } 465280304Sjkim n1 = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24); 466280304Sjkim n2 = buffer[4] | (buffer[5] << 8) | (buffer[6] << 16) | (buffer[7] << 24); 467280304Sjkim /* Instead of swapping halves, swap names each round */ 468238384Sjkim 469280304Sjkim n2 ^= f(c, n1 + c->k[0]); 470280304Sjkim n1 ^= f(c, n2 + c->k[1]); 471280304Sjkim n2 ^= f(c, n1 + c->k[2]); 472280304Sjkim n1 ^= f(c, n2 + c->k[3]); 473280304Sjkim n2 ^= f(c, n1 + c->k[4]); 474280304Sjkim n1 ^= f(c, n2 + c->k[5]); 475280304Sjkim n2 ^= f(c, n1 + c->k[6]); 476280304Sjkim n1 ^= f(c, n2 + c->k[7]); 477238384Sjkim 478280304Sjkim n2 ^= f(c, n1 + c->k[0]); 479280304Sjkim n1 ^= f(c, n2 + c->k[1]); 480280304Sjkim n2 ^= f(c, n1 + c->k[2]); 481280304Sjkim n1 ^= f(c, n2 + c->k[3]); 482280304Sjkim n2 ^= f(c, n1 + c->k[4]); 483280304Sjkim n1 ^= f(c, n2 + c->k[5]); 484280304Sjkim n2 ^= f(c, n1 + c->k[6]); 485280304Sjkim n1 ^= f(c, n2 + c->k[7]); 486280304Sjkim 487280304Sjkim buffer[0] = (byte) (n1 & 0xff); 488280304Sjkim buffer[1] = (byte) ((n1 >> 8) & 0xff); 489280304Sjkim buffer[2] = (byte) ((n1 >> 16) & 0xff); 490280304Sjkim buffer[3] = (byte) (n1 >> 24); 491280304Sjkim buffer[4] = (byte) (n2 & 0xff); 492280304Sjkim buffer[5] = (byte) ((n2 >> 8) & 0xff); 493280304Sjkim buffer[6] = (byte) ((n2 >> 16) & 0xff); 494280304Sjkim buffer[7] = (byte) (n2 >> 24); 495280304Sjkim} 496280304Sjkim 497238384Sjkim/* Get mac with specified number of bits from MAC state buffer */ 498280304Sjkimvoid get_mac(byte * buffer, int nbits, byte * out) 499280304Sjkim{ 500280304Sjkim int nbytes = nbits >> 3; 501280304Sjkim int rembits = nbits & 7; 502280304Sjkim int mask = rembits ? ((1 < rembits) - 1) : 0; 503280304Sjkim int i; 504280304Sjkim for (i = 0; i < nbytes; i++) 505280304Sjkim out[i] = buffer[i]; 506280304Sjkim if (rembits) 507280304Sjkim out[i] = buffer[i] & mask; 508280304Sjkim} 509238384Sjkim 510280304Sjkim/* 511280304Sjkim * Compute mac of specified length (in bits) from data. Context should be 512280304Sjkim * initialized with key and subst blocks 513280304Sjkim */ 514280304Sjkimint gost_mac(gost_ctx * ctx, int mac_len, const unsigned char *data, 515280304Sjkim unsigned int data_len, unsigned char *mac) 516280304Sjkim{ 517280304Sjkim byte buffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 518280304Sjkim byte buf2[8]; 519280304Sjkim unsigned int i; 520280304Sjkim for (i = 0; i + 8 <= data_len; i += 8) 521280304Sjkim mac_block(ctx, buffer, data + i); 522280304Sjkim if (i < data_len) { 523280304Sjkim memset(buf2, 0, 8); 524280304Sjkim memcpy(buf2, data + i, data_len - i); 525280304Sjkim mac_block(ctx, buffer, buf2); 526280304Sjkim i += 8; 527280304Sjkim } 528280304Sjkim if (i == 8) { 529280304Sjkim memset(buf2, 0, 8); 530280304Sjkim mac_block(ctx, buffer, buf2); 531280304Sjkim } 532280304Sjkim get_mac(buffer, mac_len, mac); 533280304Sjkim return 1; 534280304Sjkim} 535238384Sjkim 536238384Sjkim/* Compute MAC with non-zero IV. Used in some RFC 4357 algorithms */ 537280304Sjkimint gost_mac_iv(gost_ctx * ctx, int mac_len, const unsigned char *iv, 538280304Sjkim const unsigned char *data, unsigned int data_len, 539280304Sjkim unsigned char *mac) 540280304Sjkim{ 541280304Sjkim byte buffer[8]; 542280304Sjkim byte buf2[8]; 543280304Sjkim unsigned int i; 544280304Sjkim memcpy(buffer, iv, 8); 545280304Sjkim for (i = 0; i + 8 <= data_len; i += 8) 546280304Sjkim mac_block(ctx, buffer, data + i); 547280304Sjkim if (i < data_len) { 548280304Sjkim memset(buf2, 0, 8); 549280304Sjkim memcpy(buf2, data + i, data_len - i); 550280304Sjkim mac_block(ctx, buffer, buf2); 551280304Sjkim i += 8; 552280304Sjkim } 553280304Sjkim if (i == 8) { 554280304Sjkim memset(buf2, 0, 8); 555280304Sjkim mac_block(ctx, buffer, buf2); 556280304Sjkim } 557280304Sjkim get_mac(buffer, mac_len, mac); 558280304Sjkim return 1; 559280304Sjkim} 560238384Sjkim 561238384Sjkim/* Implements key meshing algorithm by modifing ctx and IV in place */ 562280304Sjkimvoid cryptopro_key_meshing(gost_ctx * ctx, unsigned char *iv) 563280304Sjkim{ 564280304Sjkim unsigned char newkey[32], newiv[8]; 565280304Sjkim /* Set static keymeshing key */ 566280304Sjkim /* "Decrypt" key with keymeshing key */ 567280304Sjkim gost_dec(ctx, CryptoProKeyMeshingKey, newkey, 4); 568280304Sjkim /* set new key */ 569280304Sjkim gost_key(ctx, newkey); 570280304Sjkim /* Encrypt iv with new key */ 571280304Sjkim gostcrypt(ctx, iv, newiv); 572280304Sjkim memcpy(iv, newiv, 8); 573280304Sjkim} 574