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