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