1 /**********************************************************************
3 * Copyright (c) 2005-2006 Cryptocom LTD *
4 * This file is distributed under the same license as OpenSSL *
6 * Implementation of GOST 28147-89 encryption algorithm *
7 * No OpenSSL libraries required to compile and use *
9 **********************************************************************/
12 /* Substitution blocks from RFC 4357
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.
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}
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}
44 /* Test paramset from GOST 28147 */
45 gost_subst_block Gost28147_TestParamSet =
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}
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}
71 /* 1.2.643.2.2.31.2 */
72 gost_subst_block Gost28147_CryptoProParamSetB=
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}
83 /* 1.2.643.2.2.31.3 */
84 gost_subst_block Gost28147_CryptoProParamSetC=
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}
96 /* 1.2.643.2.2.31.4 */
97 gost_subst_block Gost28147_CryptoProParamSetD=
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}
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
116 /* Initialization of gost_ctx subst blocks*/
117 void kboxinit(gost_ctx *c, const gost_subst_block *b) {
120 for (i = 0; i < 256; i++) {
121 c->k87[i] = (b->k8[i>>4] <<4 | b->k7 [i &15])<<24;
122 c->k65[i] = (b->k6[i>>4] << 4 | b->k5 [i &15])<<16;
123 c->k43[i] = (b->k4[i>>4] <<4 | b->k3 [i &15])<<8;
124 c->k21[i] = b->k2[i>>4] <<4 | b->k1 [i &15];
129 /* Part of GOST 28147 algorithm moved into separate function */
131 f(gost_ctx *c,word32 x)
132 { x = c->k87[x>>24 & 255] | c->k65[x>>16 & 255]|
133 c->k43[x>> 8 & 255] | c->k21[x & 255];
134 /* Rotate left 11 bits */
135 return x<<11 | x>>(32-11);
137 /* Low-level encryption routine - encrypts one 64 bit block*/
138 void gostcrypt(gost_ctx *c, const byte *in, byte *out)
140 register word32 n1, n2; /* As named in the GOST */
141 n1 = in[0]|(in[1]<<8)|(in[2]<<16)|(in[3]<<24);
142 n2 = in[4]|(in[5]<<8)|(in[6]<<16)|(in[7]<<24);
143 /* Instead of swapping halves, swap names each round */
145 n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
146 n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
147 n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
148 n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
150 n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
151 n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
152 n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
153 n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
155 n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
156 n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
157 n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
158 n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
160 n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]);
161 n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]);
162 n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]);
163 n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]);
165 out[0] = (n2&0xff); out[1] = (n2>>8)&0xff; out[2]=(n2>>16)&0xff; out[3]=n2>>24;
166 out[4] = (n1&0xff); out[5] = (n1>>8)&0xff; out[6]=(n1>>16)&0xff; out[7]=n1>>24;
168 /* Low-level decryption routine. Decrypts one 64-bit block */
169 void gostdecrypt(gost_ctx *c, const byte *in,byte *out)
171 register word32 n1, n2; /* As named in the GOST */
172 n1 = in[0]|(in[1]<<8)|(in[2]<<16)|(in[3]<<24);
173 n2 = in[4]|(in[5]<<8)|(in[6]<<16)|(in[7]<<24);
175 n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
176 n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
177 n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
178 n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
180 n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]);
181 n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]);
182 n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]);
183 n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]);
185 n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]);
186 n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]);
187 n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]);
188 n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]);
190 n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]);
191 n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]);
192 n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]);
193 n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]);
194 out[0] = (n2&0xff); out[1] = (n2>>8)&0xff; out[2]=(n2>>16)&0xff; out[3]=n2>>24;
195 out[4] = (n1&0xff); out[5] = (n1>>8)&0xff; out[6]=(n1>>16)&0xff; out[7]=n1>>24;
198 /* Encrypts several blocks in ECB mode */
199 void gost_enc(gost_ctx *c,const byte *clear,byte *cipher, int blocks)
202 for(i=0;i<blocks;i++){
203 gostcrypt(c,clear,cipher);
208 /* Decrypts several blocks in ECB mode */
209 void gost_dec(gost_ctx *c, const byte *cipher,byte *clear, int blocks)
212 for(i=0;i<blocks;i++) {
213 gostdecrypt(c,cipher,clear);
220 /* Encrypts several full blocks in CFB mode using 8byte IV */
221 void gost_enc_cfb(gost_ctx *ctx,const byte *iv,const byte *clear,byte *cipher, int blocks) {
228 for(i=0,in=clear,out=cipher;i<blocks;i++,in+=8,out+=8) {
229 gostcrypt(ctx,cur_iv,gamma);
231 cur_iv[j]=out[j]=in[j]^gamma[j];
236 /* Decrypts several full blocks in CFB mode using 8byte IV */
237 void gost_dec_cfb(gost_ctx *ctx,const byte *iv,const byte *cipher,byte *clear, int blocks) {
244 for(i=0,in=cipher,out=clear;i<blocks;i++,in+=8,out+=8) {
245 gostcrypt(ctx,cur_iv,gamma);
247 out[j]=(cur_iv[j]=in[j])^gamma[j];
252 /* Encrypts one block using specified key */
253 void gost_enc_with_key(gost_ctx *c,byte *key,byte *inblock,byte *outblock)
256 gostcrypt(c,inblock,outblock);
259 /* Set 256 bit key into context */
260 void gost_key(gost_ctx *c, const byte *k)
263 for(i=0,j=0;i<8;i++,j+=4) {
264 c->k[i]=k[j]|(k[j+1]<<8)|(k[j+2]<<16)|(k[j+3]<<24);
267 /* Retrieve 256-bit key from context */
268 void gost_get_key(gost_ctx *c, byte *k)
271 for(i=0,j=0;i<8;i++,j+=4) {
273 k[j+1]=(c->k[i]>>8 )&0xFF;
274 k[j+2]=(c->k[i]>>16) &0xFF;
275 k[j+3]=(c->k[i]>>24) &0xFF;
279 /* Initalize context. Provides default value for subst_block */
280 void gost_init(gost_ctx *c, const gost_subst_block *b)
283 b=&GostR3411_94_TestParamSet;
287 /* Cleans up key from context */
288 void gost_destroy(gost_ctx *c)
290 int i; for(i=0;i<8;i++) c->k[i]=0;
293 /* Compute GOST 28147 mac block
296 * gost_ctx *c - context initalized with substitution blocks and key
297 * buffer - 8-byte mac state buffer
298 * block 8-byte block to process.
300 void mac_block(gost_ctx *c,byte *buffer,const byte *block) {
302 register word32 n1, n2; /* As named in the GOST */
304 for (i=0; i<8; i++) {
307 n1 = buffer[0]|(buffer[1]<<8)|(buffer[2]<<16)|(buffer[3]<<24);
308 n2 = buffer[4]|(buffer[5]<<8)|(buffer[6]<<16)|(buffer[7]<<24);
309 /* Instead of swapping halves, swap names each round */
311 n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
312 n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
313 n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
314 n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
316 n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
317 n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
318 n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
319 n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
321 buffer[0] = (n1&0xff); buffer[1] = (n1>>8)&0xff; buffer[2]=(n1>>16)&0xff; buffer[3]=n1>>24;
322 buffer[4] = (n2&0xff); buffer[5] = (n2>>8)&0xff; buffer[6]=(n2>>16)&0xff; buffer[7]=n2>>24;
325 /* Get mac with specified number of bits from MAC state buffer */
326 void get_mac(byte *buffer,int nbits,byte *out) {
327 int nbytes= nbits >> 3;
328 int rembits = nbits & 7;
329 int mask =rembits?((1<rembits)-1):0;
331 for (i=0;i<nbytes;i++) out[i]=buffer[i];
332 if (rembits) out[i]=buffer[i]&mask;
335 /* Compute mac of specified length (in bits) from data.
336 * Context should be initialized with key and subst blocks */
337 int gost_mac(gost_ctx *ctx,int mac_len,const unsigned char *data,
338 unsigned int data_len,unsigned char *mac)
340 byte buffer[8]={0,0,0,0,0,0,0,0};
343 for (i=0;i+8<=data_len;i+=8)
344 mac_block(ctx,buffer,data+i);
347 memcpy(buf2,data+i,data_len-i);
348 mac_block(ctx,buffer,buf2);
350 get_mac(buffer,mac_len,mac);
353 /* Compute MAC with non-zero IV. Used in some RFC 4357 algorithms */
354 int gost_mac_iv(gost_ctx *ctx,int mac_len,const unsigned char *iv,const unsigned char *data,
355 unsigned int data_len,unsigned char *mac)
360 memcpy (buffer,iv,8);
361 for (i=0;i+8<=data_len;i+=8)
362 mac_block(ctx,buffer,data+i);
365 memcpy(buf2,data+i,data_len-i);
366 mac_block(ctx,buffer,buf2);
368 get_mac(buffer,mac_len,mac);
372 /* Implements key meshing algorithm by modifing ctx and IV in place */
373 void cryptopro_key_meshing(gost_ctx *ctx, unsigned char *iv) {
374 unsigned char newkey[32],newiv[8];
375 /* Set static keymeshing key */
376 /* "Decrypt" key with keymeshing key */
377 gost_dec(ctx,CryptoProKeyMeshingKey,newkey,4);
379 gost_key(ctx,newkey);
380 /* Encrypt iv with new key */
381 gostcrypt(ctx,iv,newiv);