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