Branch data Line data Source code
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 : 38 : static void kboxinit(gost_ctx *c, const gost_subst_block *b)
118 : : {
119 : : int i;
120 : :
121 [ + + ]: 9766 : for (i = 0; i < 256; i++)
122 : : {
123 : 9728 : c->k87[i] = (word32)(b->k8[i>>4] <<4 | b->k7 [i &15])<<24;
124 : 9728 : c->k65[i] = (b->k6[i>>4] << 4 | b->k5 [i &15])<<16;
125 : 9728 : c->k43[i] = (b->k4[i>>4] <<4 | b->k3 [i &15])<<8;
126 : 9728 : c->k21[i] = b->k2[i>>4] <<4 | b->k1 [i &15];
127 : :
128 : : }
129 : 38 : }
130 : :
131 : : /* Part of GOST 28147 algorithm moved into separate function */
132 : 54906464 : static word32 f(gost_ctx *c,word32 x)
133 : : {
134 : 164719392 : x = c->k87[x>>24 & 255] | c->k65[x>>16 & 255]|
135 : 109812928 : c->k43[x>> 8 & 255] | c->k21[x & 255];
136 : : /* Rotate left 11 bits */
137 : 54906464 : return x<<11 | x>>(32-11);
138 : : }
139 : : /* Low-level encryption routine - encrypts one 64 bit block*/
140 : 1326630 : void gostcrypt(gost_ctx *c, const byte *in, byte *out)
141 : : {
142 : : register word32 n1, n2; /* As named in the GOST */
143 : 1326630 : n1 = in[0]|(in[1]<<8)|(in[2]<<16)|((word32)in[3]<<24);
144 : 1326630 : n2 = in[4]|(in[5]<<8)|(in[6]<<16)|((word32)in[7]<<24);
145 : : /* Instead of swapping halves, swap names each round */
146 : :
147 : 1326630 : n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
148 : 1326630 : n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
149 : 1326630 : n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
150 : 1326630 : n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
151 : :
152 : 1326630 : n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
153 : 1326630 : n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
154 : 1326630 : n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
155 : 1326630 : n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
156 : :
157 : 1326630 : n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
158 : 1326630 : n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
159 : 1326630 : n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
160 : 1326630 : n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
161 : :
162 : 1326630 : n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]);
163 : 1326630 : n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]);
164 : 1326630 : n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]);
165 : 1326630 : n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]);
166 : :
167 : 1326630 : out[0] = (byte)(n2&0xff); out[1] = (byte)((n2>>8)&0xff);
168 : 1326630 : out[2] = (byte)((n2>>16)&0xff); out[3]=(byte)(n2>>24);
169 : 1326630 : out[4] = (byte)(n1&0xff); out[5] = (byte)((n1>>8)&0xff);
170 : 1326630 : out[6] = (byte)((n1>>16)&0xff); out[7] = (byte)(n1>>24);
171 : 1326630 : }
172 : : /* Low-level decryption routine. Decrypts one 64-bit block */
173 : 61448 : void gostdecrypt(gost_ctx *c, const byte *in,byte *out)
174 : : {
175 : : register word32 n1, n2; /* As named in the GOST */
176 : 61448 : n1 = in[0]|(in[1]<<8)|(in[2]<<16)|((word32)in[3]<<24);
177 : 61448 : n2 = in[4]|(in[5]<<8)|(in[6]<<16)|((word32)in[7]<<24);
178 : :
179 : 61448 : n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
180 : 61448 : n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
181 : 61448 : n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
182 : 61448 : n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
183 : :
184 : 61448 : n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]);
185 : 61448 : n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]);
186 : 61448 : n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]);
187 : 61448 : n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]);
188 : :
189 : 61448 : n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]);
190 : 61448 : n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]);
191 : 61448 : n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]);
192 : 61448 : n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]);
193 : :
194 : 61448 : n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]);
195 : 61448 : n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]);
196 : 61448 : n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]);
197 : 61448 : n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]);
198 : :
199 : 61448 : out[0] = (byte)(n2&0xff); out[1] = (byte)((n2>>8)&0xff);
200 : 61448 : out[2] = (byte)((n2>>16)&0xff); out[3]=(byte)(n2>>24);
201 : 61448 : out[4] = (byte)(n1&0xff); out[5] = (byte)((n1>>8)&0xff);
202 : 61448 : out[6] = (byte)((n1>>16)&0xff); out[7] = (byte)(n1>>24);
203 : 61448 : }
204 : :
205 : : /* Encrypts several blocks in ECB mode */
206 : 0 : void gost_enc(gost_ctx *c,const byte *clear,byte *cipher, int blocks)
207 : : {
208 : : int i;
209 [ # # ]: 0 : for(i=0;i<blocks;i++)
210 : : {
211 : 0 : gostcrypt(c,clear,cipher);
212 : 0 : clear+=8;
213 : 0 : cipher+=8;
214 : : }
215 : 0 : }
216 : : /* Decrypts several blocks in ECB mode */
217 : 15362 : void gost_dec(gost_ctx *c, const byte *cipher,byte *clear, int blocks)
218 : : {
219 : : int i;
220 [ + + ]: 76810 : for(i=0;i<blocks;i++)
221 : : {
222 : 61448 : gostdecrypt(c,cipher,clear);
223 : 61448 : clear+=8;
224 : 61448 : cipher+=8;
225 : : }
226 : 15362 : }
227 : :
228 : : /* Encrypts several full blocks in CFB mode using 8byte IV */
229 : 0 : void 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 [ # # ]: 0 : for(i=0,in=clear,out=cipher;i<blocks;i++,in+=8,out+=8)
238 : : {
239 : 0 : gostcrypt(ctx,cur_iv,gamma);
240 [ # # ]: 0 : for (j=0;j<8;j++)
241 : : {
242 : 0 : cur_iv[j]=out[j]=in[j]^gamma[j];
243 : : }
244 : : }
245 : 0 : }
246 : : /* Decrypts several full blocks in CFB mode using 8byte IV */
247 : 0 : 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 [ # # ]: 0 : for(i=0,in=cipher,out=clear;i<blocks;i++,in+=8,out+=8)
256 : : {
257 : 0 : gostcrypt(ctx,cur_iv,gamma);
258 [ # # ]: 0 : for (j=0;j<8;j++)
259 : : {
260 : 0 : out[j]=(cur_iv[j]=in[j])^gamma[j];
261 : : }
262 : : }
263 : 0 : }
264 : :
265 : : /* Encrypts one block using specified key */
266 : 276 : void gost_enc_with_key(gost_ctx *c,byte *key,byte *inblock,byte *outblock)
267 : : {
268 : 276 : gost_key(c,key);
269 : 276 : gostcrypt(c,inblock,outblock);
270 : 276 : }
271 : :
272 : : /* Set 256 bit key into context */
273 : 15653 : void gost_key(gost_ctx *c, const byte *k)
274 : : {
275 : : int i,j;
276 [ + + ]: 140877 : for(i=0,j=0;i<8;i++,j+=4)
277 : : {
278 : 125224 : c->k[i]=k[j]|(k[j+1]<<8)|(k[j+2]<<16)|((word32)k[j+3]<<24);
279 : : }
280 : 15653 : }
281 : :
282 : : /* Retrieve 256-bit key from context */
283 : 0 : void gost_get_key(gost_ctx *c, byte *k)
284 : : {
285 : : int i,j;
286 [ # # ]: 0 : for(i=0,j=0;i<8;i++,j+=4)
287 : : {
288 : 0 : k[j]=(byte)(c->k[i]& 0xFF);
289 : 0 : k[j+1]=(byte)((c->k[i]>>8 )&0xFF);
290 : 0 : k[j+2]=(byte)((c->k[i]>>16) &0xFF);
291 : 0 : k[j+3]=(byte)((c->k[i]>>24) &0xFF);
292 : : }
293 : 0 : }
294 : :
295 : : /* Initalize context. Provides default value for subst_block */
296 : 38 : void gost_init(gost_ctx *c, const gost_subst_block *b)
297 : : {
298 [ - + ]: 38 : if(!b)
299 : : {
300 : 0 : b=&GostR3411_94_TestParamSet;
301 : : }
302 : 38 : kboxinit(c,b);
303 : 38 : }
304 : :
305 : : /* Cleans up key from context */
306 : 8 : void gost_destroy(gost_ctx *c)
307 : : {
308 [ + + ]: 72 : int i; for(i=0;i<8;i++) c->k[i]=0;
309 : 8 : }
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 : 655498 : 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 [ + + ]: 5899482 : for (i=0; i<8; i++)
323 : : {
324 : 5243984 : buffer[i]^=block[i];
325 : : }
326 : 655498 : n1 = buffer[0]|(buffer[1]<<8)|(buffer[2]<<16)|((word32)buffer[3]<<24);
327 : 655498 : n2 = buffer[4]|(buffer[5]<<8)|(buffer[6]<<16)|((word32)buffer[7]<<24);
328 : : /* Instead of swapping halves, swap names each round */
329 : :
330 : 655498 : n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
331 : 655498 : n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
332 : 655498 : n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
333 : 655498 : n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
334 : :
335 : 655498 : n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
336 : 655498 : n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
337 : 655498 : n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
338 : 655498 : n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
339 : :
340 : 655498 : buffer[0] = (byte)(n1&0xff); buffer[1] = (byte)((n1>>8)&0xff);
341 : 655498 : buffer[2] = (byte)((n1>>16)&0xff); buffer[3] = (byte)(n1>>24);
342 : 655498 : buffer[4] = (byte)(n2&0xff); buffer[5] = (byte)((n2>>8)&0xff);
343 : 655498 : buffer[6] = (byte)((n2>>16)&0xff); buffer[7] = (byte)(n2>>24);
344 : 655498 : }
345 : :
346 : : /* Get mac with specified number of bits from MAC state buffer */
347 : 7 : void get_mac(byte *buffer,int nbits,byte *out)
348 : : {
349 : 7 : int nbytes= nbits >> 3;
350 : 7 : int rembits = nbits & 7;
351 [ - + ][ # # ]: 7 : int mask =rembits?((1<rembits)-1):0;
352 : : int i;
353 [ + + ]: 35 : for (i=0;i<nbytes;i++) out[i]=buffer[i];
354 [ - + ]: 7 : if (rembits) out[i]=buffer[i]&mask;
355 : 7 : }
356 : :
357 : : /* Compute mac of specified length (in bits) from data.
358 : : * Context should be initialized with key and subst blocks */
359 : 0 : int gost_mac(gost_ctx *ctx,int mac_len,const unsigned char *data,
360 : : unsigned int data_len,unsigned char *mac)
361 : : {
362 : 0 : byte buffer[8]={0,0,0,0,0,0,0,0};
363 : : byte buf2[8];
364 : : unsigned int i;
365 [ # # ]: 0 : for (i=0;i+8<=data_len;i+=8)
366 : 0 : mac_block(ctx,buffer,data+i);
367 [ # # ]: 0 : if (i<data_len)
368 : : {
369 : : memset(buf2,0,8);
370 : 0 : memcpy(buf2,data+i,data_len-i);
371 : 0 : mac_block(ctx,buffer,buf2);
372 : 0 : i+=8;
373 : : }
374 [ # # ]: 0 : if (i==8)
375 : : {
376 : : memset(buf2,0,8);
377 : 0 : mac_block(ctx,buffer,buf2);
378 : : }
379 : 0 : get_mac(buffer,mac_len,mac);
380 : 0 : return 1;
381 : : }
382 : :
383 : : /* Compute MAC with non-zero IV. Used in some RFC 4357 algorithms */
384 : 0 : int gost_mac_iv(gost_ctx *ctx,int mac_len,const unsigned char *iv,const unsigned char *data,
385 : : unsigned int data_len,unsigned char *mac)
386 : : {
387 : : byte buffer[8];
388 : : byte buf2[8];
389 : : unsigned int i;
390 : : memcpy (buffer,iv,8);
391 [ # # ]: 0 : for (i=0;i+8<=data_len;i+=8)
392 : 0 : mac_block(ctx,buffer,data+i);
393 [ # # ]: 0 : if (i<data_len)
394 : : {
395 : : memset(buf2,0,8);
396 : 0 : memcpy(buf2,data+i,data_len-i);
397 : 0 : mac_block(ctx,buffer,buf2);
398 : 0 : i+=8;
399 : : }
400 [ # # ]: 0 : if (i==8)
401 : : {
402 : : memset(buf2,0,8);
403 : 0 : mac_block(ctx,buffer,buf2);
404 : : }
405 : 0 : get_mac(buffer,mac_len,mac);
406 : 0 : return 1;
407 : : }
408 : :
409 : : /* Implements key meshing algorithm by modifing ctx and IV in place */
410 : 15362 : void cryptopro_key_meshing(gost_ctx *ctx, unsigned char *iv)
411 : : {
412 : : unsigned char newkey[32],newiv[8];
413 : : /* Set static keymeshing key */
414 : : /* "Decrypt" key with keymeshing key */
415 : 15362 : gost_dec(ctx,CryptoProKeyMeshingKey,newkey,4);
416 : : /* set new key */
417 : 15362 : gost_key(ctx,newkey);
418 : : /* Encrypt iv with new key */
419 : 15362 : gostcrypt(ctx,iv,newiv);
420 : : memcpy(iv,newiv,8);
421 : 15362 : }
|