]>
Commit | Line | Data |
---|---|---|
a04549cc DSH |
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 = { | |
926c41bd DSH |
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 | }; | |
a04549cc DSH |
32 | /* Substitution blocks for hash function 1.2.643.2.9.1.6.1 */ |
33 | gost_subst_block GostR3411_94_CryptoProParamSet= { | |
926c41bd DSH |
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 | } ; | |
a04549cc DSH |
43 | |
44 | /* Test paramset from GOST 28147 */ | |
45 | gost_subst_block Gost28147_TestParamSet = | |
926c41bd | 46 | { |
a04549cc DSH |
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} | |
926c41bd | 55 | }; |
a04549cc DSH |
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} | |
926c41bd | 70 | }; |
a04549cc DSH |
71 | /* 1.2.643.2.2.31.2 */ |
72 | gost_subst_block Gost28147_CryptoProParamSetB= | |
926c41bd | 73 | { |
a04549cc DSH |
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} | |
926c41bd | 82 | }; |
a04549cc DSH |
83 | /* 1.2.643.2.2.31.3 */ |
84 | gost_subst_block Gost28147_CryptoProParamSetC= | |
926c41bd | 85 | { |
a04549cc DSH |
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} | |
926c41bd | 94 | }; |
a04549cc DSH |
95 | |
96 | /* 1.2.643.2.2.31.4 */ | |
97 | gost_subst_block Gost28147_CryptoProParamSetD= | |
926c41bd | 98 | { |
a04549cc DSH |
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} | |
926c41bd | 107 | }; |
a04549cc DSH |
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 | |
926c41bd | 115 | }; |
a04549cc | 116 | /* Initialization of gost_ctx subst blocks*/ |
84948b39 | 117 | static void kboxinit(gost_ctx *c, const gost_subst_block *b) |
926c41bd | 118 | { |
a04549cc DSH |
119 | int i; |
120 | ||
926c41bd DSH |
121 | for (i = 0; i < 256; i++) |
122 | { | |
a04549cc DSH |
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 | ||
926c41bd | 128 | } |
a04549cc | 129 | } |
a04549cc DSH |
130 | |
131 | /* Part of GOST 28147 algorithm moved into separate function */ | |
926c41bd DSH |
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 | } | |
a04549cc DSH |
139 | /* Low-level encryption routine - encrypts one 64 bit block*/ |
140 | void gostcrypt(gost_ctx *c, const byte *in, byte *out) | |
926c41bd DSH |
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 */ | |
a04549cc | 146 | |
926c41bd DSH |
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]); | |
a04549cc | 151 | |
926c41bd DSH |
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]); | |
a04549cc | 156 | |
926c41bd DSH |
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]); | |
a04549cc | 161 | |
926c41bd DSH |
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]); | |
a04549cc | 166 | |
926c41bd DSH |
167 | out[0] = (n2&0xff); out[1] = (n2>>8)&0xff; out[2]=(n2>>16)&0xff; out[3]=n2>>24; |
168 | out[4] = (n1&0xff); out[5] = (n1>>8)&0xff; out[6]=(n1>>16)&0xff; out[7]=n1>>24; | |
169 | } | |
a04549cc DSH |
170 | /* Low-level decryption routine. Decrypts one 64-bit block */ |
171 | void gostdecrypt(gost_ctx *c, const byte *in,byte *out) | |
926c41bd | 172 | { |
a04549cc DSH |
173 | register word32 n1, n2; /* As named in the GOST */ |
174 | n1 = in[0]|(in[1]<<8)|(in[2]<<16)|(in[3]<<24); | |
175 | n2 = in[4]|(in[5]<<8)|(in[6]<<16)|(in[7]<<24); | |
176 | ||
177 | n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]); | |
178 | n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]); | |
179 | n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]); | |
180 | n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]); | |
181 | ||
182 | n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]); | |
183 | n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]); | |
184 | n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]); | |
185 | n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]); | |
186 | ||
187 | n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]); | |
188 | n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]); | |
189 | n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]); | |
190 | n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]); | |
191 | ||
192 | n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]); | |
193 | n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]); | |
194 | n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]); | |
195 | n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]); | |
196 | out[0] = (n2&0xff); out[1] = (n2>>8)&0xff; out[2]=(n2>>16)&0xff; out[3]=n2>>24; | |
197 | out[4] = (n1&0xff); out[5] = (n1>>8)&0xff; out[6]=(n1>>16)&0xff; out[7]=n1>>24; | |
926c41bd | 198 | } |
a04549cc DSH |
199 | |
200 | /* Encrypts several blocks in ECB mode */ | |
201 | void gost_enc(gost_ctx *c,const byte *clear,byte *cipher, int blocks) | |
926c41bd | 202 | { |
a04549cc | 203 | int i; |
926c41bd DSH |
204 | for(i=0;i<blocks;i++) |
205 | { | |
a04549cc DSH |
206 | gostcrypt(c,clear,cipher); |
207 | clear+=8; | |
208 | cipher+=8; | |
926c41bd | 209 | } |
a04549cc | 210 | } |
a04549cc DSH |
211 | /* Decrypts several blocks in ECB mode */ |
212 | void gost_dec(gost_ctx *c, const byte *cipher,byte *clear, int blocks) | |
926c41bd | 213 | { |
a04549cc | 214 | int i; |
926c41bd DSH |
215 | for(i=0;i<blocks;i++) |
216 | { | |
a04549cc DSH |
217 | gostdecrypt(c,cipher,clear); |
218 | clear+=8; | |
219 | cipher+=8; | |
926c41bd | 220 | } |
a04549cc DSH |
221 | } |
222 | ||
a04549cc | 223 | /* Encrypts several full blocks in CFB mode using 8byte IV */ |
926c41bd DSH |
224 | void gost_enc_cfb(gost_ctx *ctx,const byte *iv,const byte *clear,byte *cipher, int blocks) |
225 | { | |
a04549cc DSH |
226 | byte cur_iv[8]; |
227 | byte gamma[8]; | |
228 | int i,j; | |
229 | const byte *in; | |
230 | byte *out; | |
231 | memcpy(cur_iv,iv,8); | |
926c41bd DSH |
232 | for(i=0,in=clear,out=cipher;i<blocks;i++,in+=8,out+=8) |
233 | { | |
a04549cc | 234 | gostcrypt(ctx,cur_iv,gamma); |
926c41bd DSH |
235 | for (j=0;j<8;j++) |
236 | { | |
a04549cc | 237 | cur_iv[j]=out[j]=in[j]^gamma[j]; |
926c41bd DSH |
238 | } |
239 | } | |
a04549cc | 240 | } |
a04549cc | 241 | /* Decrypts several full blocks in CFB mode using 8byte IV */ |
926c41bd DSH |
242 | void gost_dec_cfb(gost_ctx *ctx,const byte *iv,const byte *cipher,byte *clear, int blocks) |
243 | { | |
a04549cc DSH |
244 | byte cur_iv[8]; |
245 | byte gamma[8]; | |
246 | int i,j; | |
247 | const byte *in; | |
248 | byte *out; | |
249 | memcpy(cur_iv,iv,8); | |
926c41bd DSH |
250 | for(i=0,in=cipher,out=clear;i<blocks;i++,in+=8,out+=8) |
251 | { | |
a04549cc | 252 | gostcrypt(ctx,cur_iv,gamma); |
926c41bd DSH |
253 | for (j=0;j<8;j++) |
254 | { | |
a04549cc | 255 | out[j]=(cur_iv[j]=in[j])^gamma[j]; |
926c41bd DSH |
256 | } |
257 | } | |
a04549cc | 258 | } |
a04549cc DSH |
259 | |
260 | /* Encrypts one block using specified key */ | |
261 | void gost_enc_with_key(gost_ctx *c,byte *key,byte *inblock,byte *outblock) | |
926c41bd | 262 | { |
a04549cc DSH |
263 | gost_key(c,key); |
264 | gostcrypt(c,inblock,outblock); | |
926c41bd | 265 | } |
a04549cc | 266 | |
a04549cc DSH |
267 | /* Set 256 bit key into context */ |
268 | void gost_key(gost_ctx *c, const byte *k) | |
926c41bd | 269 | { |
a04549cc | 270 | int i,j; |
926c41bd DSH |
271 | for(i=0,j=0;i<8;i++,j+=4) |
272 | { | |
a04549cc | 273 | c->k[i]=k[j]|(k[j+1]<<8)|(k[j+2]<<16)|(k[j+3]<<24); |
926c41bd DSH |
274 | } |
275 | } | |
276 | ||
a04549cc DSH |
277 | /* Retrieve 256-bit key from context */ |
278 | void gost_get_key(gost_ctx *c, byte *k) | |
926c41bd | 279 | { |
a04549cc | 280 | int i,j; |
926c41bd DSH |
281 | for(i=0,j=0;i<8;i++,j+=4) |
282 | { | |
a04549cc DSH |
283 | k[j]=c->k[i]& 0xFF; |
284 | k[j+1]=(c->k[i]>>8 )&0xFF; | |
285 | k[j+2]=(c->k[i]>>16) &0xFF; | |
286 | k[j+3]=(c->k[i]>>24) &0xFF; | |
926c41bd DSH |
287 | } |
288 | } | |
a04549cc | 289 | |
a04549cc DSH |
290 | /* Initalize context. Provides default value for subst_block */ |
291 | void gost_init(gost_ctx *c, const gost_subst_block *b) | |
926c41bd DSH |
292 | { |
293 | if(!b) | |
294 | { | |
a04549cc | 295 | b=&GostR3411_94_TestParamSet; |
926c41bd | 296 | } |
a04549cc | 297 | kboxinit(c,b); |
926c41bd DSH |
298 | } |
299 | ||
a04549cc DSH |
300 | /* Cleans up key from context */ |
301 | void gost_destroy(gost_ctx *c) | |
926c41bd | 302 | { |
a04549cc | 303 | int i; for(i=0;i<8;i++) c->k[i]=0; |
926c41bd | 304 | } |
a04549cc DSH |
305 | |
306 | /* Compute GOST 28147 mac block | |
307 | * | |
308 | * Parameters | |
309 | * gost_ctx *c - context initalized with substitution blocks and key | |
310 | * buffer - 8-byte mac state buffer | |
311 | * block 8-byte block to process. | |
312 | * */ | |
926c41bd DSH |
313 | void mac_block(gost_ctx *c,byte *buffer,const byte *block) |
314 | { | |
315 | register word32 n1, n2; /* As named in the GOST */ | |
316 | int i; | |
317 | for (i=0; i<8; i++) | |
318 | { | |
319 | buffer[i]^=block[i]; | |
320 | } | |
321 | n1 = buffer[0]|(buffer[1]<<8)|(buffer[2]<<16)|(buffer[3]<<24); | |
322 | n2 = buffer[4]|(buffer[5]<<8)|(buffer[6]<<16)|(buffer[7]<<24); | |
323 | /* Instead of swapping halves, swap names each round */ | |
a04549cc | 324 | |
926c41bd DSH |
325 | n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]); |
326 | n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]); | |
327 | n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]); | |
328 | n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]); | |
a04549cc | 329 | |
926c41bd DSH |
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]); | |
a04549cc DSH |
334 | |
335 | buffer[0] = (n1&0xff); buffer[1] = (n1>>8)&0xff; buffer[2]=(n1>>16)&0xff; buffer[3]=n1>>24; | |
336 | buffer[4] = (n2&0xff); buffer[5] = (n2>>8)&0xff; buffer[6]=(n2>>16)&0xff; buffer[7]=n2>>24; | |
926c41bd | 337 | } |
a04549cc DSH |
338 | |
339 | /* Get mac with specified number of bits from MAC state buffer */ | |
926c41bd DSH |
340 | void get_mac(byte *buffer,int nbits,byte *out) |
341 | { | |
a04549cc DSH |
342 | int nbytes= nbits >> 3; |
343 | int rembits = nbits & 7; | |
344 | int mask =rembits?((1<rembits)-1):0; | |
345 | int i; | |
346 | for (i=0;i<nbytes;i++) out[i]=buffer[i]; | |
347 | if (rembits) out[i]=buffer[i]&mask; | |
926c41bd | 348 | } |
a04549cc DSH |
349 | |
350 | /* Compute mac of specified length (in bits) from data. | |
351 | * Context should be initialized with key and subst blocks */ | |
352 | int gost_mac(gost_ctx *ctx,int mac_len,const unsigned char *data, | |
926c41bd DSH |
353 | unsigned int data_len,unsigned char *mac) |
354 | { | |
a04549cc DSH |
355 | byte buffer[8]={0,0,0,0,0,0,0,0}; |
356 | byte buf2[8]; | |
357 | int i; | |
358 | for (i=0;i+8<=data_len;i+=8) | |
359 | mac_block(ctx,buffer,data+i); | |
926c41bd DSH |
360 | if (i<data_len) |
361 | { | |
a04549cc DSH |
362 | memset(buf2,0,8); |
363 | memcpy(buf2,data+i,data_len-i); | |
364 | mac_block(ctx,buffer,buf2); | |
926c41bd | 365 | } |
a04549cc DSH |
366 | get_mac(buffer,mac_len,mac); |
367 | return 1; | |
926c41bd DSH |
368 | } |
369 | ||
a04549cc DSH |
370 | /* Compute MAC with non-zero IV. Used in some RFC 4357 algorithms */ |
371 | int gost_mac_iv(gost_ctx *ctx,int mac_len,const unsigned char *iv,const unsigned char *data, | |
926c41bd DSH |
372 | unsigned int data_len,unsigned char *mac) |
373 | { | |
a04549cc DSH |
374 | byte buffer[8]; |
375 | byte buf2[8]; | |
376 | int i; | |
377 | memcpy (buffer,iv,8); | |
378 | for (i=0;i+8<=data_len;i+=8) | |
379 | mac_block(ctx,buffer,data+i); | |
926c41bd DSH |
380 | if (i<data_len) |
381 | { | |
a04549cc DSH |
382 | memset(buf2,0,8); |
383 | memcpy(buf2,data+i,data_len-i); | |
384 | mac_block(ctx,buffer,buf2); | |
926c41bd | 385 | } |
a04549cc DSH |
386 | get_mac(buffer,mac_len,mac); |
387 | return 1; | |
926c41bd | 388 | } |
a04549cc DSH |
389 | |
390 | /* Implements key meshing algorithm by modifing ctx and IV in place */ | |
926c41bd DSH |
391 | void cryptopro_key_meshing(gost_ctx *ctx, unsigned char *iv) |
392 | { | |
a04549cc DSH |
393 | unsigned char newkey[32],newiv[8]; |
394 | /* Set static keymeshing key */ | |
395 | /* "Decrypt" key with keymeshing key */ | |
396 | gost_dec(ctx,CryptoProKeyMeshingKey,newkey,4); | |
397 | /* set new key */ | |
398 | gost_key(ctx,newkey); | |
399 | /* Encrypt iv with new key */ | |
400 | gostcrypt(ctx,iv,newiv); | |
401 | memcpy(iv,newiv,8); | |
926c41bd | 402 | } |