Botan 2.19.3
Crypto and TLS for C&
twofish.cpp
Go to the documentation of this file.
1/*
2* Twofish
3* (C) 1999-2007,2017 Jack Lloyd
4*
5* The key schedule implemenation is based on a public domain
6* implementation by Matthew Skala
7*
8* Botan is released under the Simplified BSD License (see license.txt)
9*/
10
11#include <botan/twofish.h>
12#include <botan/loadstor.h>
13#include <botan/rotate.h>
14
15namespace Botan {
16
17namespace {
18
19inline void TF_E(uint32_t A, uint32_t B, uint32_t& C, uint32_t& D,
20 uint32_t RK1, uint32_t RK2,
21 const secure_vector<uint32_t>& SB)
22 {
23 uint32_t X = SB[ get_byte(3, A)] ^ SB[256+get_byte(2, A)] ^
24 SB[512+get_byte(1, A)] ^ SB[768+get_byte(0, A)];
25 uint32_t Y = SB[ get_byte(0, B)] ^ SB[256+get_byte(3, B)] ^
26 SB[512+get_byte(2, B)] ^ SB[768+get_byte(1, B)];
27
28 X += Y;
29 Y += X;
30
31 X += RK1;
32 Y += RK2;
33
34 C = rotr<1>(C ^ X);
35 D = rotl<1>(D) ^ Y;
36 }
37
38inline void TF_D(uint32_t A, uint32_t B, uint32_t& C, uint32_t& D,
39 uint32_t RK1, uint32_t RK2,
40 const secure_vector<uint32_t>& SB)
41 {
42 uint32_t X = SB[ get_byte(3, A)] ^ SB[256+get_byte(2, A)] ^
43 SB[512+get_byte(1, A)] ^ SB[768+get_byte(0, A)];
44 uint32_t Y = SB[ get_byte(0, B)] ^ SB[256+get_byte(3, B)] ^
45 SB[512+get_byte(2, B)] ^ SB[768+get_byte(1, B)];
46
47 X += Y;
48 Y += X;
49
50 X += RK1;
51 Y += RK2;
52
53 C = rotl<1>(C) ^ X;
54 D = rotr<1>(D ^ Y);
55 }
56
57}
58
59/*
60* Twofish Encryption
61*/
62void Twofish::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
63 {
64 verify_key_set(m_SB.empty() == false);
65
66 while(blocks >= 2)
67 {
68 uint32_t A0, B0, C0, D0;
69 uint32_t A1, B1, C1, D1;
70 load_le(in, A0, B0, C0, D0, A1, B1, C1, D1);
71
72 A0 ^= m_RK[0];
73 A1 ^= m_RK[0];
74 B0 ^= m_RK[1];
75 B1 ^= m_RK[1];
76 C0 ^= m_RK[2];
77 C1 ^= m_RK[2];
78 D0 ^= m_RK[3];
79 D1 ^= m_RK[3];
80
81 for(size_t k = 8; k != 40; k += 4)
82 {
83 TF_E(A0, B0, C0, D0, m_RK[k+0], m_RK[k+1], m_SB);
84 TF_E(A1, B1, C1, D1, m_RK[k+0], m_RK[k+1], m_SB);
85
86 TF_E(C0, D0, A0, B0, m_RK[k+2], m_RK[k+3], m_SB);
87 TF_E(C1, D1, A1, B1, m_RK[k+2], m_RK[k+3], m_SB);
88 }
89
90 C0 ^= m_RK[4];
91 C1 ^= m_RK[4];
92 D0 ^= m_RK[5];
93 D1 ^= m_RK[5];
94 A0 ^= m_RK[6];
95 A1 ^= m_RK[6];
96 B0 ^= m_RK[7];
97 B1 ^= m_RK[7];
98
99 store_le(out, C0, D0, A0, B0, C1, D1, A1, B1);
100
101 blocks -= 2;
102 out += 2*BLOCK_SIZE;
103 in += 2*BLOCK_SIZE;
104 }
105
106 if(blocks)
107 {
108 uint32_t A, B, C, D;
109 load_le(in, A, B, C, D);
110
111 A ^= m_RK[0];
112 B ^= m_RK[1];
113 C ^= m_RK[2];
114 D ^= m_RK[3];
115
116 for(size_t k = 8; k != 40; k += 4)
117 {
118 TF_E(A, B, C, D, m_RK[k ], m_RK[k+1], m_SB);
119 TF_E(C, D, A, B, m_RK[k+2], m_RK[k+3], m_SB);
120 }
121
122 C ^= m_RK[4];
123 D ^= m_RK[5];
124 A ^= m_RK[6];
125 B ^= m_RK[7];
126
127 store_le(out, C, D, A, B);
128 }
129 }
130
131/*
132* Twofish Decryption
133*/
134void Twofish::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
135 {
136 verify_key_set(m_SB.empty() == false);
137
138 while(blocks >= 2)
139 {
140 uint32_t A0, B0, C0, D0;
141 uint32_t A1, B1, C1, D1;
142 load_le(in, A0, B0, C0, D0, A1, B1, C1, D1);
143
144 A0 ^= m_RK[4];
145 A1 ^= m_RK[4];
146 B0 ^= m_RK[5];
147 B1 ^= m_RK[5];
148 C0 ^= m_RK[6];
149 C1 ^= m_RK[6];
150 D0 ^= m_RK[7];
151 D1 ^= m_RK[7];
152
153 for(size_t k = 40; k != 8; k -= 4)
154 {
155 TF_D(A0, B0, C0, D0, m_RK[k-2], m_RK[k-1], m_SB);
156 TF_D(A1, B1, C1, D1, m_RK[k-2], m_RK[k-1], m_SB);
157
158 TF_D(C0, D0, A0, B0, m_RK[k-4], m_RK[k-3], m_SB);
159 TF_D(C1, D1, A1, B1, m_RK[k-4], m_RK[k-3], m_SB);
160 }
161
162 C0 ^= m_RK[0];
163 C1 ^= m_RK[0];
164 D0 ^= m_RK[1];
165 D1 ^= m_RK[1];
166 A0 ^= m_RK[2];
167 A1 ^= m_RK[2];
168 B0 ^= m_RK[3];
169 B1 ^= m_RK[3];
170
171 store_le(out, C0, D0, A0, B0, C1, D1, A1, B1);
172
173 blocks -= 2;
174 out += 2*BLOCK_SIZE;
175 in += 2*BLOCK_SIZE;
176 }
177
178 if(blocks)
179 {
180 uint32_t A, B, C, D;
181 load_le(in, A, B, C, D);
182
183 A ^= m_RK[4];
184 B ^= m_RK[5];
185 C ^= m_RK[6];
186 D ^= m_RK[7];
187
188 for(size_t k = 40; k != 8; k -= 4)
189 {
190 TF_D(A, B, C, D, m_RK[k-2], m_RK[k-1], m_SB);
191 TF_D(C, D, A, B, m_RK[k-4], m_RK[k-3], m_SB);
192 }
193
194 C ^= m_RK[0];
195 D ^= m_RK[1];
196 A ^= m_RK[2];
197 B ^= m_RK[3];
198
199 store_le(out, C, D, A, B);
200 }
201 }
202
203/*
204* Twofish Key Schedule
205*/
206void Twofish::key_schedule(const uint8_t key[], size_t length)
207 {
208 m_SB.resize(1024);
209 m_RK.resize(40);
210
212
213 for(size_t i = 0; i != length; ++i)
214 {
215 /*
216 * Do one column of the RS matrix multiplcation
217 */
218 if(key[i])
219 {
220 uint8_t X = POLY_TO_EXP[key[i] - 1];
221
222 uint8_t RS1 = RS[(4*i ) % 32];
223 uint8_t RS2 = RS[(4*i+1) % 32];
224 uint8_t RS3 = RS[(4*i+2) % 32];
225 uint8_t RS4 = RS[(4*i+3) % 32];
226
227 S[4*(i/8) ] ^= EXP_TO_POLY[(X + POLY_TO_EXP[RS1 - 1]) % 255];
228 S[4*(i/8)+1] ^= EXP_TO_POLY[(X + POLY_TO_EXP[RS2 - 1]) % 255];
229 S[4*(i/8)+2] ^= EXP_TO_POLY[(X + POLY_TO_EXP[RS3 - 1]) % 255];
230 S[4*(i/8)+3] ^= EXP_TO_POLY[(X + POLY_TO_EXP[RS4 - 1]) % 255];
231 }
232 }
233
234 if(length == 16)
235 {
236 for(size_t i = 0; i != 256; ++i)
237 {
238 m_SB[ i] = MDS0[Q0[Q0[i]^S[ 0]]^S[ 4]];
239 m_SB[256+i] = MDS1[Q0[Q1[i]^S[ 1]]^S[ 5]];
240 m_SB[512+i] = MDS2[Q1[Q0[i]^S[ 2]]^S[ 6]];
241 m_SB[768+i] = MDS3[Q1[Q1[i]^S[ 3]]^S[ 7]];
242 }
243
244 for(size_t i = 0; i < 40; i += 2)
245 {
246 uint32_t X = MDS0[Q0[Q0[i ]^key[ 8]]^key[ 0]] ^
247 MDS1[Q0[Q1[i ]^key[ 9]]^key[ 1]] ^
248 MDS2[Q1[Q0[i ]^key[10]]^key[ 2]] ^
249 MDS3[Q1[Q1[i ]^key[11]]^key[ 3]];
250 uint32_t Y = MDS0[Q0[Q0[i+1]^key[12]]^key[ 4]] ^
251 MDS1[Q0[Q1[i+1]^key[13]]^key[ 5]] ^
252 MDS2[Q1[Q0[i+1]^key[14]]^key[ 6]] ^
253 MDS3[Q1[Q1[i+1]^key[15]]^key[ 7]];
254 Y = rotl<8>(Y);
255 X += Y; Y += X;
256
257 m_RK[i] = X;
258 m_RK[i+1] = rotl<9>(Y);
259 }
260 }
261 else if(length == 24)
262 {
263 for(size_t i = 0; i != 256; ++i)
264 {
265 m_SB[ i] = MDS0[Q0[Q0[Q1[i]^S[ 0]]^S[ 4]]^S[ 8]];
266 m_SB[256+i] = MDS1[Q0[Q1[Q1[i]^S[ 1]]^S[ 5]]^S[ 9]];
267 m_SB[512+i] = MDS2[Q1[Q0[Q0[i]^S[ 2]]^S[ 6]]^S[10]];
268 m_SB[768+i] = MDS3[Q1[Q1[Q0[i]^S[ 3]]^S[ 7]]^S[11]];
269 }
270
271 for(size_t i = 0; i < 40; i += 2)
272 {
273 uint32_t X = MDS0[Q0[Q0[Q1[i ]^key[16]]^key[ 8]]^key[ 0]] ^
274 MDS1[Q0[Q1[Q1[i ]^key[17]]^key[ 9]]^key[ 1]] ^
275 MDS2[Q1[Q0[Q0[i ]^key[18]]^key[10]]^key[ 2]] ^
276 MDS3[Q1[Q1[Q0[i ]^key[19]]^key[11]]^key[ 3]];
277 uint32_t Y = MDS0[Q0[Q0[Q1[i+1]^key[20]]^key[12]]^key[ 4]] ^
278 MDS1[Q0[Q1[Q1[i+1]^key[21]]^key[13]]^key[ 5]] ^
279 MDS2[Q1[Q0[Q0[i+1]^key[22]]^key[14]]^key[ 6]] ^
280 MDS3[Q1[Q1[Q0[i+1]^key[23]]^key[15]]^key[ 7]];
281 Y = rotl<8>(Y);
282 X += Y; Y += X;
283
284 m_RK[i] = X;
285 m_RK[i+1] = rotl<9>(Y);
286 }
287 }
288 else if(length == 32)
289 {
290 for(size_t i = 0; i != 256; ++i)
291 {
292 m_SB[ i] = MDS0[Q0[Q0[Q1[Q1[i]^S[ 0]]^S[ 4]]^S[ 8]]^S[12]];
293 m_SB[256+i] = MDS1[Q0[Q1[Q1[Q0[i]^S[ 1]]^S[ 5]]^S[ 9]]^S[13]];
294 m_SB[512+i] = MDS2[Q1[Q0[Q0[Q0[i]^S[ 2]]^S[ 6]]^S[10]]^S[14]];
295 m_SB[768+i] = MDS3[Q1[Q1[Q0[Q1[i]^S[ 3]]^S[ 7]]^S[11]]^S[15]];
296 }
297
298 for(size_t i = 0; i < 40; i += 2)
299 {
300 uint32_t X = MDS0[Q0[Q0[Q1[Q1[i ]^key[24]]^key[16]]^key[ 8]]^key[ 0]] ^
301 MDS1[Q0[Q1[Q1[Q0[i ]^key[25]]^key[17]]^key[ 9]]^key[ 1]] ^
302 MDS2[Q1[Q0[Q0[Q0[i ]^key[26]]^key[18]]^key[10]]^key[ 2]] ^
303 MDS3[Q1[Q1[Q0[Q1[i ]^key[27]]^key[19]]^key[11]]^key[ 3]];
304 uint32_t Y = MDS0[Q0[Q0[Q1[Q1[i+1]^key[28]]^key[20]]^key[12]]^key[ 4]] ^
305 MDS1[Q0[Q1[Q1[Q0[i+1]^key[29]]^key[21]]^key[13]]^key[ 5]] ^
306 MDS2[Q1[Q0[Q0[Q0[i+1]^key[30]]^key[22]]^key[14]]^key[ 6]] ^
307 MDS3[Q1[Q1[Q0[Q1[i+1]^key[31]]^key[23]]^key[15]]^key[ 7]];
308 Y = rotl<8>(Y);
309 X += Y; Y += X;
310
311 m_RK[i] = X;
312 m_RK[i+1] = rotl<9>(Y);
313 }
314 }
315 }
316
317/*
318* Clear memory of sensitive data
319*/
321 {
322 zap(m_SB);
323 zap(m_RK);
324 }
325
326}
void verify_key_set(bool cond) const
Definition sym_algo.h:171
void clear() override
Definition twofish.cpp:320
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
Definition twofish.cpp:62
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
Definition twofish.cpp:134
fe Y
Definition ge.cpp:28
fe X
Definition ge.cpp:27
void zap(std::vector< T, Alloc > &vec)
Definition secmem.h:124
T load_le(const uint8_t in[], size_t off)
Definition loadstor.h:123
void store_le(uint16_t in, uint8_t out[2])
Definition loadstor.h:454
constexpr uint8_t get_byte(size_t byte_num, T input)
Definition loadstor.h:41
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:65