OLD | NEW |
(Empty) | |
| 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*/ |
| 22 gost_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 */ |
| 33 gost_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 */ |
| 45 gost_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 */ |
| 61 gost_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 */ |
| 72 gost_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 */ |
| 84 gost_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 */ |
| 97 gost_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 |
| 110 const 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*/ |
| 117 static 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 */ |
| 132 static 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*/ |
| 140 void 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 */ |
| 173 void 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 */ |
| 206 void 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 */ |
| 217 void 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 */ |
| 229 void gost_enc_cfb(gost_ctx *ctx,const byte *iv,const byte *clear,byte *cipher, i
nt 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 */ |
| 247 void 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 */ |
| 266 void 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 */ |
| 273 void 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 */ |
| 283 void 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 */ |
| 296 void 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 */ |
| 306 void 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 * */ |
| 318 void 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 */ |
| 347 void 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 */ |
| 359 int 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 */ |
| 378 int 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 */ |
| 398 void 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 } |
OLD | NEW |