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