Coverage Report

Created: 2024-06-28 06:39

/src/botan/src/lib/block/serpent/serpent.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
* Serpent
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/serpent.h>
9
10
#include <botan/internal/loadstor.h>
11
#include <botan/internal/rotate.h>
12
#include <botan/internal/serpent_sbox.h>
13
14
#if defined(BOTAN_HAS_SERPENT_SIMD) || defined(BOTAN_HAS_SERPENT_AVX2) || defined(BOTAN_HAS_SERPENT_AVX512)
15
   #include <botan/internal/cpuid.h>
16
#endif
17
18
namespace Botan {
19
20
/*
21
* Serpent Encryption
22
*/
23
1.99k
void Serpent::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const {
24
1.99k
   using namespace Botan::Serpent_F;
25
26
1.99k
   assert_key_material_set();
27
28
1.99k
#if defined(BOTAN_HAS_SERPENT_AVX512)
29
1.99k
   if(CPUID::has_avx512()) {
30
0
      while(blocks >= 16) {
31
0
         avx512_encrypt_16(in, out);
32
0
         in += 16 * BLOCK_SIZE;
33
0
         out += 16 * BLOCK_SIZE;
34
0
         blocks -= 16;
35
0
      }
36
0
   }
37
1.99k
#endif
38
39
1.99k
#if defined(BOTAN_HAS_SERPENT_AVX2)
40
1.99k
   if(CPUID::has_avx2()) {
41
2.15k
      while(blocks >= 8) {
42
159
         avx2_encrypt_8(in, out);
43
159
         in += 8 * BLOCK_SIZE;
44
159
         out += 8 * BLOCK_SIZE;
45
159
         blocks -= 8;
46
159
      }
47
1.99k
   }
48
1.99k
#endif
49
50
1.99k
#if defined(BOTAN_HAS_SERPENT_SIMD)
51
1.99k
   if(CPUID::has_simd_32()) {
52
1.99k
      while(blocks >= 4) {
53
2
         simd_encrypt_4(in, out);
54
2
         in += 4 * BLOCK_SIZE;
55
2
         out += 4 * BLOCK_SIZE;
56
2
         blocks -= 4;
57
2
      }
58
1.99k
   }
59
1.99k
#endif
60
61
1.99k
   const Key_Inserter key_xor(m_round_key.data());
62
63
4.02k
   for(size_t i = 0; i < blocks; ++i) {
64
2.03k
      uint32_t B0, B1, B2, B3;
65
2.03k
      load_le(in + 16 * i, B0, B1, B2, B3);
66
67
2.03k
      key_xor(0, B0, B1, B2, B3);
68
2.03k
      SBoxE0(B0, B1, B2, B3);
69
2.03k
      transform(B0, B1, B2, B3);
70
2.03k
      key_xor(1, B0, B1, B2, B3);
71
2.03k
      SBoxE1(B0, B1, B2, B3);
72
2.03k
      transform(B0, B1, B2, B3);
73
2.03k
      key_xor(2, B0, B1, B2, B3);
74
2.03k
      SBoxE2(B0, B1, B2, B3);
75
2.03k
      transform(B0, B1, B2, B3);
76
2.03k
      key_xor(3, B0, B1, B2, B3);
77
2.03k
      SBoxE3(B0, B1, B2, B3);
78
2.03k
      transform(B0, B1, B2, B3);
79
2.03k
      key_xor(4, B0, B1, B2, B3);
80
2.03k
      SBoxE4(B0, B1, B2, B3);
81
2.03k
      transform(B0, B1, B2, B3);
82
2.03k
      key_xor(5, B0, B1, B2, B3);
83
2.03k
      SBoxE5(B0, B1, B2, B3);
84
2.03k
      transform(B0, B1, B2, B3);
85
2.03k
      key_xor(6, B0, B1, B2, B3);
86
2.03k
      SBoxE6(B0, B1, B2, B3);
87
2.03k
      transform(B0, B1, B2, B3);
88
2.03k
      key_xor(7, B0, B1, B2, B3);
89
2.03k
      SBoxE7(B0, B1, B2, B3);
90
2.03k
      transform(B0, B1, B2, B3);
91
2.03k
      key_xor(8, B0, B1, B2, B3);
92
2.03k
      SBoxE0(B0, B1, B2, B3);
93
2.03k
      transform(B0, B1, B2, B3);
94
2.03k
      key_xor(9, B0, B1, B2, B3);
95
2.03k
      SBoxE1(B0, B1, B2, B3);
96
2.03k
      transform(B0, B1, B2, B3);
97
2.03k
      key_xor(10, B0, B1, B2, B3);
98
2.03k
      SBoxE2(B0, B1, B2, B3);
99
2.03k
      transform(B0, B1, B2, B3);
100
2.03k
      key_xor(11, B0, B1, B2, B3);
101
2.03k
      SBoxE3(B0, B1, B2, B3);
102
2.03k
      transform(B0, B1, B2, B3);
103
2.03k
      key_xor(12, B0, B1, B2, B3);
104
2.03k
      SBoxE4(B0, B1, B2, B3);
105
2.03k
      transform(B0, B1, B2, B3);
106
2.03k
      key_xor(13, B0, B1, B2, B3);
107
2.03k
      SBoxE5(B0, B1, B2, B3);
108
2.03k
      transform(B0, B1, B2, B3);
109
2.03k
      key_xor(14, B0, B1, B2, B3);
110
2.03k
      SBoxE6(B0, B1, B2, B3);
111
2.03k
      transform(B0, B1, B2, B3);
112
2.03k
      key_xor(15, B0, B1, B2, B3);
113
2.03k
      SBoxE7(B0, B1, B2, B3);
114
2.03k
      transform(B0, B1, B2, B3);
115
2.03k
      key_xor(16, B0, B1, B2, B3);
116
2.03k
      SBoxE0(B0, B1, B2, B3);
117
2.03k
      transform(B0, B1, B2, B3);
118
2.03k
      key_xor(17, B0, B1, B2, B3);
119
2.03k
      SBoxE1(B0, B1, B2, B3);
120
2.03k
      transform(B0, B1, B2, B3);
121
2.03k
      key_xor(18, B0, B1, B2, B3);
122
2.03k
      SBoxE2(B0, B1, B2, B3);
123
2.03k
      transform(B0, B1, B2, B3);
124
2.03k
      key_xor(19, B0, B1, B2, B3);
125
2.03k
      SBoxE3(B0, B1, B2, B3);
126
2.03k
      transform(B0, B1, B2, B3);
127
2.03k
      key_xor(20, B0, B1, B2, B3);
128
2.03k
      SBoxE4(B0, B1, B2, B3);
129
2.03k
      transform(B0, B1, B2, B3);
130
2.03k
      key_xor(21, B0, B1, B2, B3);
131
2.03k
      SBoxE5(B0, B1, B2, B3);
132
2.03k
      transform(B0, B1, B2, B3);
133
2.03k
      key_xor(22, B0, B1, B2, B3);
134
2.03k
      SBoxE6(B0, B1, B2, B3);
135
2.03k
      transform(B0, B1, B2, B3);
136
2.03k
      key_xor(23, B0, B1, B2, B3);
137
2.03k
      SBoxE7(B0, B1, B2, B3);
138
2.03k
      transform(B0, B1, B2, B3);
139
2.03k
      key_xor(24, B0, B1, B2, B3);
140
2.03k
      SBoxE0(B0, B1, B2, B3);
141
2.03k
      transform(B0, B1, B2, B3);
142
2.03k
      key_xor(25, B0, B1, B2, B3);
143
2.03k
      SBoxE1(B0, B1, B2, B3);
144
2.03k
      transform(B0, B1, B2, B3);
145
2.03k
      key_xor(26, B0, B1, B2, B3);
146
2.03k
      SBoxE2(B0, B1, B2, B3);
147
2.03k
      transform(B0, B1, B2, B3);
148
2.03k
      key_xor(27, B0, B1, B2, B3);
149
2.03k
      SBoxE3(B0, B1, B2, B3);
150
2.03k
      transform(B0, B1, B2, B3);
151
2.03k
      key_xor(28, B0, B1, B2, B3);
152
2.03k
      SBoxE4(B0, B1, B2, B3);
153
2.03k
      transform(B0, B1, B2, B3);
154
2.03k
      key_xor(29, B0, B1, B2, B3);
155
2.03k
      SBoxE5(B0, B1, B2, B3);
156
2.03k
      transform(B0, B1, B2, B3);
157
2.03k
      key_xor(30, B0, B1, B2, B3);
158
2.03k
      SBoxE6(B0, B1, B2, B3);
159
2.03k
      transform(B0, B1, B2, B3);
160
2.03k
      key_xor(31, B0, B1, B2, B3);
161
2.03k
      SBoxE7(B0, B1, B2, B3);
162
2.03k
      key_xor(32, B0, B1, B2, B3);
163
164
2.03k
      store_le(out + 16 * i, B0, B1, B2, B3);
165
2.03k
   }
166
1.99k
}
167
168
/*
169
* Serpent Decryption
170
*/
171
411
void Serpent::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const {
172
411
   using namespace Botan::Serpent_F;
173
174
411
   assert_key_material_set();
175
176
411
#if defined(BOTAN_HAS_SERPENT_AVX512)
177
411
   if(CPUID::has_avx512()) {
178
0
      while(blocks >= 16) {
179
0
         avx512_decrypt_16(in, out);
180
0
         in += 16 * BLOCK_SIZE;
181
0
         out += 16 * BLOCK_SIZE;
182
0
         blocks -= 16;
183
0
      }
184
0
   }
185
411
#endif
186
187
411
#if defined(BOTAN_HAS_SERPENT_AVX2)
188
411
   if(CPUID::has_avx2()) {
189
684
      while(blocks >= 8) {
190
273
         avx2_decrypt_8(in, out);
191
273
         in += 8 * BLOCK_SIZE;
192
273
         out += 8 * BLOCK_SIZE;
193
273
         blocks -= 8;
194
273
      }
195
411
   }
196
411
#endif
197
198
411
#if defined(BOTAN_HAS_SERPENT_SIMD)
199
411
   if(CPUID::has_simd_32()) {
200
424
      while(blocks >= 4) {
201
13
         simd_decrypt_4(in, out);
202
13
         in += 4 * BLOCK_SIZE;
203
13
         out += 4 * BLOCK_SIZE;
204
13
         blocks -= 4;
205
13
      }
206
411
   }
207
411
#endif
208
209
411
   const Key_Inserter key_xor(m_round_key.data());
210
211
817
   for(size_t i = 0; i < blocks; ++i) {
212
406
      uint32_t B0, B1, B2, B3;
213
406
      load_le(in + 16 * i, B0, B1, B2, B3);
214
215
406
      key_xor(32, B0, B1, B2, B3);
216
406
      SBoxD7(B0, B1, B2, B3);
217
406
      key_xor(31, B0, B1, B2, B3);
218
406
      i_transform(B0, B1, B2, B3);
219
406
      SBoxD6(B0, B1, B2, B3);
220
406
      key_xor(30, B0, B1, B2, B3);
221
406
      i_transform(B0, B1, B2, B3);
222
406
      SBoxD5(B0, B1, B2, B3);
223
406
      key_xor(29, B0, B1, B2, B3);
224
406
      i_transform(B0, B1, B2, B3);
225
406
      SBoxD4(B0, B1, B2, B3);
226
406
      key_xor(28, B0, B1, B2, B3);
227
406
      i_transform(B0, B1, B2, B3);
228
406
      SBoxD3(B0, B1, B2, B3);
229
406
      key_xor(27, B0, B1, B2, B3);
230
406
      i_transform(B0, B1, B2, B3);
231
406
      SBoxD2(B0, B1, B2, B3);
232
406
      key_xor(26, B0, B1, B2, B3);
233
406
      i_transform(B0, B1, B2, B3);
234
406
      SBoxD1(B0, B1, B2, B3);
235
406
      key_xor(25, B0, B1, B2, B3);
236
406
      i_transform(B0, B1, B2, B3);
237
406
      SBoxD0(B0, B1, B2, B3);
238
406
      key_xor(24, B0, B1, B2, B3);
239
406
      i_transform(B0, B1, B2, B3);
240
406
      SBoxD7(B0, B1, B2, B3);
241
406
      key_xor(23, B0, B1, B2, B3);
242
406
      i_transform(B0, B1, B2, B3);
243
406
      SBoxD6(B0, B1, B2, B3);
244
406
      key_xor(22, B0, B1, B2, B3);
245
406
      i_transform(B0, B1, B2, B3);
246
406
      SBoxD5(B0, B1, B2, B3);
247
406
      key_xor(21, B0, B1, B2, B3);
248
406
      i_transform(B0, B1, B2, B3);
249
406
      SBoxD4(B0, B1, B2, B3);
250
406
      key_xor(20, B0, B1, B2, B3);
251
406
      i_transform(B0, B1, B2, B3);
252
406
      SBoxD3(B0, B1, B2, B3);
253
406
      key_xor(19, B0, B1, B2, B3);
254
406
      i_transform(B0, B1, B2, B3);
255
406
      SBoxD2(B0, B1, B2, B3);
256
406
      key_xor(18, B0, B1, B2, B3);
257
406
      i_transform(B0, B1, B2, B3);
258
406
      SBoxD1(B0, B1, B2, B3);
259
406
      key_xor(17, B0, B1, B2, B3);
260
406
      i_transform(B0, B1, B2, B3);
261
406
      SBoxD0(B0, B1, B2, B3);
262
406
      key_xor(16, B0, B1, B2, B3);
263
406
      i_transform(B0, B1, B2, B3);
264
406
      SBoxD7(B0, B1, B2, B3);
265
406
      key_xor(15, B0, B1, B2, B3);
266
406
      i_transform(B0, B1, B2, B3);
267
406
      SBoxD6(B0, B1, B2, B3);
268
406
      key_xor(14, B0, B1, B2, B3);
269
406
      i_transform(B0, B1, B2, B3);
270
406
      SBoxD5(B0, B1, B2, B3);
271
406
      key_xor(13, B0, B1, B2, B3);
272
406
      i_transform(B0, B1, B2, B3);
273
406
      SBoxD4(B0, B1, B2, B3);
274
406
      key_xor(12, B0, B1, B2, B3);
275
406
      i_transform(B0, B1, B2, B3);
276
406
      SBoxD3(B0, B1, B2, B3);
277
406
      key_xor(11, B0, B1, B2, B3);
278
406
      i_transform(B0, B1, B2, B3);
279
406
      SBoxD2(B0, B1, B2, B3);
280
406
      key_xor(10, B0, B1, B2, B3);
281
406
      i_transform(B0, B1, B2, B3);
282
406
      SBoxD1(B0, B1, B2, B3);
283
406
      key_xor(9, B0, B1, B2, B3);
284
406
      i_transform(B0, B1, B2, B3);
285
406
      SBoxD0(B0, B1, B2, B3);
286
406
      key_xor(8, B0, B1, B2, B3);
287
406
      i_transform(B0, B1, B2, B3);
288
406
      SBoxD7(B0, B1, B2, B3);
289
406
      key_xor(7, B0, B1, B2, B3);
290
406
      i_transform(B0, B1, B2, B3);
291
406
      SBoxD6(B0, B1, B2, B3);
292
406
      key_xor(6, B0, B1, B2, B3);
293
406
      i_transform(B0, B1, B2, B3);
294
406
      SBoxD5(B0, B1, B2, B3);
295
406
      key_xor(5, B0, B1, B2, B3);
296
406
      i_transform(B0, B1, B2, B3);
297
406
      SBoxD4(B0, B1, B2, B3);
298
406
      key_xor(4, B0, B1, B2, B3);
299
406
      i_transform(B0, B1, B2, B3);
300
406
      SBoxD3(B0, B1, B2, B3);
301
406
      key_xor(3, B0, B1, B2, B3);
302
406
      i_transform(B0, B1, B2, B3);
303
406
      SBoxD2(B0, B1, B2, B3);
304
406
      key_xor(2, B0, B1, B2, B3);
305
406
      i_transform(B0, B1, B2, B3);
306
406
      SBoxD1(B0, B1, B2, B3);
307
406
      key_xor(1, B0, B1, B2, B3);
308
406
      i_transform(B0, B1, B2, B3);
309
406
      SBoxD0(B0, B1, B2, B3);
310
406
      key_xor(0, B0, B1, B2, B3);
311
312
406
      store_le(out + 16 * i, B0, B1, B2, B3);
313
406
   }
314
411
}
315
316
2.41k
bool Serpent::has_keying_material() const {
317
2.41k
   return !m_round_key.empty();
318
2.41k
}
319
320
/*
321
* Serpent Key Schedule
322
*/
323
540
void Serpent::key_schedule(std::span<const uint8_t> key) {
324
540
   using namespace Botan::Serpent_F;
325
326
540
   const uint32_t PHI = 0x9E3779B9;
327
328
540
   secure_vector<uint32_t> W(140);
329
2.85k
   for(size_t i = 0; i != key.size() / 4; ++i) {
330
2.31k
      W[i] = load_le<uint32_t>(key.data(), i);
331
2.31k
   }
332
333
540
   W[key.size() / 4] |= uint32_t(1) << ((key.size() % 4) * 8);
334
335
71.8k
   for(size_t i = 8; i != 140; ++i) {
336
71.2k
      uint32_t wi = W[i - 8] ^ W[i - 5] ^ W[i - 3] ^ W[i - 1] ^ PHI ^ uint32_t(i - 8);
337
71.2k
      W[i] = rotl<11>(wi);
338
71.2k
   }
339
340
540
   SBoxE0(W[20], W[21], W[22], W[23]);
341
540
   SBoxE0(W[52], W[53], W[54], W[55]);
342
540
   SBoxE0(W[84], W[85], W[86], W[87]);
343
540
   SBoxE0(W[116], W[117], W[118], W[119]);
344
345
540
   SBoxE1(W[16], W[17], W[18], W[19]);
346
540
   SBoxE1(W[48], W[49], W[50], W[51]);
347
540
   SBoxE1(W[80], W[81], W[82], W[83]);
348
540
   SBoxE1(W[112], W[113], W[114], W[115]);
349
350
540
   SBoxE2(W[12], W[13], W[14], W[15]);
351
540
   SBoxE2(W[44], W[45], W[46], W[47]);
352
540
   SBoxE2(W[76], W[77], W[78], W[79]);
353
540
   SBoxE2(W[108], W[109], W[110], W[111]);
354
355
540
   SBoxE3(W[8], W[9], W[10], W[11]);
356
540
   SBoxE3(W[40], W[41], W[42], W[43]);
357
540
   SBoxE3(W[72], W[73], W[74], W[75]);
358
540
   SBoxE3(W[104], W[105], W[106], W[107]);
359
540
   SBoxE3(W[136], W[137], W[138], W[139]);
360
361
540
   SBoxE4(W[36], W[37], W[38], W[39]);
362
540
   SBoxE4(W[68], W[69], W[70], W[71]);
363
540
   SBoxE4(W[100], W[101], W[102], W[103]);
364
540
   SBoxE4(W[132], W[133], W[134], W[135]);
365
366
540
   SBoxE5(W[32], W[33], W[34], W[35]);
367
540
   SBoxE5(W[64], W[65], W[66], W[67]);
368
540
   SBoxE5(W[96], W[97], W[98], W[99]);
369
540
   SBoxE5(W[128], W[129], W[130], W[131]);
370
371
540
   SBoxE6(W[28], W[29], W[30], W[31]);
372
540
   SBoxE6(W[60], W[61], W[62], W[63]);
373
540
   SBoxE6(W[92], W[93], W[94], W[95]);
374
540
   SBoxE6(W[124], W[125], W[126], W[127]);
375
376
540
   SBoxE7(W[24], W[25], W[26], W[27]);
377
540
   SBoxE7(W[56], W[57], W[58], W[59]);
378
540
   SBoxE7(W[88], W[89], W[90], W[91]);
379
540
   SBoxE7(W[120], W[121], W[122], W[123]);
380
381
540
   m_round_key.assign(W.begin() + 8, W.end());
382
540
}
383
384
22
void Serpent::clear() {
385
22
   zap(m_round_key);
386
22
}
387
388
0
std::string Serpent::provider() const {
389
0
#if defined(BOTAN_HAS_SERPENT_AVX512)
390
0
   if(CPUID::has_avx512()) {
391
0
      return "avx512";
392
0
   }
393
0
#endif
394
395
0
#if defined(BOTAN_HAS_SERPENT_AVX2)
396
0
   if(CPUID::has_avx2()) {
397
0
      return "avx2";
398
0
   }
399
0
#endif
400
401
0
#if defined(BOTAN_HAS_SERPENT_SIMD)
402
0
   if(CPUID::has_simd_32()) {
403
0
      return "simd";
404
0
   }
405
0
#endif
406
407
0
   return "base";
408
0
}
409
410
}  // namespace Botan