Botan  1.10.17
gost_3411.cpp
Go to the documentation of this file.
1 /*
2 * GOST 34.11
3 * (C) 2009 Jack Lloyd
4 *
5 * Distributed under the terms of the Botan license
6 */
7 
8 #include <botan/gost_3411.h>
9 #include <botan/loadstor.h>
10 #include <botan/rotate.h>
11 #include <botan/internal/xor_buf.h>
12 
13 namespace Botan {
14 
15 /**
16 * GOST 34.11 Constructor
17 */
19  cipher(GOST_28147_89_Params("R3411_CryptoPro")),
20  buffer(32),
21  sum(32),
22  hash(32)
23  {
24  count = 0;
25  position = 0;
26  }
27 
29  {
30  cipher.clear();
31  zeroise(sum);
32  zeroise(hash);
33  count = 0;
34  position = 0;
35  }
36 
37 /**
38 * Hash additional inputs
39 */
40 void GOST_34_11::add_data(const byte input[], size_t length)
41  {
42  count += length;
43 
44  if(position)
45  {
46  buffer.copy(position, input, length);
47 
48  if(position + length >= hash_block_size())
49  {
50  compress_n(&buffer[0], 1);
51  input += (hash_block_size() - position);
52  length -= (hash_block_size() - position);
53  position = 0;
54  }
55  }
56 
57  const size_t full_blocks = length / hash_block_size();
58  const size_t remaining = length % hash_block_size();
59 
60  if(full_blocks)
61  compress_n(input, full_blocks);
62 
63  buffer.copy(position, input + full_blocks * hash_block_size(), remaining);
64  position += remaining;
65  }
66 
67 /**
68 * The GOST 34.11 compression function
69 */
70 void GOST_34_11::compress_n(const byte input[], size_t blocks)
71  {
72  for(size_t i = 0; i != blocks; ++i)
73  {
74  for(u16bit j = 0, carry = 0; j != 32; ++j)
75  {
76  u16bit s = sum[j] + input[32*i+j] + carry;
77  carry = get_byte(0, s);
78  sum[j] = get_byte(1, s);
79  }
80 
81  byte S[32] = { 0 };
82 
83  u64bit U[4], V[4];
84  load_be(U, &hash[0], 4);
85  load_be(V, input + 32*i, 4);
86 
87  for(size_t j = 0; j != 4; ++j)
88  {
89  byte key[32] = { 0 };
90 
91  // P transformation
92  for(size_t k = 0; k != 4; ++k)
93  {
94  const uint64_t UVk = U[k] ^ V[k];
95  for(size_t l = 0; l != 8; ++l)
96  key[4*l+k] = get_byte(l, UVk);
97  }
98 
99  cipher.set_key(key, 32);
100  cipher.encrypt(&hash[8*j], S + 8*j);
101 
102  if(j == 3)
103  break;
104 
105  // A(x)
106  u64bit A_U = U[0];
107  U[0] = U[1];
108  U[1] = U[2];
109  U[2] = U[3];
110  U[3] = U[0] ^ A_U;
111 
112  if(j == 1) // C_3
113  {
114  U[0] ^= 0x00FF00FF00FF00FF;
115  U[1] ^= 0xFF00FF00FF00FF00;
116  U[2] ^= 0x00FFFF00FF0000FF;
117  U[3] ^= 0xFF000000FFFF00FF;
118  }
119 
120  // A(A(x))
121  u64bit AA_V_1 = V[0] ^ V[1];
122  u64bit AA_V_2 = V[1] ^ V[2];
123  V[0] = V[2];
124  V[1] = V[3];
125  V[2] = AA_V_1;
126  V[3] = AA_V_2;
127  }
128 
129  byte S2[32] = { 0 };
130 
131  // 12 rounds of psi
132  S2[ 0] = S[24];
133  S2[ 1] = S[25];
134  S2[ 2] = S[26];
135  S2[ 3] = S[27];
136  S2[ 4] = S[28];
137  S2[ 5] = S[29];
138  S2[ 6] = S[30];
139  S2[ 7] = S[31];
140  S2[ 8] = S[ 0] ^ S[ 2] ^ S[ 4] ^ S[ 6] ^ S[24] ^ S[30];
141  S2[ 9] = S[ 1] ^ S[ 3] ^ S[ 5] ^ S[ 7] ^ S[25] ^ S[31];
142  S2[10] = S[ 0] ^ S[ 8] ^ S[24] ^ S[26] ^ S[30];
143  S2[11] = S[ 1] ^ S[ 9] ^ S[25] ^ S[27] ^ S[31];
144  S2[12] = S[ 0] ^ S[ 4] ^ S[ 6] ^ S[10] ^ S[24] ^ S[26] ^ S[28] ^ S[30];
145  S2[13] = S[ 1] ^ S[ 5] ^ S[ 7] ^ S[11] ^ S[25] ^ S[27] ^ S[29] ^ S[31];
146  S2[14] = S[ 0] ^ S[ 4] ^ S[ 8] ^ S[12] ^ S[24] ^ S[26] ^ S[28];
147  S2[15] = S[ 1] ^ S[ 5] ^ S[ 9] ^ S[13] ^ S[25] ^ S[27] ^ S[29];
148  S2[16] = S[ 2] ^ S[ 6] ^ S[10] ^ S[14] ^ S[26] ^ S[28] ^ S[30];
149  S2[17] = S[ 3] ^ S[ 7] ^ S[11] ^ S[15] ^ S[27] ^ S[29] ^ S[31];
150  S2[18] = S[ 0] ^ S[ 2] ^ S[ 6] ^ S[ 8] ^ S[12] ^ S[16] ^ S[24] ^ S[28];
151  S2[19] = S[ 1] ^ S[ 3] ^ S[ 7] ^ S[ 9] ^ S[13] ^ S[17] ^ S[25] ^ S[29];
152  S2[20] = S[ 2] ^ S[ 4] ^ S[ 8] ^ S[10] ^ S[14] ^ S[18] ^ S[26] ^ S[30];
153  S2[21] = S[ 3] ^ S[ 5] ^ S[ 9] ^ S[11] ^ S[15] ^ S[19] ^ S[27] ^ S[31];
154  S2[22] = S[ 0] ^ S[ 2] ^ S[10] ^ S[12] ^ S[16] ^ S[20] ^ S[24] ^ S[28] ^ S[30];
155  S2[23] = S[ 1] ^ S[ 3] ^ S[11] ^ S[13] ^ S[17] ^ S[21] ^ S[25] ^ S[29] ^ S[31];
156  S2[24] = S[ 0] ^ S[ 6] ^ S[12] ^ S[14] ^ S[18] ^ S[22] ^ S[24] ^ S[26];
157  S2[25] = S[ 1] ^ S[ 7] ^ S[13] ^ S[15] ^ S[19] ^ S[23] ^ S[25] ^ S[27];
158  S2[26] = S[ 2] ^ S[ 8] ^ S[14] ^ S[16] ^ S[20] ^ S[24] ^ S[26] ^ S[28];
159  S2[27] = S[ 3] ^ S[ 9] ^ S[15] ^ S[17] ^ S[21] ^ S[25] ^ S[27] ^ S[29];
160  S2[28] = S[ 4] ^ S[10] ^ S[16] ^ S[18] ^ S[22] ^ S[26] ^ S[28] ^ S[30];
161  S2[29] = S[ 5] ^ S[11] ^ S[17] ^ S[19] ^ S[23] ^ S[27] ^ S[29] ^ S[31];
162  S2[30] = S[ 0] ^ S[ 2] ^ S[ 4] ^ S[12] ^ S[18] ^ S[20] ^ S[28];
163  S2[31] = S[ 1] ^ S[ 3] ^ S[ 5] ^ S[13] ^ S[19] ^ S[21] ^ S[29];
164 
165  xor_buf(S, S2, input + 32*i, 32);
166 
167  S2[0] = S[0] ^ S[2] ^ S[4] ^ S[6] ^ S[24] ^ S[30];
168  S2[1] = S[1] ^ S[3] ^ S[5] ^ S[7] ^ S[25] ^ S[31];
169 
170  copy_mem(S, S+2, 30);
171  S[30] = S2[0];
172  S[31] = S2[1];
173 
174  xor_buf(S, &hash[0], 32);
175 
176  // 61 rounds of psi
177  S2[ 0] = S[ 2] ^ S[ 6] ^ S[14] ^ S[20] ^ S[22] ^ S[26] ^ S[28] ^ S[30];
178  S2[ 1] = S[ 3] ^ S[ 7] ^ S[15] ^ S[21] ^ S[23] ^ S[27] ^ S[29] ^ S[31];
179  S2[ 2] = S[ 0] ^ S[ 2] ^ S[ 6] ^ S[ 8] ^ S[16] ^ S[22] ^ S[28];
180  S2[ 3] = S[ 1] ^ S[ 3] ^ S[ 7] ^ S[ 9] ^ S[17] ^ S[23] ^ S[29];
181  S2[ 4] = S[ 2] ^ S[ 4] ^ S[ 8] ^ S[10] ^ S[18] ^ S[24] ^ S[30];
182  S2[ 5] = S[ 3] ^ S[ 5] ^ S[ 9] ^ S[11] ^ S[19] ^ S[25] ^ S[31];
183  S2[ 6] = S[ 0] ^ S[ 2] ^ S[10] ^ S[12] ^ S[20] ^ S[24] ^ S[26] ^ S[30];
184  S2[ 7] = S[ 1] ^ S[ 3] ^ S[11] ^ S[13] ^ S[21] ^ S[25] ^ S[27] ^ S[31];
185  S2[ 8] = S[ 0] ^ S[ 6] ^ S[12] ^ S[14] ^ S[22] ^ S[24] ^ S[26] ^ S[28] ^ S[30];
186  S2[ 9] = S[ 1] ^ S[ 7] ^ S[13] ^ S[15] ^ S[23] ^ S[25] ^ S[27] ^ S[29] ^ S[31];
187  S2[10] = S[ 0] ^ S[ 4] ^ S[ 6] ^ S[ 8] ^ S[14] ^ S[16] ^ S[26] ^ S[28];
188  S2[11] = S[ 1] ^ S[ 5] ^ S[ 7] ^ S[ 9] ^ S[15] ^ S[17] ^ S[27] ^ S[29];
189  S2[12] = S[ 2] ^ S[ 6] ^ S[ 8] ^ S[10] ^ S[16] ^ S[18] ^ S[28] ^ S[30];
190  S2[13] = S[ 3] ^ S[ 7] ^ S[ 9] ^ S[11] ^ S[17] ^ S[19] ^ S[29] ^ S[31];
191  S2[14] = S[ 0] ^ S[ 2] ^ S[ 6] ^ S[ 8] ^ S[10] ^ S[12] ^ S[18] ^ S[20] ^ S[24];
192  S2[15] = S[ 1] ^ S[ 3] ^ S[ 7] ^ S[ 9] ^ S[11] ^ S[13] ^ S[19] ^ S[21] ^ S[25];
193  S2[16] = S[ 2] ^ S[ 4] ^ S[ 8] ^ S[10] ^ S[12] ^ S[14] ^ S[20] ^ S[22] ^ S[26];
194  S2[17] = S[ 3] ^ S[ 5] ^ S[ 9] ^ S[11] ^ S[13] ^ S[15] ^ S[21] ^ S[23] ^ S[27];
195  S2[18] = S[ 4] ^ S[ 6] ^ S[10] ^ S[12] ^ S[14] ^ S[16] ^ S[22] ^ S[24] ^ S[28];
196  S2[19] = S[ 5] ^ S[ 7] ^ S[11] ^ S[13] ^ S[15] ^ S[17] ^ S[23] ^ S[25] ^ S[29];
197  S2[20] = S[ 6] ^ S[ 8] ^ S[12] ^ S[14] ^ S[16] ^ S[18] ^ S[24] ^ S[26] ^ S[30];
198  S2[21] = S[ 7] ^ S[ 9] ^ S[13] ^ S[15] ^ S[17] ^ S[19] ^ S[25] ^ S[27] ^ S[31];
199  S2[22] = S[ 0] ^ S[ 2] ^ S[ 4] ^ S[ 6] ^ S[ 8] ^ S[10] ^ S[14] ^ S[16] ^
200  S[18] ^ S[20] ^ S[24] ^ S[26] ^ S[28] ^ S[30];
201  S2[23] = S[ 1] ^ S[ 3] ^ S[ 5] ^ S[ 7] ^ S[ 9] ^ S[11] ^ S[15] ^ S[17] ^
202  S[19] ^ S[21] ^ S[25] ^ S[27] ^ S[29] ^ S[31];
203  S2[24] = S[ 0] ^ S[ 8] ^ S[10] ^ S[12] ^ S[16] ^ S[18] ^ S[20] ^ S[22] ^
204  S[24] ^ S[26] ^ S[28];
205  S2[25] = S[ 1] ^ S[ 9] ^ S[11] ^ S[13] ^ S[17] ^ S[19] ^ S[21] ^ S[23] ^
206  S[25] ^ S[27] ^ S[29];
207  S2[26] = S[ 2] ^ S[10] ^ S[12] ^ S[14] ^ S[18] ^ S[20] ^ S[22] ^ S[24] ^
208  S[26] ^ S[28] ^ S[30];
209  S2[27] = S[ 3] ^ S[11] ^ S[13] ^ S[15] ^ S[19] ^ S[21] ^ S[23] ^ S[25] ^
210  S[27] ^ S[29] ^ S[31];
211  S2[28] = S[ 0] ^ S[ 2] ^ S[ 6] ^ S[12] ^ S[14] ^ S[16] ^ S[20] ^ S[22] ^ S[26] ^ S[28];
212  S2[29] = S[ 1] ^ S[ 3] ^ S[ 7] ^ S[13] ^ S[15] ^ S[17] ^ S[21] ^ S[23] ^ S[27] ^ S[29];
213  S2[30] = S[ 2] ^ S[ 4] ^ S[ 8] ^ S[14] ^ S[16] ^ S[18] ^ S[22] ^ S[24] ^ S[28] ^ S[30];
214  S2[31] = S[ 3] ^ S[ 5] ^ S[ 9] ^ S[15] ^ S[17] ^ S[19] ^ S[23] ^ S[25] ^ S[29] ^ S[31];
215 
216  hash.copy(S2, 32);
217  }
218  }
219 
220 /**
221 * Produce the final GOST 34.11 output
222 */
223 void GOST_34_11::final_result(byte out[])
224  {
225  if(position)
226  {
227  clear_mem(&buffer[0] + position, buffer.size() - position);
228  compress_n(&buffer[0], 1);
229  }
230 
231  SecureVector<byte> length_buf(32);
232  const u64bit bit_count = count * 8;
233  store_le(bit_count, &length_buf[0]);
234 
235  SecureVector<byte> sum_buf = sum;
236 
237  compress_n(&length_buf[0], 1);
238  compress_n(&sum_buf[0], 1);
239 
240  copy_mem(out, &hash[0], 32);
241 
242  clear();
243  }
244 
245 }
T load_be(const byte in[], size_t off)
Definition: loadstor.h:100
void clear_mem(T *ptr, size_t n)
Definition: mem_ops.h:32
void store_le(u16bit in, byte out[2])
Definition: loadstor.h:427
byte get_byte(size_t byte_num, T input)
Definition: get_byte.h:21
void copy(const T in[], size_t n)
Definition: secmem.h:126
unsigned char byte
Definition: types.h:22
unsigned long long u64bit
Definition: types.h:49
void encrypt(const byte in[], byte out[]) const
Definition: block_cipher.h:47
void set_key(const SymmetricKey &key)
Definition: sym_algo.h:60
unsigned short u16bit
Definition: types.h:27
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:22
size_t size() const
Definition: secmem.h:29
void xor_buf(byte out[], const byte in[], size_t length)
Definition: xor_buf.h:21
void zeroise(MemoryRegion< T > &vec)
Definition: secmem.h:428
size_t hash_block_size() const
Definition: gost_3411.h:24