Coverage Report

Created: 2023-06-07 07:00

/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