Coverage Report

Created: 2020-08-01 06:18

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