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