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