Coverage Report

Created: 2020-11-21 08:34

/src/botan/src/lib/block/cast128/cast128.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
* CAST-128
3
* (C) 1999-2007 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7
8
#include <botan/internal/cast128.h>
9
#include <botan/internal/cast_sboxes.h>
10
#include <botan/internal/loadstor.h>
11
#include <botan/internal/rotate.h>
12
13
namespace Botan {
14
15
namespace {
16
17
/*
18
* CAST-128 Round Type 1
19
*/
20
inline uint32_t F1(uint32_t R, uint32_t MK, uint8_t RK)
21
0
   {
22
0
   const uint32_t T = rotl_var(MK + R, RK);
23
0
   return (CAST_SBOX1[get_byte(0, T)] ^ CAST_SBOX2[get_byte(1, T)]) -
24
0
           CAST_SBOX3[get_byte(2, T)] + CAST_SBOX4[get_byte(3, T)];
25
0
   }
26
27
/*
28
* CAST-128 Round Type 2
29
*/
30
inline uint32_t F2(uint32_t R, uint32_t MK, uint8_t RK)
31
0
   {
32
0
   const uint32_t T = rotl_var(MK ^ R, RK);
33
0
   return (CAST_SBOX1[get_byte(0, T)]  - CAST_SBOX2[get_byte(1, T)] +
34
0
           CAST_SBOX3[get_byte(2, T)]) ^ CAST_SBOX4[get_byte(3, T)];
35
0
   }
36
37
/*
38
* CAST-128 Round Type 3
39
*/
40
inline uint32_t F3(uint32_t R, uint32_t MK, uint8_t RK)
41
0
   {
42
0
   const uint32_t T = rotl_var(MK - R, RK);
43
0
   return ((CAST_SBOX1[get_byte(0, T)]  + CAST_SBOX2[get_byte(1, T)]) ^
44
0
            CAST_SBOX3[get_byte(2, T)]) - CAST_SBOX4[get_byte(3, T)];
45
0
   }
46
47
}
48
49
/*
50
* CAST-128 Encryption
51
*/
52
void CAST_128::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
53
0
   {
54
0
   verify_key_set(m_RK.empty() == false);
55
56
0
   while(blocks >= 2)
57
0
      {
58
0
      uint32_t L0, R0, L1, R1;
59
0
      load_be(in, L0, R0, L1, R1);
60
61
0
      L0 ^= F1(R0, m_MK[ 0], m_RK[ 0]);
62
0
      L1 ^= F1(R1, m_MK[ 0], m_RK[ 0]);
63
0
      R0 ^= F2(L0, m_MK[ 1], m_RK[ 1]);
64
0
      R1 ^= F2(L1, m_MK[ 1], m_RK[ 1]);
65
0
      L0 ^= F3(R0, m_MK[ 2], m_RK[ 2]);
66
0
      L1 ^= F3(R1, m_MK[ 2], m_RK[ 2]);
67
0
      R0 ^= F1(L0, m_MK[ 3], m_RK[ 3]);
68
0
      R1 ^= F1(L1, m_MK[ 3], m_RK[ 3]);
69
0
      L0 ^= F2(R0, m_MK[ 4], m_RK[ 4]);
70
0
      L1 ^= F2(R1, m_MK[ 4], m_RK[ 4]);
71
0
      R0 ^= F3(L0, m_MK[ 5], m_RK[ 5]);
72
0
      R1 ^= F3(L1, m_MK[ 5], m_RK[ 5]);
73
0
      L0 ^= F1(R0, m_MK[ 6], m_RK[ 6]);
74
0
      L1 ^= F1(R1, m_MK[ 6], m_RK[ 6]);
75
0
      R0 ^= F2(L0, m_MK[ 7], m_RK[ 7]);
76
0
      R1 ^= F2(L1, m_MK[ 7], m_RK[ 7]);
77
0
      L0 ^= F3(R0, m_MK[ 8], m_RK[ 8]);
78
0
      L1 ^= F3(R1, m_MK[ 8], m_RK[ 8]);
79
0
      R0 ^= F1(L0, m_MK[ 9], m_RK[ 9]);
80
0
      R1 ^= F1(L1, m_MK[ 9], m_RK[ 9]);
81
0
      L0 ^= F2(R0, m_MK[10], m_RK[10]);
82
0
      L1 ^= F2(R1, m_MK[10], m_RK[10]);
83
0
      R0 ^= F3(L0, m_MK[11], m_RK[11]);
84
0
      R1 ^= F3(L1, m_MK[11], m_RK[11]);
85
0
      L0 ^= F1(R0, m_MK[12], m_RK[12]);
86
0
      L1 ^= F1(R1, m_MK[12], m_RK[12]);
87
0
      R0 ^= F2(L0, m_MK[13], m_RK[13]);
88
0
      R1 ^= F2(L1, m_MK[13], m_RK[13]);
89
0
      L0 ^= F3(R0, m_MK[14], m_RK[14]);
90
0
      L1 ^= F3(R1, m_MK[14], m_RK[14]);
91
0
      R0 ^= F1(L0, m_MK[15], m_RK[15]);
92
0
      R1 ^= F1(L1, m_MK[15], m_RK[15]);
93
94
0
      store_be(out, R0, L0, R1, L1);
95
96
0
      blocks -= 2;
97
0
      out += 2 * BLOCK_SIZE;
98
0
      in  += 2 * BLOCK_SIZE;
99
0
      }
100
101
0
   if(blocks)
102
0
      {
103
0
      uint32_t L, R;
104
0
      load_be(in, L, R);
105
106
0
      L ^= F1(R, m_MK[ 0], m_RK[ 0]);
107
0
      R ^= F2(L, m_MK[ 1], m_RK[ 1]);
108
0
      L ^= F3(R, m_MK[ 2], m_RK[ 2]);
109
0
      R ^= F1(L, m_MK[ 3], m_RK[ 3]);
110
0
      L ^= F2(R, m_MK[ 4], m_RK[ 4]);
111
0
      R ^= F3(L, m_MK[ 5], m_RK[ 5]);
112
0
      L ^= F1(R, m_MK[ 6], m_RK[ 6]);
113
0
      R ^= F2(L, m_MK[ 7], m_RK[ 7]);
114
0
      L ^= F3(R, m_MK[ 8], m_RK[ 8]);
115
0
      R ^= F1(L, m_MK[ 9], m_RK[ 9]);
116
0
      L ^= F2(R, m_MK[10], m_RK[10]);
117
0
      R ^= F3(L, m_MK[11], m_RK[11]);
118
0
      L ^= F1(R, m_MK[12], m_RK[12]);
119
0
      R ^= F2(L, m_MK[13], m_RK[13]);
120
0
      L ^= F3(R, m_MK[14], m_RK[14]);
121
0
      R ^= F1(L, m_MK[15], m_RK[15]);
122
123
0
      store_be(out, R, L);
124
0
      }
125
0
   }
126
127
/*
128
* CAST-128 Decryption
129
*/
130
void CAST_128::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
131
0
   {
132
0
   verify_key_set(m_RK.empty() == false);
133
134
0
   while(blocks >= 2)
135
0
      {
136
0
      uint32_t L0, R0, L1, R1;
137
0
      load_be(in, L0, R0, L1, R1);
138
139
0
      L0 ^= F1(R0, m_MK[15], m_RK[15]);
140
0
      L1 ^= F1(R1, m_MK[15], m_RK[15]);
141
0
      R0 ^= F3(L0, m_MK[14], m_RK[14]);
142
0
      R1 ^= F3(L1, m_MK[14], m_RK[14]);
143
0
      L0 ^= F2(R0, m_MK[13], m_RK[13]);
144
0
      L1 ^= F2(R1, m_MK[13], m_RK[13]);
145
0
      R0 ^= F1(L0, m_MK[12], m_RK[12]);
146
0
      R1 ^= F1(L1, m_MK[12], m_RK[12]);
147
0
      L0 ^= F3(R0, m_MK[11], m_RK[11]);
148
0
      L1 ^= F3(R1, m_MK[11], m_RK[11]);
149
0
      R0 ^= F2(L0, m_MK[10], m_RK[10]);
150
0
      R1 ^= F2(L1, m_MK[10], m_RK[10]);
151
0
      L0 ^= F1(R0, m_MK[ 9], m_RK[ 9]);
152
0
      L1 ^= F1(R1, m_MK[ 9], m_RK[ 9]);
153
0
      R0 ^= F3(L0, m_MK[ 8], m_RK[ 8]);
154
0
      R1 ^= F3(L1, m_MK[ 8], m_RK[ 8]);
155
0
      L0 ^= F2(R0, m_MK[ 7], m_RK[ 7]);
156
0
      L1 ^= F2(R1, m_MK[ 7], m_RK[ 7]);
157
0
      R0 ^= F1(L0, m_MK[ 6], m_RK[ 6]);
158
0
      R1 ^= F1(L1, m_MK[ 6], m_RK[ 6]);
159
0
      L0 ^= F3(R0, m_MK[ 5], m_RK[ 5]);
160
0
      L1 ^= F3(R1, m_MK[ 5], m_RK[ 5]);
161
0
      R0 ^= F2(L0, m_MK[ 4], m_RK[ 4]);
162
0
      R1 ^= F2(L1, m_MK[ 4], m_RK[ 4]);
163
0
      L0 ^= F1(R0, m_MK[ 3], m_RK[ 3]);
164
0
      L1 ^= F1(R1, m_MK[ 3], m_RK[ 3]);
165
0
      R0 ^= F3(L0, m_MK[ 2], m_RK[ 2]);
166
0
      R1 ^= F3(L1, m_MK[ 2], m_RK[ 2]);
167
0
      L0 ^= F2(R0, m_MK[ 1], m_RK[ 1]);
168
0
      L1 ^= F2(R1, m_MK[ 1], m_RK[ 1]);
169
0
      R0 ^= F1(L0, m_MK[ 0], m_RK[ 0]);
170
0
      R1 ^= F1(L1, m_MK[ 0], m_RK[ 0]);
171
172
0
      store_be(out, R0, L0, R1, L1);
173
174
0
      blocks -= 2;
175
0
      out += 2 * BLOCK_SIZE;
176
0
      in  += 2 * BLOCK_SIZE;
177
0
      }
178
179
0
   if(blocks)
180
0
      {
181
0
      uint32_t L, R;
182
0
      load_be(in, L, R);
183
184
0
      L ^= F1(R, m_MK[15], m_RK[15]);
185
0
      R ^= F3(L, m_MK[14], m_RK[14]);
186
0
      L ^= F2(R, m_MK[13], m_RK[13]);
187
0
      R ^= F1(L, m_MK[12], m_RK[12]);
188
0
      L ^= F3(R, m_MK[11], m_RK[11]);
189
0
      R ^= F2(L, m_MK[10], m_RK[10]);
190
0
      L ^= F1(R, m_MK[ 9], m_RK[ 9]);
191
0
      R ^= F3(L, m_MK[ 8], m_RK[ 8]);
192
0
      L ^= F2(R, m_MK[ 7], m_RK[ 7]);
193
0
      R ^= F1(L, m_MK[ 6], m_RK[ 6]);
194
0
      L ^= F3(R, m_MK[ 5], m_RK[ 5]);
195
0
      R ^= F2(L, m_MK[ 4], m_RK[ 4]);
196
0
      L ^= F1(R, m_MK[ 3], m_RK[ 3]);
197
0
      R ^= F3(L, m_MK[ 2], m_RK[ 2]);
198
0
      L ^= F2(R, m_MK[ 1], m_RK[ 1]);
199
0
      R ^= F1(L, m_MK[ 0], m_RK[ 0]);
200
201
0
      store_be(out, R, L);
202
0
      }
203
0
   }
204
205
/*
206
* CAST-128 Key Schedule
207
*/
208
void CAST_128::key_schedule(const uint8_t key[], size_t length)
209
0
   {
210
0
   m_MK.resize(48);
211
0
   m_RK.resize(48);
212
213
0
   secure_vector<uint8_t> key16(16);
214
0
   copy_mem(key16.data(), key, length);
215
216
0
   secure_vector<uint32_t> X(4);
217
0
   for(size_t i = 0; i != 4; ++i)
218
0
      X[i] = load_be<uint32_t>(key16.data(), i);
219
220
0
   cast_ks(m_MK, X);
221
222
0
   secure_vector<uint32_t> RK32(48);
223
0
   cast_ks(RK32, X);
224
225
0
   for(size_t i = 0; i != 16; ++i)
226
0
      m_RK[i] = RK32[i] % 32;
227
0
   }
228
229
void CAST_128::clear()
230
0
   {
231
0
   zap(m_MK);
232
0
   zap(m_RK);
233
0
   }
234
235
/*
236
* S-Box Based Key Expansion
237
*/
238
void CAST_128::cast_ks(secure_vector<uint32_t>& K,
239
                       secure_vector<uint32_t>& X)
240
0
   {
241
0
   static const uint32_t S5[256] = {
242
0
      0x7EC90C04, 0x2C6E74B9, 0x9B0E66DF, 0xA6337911, 0xB86A7FFF, 0x1DD358F5,
243
0
      0x44DD9D44, 0x1731167F, 0x08FBF1FA, 0xE7F511CC, 0xD2051B00, 0x735ABA00,
244
0
      0x2AB722D8, 0x386381CB, 0xACF6243A, 0x69BEFD7A, 0xE6A2E77F, 0xF0C720CD,
245
0
      0xC4494816, 0xCCF5C180, 0x38851640, 0x15B0A848, 0xE68B18CB, 0x4CAADEFF,
246
0
      0x5F480A01, 0x0412B2AA, 0x259814FC, 0x41D0EFE2, 0x4E40B48D, 0x248EB6FB,
247
0
      0x8DBA1CFE, 0x41A99B02, 0x1A550A04, 0xBA8F65CB, 0x7251F4E7, 0x95A51725,
248
0
      0xC106ECD7, 0x97A5980A, 0xC539B9AA, 0x4D79FE6A, 0xF2F3F763, 0x68AF8040,
249
0
      0xED0C9E56, 0x11B4958B, 0xE1EB5A88, 0x8709E6B0, 0xD7E07156, 0x4E29FEA7,
250
0
      0x6366E52D, 0x02D1C000, 0xC4AC8E05, 0x9377F571, 0x0C05372A, 0x578535F2,
251
0
      0x2261BE02, 0xD642A0C9, 0xDF13A280, 0x74B55BD2, 0x682199C0, 0xD421E5EC,
252
0
      0x53FB3CE8, 0xC8ADEDB3, 0x28A87FC9, 0x3D959981, 0x5C1FF900, 0xFE38D399,
253
0
      0x0C4EFF0B, 0x062407EA, 0xAA2F4FB1, 0x4FB96976, 0x90C79505, 0xB0A8A774,
254
0
      0xEF55A1FF, 0xE59CA2C2, 0xA6B62D27, 0xE66A4263, 0xDF65001F, 0x0EC50966,
255
0
      0xDFDD55BC, 0x29DE0655, 0x911E739A, 0x17AF8975, 0x32C7911C, 0x89F89468,
256
0
      0x0D01E980, 0x524755F4, 0x03B63CC9, 0x0CC844B2, 0xBCF3F0AA, 0x87AC36E9,
257
0
      0xE53A7426, 0x01B3D82B, 0x1A9E7449, 0x64EE2D7E, 0xCDDBB1DA, 0x01C94910,
258
0
      0xB868BF80, 0x0D26F3FD, 0x9342EDE7, 0x04A5C284, 0x636737B6, 0x50F5B616,
259
0
      0xF24766E3, 0x8ECA36C1, 0x136E05DB, 0xFEF18391, 0xFB887A37, 0xD6E7F7D4,
260
0
      0xC7FB7DC9, 0x3063FCDF, 0xB6F589DE, 0xEC2941DA, 0x26E46695, 0xB7566419,
261
0
      0xF654EFC5, 0xD08D58B7, 0x48925401, 0xC1BACB7F, 0xE5FF550F, 0xB6083049,
262
0
      0x5BB5D0E8, 0x87D72E5A, 0xAB6A6EE1, 0x223A66CE, 0xC62BF3CD, 0x9E0885F9,
263
0
      0x68CB3E47, 0x086C010F, 0xA21DE820, 0xD18B69DE, 0xF3F65777, 0xFA02C3F6,
264
0
      0x407EDAC3, 0xCBB3D550, 0x1793084D, 0xB0D70EBA, 0x0AB378D5, 0xD951FB0C,
265
0
      0xDED7DA56, 0x4124BBE4, 0x94CA0B56, 0x0F5755D1, 0xE0E1E56E, 0x6184B5BE,
266
0
      0x580A249F, 0x94F74BC0, 0xE327888E, 0x9F7B5561, 0xC3DC0280, 0x05687715,
267
0
      0x646C6BD7, 0x44904DB3, 0x66B4F0A3, 0xC0F1648A, 0x697ED5AF, 0x49E92FF6,
268
0
      0x309E374F, 0x2CB6356A, 0x85808573, 0x4991F840, 0x76F0AE02, 0x083BE84D,
269
0
      0x28421C9A, 0x44489406, 0x736E4CB8, 0xC1092910, 0x8BC95FC6, 0x7D869CF4,
270
0
      0x134F616F, 0x2E77118D, 0xB31B2BE1, 0xAA90B472, 0x3CA5D717, 0x7D161BBA,
271
0
      0x9CAD9010, 0xAF462BA2, 0x9FE459D2, 0x45D34559, 0xD9F2DA13, 0xDBC65487,
272
0
      0xF3E4F94E, 0x176D486F, 0x097C13EA, 0x631DA5C7, 0x445F7382, 0x175683F4,
273
0
      0xCDC66A97, 0x70BE0288, 0xB3CDCF72, 0x6E5DD2F3, 0x20936079, 0x459B80A5,
274
0
      0xBE60E2DB, 0xA9C23101, 0xEBA5315C, 0x224E42F2, 0x1C5C1572, 0xF6721B2C,
275
0
      0x1AD2FFF3, 0x8C25404E, 0x324ED72F, 0x4067B7FD, 0x0523138E, 0x5CA3BC78,
276
0
      0xDC0FD66E, 0x75922283, 0x784D6B17, 0x58EBB16E, 0x44094F85, 0x3F481D87,
277
0
      0xFCFEAE7B, 0x77B5FF76, 0x8C2302BF, 0xAAF47556, 0x5F46B02A, 0x2B092801,
278
0
      0x3D38F5F7, 0x0CA81F36, 0x52AF4A8A, 0x66D5E7C0, 0xDF3B0874, 0x95055110,
279
0
      0x1B5AD7A8, 0xF61ED5AD, 0x6CF6E479, 0x20758184, 0xD0CEFA65, 0x88F7BE58,
280
0
      0x4A046826, 0x0FF6F8F3, 0xA09C7F70, 0x5346ABA0, 0x5CE96C28, 0xE176EDA3,
281
0
      0x6BAC307F, 0x376829D2, 0x85360FA9, 0x17E3FE2A, 0x24B79767, 0xF5A96B20,
282
0
      0xD6CD2595, 0x68FF1EBF, 0x7555442C, 0xF19F06BE, 0xF9E0659A, 0xEEB9491D,
283
0
      0x34010718, 0xBB30CAB8, 0xE822FE15, 0x88570983, 0x750E6249, 0xDA627E55,
284
0
      0x5E76FFA8, 0xB1534546, 0x6D47DE08, 0xEFE9E7D4 };
285
286
0
   static const uint32_t S6[256] = {
287
0
      0xF6FA8F9D, 0x2CAC6CE1, 0x4CA34867, 0xE2337F7C, 0x95DB08E7, 0x016843B4,
288
0
      0xECED5CBC, 0x325553AC, 0xBF9F0960, 0xDFA1E2ED, 0x83F0579D, 0x63ED86B9,
289
0
      0x1AB6A6B8, 0xDE5EBE39, 0xF38FF732, 0x8989B138, 0x33F14961, 0xC01937BD,
290
0
      0xF506C6DA, 0xE4625E7E, 0xA308EA99, 0x4E23E33C, 0x79CBD7CC, 0x48A14367,
291
0
      0xA3149619, 0xFEC94BD5, 0xA114174A, 0xEAA01866, 0xA084DB2D, 0x09A8486F,
292
0
      0xA888614A, 0x2900AF98, 0x01665991, 0xE1992863, 0xC8F30C60, 0x2E78EF3C,
293
0
      0xD0D51932, 0xCF0FEC14, 0xF7CA07D2, 0xD0A82072, 0xFD41197E, 0x9305A6B0,
294
0
      0xE86BE3DA, 0x74BED3CD, 0x372DA53C, 0x4C7F4448, 0xDAB5D440, 0x6DBA0EC3,
295
0
      0x083919A7, 0x9FBAEED9, 0x49DBCFB0, 0x4E670C53, 0x5C3D9C01, 0x64BDB941,
296
0
      0x2C0E636A, 0xBA7DD9CD, 0xEA6F7388, 0xE70BC762, 0x35F29ADB, 0x5C4CDD8D,
297
0
      0xF0D48D8C, 0xB88153E2, 0x08A19866, 0x1AE2EAC8, 0x284CAF89, 0xAA928223,
298
0
      0x9334BE53, 0x3B3A21BF, 0x16434BE3, 0x9AEA3906, 0xEFE8C36E, 0xF890CDD9,
299
0
      0x80226DAE, 0xC340A4A3, 0xDF7E9C09, 0xA694A807, 0x5B7C5ECC, 0x221DB3A6,
300
0
      0x9A69A02F, 0x68818A54, 0xCEB2296F, 0x53C0843A, 0xFE893655, 0x25BFE68A,
301
0
      0xB4628ABC, 0xCF222EBF, 0x25AC6F48, 0xA9A99387, 0x53BDDB65, 0xE76FFBE7,
302
0
      0xE967FD78, 0x0BA93563, 0x8E342BC1, 0xE8A11BE9, 0x4980740D, 0xC8087DFC,
303
0
      0x8DE4BF99, 0xA11101A0, 0x7FD37975, 0xDA5A26C0, 0xE81F994F, 0x9528CD89,
304
0
      0xFD339FED, 0xB87834BF, 0x5F04456D, 0x22258698, 0xC9C4C83B, 0x2DC156BE,
305
0
      0x4F628DAA, 0x57F55EC5, 0xE2220ABE, 0xD2916EBF, 0x4EC75B95, 0x24F2C3C0,
306
0
      0x42D15D99, 0xCD0D7FA0, 0x7B6E27FF, 0xA8DC8AF0, 0x7345C106, 0xF41E232F,
307
0
      0x35162386, 0xE6EA8926, 0x3333B094, 0x157EC6F2, 0x372B74AF, 0x692573E4,
308
0
      0xE9A9D848, 0xF3160289, 0x3A62EF1D, 0xA787E238, 0xF3A5F676, 0x74364853,
309
0
      0x20951063, 0x4576698D, 0xB6FAD407, 0x592AF950, 0x36F73523, 0x4CFB6E87,
310
0
      0x7DA4CEC0, 0x6C152DAA, 0xCB0396A8, 0xC50DFE5D, 0xFCD707AB, 0x0921C42F,
311
0
      0x89DFF0BB, 0x5FE2BE78, 0x448F4F33, 0x754613C9, 0x2B05D08D, 0x48B9D585,
312
0
      0xDC049441, 0xC8098F9B, 0x7DEDE786, 0xC39A3373, 0x42410005, 0x6A091751,
313
0
      0x0EF3C8A6, 0x890072D6, 0x28207682, 0xA9A9F7BE, 0xBF32679D, 0xD45B5B75,
314
0
      0xB353FD00, 0xCBB0E358, 0x830F220A, 0x1F8FB214, 0xD372CF08, 0xCC3C4A13,
315
0
      0x8CF63166, 0x061C87BE, 0x88C98F88, 0x6062E397, 0x47CF8E7A, 0xB6C85283,
316
0
      0x3CC2ACFB, 0x3FC06976, 0x4E8F0252, 0x64D8314D, 0xDA3870E3, 0x1E665459,
317
0
      0xC10908F0, 0x513021A5, 0x6C5B68B7, 0x822F8AA0, 0x3007CD3E, 0x74719EEF,
318
0
      0xDC872681, 0x073340D4, 0x7E432FD9, 0x0C5EC241, 0x8809286C, 0xF592D891,
319
0
      0x08A930F6, 0x957EF305, 0xB7FBFFBD, 0xC266E96F, 0x6FE4AC98, 0xB173ECC0,
320
0
      0xBC60B42A, 0x953498DA, 0xFBA1AE12, 0x2D4BD736, 0x0F25FAAB, 0xA4F3FCEB,
321
0
      0xE2969123, 0x257F0C3D, 0x9348AF49, 0x361400BC, 0xE8816F4A, 0x3814F200,
322
0
      0xA3F94043, 0x9C7A54C2, 0xBC704F57, 0xDA41E7F9, 0xC25AD33A, 0x54F4A084,
323
0
      0xB17F5505, 0x59357CBE, 0xEDBD15C8, 0x7F97C5AB, 0xBA5AC7B5, 0xB6F6DEAF,
324
0
      0x3A479C3A, 0x5302DA25, 0x653D7E6A, 0x54268D49, 0x51A477EA, 0x5017D55B,
325
0
      0xD7D25D88, 0x44136C76, 0x0404A8C8, 0xB8E5A121, 0xB81A928A, 0x60ED5869,
326
0
      0x97C55B96, 0xEAEC991B, 0x29935913, 0x01FDB7F1, 0x088E8DFA, 0x9AB6F6F5,
327
0
      0x3B4CBF9F, 0x4A5DE3AB, 0xE6051D35, 0xA0E1D855, 0xD36B4CF1, 0xF544EDEB,
328
0
      0xB0E93524, 0xBEBB8FBD, 0xA2D762CF, 0x49C92F54, 0x38B5F331, 0x7128A454,
329
0
      0x48392905, 0xA65B1DB8, 0x851C97BD, 0xD675CF2F };
330
331
0
   static const uint32_t S7[256] = {
332
0
      0x85E04019, 0x332BF567, 0x662DBFFF, 0xCFC65693, 0x2A8D7F6F, 0xAB9BC912,
333
0
      0xDE6008A1, 0x2028DA1F, 0x0227BCE7, 0x4D642916, 0x18FAC300, 0x50F18B82,
334
0
      0x2CB2CB11, 0xB232E75C, 0x4B3695F2, 0xB28707DE, 0xA05FBCF6, 0xCD4181E9,
335
0
      0xE150210C, 0xE24EF1BD, 0xB168C381, 0xFDE4E789, 0x5C79B0D8, 0x1E8BFD43,
336
0
      0x4D495001, 0x38BE4341, 0x913CEE1D, 0x92A79C3F, 0x089766BE, 0xBAEEADF4,
337
0
      0x1286BECF, 0xB6EACB19, 0x2660C200, 0x7565BDE4, 0x64241F7A, 0x8248DCA9,
338
0
      0xC3B3AD66, 0x28136086, 0x0BD8DFA8, 0x356D1CF2, 0x107789BE, 0xB3B2E9CE,
339
0
      0x0502AA8F, 0x0BC0351E, 0x166BF52A, 0xEB12FF82, 0xE3486911, 0xD34D7516,
340
0
      0x4E7B3AFF, 0x5F43671B, 0x9CF6E037, 0x4981AC83, 0x334266CE, 0x8C9341B7,
341
0
      0xD0D854C0, 0xCB3A6C88, 0x47BC2829, 0x4725BA37, 0xA66AD22B, 0x7AD61F1E,
342
0
      0x0C5CBAFA, 0x4437F107, 0xB6E79962, 0x42D2D816, 0x0A961288, 0xE1A5C06E,
343
0
      0x13749E67, 0x72FC081A, 0xB1D139F7, 0xF9583745, 0xCF19DF58, 0xBEC3F756,
344
0
      0xC06EBA30, 0x07211B24, 0x45C28829, 0xC95E317F, 0xBC8EC511, 0x38BC46E9,
345
0
      0xC6E6FA14, 0xBAE8584A, 0xAD4EBC46, 0x468F508B, 0x7829435F, 0xF124183B,
346
0
      0x821DBA9F, 0xAFF60FF4, 0xEA2C4E6D, 0x16E39264, 0x92544A8B, 0x009B4FC3,
347
0
      0xABA68CED, 0x9AC96F78, 0x06A5B79A, 0xB2856E6E, 0x1AEC3CA9, 0xBE838688,
348
0
      0x0E0804E9, 0x55F1BE56, 0xE7E5363B, 0xB3A1F25D, 0xF7DEBB85, 0x61FE033C,
349
0
      0x16746233, 0x3C034C28, 0xDA6D0C74, 0x79AAC56C, 0x3CE4E1AD, 0x51F0C802,
350
0
      0x98F8F35A, 0x1626A49F, 0xEED82B29, 0x1D382FE3, 0x0C4FB99A, 0xBB325778,
351
0
      0x3EC6D97B, 0x6E77A6A9, 0xCB658B5C, 0xD45230C7, 0x2BD1408B, 0x60C03EB7,
352
0
      0xB9068D78, 0xA33754F4, 0xF430C87D, 0xC8A71302, 0xB96D8C32, 0xEBD4E7BE,
353
0
      0xBE8B9D2D, 0x7979FB06, 0xE7225308, 0x8B75CF77, 0x11EF8DA4, 0xE083C858,
354
0
      0x8D6B786F, 0x5A6317A6, 0xFA5CF7A0, 0x5DDA0033, 0xF28EBFB0, 0xF5B9C310,
355
0
      0xA0EAC280, 0x08B9767A, 0xA3D9D2B0, 0x79D34217, 0x021A718D, 0x9AC6336A,
356
0
      0x2711FD60, 0x438050E3, 0x069908A8, 0x3D7FEDC4, 0x826D2BEF, 0x4EEB8476,
357
0
      0x488DCF25, 0x36C9D566, 0x28E74E41, 0xC2610ACA, 0x3D49A9CF, 0xBAE3B9DF,
358
0
      0xB65F8DE6, 0x92AEAF64, 0x3AC7D5E6, 0x9EA80509, 0xF22B017D, 0xA4173F70,
359
0
      0xDD1E16C3, 0x15E0D7F9, 0x50B1B887, 0x2B9F4FD5, 0x625ABA82, 0x6A017962,
360
0
      0x2EC01B9C, 0x15488AA9, 0xD716E740, 0x40055A2C, 0x93D29A22, 0xE32DBF9A,
361
0
      0x058745B9, 0x3453DC1E, 0xD699296E, 0x496CFF6F, 0x1C9F4986, 0xDFE2ED07,
362
0
      0xB87242D1, 0x19DE7EAE, 0x053E561A, 0x15AD6F8C, 0x66626C1C, 0x7154C24C,
363
0
      0xEA082B2A, 0x93EB2939, 0x17DCB0F0, 0x58D4F2AE, 0x9EA294FB, 0x52CF564C,
364
0
      0x9883FE66, 0x2EC40581, 0x763953C3, 0x01D6692E, 0xD3A0C108, 0xA1E7160E,
365
0
      0xE4F2DFA6, 0x693ED285, 0x74904698, 0x4C2B0EDD, 0x4F757656, 0x5D393378,
366
0
      0xA132234F, 0x3D321C5D, 0xC3F5E194, 0x4B269301, 0xC79F022F, 0x3C997E7E,
367
0
      0x5E4F9504, 0x3FFAFBBD, 0x76F7AD0E, 0x296693F4, 0x3D1FCE6F, 0xC61E45BE,
368
0
      0xD3B5AB34, 0xF72BF9B7, 0x1B0434C0, 0x4E72B567, 0x5592A33D, 0xB5229301,
369
0
      0xCFD2A87F, 0x60AEB767, 0x1814386B, 0x30BCC33D, 0x38A0C07D, 0xFD1606F2,
370
0
      0xC363519B, 0x589DD390, 0x5479F8E6, 0x1CB8D647, 0x97FD61A9, 0xEA7759F4,
371
0
      0x2D57539D, 0x569A58CF, 0xE84E63AD, 0x462E1B78, 0x6580F87E, 0xF3817914,
372
0
      0x91DA55F4, 0x40A230F3, 0xD1988F35, 0xB6E318D2, 0x3FFA50BC, 0x3D40F021,
373
0
      0xC3C0BDAE, 0x4958C24C, 0x518F36B2, 0x84B1D370, 0x0FEDCE83, 0x878DDADA,
374
0
      0xF2A279C7, 0x94E01BE8, 0x90716F4B, 0x954B8AA3 };
375
376
0
   static const uint32_t S8[256] = {
377
0
      0xE216300D, 0xBBDDFFFC, 0xA7EBDABD, 0x35648095, 0x7789F8B7, 0xE6C1121B,
378
0
      0x0E241600, 0x052CE8B5, 0x11A9CFB0, 0xE5952F11, 0xECE7990A, 0x9386D174,
379
0
      0x2A42931C, 0x76E38111, 0xB12DEF3A, 0x37DDDDFC, 0xDE9ADEB1, 0x0A0CC32C,
380
0
      0xBE197029, 0x84A00940, 0xBB243A0F, 0xB4D137CF, 0xB44E79F0, 0x049EEDFD,
381
0
      0x0B15A15D, 0x480D3168, 0x8BBBDE5A, 0x669DED42, 0xC7ECE831, 0x3F8F95E7,
382
0
      0x72DF191B, 0x7580330D, 0x94074251, 0x5C7DCDFA, 0xABBE6D63, 0xAA402164,
383
0
      0xB301D40A, 0x02E7D1CA, 0x53571DAE, 0x7A3182A2, 0x12A8DDEC, 0xFDAA335D,
384
0
      0x176F43E8, 0x71FB46D4, 0x38129022, 0xCE949AD4, 0xB84769AD, 0x965BD862,
385
0
      0x82F3D055, 0x66FB9767, 0x15B80B4E, 0x1D5B47A0, 0x4CFDE06F, 0xC28EC4B8,
386
0
      0x57E8726E, 0x647A78FC, 0x99865D44, 0x608BD593, 0x6C200E03, 0x39DC5FF6,
387
0
      0x5D0B00A3, 0xAE63AFF2, 0x7E8BD632, 0x70108C0C, 0xBBD35049, 0x2998DF04,
388
0
      0x980CF42A, 0x9B6DF491, 0x9E7EDD53, 0x06918548, 0x58CB7E07, 0x3B74EF2E,
389
0
      0x522FFFB1, 0xD24708CC, 0x1C7E27CD, 0xA4EB215B, 0x3CF1D2E2, 0x19B47A38,
390
0
      0x424F7618, 0x35856039, 0x9D17DEE7, 0x27EB35E6, 0xC9AFF67B, 0x36BAF5B8,
391
0
      0x09C467CD, 0xC18910B1, 0xE11DBF7B, 0x06CD1AF8, 0x7170C608, 0x2D5E3354,
392
0
      0xD4DE495A, 0x64C6D006, 0xBCC0C62C, 0x3DD00DB3, 0x708F8F34, 0x77D51B42,
393
0
      0x264F620F, 0x24B8D2BF, 0x15C1B79E, 0x46A52564, 0xF8D7E54E, 0x3E378160,
394
0
      0x7895CDA5, 0x859C15A5, 0xE6459788, 0xC37BC75F, 0xDB07BA0C, 0x0676A3AB,
395
0
      0x7F229B1E, 0x31842E7B, 0x24259FD7, 0xF8BEF472, 0x835FFCB8, 0x6DF4C1F2,
396
0
      0x96F5B195, 0xFD0AF0FC, 0xB0FE134C, 0xE2506D3D, 0x4F9B12EA, 0xF215F225,
397
0
      0xA223736F, 0x9FB4C428, 0x25D04979, 0x34C713F8, 0xC4618187, 0xEA7A6E98,
398
0
      0x7CD16EFC, 0x1436876C, 0xF1544107, 0xBEDEEE14, 0x56E9AF27, 0xA04AA441,
399
0
      0x3CF7C899, 0x92ECBAE6, 0xDD67016D, 0x151682EB, 0xA842EEDF, 0xFDBA60B4,
400
0
      0xF1907B75, 0x20E3030F, 0x24D8C29E, 0xE139673B, 0xEFA63FB8, 0x71873054,
401
0
      0xB6F2CF3B, 0x9F326442, 0xCB15A4CC, 0xB01A4504, 0xF1E47D8D, 0x844A1BE5,
402
0
      0xBAE7DFDC, 0x42CBDA70, 0xCD7DAE0A, 0x57E85B7A, 0xD53F5AF6, 0x20CF4D8C,
403
0
      0xCEA4D428, 0x79D130A4, 0x3486EBFB, 0x33D3CDDC, 0x77853B53, 0x37EFFCB5,
404
0
      0xC5068778, 0xE580B3E6, 0x4E68B8F4, 0xC5C8B37E, 0x0D809EA2, 0x398FEB7C,
405
0
      0x132A4F94, 0x43B7950E, 0x2FEE7D1C, 0x223613BD, 0xDD06CAA2, 0x37DF932B,
406
0
      0xC4248289, 0xACF3EBC3, 0x5715F6B7, 0xEF3478DD, 0xF267616F, 0xC148CBE4,
407
0
      0x9052815E, 0x5E410FAB, 0xB48A2465, 0x2EDA7FA4, 0xE87B40E4, 0xE98EA084,
408
0
      0x5889E9E1, 0xEFD390FC, 0xDD07D35B, 0xDB485694, 0x38D7E5B2, 0x57720101,
409
0
      0x730EDEBC, 0x5B643113, 0x94917E4F, 0x503C2FBA, 0x646F1282, 0x7523D24A,
410
0
      0xE0779695, 0xF9C17A8F, 0x7A5B2121, 0xD187B896, 0x29263A4D, 0xBA510CDF,
411
0
      0x81F47C9F, 0xAD1163ED, 0xEA7B5965, 0x1A00726E, 0x11403092, 0x00DA6D77,
412
0
      0x4A0CDD61, 0xAD1F4603, 0x605BDFB0, 0x9EEDC364, 0x22EBE6A8, 0xCEE7D28A,
413
0
      0xA0E736A0, 0x5564A6B9, 0x10853209, 0xC7EB8F37, 0x2DE705CA, 0x8951570F,
414
0
      0xDF09822B, 0xBD691A6C, 0xAA12E4F2, 0x87451C0F, 0xE0F6A27A, 0x3ADA4819,
415
0
      0x4CF1764F, 0x0D771C2B, 0x67CDB156, 0x350D8384, 0x5938FA0F, 0x42399EF3,
416
0
      0x36997B07, 0x0E84093D, 0x4AA93E61, 0x8360D87B, 0x1FA98B0C, 0x1149382C,
417
0
      0xE97625A5, 0x0614D1B7, 0x0E25244B, 0x0C768347, 0x589E8D82, 0x0D2059D1,
418
0
      0xA466BB1E, 0xF8DA0A82, 0x04F19130, 0xBA6E4EC0, 0x99265164, 0x1EE7230D,
419
0
      0x50B2AD80, 0xEAEE6801, 0x8DB2A283, 0xEA8BF59E };
420
421
0
   class ByteReader final
422
0
      {
423
0
      public:
424
0
         uint8_t operator()(size_t i) const
425
0
            {
426
0
            return static_cast<uint8_t>(m_X[i/4] >> (8*(3 - (i%4))));
427
0
            }
428
429
0
         explicit ByteReader(const uint32_t* x) : m_X(x) {}
430
0
      private:
431
0
         const uint32_t* m_X;
432
0
      };
433
434
0
   secure_vector<uint32_t> Z(4);
435
0
   ByteReader x(X.data()), z(Z.data());
436
437
0
   Z[0]  = X[0] ^ S5[x(13)] ^ S6[x(15)] ^ S7[x(12)] ^ S8[x(14)] ^ S7[x( 8)];
438
0
   Z[1]  = X[2] ^ S5[z( 0)] ^ S6[z( 2)] ^ S7[z( 1)] ^ S8[z( 3)] ^ S8[x(10)];
439
0
   Z[2]  = X[3] ^ S5[z( 7)] ^ S6[z( 6)] ^ S7[z( 5)] ^ S8[z( 4)] ^ S5[x( 9)];
440
0
   Z[3]  = X[1] ^ S5[z(10)] ^ S6[z( 9)] ^ S7[z(11)] ^ S8[z( 8)] ^ S6[x(11)];
441
0
   K[ 0] = S5[z( 8)] ^ S6[z( 9)] ^ S7[z( 7)] ^ S8[z( 6)] ^ S5[z( 2)];
442
0
   K[ 1] = S5[z(10)] ^ S6[z(11)] ^ S7[z( 5)] ^ S8[z( 4)] ^ S6[z( 6)];
443
0
   K[ 2] = S5[z(12)] ^ S6[z(13)] ^ S7[z( 3)] ^ S8[z( 2)] ^ S7[z( 9)];
444
0
   K[ 3] = S5[z(14)] ^ S6[z(15)] ^ S7[z( 1)] ^ S8[z( 0)] ^ S8[z(12)];
445
0
   X[0]  = Z[2] ^ S5[z( 5)] ^ S6[z( 7)] ^ S7[z( 4)] ^ S8[z( 6)] ^ S7[z( 0)];
446
0
   X[1]  = Z[0] ^ S5[x( 0)] ^ S6[x( 2)] ^ S7[x( 1)] ^ S8[x( 3)] ^ S8[z( 2)];
447
0
   X[2]  = Z[1] ^ S5[x( 7)] ^ S6[x( 6)] ^ S7[x( 5)] ^ S8[x( 4)] ^ S5[z( 1)];
448
0
   X[3]  = Z[3] ^ S5[x(10)] ^ S6[x( 9)] ^ S7[x(11)] ^ S8[x( 8)] ^ S6[z( 3)];
449
0
   K[ 4] = S5[x( 3)] ^ S6[x( 2)] ^ S7[x(12)] ^ S8[x(13)] ^ S5[x( 8)];
450
0
   K[ 5] = S5[x( 1)] ^ S6[x( 0)] ^ S7[x(14)] ^ S8[x(15)] ^ S6[x(13)];
451
0
   K[ 6] = S5[x( 7)] ^ S6[x( 6)] ^ S7[x( 8)] ^ S8[x( 9)] ^ S7[x( 3)];
452
0
   K[ 7] = S5[x( 5)] ^ S6[x( 4)] ^ S7[x(10)] ^ S8[x(11)] ^ S8[x( 7)];
453
0
   Z[0]  = X[0] ^ S5[x(13)] ^ S6[x(15)] ^ S7[x(12)] ^ S8[x(14)] ^ S7[x( 8)];
454
0
   Z[1]  = X[2] ^ S5[z( 0)] ^ S6[z( 2)] ^ S7[z( 1)] ^ S8[z( 3)] ^ S8[x(10)];
455
0
   Z[2]  = X[3] ^ S5[z( 7)] ^ S6[z( 6)] ^ S7[z( 5)] ^ S8[z( 4)] ^ S5[x( 9)];
456
0
   Z[3]  = X[1] ^ S5[z(10)] ^ S6[z( 9)] ^ S7[z(11)] ^ S8[z( 8)] ^ S6[x(11)];
457
0
   K[ 8] = S5[z( 3)] ^ S6[z( 2)] ^ S7[z(12)] ^ S8[z(13)] ^ S5[z( 9)];
458
0
   K[ 9] = S5[z( 1)] ^ S6[z( 0)] ^ S7[z(14)] ^ S8[z(15)] ^ S6[z(12)];
459
0
   K[10] = S5[z( 7)] ^ S6[z( 6)] ^ S7[z( 8)] ^ S8[z( 9)] ^ S7[z( 2)];
460
0
   K[11] = S5[z( 5)] ^ S6[z( 4)] ^ S7[z(10)] ^ S8[z(11)] ^ S8[z( 6)];
461
0
   X[0]  = Z[2] ^ S5[z( 5)] ^ S6[z( 7)] ^ S7[z( 4)] ^ S8[z( 6)] ^ S7[z( 0)];
462
0
   X[1]  = Z[0] ^ S5[x( 0)] ^ S6[x( 2)] ^ S7[x( 1)] ^ S8[x( 3)] ^ S8[z( 2)];
463
0
   X[2]  = Z[1] ^ S5[x( 7)] ^ S6[x( 6)] ^ S7[x( 5)] ^ S8[x( 4)] ^ S5[z( 1)];
464
0
   X[3]  = Z[3] ^ S5[x(10)] ^ S6[x( 9)] ^ S7[x(11)] ^ S8[x( 8)] ^ S6[z( 3)];
465
0
   K[12] = S5[x( 8)] ^ S6[x( 9)] ^ S7[x( 7)] ^ S8[x( 6)] ^ S5[x( 3)];
466
0
   K[13] = S5[x(10)] ^ S6[x(11)] ^ S7[x( 5)] ^ S8[x( 4)] ^ S6[x( 7)];
467
0
   K[14] = S5[x(12)] ^ S6[x(13)] ^ S7[x( 3)] ^ S8[x( 2)] ^ S7[x( 8)];
468
0
   K[15] = S5[x(14)] ^ S6[x(15)] ^ S7[x( 1)] ^ S8[x( 0)] ^ S8[x(13)];
469
0
   }
470
471
}