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/* Substitution blocks from RFC 4357 13 14 Note: our implementation of gost 28147-89 algorithm 15 uses S-box matrix rotated 90 degrees counterclockwise, relative to 16 examples given in RFC. 17 18 19*/ 20 21/* Substitution blocks from test examples for GOST R 34.11-94*/ 22gost_subst_block GostR3411_94_TestParamSet = { 23 {0X1,0XF,0XD,0X0,0X5,0X7,0XA,0X4,0X9,0X2,0X3,0XE,0X6,0XB,0X8,0XC}, 24 {0XD,0XB,0X4,0X1,0X3,0XF,0X5,0X9,0X0,0XA,0XE,0X7,0X6,0X8,0X2,0XC}, 25 {0X4,0XB,0XA,0X0,0X7,0X2,0X1,0XD,0X3,0X6,0X8,0X5,0X9,0XC,0XF,0XE}, 26 {0X6,0XC,0X7,0X1,0X5,0XF,0XD,0X8,0X4,0XA,0X9,0XE,0X0,0X3,0XB,0X2}, 27 {0X7,0XD,0XA,0X1,0X0,0X8,0X9,0XF,0XE,0X4,0X6,0XC,0XB,0X2,0X5,0X3}, 28 {0X5,0X8,0X1,0XD,0XA,0X3,0X4,0X2,0XE,0XF,0XC,0X7,0X6,0X0,0X9,0XB}, 29 {0XE,0XB,0X4,0XC,0X6,0XD,0XF,0XA,0X2,0X3,0X8,0X1,0X0,0X7,0X5,0X9}, 30 {0X4,0XA,0X9,0X2,0XD,0X8,0X0,0XE,0X6,0XB,0X1,0XC,0X7,0XF,0X5,0X3} 31 }; 32/* Substitution blocks for hash function 1.2.643.2.9.1.6.1 */ 33gost_subst_block GostR3411_94_CryptoProParamSet= { 34 {0x1,0x3,0xA,0x9,0x5,0xB,0x4,0xF,0x8,0x6,0x7,0xE,0xD,0x0,0x2,0xC}, 35 {0xD,0xE,0x4,0x1,0x7,0x0,0x5,0xA,0x3,0xC,0x8,0xF,0x6,0x2,0x9,0xB}, 36 {0x7,0x6,0x2,0x4,0xD,0x9,0xF,0x0,0xA,0x1,0x5,0xB,0x8,0xE,0xC,0x3}, 37 {0x7,0x6,0x4,0xB,0x9,0xC,0x2,0xA,0x1,0x8,0x0,0xE,0xF,0xD,0x3,0x5}, 38 {0x4,0xA,0x7,0xC,0x0,0xF,0x2,0x8,0xE,0x1,0x6,0x5,0xD,0xB,0x9,0x3}, 39 {0x7,0xF,0xC,0xE,0x9,0x4,0x1,0x0,0x3,0xB,0x5,0x2,0x6,0xA,0x8,0xD}, 40 {0x5,0xF,0x4,0x0,0x2,0xD,0xB,0x9,0x1,0x7,0x6,0x3,0xC,0xE,0xA,0x8}, 41 {0xA,0x4,0x5,0x6,0x8,0x1,0x3,0x7,0xD,0xC,0xE,0x0,0x9,0x2,0xB,0xF} 42 } ; 43 44/* Test paramset from GOST 28147 */ 45gost_subst_block Gost28147_TestParamSet = 46 { 47 {0xC,0x6,0x5,0x2,0xB,0x0,0x9,0xD,0x3,0xE,0x7,0xA,0xF,0x4,0x1,0x8}, 48 {0x9,0xB,0xC,0x0,0x3,0x6,0x7,0x5,0x4,0x8,0xE,0xF,0x1,0xA,0x2,0xD}, 49 {0x8,0xF,0x6,0xB,0x1,0x9,0xC,0x5,0xD,0x3,0x7,0xA,0x0,0xE,0x2,0x4}, 50 {0x3,0xE,0x5,0x9,0x6,0x8,0x0,0xD,0xA,0xB,0x7,0xC,0x2,0x1,0xF,0x4}, 51 {0xE,0x9,0xB,0x2,0x5,0xF,0x7,0x1,0x0,0xD,0xC,0x6,0xA,0x4,0x3,0x8}, 52 {0xD,0x8,0xE,0xC,0x7,0x3,0x9,0xA,0x1,0x5,0x2,0x4,0x6,0xF,0x0,0xB}, 53 {0xC,0x9,0xF,0xE,0x8,0x1,0x3,0xA,0x2,0x7,0x4,0xD,0x6,0x0,0xB,0x5}, 54 {0x4,0x2,0xF,0x5,0x9,0x1,0x0,0x8,0xE,0x3,0xB,0xC,0xD,0x7,0xA,0x6} 55 }; 56 57 58 59 60/* 1.2.643.2.2.31.1 */ 61gost_subst_block Gost28147_CryptoProParamSetA= { 62 {0xB,0xA,0xF,0x5,0x0,0xC,0xE,0x8,0x6,0x2,0x3,0x9,0x1,0x7,0xD,0x4}, 63 {0x1,0xD,0x2,0x9,0x7,0xA,0x6,0x0,0x8,0xC,0x4,0x5,0xF,0x3,0xB,0xE}, 64 {0x3,0xA,0xD,0xC,0x1,0x2,0x0,0xB,0x7,0x5,0x9,0x4,0x8,0xF,0xE,0x6}, 65 {0xB,0x5,0x1,0x9,0x8,0xD,0xF,0x0,0xE,0x4,0x2,0x3,0xC,0x7,0xA,0x6}, 66 {0xE,0x7,0xA,0xC,0xD,0x1,0x3,0x9,0x0,0x2,0xB,0x4,0xF,0x8,0x5,0x6}, 67 {0xE,0x4,0x6,0x2,0xB,0x3,0xD,0x8,0xC,0xF,0x5,0xA,0x0,0x7,0x1,0x9}, 68 {0x3,0x7,0xE,0x9,0x8,0xA,0xF,0x0,0x5,0x2,0x6,0xC,0xB,0x4,0xD,0x1}, 69 {0x9,0x6,0x3,0x2,0x8,0xB,0x1,0x7,0xA,0x4,0xE,0xF,0xC,0x0,0xD,0x5} 70 }; 71/* 1.2.643.2.2.31.2 */ 72gost_subst_block Gost28147_CryptoProParamSetB= 73 { 74 {0x0,0x4,0xB,0xE,0x8,0x3,0x7,0x1,0xA,0x2,0x9,0x6,0xF,0xD,0x5,0xC}, 75 {0x5,0x2,0xA,0xB,0x9,0x1,0xC,0x3,0x7,0x4,0xD,0x0,0x6,0xF,0x8,0xE}, 76 {0x8,0x3,0x2,0x6,0x4,0xD,0xE,0xB,0xC,0x1,0x7,0xF,0xA,0x0,0x9,0x5}, 77 {0x2,0x7,0xC,0xF,0x9,0x5,0xA,0xB,0x1,0x4,0x0,0xD,0x6,0x8,0xE,0x3}, 78 {0x7,0x5,0x0,0xD,0xB,0x6,0x1,0x2,0x3,0xA,0xC,0xF,0x4,0xE,0x9,0x8}, 79 {0xE,0xC,0x0,0xA,0x9,0x2,0xD,0xB,0x7,0x5,0x8,0xF,0x3,0x6,0x1,0x4}, 80 {0x0,0x1,0x2,0xA,0x4,0xD,0x5,0xC,0x9,0x7,0x3,0xF,0xB,0x8,0x6,0xE}, 81 {0x8,0x4,0xB,0x1,0x3,0x5,0x0,0x9,0x2,0xE,0xA,0xC,0xD,0x6,0x7,0xF} 82 }; 83/* 1.2.643.2.2.31.3 */ 84gost_subst_block Gost28147_CryptoProParamSetC= 85 { 86 {0x7,0x4,0x0,0x5,0xA,0x2,0xF,0xE,0xC,0x6,0x1,0xB,0xD,0x9,0x3,0x8}, 87 {0xA,0x9,0x6,0x8,0xD,0xE,0x2,0x0,0xF,0x3,0x5,0xB,0x4,0x1,0xC,0x7}, 88 {0xC,0x9,0xB,0x1,0x8,0xE,0x2,0x4,0x7,0x3,0x6,0x5,0xA,0x0,0xF,0xD}, 89 {0x8,0xD,0xB,0x0,0x4,0x5,0x1,0x2,0x9,0x3,0xC,0xE,0x6,0xF,0xA,0x7}, 90 {0x3,0x6,0x0,0x1,0x5,0xD,0xA,0x8,0xB,0x2,0x9,0x7,0xE,0xF,0xC,0x4}, 91 {0x8,0x2,0x5,0x0,0x4,0x9,0xF,0xA,0x3,0x7,0xC,0xD,0x6,0xE,0x1,0xB}, 92 {0x0,0x1,0x7,0xD,0xB,0x4,0x5,0x2,0x8,0xE,0xF,0xC,0x9,0xA,0x6,0x3}, 93 {0x1,0xB,0xC,0x2,0x9,0xD,0x0,0xF,0x4,0x5,0x8,0xE,0xA,0x7,0x6,0x3} 94 }; 95 96/* 1.2.643.2.2.31.4 */ 97gost_subst_block Gost28147_CryptoProParamSetD= 98 { 99 {0x1,0xA,0x6,0x8,0xF,0xB,0x0,0x4,0xC,0x3,0x5,0x9,0x7,0xD,0x2,0xE}, 100 {0x3,0x0,0x6,0xF,0x1,0xE,0x9,0x2,0xD,0x8,0xC,0x4,0xB,0xA,0x5,0x7}, 101 {0x8,0x0,0xF,0x3,0x2,0x5,0xE,0xB,0x1,0xA,0x4,0x7,0xC,0x9,0xD,0x6}, 102 {0x0,0xC,0x8,0x9,0xD,0x2,0xA,0xB,0x7,0x3,0x6,0x5,0x4,0xE,0xF,0x1}, 103 {0x1,0x5,0xE,0xC,0xA,0x7,0x0,0xD,0x6,0x2,0xB,0x4,0x9,0x3,0xF,0x8}, 104 {0x1,0xC,0xB,0x0,0xF,0xE,0x6,0x5,0xA,0xD,0x4,0x8,0x9,0x3,0x7,0x2}, 105 {0xB,0x6,0x3,0x4,0xC,0xF,0xE,0x2,0x7,0xD,0x8,0x0,0x5,0xA,0x9,0x1}, 106 {0xF,0xC,0x2,0xA,0x6,0x4,0x5,0x0,0x7,0x9,0xE,0xD,0x1,0xB,0x8,0x3} 107 }; 108 109 110const byte CryptoProKeyMeshingKey[]={ 111 0x69, 0x00, 0x72, 0x22, 0x64, 0xC9, 0x04, 0x23, 112 0x8D, 0x3A, 0xDB, 0x96, 0x46, 0xE9, 0x2A, 0xC4, 113 0x18, 0xFE, 0xAC, 0x94, 0x00, 0xED, 0x07, 0x12, 114 0xC0, 0x86, 0xDC, 0xC2, 0xEF, 0x4C, 0xA9, 0x2B 115 }; 116/* Initialization of gost_ctx subst blocks*/ 117static void kboxinit(gost_ctx *c, const gost_subst_block *b) 118 { 119 int i; 120 121 for (i = 0; i < 256; i++) 122 { 123 c->k87[i] = (b->k8[i>>4] <<4 | b->k7 [i &15])<<24; 124 c->k65[i] = (b->k6[i>>4] << 4 | b->k5 [i &15])<<16; 125 c->k43[i] = (b->k4[i>>4] <<4 | b->k3 [i &15])<<8; 126 c->k21[i] = b->k2[i>>4] <<4 | b->k1 [i &15]; 127 128 } 129 } 130 131/* Part of GOST 28147 algorithm moved into separate function */ 132static word32 f(gost_ctx *c,word32 x) 133 { 134 x = c->k87[x>>24 & 255] | c->k65[x>>16 & 255]| 135 c->k43[x>> 8 & 255] | c->k21[x & 255]; 136 /* Rotate left 11 bits */ 137 return x<<11 | x>>(32-11); 138 } 139/* Low-level encryption routine - encrypts one 64 bit block*/ 140void gostcrypt(gost_ctx *c, const byte *in, byte *out) 141 { 142 register word32 n1, n2; /* As named in the GOST */ 143 n1 = in[0]|(in[1]<<8)|(in[2]<<16)|(in[3]<<24); 144 n2 = in[4]|(in[5]<<8)|(in[6]<<16)|(in[7]<<24); 145 /* Instead of swapping halves, swap names each round */ 146 147 n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]); 148 n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]); 149 n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]); 150 n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]); 151 152 n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]); 153 n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]); 154 n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]); 155 n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]); 156 157 n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]); 158 n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]); 159 n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]); 160 n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]); 161 162 n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]); 163 n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]); 164 n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]); 165 n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]); 166 167 out[0] = (byte)(n2&0xff); out[1] = (byte)((n2>>8)&0xff); 168 out[2] = (byte)((n2>>16)&0xff); out[3]=(byte)(n2>>24); 169 out[4] = (byte)(n1&0xff); out[5] = (byte)((n1>>8)&0xff); 170 out[6] = (byte)((n1>>16)&0xff); out[7] = (byte)(n1>>24); 171 } 172/* Low-level decryption routine. Decrypts one 64-bit block */ 173void gostdecrypt(gost_ctx *c, const byte *in,byte *out) 174 { 175 register word32 n1, n2; /* As named in the GOST */ 176 n1 = in[0]|(in[1]<<8)|(in[2]<<16)|(in[3]<<24); 177 n2 = in[4]|(in[5]<<8)|(in[6]<<16)|(in[7]<<24); 178 179 n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]); 180 n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]); 181 n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]); 182 n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]); 183 184 n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]); 185 n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]); 186 n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]); 187 n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]); 188 189 n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]); 190 n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]); 191 n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]); 192 n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]); 193 194 n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]); 195 n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]); 196 n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]); 197 n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]); 198 199 out[0] = (byte)(n2&0xff); out[1] = (byte)((n2>>8)&0xff); 200 out[2] = (byte)((n2>>16)&0xff); out[3]=(byte)(n2>>24); 201 out[4] = (byte)(n1&0xff); out[5] = (byte)((n1>>8)&0xff); 202 out[6] = (byte)((n1>>16)&0xff); out[7] = (byte)(n1>>24); 203 } 204 205/* Encrypts several blocks in ECB mode */ 206void gost_enc(gost_ctx *c,const byte *clear,byte *cipher, int blocks) 207 { 208 int i; 209 for(i=0;i<blocks;i++) 210 { 211 gostcrypt(c,clear,cipher); 212 clear+=8; 213 cipher+=8; 214 } 215 } 216/* Decrypts several blocks in ECB mode */ 217void gost_dec(gost_ctx *c, const byte *cipher,byte *clear, int blocks) 218 { 219 int i; 220 for(i=0;i<blocks;i++) 221 { 222 gostdecrypt(c,cipher,clear); 223 clear+=8; 224 cipher+=8; 225 } 226 } 227 228/* Encrypts several full blocks in CFB mode using 8byte IV */ 229void gost_enc_cfb(gost_ctx *ctx,const byte *iv,const byte *clear,byte *cipher, int blocks) 230 { 231 byte cur_iv[8]; 232 byte gamma[8]; 233 int i,j; 234 const byte *in; 235 byte *out; 236 memcpy(cur_iv,iv,8); 237 for(i=0,in=clear,out=cipher;i<blocks;i++,in+=8,out+=8) 238 { 239 gostcrypt(ctx,cur_iv,gamma); 240 for (j=0;j<8;j++) 241 { 242 cur_iv[j]=out[j]=in[j]^gamma[j]; 243 } 244 } 245 } 246/* Decrypts several full blocks in CFB mode using 8byte IV */ 247void gost_dec_cfb(gost_ctx *ctx,const byte *iv,const byte *cipher,byte *clear, int blocks) 248 { 249 byte cur_iv[8]; 250 byte gamma[8]; 251 int i,j; 252 const byte *in; 253 byte *out; 254 memcpy(cur_iv,iv,8); 255 for(i=0,in=cipher,out=clear;i<blocks;i++,in+=8,out+=8) 256 { 257 gostcrypt(ctx,cur_iv,gamma); 258 for (j=0;j<8;j++) 259 { 260 out[j]=(cur_iv[j]=in[j])^gamma[j]; 261 } 262 } 263 } 264 265/* Encrypts one block using specified key */ 266void gost_enc_with_key(gost_ctx *c,byte *key,byte *inblock,byte *outblock) 267 { 268 gost_key(c,key); 269 gostcrypt(c,inblock,outblock); 270 } 271 272/* Set 256 bit key into context */ 273void gost_key(gost_ctx *c, const byte *k) 274 { 275 int i,j; 276 for(i=0,j=0;i<8;i++,j+=4) 277 { 278 c->k[i]=k[j]|(k[j+1]<<8)|(k[j+2]<<16)|(k[j+3]<<24); 279 } 280 } 281 282/* Retrieve 256-bit key from context */ 283void gost_get_key(gost_ctx *c, byte *k) 284 { 285 int i,j; 286 for(i=0,j=0;i<8;i++,j+=4) 287 { 288 k[j]=(byte)(c->k[i]& 0xFF); 289 k[j+1]=(byte)((c->k[i]>>8 )&0xFF); 290 k[j+2]=(byte)((c->k[i]>>16) &0xFF); 291 k[j+3]=(byte)((c->k[i]>>24) &0xFF); 292 } 293 } 294 295/* Initalize context. Provides default value for subst_block */ 296void gost_init(gost_ctx *c, const gost_subst_block *b) 297 { 298 if(!b) 299 { 300 b=&GostR3411_94_TestParamSet; 301 } 302 kboxinit(c,b); 303 } 304 305/* Cleans up key from context */ 306void gost_destroy(gost_ctx *c) 307 { 308 int i; for(i=0;i<8;i++) c->k[i]=0; 309 } 310 311/* Compute GOST 28147 mac block 312 * 313 * Parameters 314 * gost_ctx *c - context initalized with substitution blocks and key 315 * buffer - 8-byte mac state buffer 316 * block 8-byte block to process. 317 * */ 318void mac_block(gost_ctx *c,byte *buffer,const byte *block) 319 { 320 register word32 n1, n2; /* As named in the GOST */ 321 int i; 322 for (i=0; i<8; i++) 323 { 324 buffer[i]^=block[i]; 325 } 326 n1 = buffer[0]|(buffer[1]<<8)|(buffer[2]<<16)|(buffer[3]<<24); 327 n2 = buffer[4]|(buffer[5]<<8)|(buffer[6]<<16)|(buffer[7]<<24); 328 /* Instead of swapping halves, swap names each round */ 329 330 n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]); 331 n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]); 332 n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]); 333 n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]); 334 335 n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]); 336 n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]); 337 n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]); 338 n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]); 339 340 buffer[0] = (byte)(n1&0xff); buffer[1] = (byte)((n1>>8)&0xff); 341 buffer[2] = (byte)((n1>>16)&0xff); buffer[3] = (byte)(n1>>24); 342 buffer[4] = (byte)(n2&0xff); buffer[5] = (byte)((n2>>8)&0xff); 343 buffer[6] = (byte)((n2>>16)&0xff); buffer[7] = (byte)(n2>>24); 344 } 345 346/* Get mac with specified number of bits from MAC state buffer */ 347void get_mac(byte *buffer,int nbits,byte *out) 348 { 349 int nbytes= nbits >> 3; 350 int rembits = nbits & 7; 351 int mask =rembits?((1<rembits)-1):0; 352 int i; 353 for (i=0;i<nbytes;i++) out[i]=buffer[i]; 354 if (rembits) out[i]=buffer[i]&mask; 355 } 356 357/* Compute mac of specified length (in bits) from data. 358 * Context should be initialized with key and subst blocks */ 359int gost_mac(gost_ctx *ctx,int mac_len,const unsigned char *data, 360 unsigned int data_len,unsigned char *mac) 361 { 362 byte buffer[8]={0,0,0,0,0,0,0,0}; 363 byte buf2[8]; 364 unsigned int i; 365 for (i=0;i+8<=data_len;i+=8) 366 mac_block(ctx,buffer,data+i); 367 if (i<data_len) 368 { 369 memset(buf2,0,8); 370 memcpy(buf2,data+i,data_len-i); 371 mac_block(ctx,buffer,buf2); 372 } 373 get_mac(buffer,mac_len,mac); 374 return 1; 375 } 376 377/* Compute MAC with non-zero IV. Used in some RFC 4357 algorithms */ 378int gost_mac_iv(gost_ctx *ctx,int mac_len,const unsigned char *iv,const unsigned char *data, 379 unsigned int data_len,unsigned char *mac) 380 { 381 byte buffer[8]; 382 byte buf2[8]; 383 unsigned int i; 384 memcpy (buffer,iv,8); 385 for (i=0;i+8<=data_len;i+=8) 386 mac_block(ctx,buffer,data+i); 387 if (i<data_len) 388 { 389 memset(buf2,0,8); 390 memcpy(buf2,data+i,data_len-i); 391 mac_block(ctx,buffer,buf2); 392 } 393 get_mac(buffer,mac_len,mac); 394 return 1; 395 } 396 397/* Implements key meshing algorithm by modifing ctx and IV in place */ 398void cryptopro_key_meshing(gost_ctx *ctx, unsigned char *iv) 399 { 400 unsigned char newkey[32],newiv[8]; 401 /* Set static keymeshing key */ 402 /* "Decrypt" key with keymeshing key */ 403 gost_dec(ctx,CryptoProKeyMeshingKey,newkey,4); 404 /* set new key */ 405 gost_key(ctx,newkey); 406 /* Encrypt iv with new key */ 407 gostcrypt(ctx,iv,newiv); 408 memcpy(iv,newiv,8); 409 } 410