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 * 9238384Sjkim **********************************************************************/ 10238384Sjkim#include <string.h> 11238384Sjkim#include "gost89.h" 12238384Sjkim/* Substitution blocks from RFC 4357 13238384Sjkim 14238384Sjkim Note: our implementation of gost 28147-89 algorithm 15238384Sjkim uses S-box matrix rotated 90 degrees counterclockwise, relative to 16238384Sjkim examples given in RFC. 17238384Sjkim 18238384Sjkim 19238384Sjkim*/ 20238384Sjkim 21238384Sjkim/* Substitution blocks from test examples for GOST R 34.11-94*/ 22238384Sjkimgost_subst_block GostR3411_94_TestParamSet = { 23238384Sjkim {0X1,0XF,0XD,0X0,0X5,0X7,0XA,0X4,0X9,0X2,0X3,0XE,0X6,0XB,0X8,0XC}, 24238384Sjkim {0XD,0XB,0X4,0X1,0X3,0XF,0X5,0X9,0X0,0XA,0XE,0X7,0X6,0X8,0X2,0XC}, 25238384Sjkim {0X4,0XB,0XA,0X0,0X7,0X2,0X1,0XD,0X3,0X6,0X8,0X5,0X9,0XC,0XF,0XE}, 26238384Sjkim {0X6,0XC,0X7,0X1,0X5,0XF,0XD,0X8,0X4,0XA,0X9,0XE,0X0,0X3,0XB,0X2}, 27238384Sjkim {0X7,0XD,0XA,0X1,0X0,0X8,0X9,0XF,0XE,0X4,0X6,0XC,0XB,0X2,0X5,0X3}, 28238384Sjkim {0X5,0X8,0X1,0XD,0XA,0X3,0X4,0X2,0XE,0XF,0XC,0X7,0X6,0X0,0X9,0XB}, 29238384Sjkim {0XE,0XB,0X4,0XC,0X6,0XD,0XF,0XA,0X2,0X3,0X8,0X1,0X0,0X7,0X5,0X9}, 30238384Sjkim {0X4,0XA,0X9,0X2,0XD,0X8,0X0,0XE,0X6,0XB,0X1,0XC,0X7,0XF,0X5,0X3} 31238384Sjkim }; 32238384Sjkim/* Substitution blocks for hash function 1.2.643.2.9.1.6.1 */ 33238384Sjkimgost_subst_block GostR3411_94_CryptoProParamSet= { 34238384Sjkim {0x1,0x3,0xA,0x9,0x5,0xB,0x4,0xF,0x8,0x6,0x7,0xE,0xD,0x0,0x2,0xC}, 35238384Sjkim {0xD,0xE,0x4,0x1,0x7,0x0,0x5,0xA,0x3,0xC,0x8,0xF,0x6,0x2,0x9,0xB}, 36238384Sjkim {0x7,0x6,0x2,0x4,0xD,0x9,0xF,0x0,0xA,0x1,0x5,0xB,0x8,0xE,0xC,0x3}, 37238384Sjkim {0x7,0x6,0x4,0xB,0x9,0xC,0x2,0xA,0x1,0x8,0x0,0xE,0xF,0xD,0x3,0x5}, 38238384Sjkim {0x4,0xA,0x7,0xC,0x0,0xF,0x2,0x8,0xE,0x1,0x6,0x5,0xD,0xB,0x9,0x3}, 39238384Sjkim {0x7,0xF,0xC,0xE,0x9,0x4,0x1,0x0,0x3,0xB,0x5,0x2,0x6,0xA,0x8,0xD}, 40238384Sjkim {0x5,0xF,0x4,0x0,0x2,0xD,0xB,0x9,0x1,0x7,0x6,0x3,0xC,0xE,0xA,0x8}, 41238384Sjkim {0xA,0x4,0x5,0x6,0x8,0x1,0x3,0x7,0xD,0xC,0xE,0x0,0x9,0x2,0xB,0xF} 42238384Sjkim } ; 43238384Sjkim 44238384Sjkim/* Test paramset from GOST 28147 */ 45238384Sjkimgost_subst_block Gost28147_TestParamSet = 46238384Sjkim { 47238384Sjkim {0xC,0x6,0x5,0x2,0xB,0x0,0x9,0xD,0x3,0xE,0x7,0xA,0xF,0x4,0x1,0x8}, 48238384Sjkim {0x9,0xB,0xC,0x0,0x3,0x6,0x7,0x5,0x4,0x8,0xE,0xF,0x1,0xA,0x2,0xD}, 49238384Sjkim {0x8,0xF,0x6,0xB,0x1,0x9,0xC,0x5,0xD,0x3,0x7,0xA,0x0,0xE,0x2,0x4}, 50238384Sjkim {0x3,0xE,0x5,0x9,0x6,0x8,0x0,0xD,0xA,0xB,0x7,0xC,0x2,0x1,0xF,0x4}, 51238384Sjkim {0xE,0x9,0xB,0x2,0x5,0xF,0x7,0x1,0x0,0xD,0xC,0x6,0xA,0x4,0x3,0x8}, 52238384Sjkim {0xD,0x8,0xE,0xC,0x7,0x3,0x9,0xA,0x1,0x5,0x2,0x4,0x6,0xF,0x0,0xB}, 53238384Sjkim {0xC,0x9,0xF,0xE,0x8,0x1,0x3,0xA,0x2,0x7,0x4,0xD,0x6,0x0,0xB,0x5}, 54238384Sjkim {0x4,0x2,0xF,0x5,0x9,0x1,0x0,0x8,0xE,0x3,0xB,0xC,0xD,0x7,0xA,0x6} 55238384Sjkim }; 56238384Sjkim 57238384Sjkim 58238384Sjkim 59238384Sjkim 60238384Sjkim/* 1.2.643.2.2.31.1 */ 61238384Sjkimgost_subst_block Gost28147_CryptoProParamSetA= { 62238384Sjkim {0xB,0xA,0xF,0x5,0x0,0xC,0xE,0x8,0x6,0x2,0x3,0x9,0x1,0x7,0xD,0x4}, 63238384Sjkim {0x1,0xD,0x2,0x9,0x7,0xA,0x6,0x0,0x8,0xC,0x4,0x5,0xF,0x3,0xB,0xE}, 64238384Sjkim {0x3,0xA,0xD,0xC,0x1,0x2,0x0,0xB,0x7,0x5,0x9,0x4,0x8,0xF,0xE,0x6}, 65238384Sjkim {0xB,0x5,0x1,0x9,0x8,0xD,0xF,0x0,0xE,0x4,0x2,0x3,0xC,0x7,0xA,0x6}, 66238384Sjkim {0xE,0x7,0xA,0xC,0xD,0x1,0x3,0x9,0x0,0x2,0xB,0x4,0xF,0x8,0x5,0x6}, 67238384Sjkim {0xE,0x4,0x6,0x2,0xB,0x3,0xD,0x8,0xC,0xF,0x5,0xA,0x0,0x7,0x1,0x9}, 68238384Sjkim {0x3,0x7,0xE,0x9,0x8,0xA,0xF,0x0,0x5,0x2,0x6,0xC,0xB,0x4,0xD,0x1}, 69238384Sjkim {0x9,0x6,0x3,0x2,0x8,0xB,0x1,0x7,0xA,0x4,0xE,0xF,0xC,0x0,0xD,0x5} 70238384Sjkim }; 71238384Sjkim/* 1.2.643.2.2.31.2 */ 72238384Sjkimgost_subst_block Gost28147_CryptoProParamSetB= 73238384Sjkim { 74238384Sjkim {0x0,0x4,0xB,0xE,0x8,0x3,0x7,0x1,0xA,0x2,0x9,0x6,0xF,0xD,0x5,0xC}, 75238384Sjkim {0x5,0x2,0xA,0xB,0x9,0x1,0xC,0x3,0x7,0x4,0xD,0x0,0x6,0xF,0x8,0xE}, 76238384Sjkim {0x8,0x3,0x2,0x6,0x4,0xD,0xE,0xB,0xC,0x1,0x7,0xF,0xA,0x0,0x9,0x5}, 77238384Sjkim {0x2,0x7,0xC,0xF,0x9,0x5,0xA,0xB,0x1,0x4,0x0,0xD,0x6,0x8,0xE,0x3}, 78238384Sjkim {0x7,0x5,0x0,0xD,0xB,0x6,0x1,0x2,0x3,0xA,0xC,0xF,0x4,0xE,0x9,0x8}, 79238384Sjkim {0xE,0xC,0x0,0xA,0x9,0x2,0xD,0xB,0x7,0x5,0x8,0xF,0x3,0x6,0x1,0x4}, 80238384Sjkim {0x0,0x1,0x2,0xA,0x4,0xD,0x5,0xC,0x9,0x7,0x3,0xF,0xB,0x8,0x6,0xE}, 81238384Sjkim {0x8,0x4,0xB,0x1,0x3,0x5,0x0,0x9,0x2,0xE,0xA,0xC,0xD,0x6,0x7,0xF} 82238384Sjkim }; 83238384Sjkim/* 1.2.643.2.2.31.3 */ 84238384Sjkimgost_subst_block Gost28147_CryptoProParamSetC= 85238384Sjkim { 86238384Sjkim {0x7,0x4,0x0,0x5,0xA,0x2,0xF,0xE,0xC,0x6,0x1,0xB,0xD,0x9,0x3,0x8}, 87238384Sjkim {0xA,0x9,0x6,0x8,0xD,0xE,0x2,0x0,0xF,0x3,0x5,0xB,0x4,0x1,0xC,0x7}, 88238384Sjkim {0xC,0x9,0xB,0x1,0x8,0xE,0x2,0x4,0x7,0x3,0x6,0x5,0xA,0x0,0xF,0xD}, 89238384Sjkim {0x8,0xD,0xB,0x0,0x4,0x5,0x1,0x2,0x9,0x3,0xC,0xE,0x6,0xF,0xA,0x7}, 90238384Sjkim {0x3,0x6,0x0,0x1,0x5,0xD,0xA,0x8,0xB,0x2,0x9,0x7,0xE,0xF,0xC,0x4}, 91238384Sjkim {0x8,0x2,0x5,0x0,0x4,0x9,0xF,0xA,0x3,0x7,0xC,0xD,0x6,0xE,0x1,0xB}, 92238384Sjkim {0x0,0x1,0x7,0xD,0xB,0x4,0x5,0x2,0x8,0xE,0xF,0xC,0x9,0xA,0x6,0x3}, 93238384Sjkim {0x1,0xB,0xC,0x2,0x9,0xD,0x0,0xF,0x4,0x5,0x8,0xE,0xA,0x7,0x6,0x3} 94238384Sjkim }; 95238384Sjkim 96238384Sjkim/* 1.2.643.2.2.31.4 */ 97238384Sjkimgost_subst_block Gost28147_CryptoProParamSetD= 98238384Sjkim { 99238384Sjkim {0x1,0xA,0x6,0x8,0xF,0xB,0x0,0x4,0xC,0x3,0x5,0x9,0x7,0xD,0x2,0xE}, 100238384Sjkim {0x3,0x0,0x6,0xF,0x1,0xE,0x9,0x2,0xD,0x8,0xC,0x4,0xB,0xA,0x5,0x7}, 101238384Sjkim {0x8,0x0,0xF,0x3,0x2,0x5,0xE,0xB,0x1,0xA,0x4,0x7,0xC,0x9,0xD,0x6}, 102238384Sjkim {0x0,0xC,0x8,0x9,0xD,0x2,0xA,0xB,0x7,0x3,0x6,0x5,0x4,0xE,0xF,0x1}, 103238384Sjkim {0x1,0x5,0xE,0xC,0xA,0x7,0x0,0xD,0x6,0x2,0xB,0x4,0x9,0x3,0xF,0x8}, 104238384Sjkim {0x1,0xC,0xB,0x0,0xF,0xE,0x6,0x5,0xA,0xD,0x4,0x8,0x9,0x3,0x7,0x2}, 105238384Sjkim {0xB,0x6,0x3,0x4,0xC,0xF,0xE,0x2,0x7,0xD,0x8,0x0,0x5,0xA,0x9,0x1}, 106238384Sjkim {0xF,0xC,0x2,0xA,0x6,0x4,0x5,0x0,0x7,0x9,0xE,0xD,0x1,0xB,0x8,0x3} 107238384Sjkim }; 108238384Sjkim 109238384Sjkim 110238384Sjkimconst byte CryptoProKeyMeshingKey[]={ 111238384Sjkim 0x69, 0x00, 0x72, 0x22, 0x64, 0xC9, 0x04, 0x23, 112238384Sjkim 0x8D, 0x3A, 0xDB, 0x96, 0x46, 0xE9, 0x2A, 0xC4, 113238384Sjkim 0x18, 0xFE, 0xAC, 0x94, 0x00, 0xED, 0x07, 0x12, 114238384Sjkim 0xC0, 0x86, 0xDC, 0xC2, 0xEF, 0x4C, 0xA9, 0x2B 115238384Sjkim }; 116238384Sjkim/* Initialization of gost_ctx subst blocks*/ 117238384Sjkimstatic void kboxinit(gost_ctx *c, const gost_subst_block *b) 118238384Sjkim { 119238384Sjkim int i; 120238384Sjkim 121238384Sjkim for (i = 0; i < 256; i++) 122238384Sjkim { 123238384Sjkim c->k87[i] = (b->k8[i>>4] <<4 | b->k7 [i &15])<<24; 124238384Sjkim c->k65[i] = (b->k6[i>>4] << 4 | b->k5 [i &15])<<16; 125238384Sjkim c->k43[i] = (b->k4[i>>4] <<4 | b->k3 [i &15])<<8; 126238384Sjkim c->k21[i] = b->k2[i>>4] <<4 | b->k1 [i &15]; 127238384Sjkim 128238384Sjkim } 129238384Sjkim } 130238384Sjkim 131238384Sjkim/* Part of GOST 28147 algorithm moved into separate function */ 132238384Sjkimstatic word32 f(gost_ctx *c,word32 x) 133238384Sjkim { 134238384Sjkim x = c->k87[x>>24 & 255] | c->k65[x>>16 & 255]| 135238384Sjkim c->k43[x>> 8 & 255] | c->k21[x & 255]; 136238384Sjkim /* Rotate left 11 bits */ 137238384Sjkim return x<<11 | x>>(32-11); 138238384Sjkim } 139238384Sjkim/* Low-level encryption routine - encrypts one 64 bit block*/ 140238384Sjkimvoid gostcrypt(gost_ctx *c, const byte *in, byte *out) 141238384Sjkim { 142238384Sjkim register word32 n1, n2; /* As named in the GOST */ 143238384Sjkim n1 = in[0]|(in[1]<<8)|(in[2]<<16)|(in[3]<<24); 144238384Sjkim n2 = in[4]|(in[5]<<8)|(in[6]<<16)|(in[7]<<24); 145238384Sjkim /* Instead of swapping halves, swap names each round */ 146238384Sjkim 147238384Sjkim n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]); 148238384Sjkim n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]); 149238384Sjkim n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]); 150238384Sjkim n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]); 151238384Sjkim 152238384Sjkim n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]); 153238384Sjkim n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]); 154238384Sjkim n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]); 155238384Sjkim n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]); 156238384Sjkim 157238384Sjkim n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]); 158238384Sjkim n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]); 159238384Sjkim n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]); 160238384Sjkim n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]); 161238384Sjkim 162238384Sjkim n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]); 163238384Sjkim n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]); 164238384Sjkim n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]); 165238384Sjkim n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]); 166238384Sjkim 167238384Sjkim out[0] = (byte)(n2&0xff); out[1] = (byte)((n2>>8)&0xff); 168238384Sjkim out[2] = (byte)((n2>>16)&0xff); out[3]=(byte)(n2>>24); 169238384Sjkim out[4] = (byte)(n1&0xff); out[5] = (byte)((n1>>8)&0xff); 170238384Sjkim out[6] = (byte)((n1>>16)&0xff); out[7] = (byte)(n1>>24); 171238384Sjkim } 172238384Sjkim/* Low-level decryption routine. Decrypts one 64-bit block */ 173238384Sjkimvoid gostdecrypt(gost_ctx *c, const byte *in,byte *out) 174238384Sjkim { 175238384Sjkim register word32 n1, n2; /* As named in the GOST */ 176238384Sjkim n1 = in[0]|(in[1]<<8)|(in[2]<<16)|(in[3]<<24); 177238384Sjkim n2 = in[4]|(in[5]<<8)|(in[6]<<16)|(in[7]<<24); 178238384Sjkim 179238384Sjkim n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]); 180238384Sjkim n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]); 181238384Sjkim n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]); 182238384Sjkim n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]); 183238384Sjkim 184238384Sjkim n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]); 185238384Sjkim n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]); 186238384Sjkim n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]); 187238384Sjkim n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]); 188238384Sjkim 189238384Sjkim n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]); 190238384Sjkim n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]); 191238384Sjkim n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]); 192238384Sjkim n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]); 193238384Sjkim 194238384Sjkim n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]); 195238384Sjkim n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]); 196238384Sjkim n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]); 197238384Sjkim n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]); 198238384Sjkim 199238384Sjkim out[0] = (byte)(n2&0xff); out[1] = (byte)((n2>>8)&0xff); 200238384Sjkim out[2] = (byte)((n2>>16)&0xff); out[3]=(byte)(n2>>24); 201238384Sjkim out[4] = (byte)(n1&0xff); out[5] = (byte)((n1>>8)&0xff); 202238384Sjkim out[6] = (byte)((n1>>16)&0xff); out[7] = (byte)(n1>>24); 203238384Sjkim } 204238384Sjkim 205238384Sjkim/* Encrypts several blocks in ECB mode */ 206238384Sjkimvoid gost_enc(gost_ctx *c,const byte *clear,byte *cipher, int blocks) 207238384Sjkim { 208238384Sjkim int i; 209238384Sjkim for(i=0;i<blocks;i++) 210238384Sjkim { 211238384Sjkim gostcrypt(c,clear,cipher); 212238384Sjkim clear+=8; 213238384Sjkim cipher+=8; 214238384Sjkim } 215238384Sjkim } 216238384Sjkim/* Decrypts several blocks in ECB mode */ 217238384Sjkimvoid gost_dec(gost_ctx *c, const byte *cipher,byte *clear, int blocks) 218238384Sjkim { 219238384Sjkim int i; 220238384Sjkim for(i=0;i<blocks;i++) 221238384Sjkim { 222238384Sjkim gostdecrypt(c,cipher,clear); 223238384Sjkim clear+=8; 224238384Sjkim cipher+=8; 225238384Sjkim } 226238384Sjkim } 227238384Sjkim 228238384Sjkim/* Encrypts several full blocks in CFB mode using 8byte IV */ 229238384Sjkimvoid gost_enc_cfb(gost_ctx *ctx,const byte *iv,const byte *clear,byte *cipher, int blocks) 230238384Sjkim { 231238384Sjkim byte cur_iv[8]; 232238384Sjkim byte gamma[8]; 233238384Sjkim int i,j; 234238384Sjkim const byte *in; 235238384Sjkim byte *out; 236238384Sjkim memcpy(cur_iv,iv,8); 237238384Sjkim for(i=0,in=clear,out=cipher;i<blocks;i++,in+=8,out+=8) 238238384Sjkim { 239238384Sjkim gostcrypt(ctx,cur_iv,gamma); 240238384Sjkim for (j=0;j<8;j++) 241238384Sjkim { 242238384Sjkim cur_iv[j]=out[j]=in[j]^gamma[j]; 243238384Sjkim } 244238384Sjkim } 245238384Sjkim } 246238384Sjkim/* Decrypts several full blocks in CFB mode using 8byte IV */ 247238384Sjkimvoid gost_dec_cfb(gost_ctx *ctx,const byte *iv,const byte *cipher,byte *clear, int blocks) 248238384Sjkim { 249238384Sjkim byte cur_iv[8]; 250238384Sjkim byte gamma[8]; 251238384Sjkim int i,j; 252238384Sjkim const byte *in; 253238384Sjkim byte *out; 254238384Sjkim memcpy(cur_iv,iv,8); 255238384Sjkim for(i=0,in=cipher,out=clear;i<blocks;i++,in+=8,out+=8) 256238384Sjkim { 257238384Sjkim gostcrypt(ctx,cur_iv,gamma); 258238384Sjkim for (j=0;j<8;j++) 259238384Sjkim { 260238384Sjkim out[j]=(cur_iv[j]=in[j])^gamma[j]; 261238384Sjkim } 262238384Sjkim } 263238384Sjkim } 264238384Sjkim 265238384Sjkim/* Encrypts one block using specified key */ 266238384Sjkimvoid gost_enc_with_key(gost_ctx *c,byte *key,byte *inblock,byte *outblock) 267238384Sjkim { 268238384Sjkim gost_key(c,key); 269238384Sjkim gostcrypt(c,inblock,outblock); 270238384Sjkim } 271238384Sjkim 272238384Sjkim/* Set 256 bit key into context */ 273238384Sjkimvoid gost_key(gost_ctx *c, const byte *k) 274238384Sjkim { 275238384Sjkim int i,j; 276238384Sjkim for(i=0,j=0;i<8;i++,j+=4) 277238384Sjkim { 278238384Sjkim c->k[i]=k[j]|(k[j+1]<<8)|(k[j+2]<<16)|(k[j+3]<<24); 279238384Sjkim } 280238384Sjkim } 281238384Sjkim 282238384Sjkim/* Retrieve 256-bit key from context */ 283238384Sjkimvoid gost_get_key(gost_ctx *c, byte *k) 284238384Sjkim { 285238384Sjkim int i,j; 286238384Sjkim for(i=0,j=0;i<8;i++,j+=4) 287238384Sjkim { 288238384Sjkim k[j]=(byte)(c->k[i]& 0xFF); 289238384Sjkim k[j+1]=(byte)((c->k[i]>>8 )&0xFF); 290238384Sjkim k[j+2]=(byte)((c->k[i]>>16) &0xFF); 291238384Sjkim k[j+3]=(byte)((c->k[i]>>24) &0xFF); 292238384Sjkim } 293238384Sjkim } 294238384Sjkim 295238384Sjkim/* Initalize context. Provides default value for subst_block */ 296238384Sjkimvoid gost_init(gost_ctx *c, const gost_subst_block *b) 297238384Sjkim { 298238384Sjkim if(!b) 299238384Sjkim { 300238384Sjkim b=&GostR3411_94_TestParamSet; 301238384Sjkim } 302238384Sjkim kboxinit(c,b); 303238384Sjkim } 304238384Sjkim 305238384Sjkim/* Cleans up key from context */ 306238384Sjkimvoid gost_destroy(gost_ctx *c) 307238384Sjkim { 308238384Sjkim int i; for(i=0;i<8;i++) c->k[i]=0; 309238384Sjkim } 310238384Sjkim 311238384Sjkim/* Compute GOST 28147 mac block 312238384Sjkim * 313238384Sjkim * Parameters 314238384Sjkim * gost_ctx *c - context initalized with substitution blocks and key 315238384Sjkim * buffer - 8-byte mac state buffer 316238384Sjkim * block 8-byte block to process. 317238384Sjkim * */ 318238384Sjkimvoid mac_block(gost_ctx *c,byte *buffer,const byte *block) 319238384Sjkim { 320238384Sjkim register word32 n1, n2; /* As named in the GOST */ 321238384Sjkim int i; 322238384Sjkim for (i=0; i<8; i++) 323238384Sjkim { 324238384Sjkim buffer[i]^=block[i]; 325238384Sjkim } 326238384Sjkim n1 = buffer[0]|(buffer[1]<<8)|(buffer[2]<<16)|(buffer[3]<<24); 327238384Sjkim n2 = buffer[4]|(buffer[5]<<8)|(buffer[6]<<16)|(buffer[7]<<24); 328238384Sjkim /* Instead of swapping halves, swap names each round */ 329238384Sjkim 330238384Sjkim n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]); 331238384Sjkim n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]); 332238384Sjkim n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]); 333238384Sjkim n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]); 334238384Sjkim 335238384Sjkim n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]); 336238384Sjkim n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]); 337238384Sjkim n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]); 338238384Sjkim n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]); 339238384Sjkim 340238384Sjkim buffer[0] = (byte)(n1&0xff); buffer[1] = (byte)((n1>>8)&0xff); 341238384Sjkim buffer[2] = (byte)((n1>>16)&0xff); buffer[3] = (byte)(n1>>24); 342238384Sjkim buffer[4] = (byte)(n2&0xff); buffer[5] = (byte)((n2>>8)&0xff); 343238384Sjkim buffer[6] = (byte)((n2>>16)&0xff); buffer[7] = (byte)(n2>>24); 344238384Sjkim } 345238384Sjkim 346238384Sjkim/* Get mac with specified number of bits from MAC state buffer */ 347238384Sjkimvoid get_mac(byte *buffer,int nbits,byte *out) 348238384Sjkim { 349238384Sjkim int nbytes= nbits >> 3; 350238384Sjkim int rembits = nbits & 7; 351238384Sjkim int mask =rembits?((1<rembits)-1):0; 352238384Sjkim int i; 353238384Sjkim for (i=0;i<nbytes;i++) out[i]=buffer[i]; 354238384Sjkim if (rembits) out[i]=buffer[i]&mask; 355238384Sjkim } 356238384Sjkim 357238384Sjkim/* Compute mac of specified length (in bits) from data. 358238384Sjkim * Context should be initialized with key and subst blocks */ 359238384Sjkimint gost_mac(gost_ctx *ctx,int mac_len,const unsigned char *data, 360238384Sjkim unsigned int data_len,unsigned char *mac) 361238384Sjkim { 362238384Sjkim byte buffer[8]={0,0,0,0,0,0,0,0}; 363238384Sjkim byte buf2[8]; 364238384Sjkim unsigned int i; 365238384Sjkim for (i=0;i+8<=data_len;i+=8) 366238384Sjkim mac_block(ctx,buffer,data+i); 367238384Sjkim if (i<data_len) 368238384Sjkim { 369238384Sjkim memset(buf2,0,8); 370238384Sjkim memcpy(buf2,data+i,data_len-i); 371238384Sjkim mac_block(ctx,buffer,buf2); 372246772Sjkim i+=8; 373246772Sjkim } 374246772Sjkim if (i==8) 375246772Sjkim { 376246772Sjkim memset(buf2,0,8); 377246772Sjkim mac_block(ctx,buffer,buf2); 378246772Sjkim } 379238384Sjkim get_mac(buffer,mac_len,mac); 380238384Sjkim return 1; 381238384Sjkim } 382238384Sjkim 383238384Sjkim/* Compute MAC with non-zero IV. Used in some RFC 4357 algorithms */ 384238384Sjkimint gost_mac_iv(gost_ctx *ctx,int mac_len,const unsigned char *iv,const unsigned char *data, 385238384Sjkim unsigned int data_len,unsigned char *mac) 386238384Sjkim { 387238384Sjkim byte buffer[8]; 388238384Sjkim byte buf2[8]; 389238384Sjkim unsigned int i; 390238384Sjkim memcpy (buffer,iv,8); 391238384Sjkim for (i=0;i+8<=data_len;i+=8) 392238384Sjkim mac_block(ctx,buffer,data+i); 393238384Sjkim if (i<data_len) 394238384Sjkim { 395238384Sjkim memset(buf2,0,8); 396238384Sjkim memcpy(buf2,data+i,data_len-i); 397238384Sjkim mac_block(ctx,buffer,buf2); 398246772Sjkim i+=8; 399238384Sjkim } 400246772Sjkim if (i==8) 401246772Sjkim { 402246772Sjkim memset(buf2,0,8); 403246772Sjkim mac_block(ctx,buffer,buf2); 404246772Sjkim } 405238384Sjkim get_mac(buffer,mac_len,mac); 406238384Sjkim return 1; 407238384Sjkim } 408238384Sjkim 409238384Sjkim/* Implements key meshing algorithm by modifing ctx and IV in place */ 410238384Sjkimvoid cryptopro_key_meshing(gost_ctx *ctx, unsigned char *iv) 411238384Sjkim { 412238384Sjkim unsigned char newkey[32],newiv[8]; 413238384Sjkim /* Set static keymeshing key */ 414238384Sjkim /* "Decrypt" key with keymeshing key */ 415238384Sjkim gost_dec(ctx,CryptoProKeyMeshingKey,newkey,4); 416238384Sjkim /* set new key */ 417238384Sjkim gost_key(ctx,newkey); 418238384Sjkim /* Encrypt iv with new key */ 419238384Sjkim gostcrypt(ctx,iv,newiv); 420238384Sjkim memcpy(iv,newiv,8); 421238384Sjkim } 422