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