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