Botan  2.7.0
Crypto and TLS for C++11
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 
15 namespace Botan {
16 
17 namespace {
18 
19 inline 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 
38 inline 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 */
62 void 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 */
134 void 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 */
206 void 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 }
fe X
Definition: ge.cpp:27
void verify_key_set(bool cond) const
Definition: sym_algo.h:89
void zap(std::vector< T, Alloc > &vec)
Definition: secmem.h:193
fe Y
Definition: ge.cpp:28
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
Definition: twofish.cpp:62
T load_le(const uint8_t in[], size_t off)
Definition: loadstor.h:121
Definition: alg_id.cpp:13
uint8_t get_byte(size_t byte_num, T input)
Definition: loadstor.h:39
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:88
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
Definition: twofish.cpp:134
void store_le(uint16_t in, uint8_t out[2])
Definition: loadstor.h:450
void clear() override
Definition: twofish.cpp:320