• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 21383948041

26 Jan 2026 10:31PM UTC coverage: 90.073% (-0.7%) from 90.741%
21383948041

push

github

web-flow
Merge pull request #5263 from randombit/jack/msvc-enable-bmi2

Enable BMI2 and GFNI codepaths for MSVC

102104 of 113357 relevant lines covered (90.07%)

11607465.43 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.85
/src/lib/block/serpent/serpent.cpp
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_CPUID)
15
   #include <botan/internal/cpuid.h>
16
#endif
17

18
namespace Botan {
19

20
/*
21
* Serpent Encryption
22
*/
23
void Serpent::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const {
24,686✔
24
   using namespace Botan::Serpent_F;
24,686✔
25

26
   assert_key_material_set();
24,686✔
27

28
#if defined(BOTAN_HAS_SERPENT_AVX512)
29
   if(CPUID::has(CPUID::Feature::AVX512)) {
18,392✔
30
      while(blocks >= 16) {
×
31
         avx512_encrypt_16(in, out);
×
32
         in += 16 * BLOCK_SIZE;
×
33
         out += 16 * BLOCK_SIZE;
×
34
         blocks -= 16;
×
35
      }
36
   }
37
#endif
38

39
#if defined(BOTAN_HAS_SERPENT_AVX2)
40
   if(CPUID::has(CPUID::Feature::AVX2)) {
18,392✔
41
      while(blocks >= 8) {
15,633✔
42
         avx2_encrypt_8(in, out);
3,523✔
43
         in += 8 * BLOCK_SIZE;
3,523✔
44
         out += 8 * BLOCK_SIZE;
3,523✔
45
         blocks -= 8;
3,523✔
46
      }
47
   }
48
#endif
49

50
#if defined(BOTAN_HAS_SERPENT_SIMD)
51
   if(CPUID::has(CPUID::Feature::SIMD_4X32)) {
36,784✔
52
      while(blocks >= 4) {
18,857✔
53
         simd_encrypt_4(in, out);
465✔
54
         in += 4 * BLOCK_SIZE;
465✔
55
         out += 4 * BLOCK_SIZE;
465✔
56
         blocks -= 4;
465✔
57
      }
58
   }
59
#endif
60

61
   const Key_Inserter key_xor(m_round_key.data());
18,392✔
62

63
   for(size_t i = 0; i < blocks; ++i) {
35,549✔
64
      uint32_t B0 = 0;
17,157✔
65
      uint32_t B1 = 0;
17,157✔
66
      uint32_t B2 = 0;
17,157✔
67
      uint32_t B3 = 0;
17,157✔
68
      load_le(in + 16 * i, B0, B1, B2, B3);
17,157✔
69

70
      key_xor(0, B0, B1, B2, B3);
17,157✔
71
      SBoxE0(B0, B1, B2, B3);
17,157✔
72
      transform(B0, B1, B2, B3);
17,157✔
73
      key_xor(1, B0, B1, B2, B3);
17,157✔
74
      SBoxE1(B0, B1, B2, B3);
17,157✔
75
      transform(B0, B1, B2, B3);
17,157✔
76
      key_xor(2, B0, B1, B2, B3);
17,157✔
77
      SBoxE2(B0, B1, B2, B3);
17,157✔
78
      transform(B0, B1, B2, B3);
17,157✔
79
      key_xor(3, B0, B1, B2, B3);
17,157✔
80
      SBoxE3(B0, B1, B2, B3);
17,157✔
81
      transform(B0, B1, B2, B3);
17,157✔
82
      key_xor(4, B0, B1, B2, B3);
17,157✔
83
      SBoxE4(B0, B1, B2, B3);
17,157✔
84
      transform(B0, B1, B2, B3);
17,157✔
85
      key_xor(5, B0, B1, B2, B3);
17,157✔
86
      SBoxE5(B0, B1, B2, B3);
17,157✔
87
      transform(B0, B1, B2, B3);
17,157✔
88
      key_xor(6, B0, B1, B2, B3);
17,157✔
89
      SBoxE6(B0, B1, B2, B3);
17,157✔
90
      transform(B0, B1, B2, B3);
17,157✔
91
      key_xor(7, B0, B1, B2, B3);
17,157✔
92
      SBoxE7(B0, B1, B2, B3);
17,157✔
93
      transform(B0, B1, B2, B3);
17,157✔
94
      key_xor(8, B0, B1, B2, B3);
17,157✔
95
      SBoxE0(B0, B1, B2, B3);
17,157✔
96
      transform(B0, B1, B2, B3);
17,157✔
97
      key_xor(9, B0, B1, B2, B3);
17,157✔
98
      SBoxE1(B0, B1, B2, B3);
17,157✔
99
      transform(B0, B1, B2, B3);
17,157✔
100
      key_xor(10, B0, B1, B2, B3);
17,157✔
101
      SBoxE2(B0, B1, B2, B3);
17,157✔
102
      transform(B0, B1, B2, B3);
17,157✔
103
      key_xor(11, B0, B1, B2, B3);
17,157✔
104
      SBoxE3(B0, B1, B2, B3);
17,157✔
105
      transform(B0, B1, B2, B3);
17,157✔
106
      key_xor(12, B0, B1, B2, B3);
17,157✔
107
      SBoxE4(B0, B1, B2, B3);
17,157✔
108
      transform(B0, B1, B2, B3);
17,157✔
109
      key_xor(13, B0, B1, B2, B3);
17,157✔
110
      SBoxE5(B0, B1, B2, B3);
17,157✔
111
      transform(B0, B1, B2, B3);
17,157✔
112
      key_xor(14, B0, B1, B2, B3);
17,157✔
113
      SBoxE6(B0, B1, B2, B3);
17,157✔
114
      transform(B0, B1, B2, B3);
17,157✔
115
      key_xor(15, B0, B1, B2, B3);
17,157✔
116
      SBoxE7(B0, B1, B2, B3);
17,157✔
117
      transform(B0, B1, B2, B3);
17,157✔
118
      key_xor(16, B0, B1, B2, B3);
17,157✔
119
      SBoxE0(B0, B1, B2, B3);
17,157✔
120
      transform(B0, B1, B2, B3);
17,157✔
121
      key_xor(17, B0, B1, B2, B3);
17,157✔
122
      SBoxE1(B0, B1, B2, B3);
17,157✔
123
      transform(B0, B1, B2, B3);
17,157✔
124
      key_xor(18, B0, B1, B2, B3);
17,157✔
125
      SBoxE2(B0, B1, B2, B3);
17,157✔
126
      transform(B0, B1, B2, B3);
17,157✔
127
      key_xor(19, B0, B1, B2, B3);
17,157✔
128
      SBoxE3(B0, B1, B2, B3);
17,157✔
129
      transform(B0, B1, B2, B3);
17,157✔
130
      key_xor(20, B0, B1, B2, B3);
17,157✔
131
      SBoxE4(B0, B1, B2, B3);
17,157✔
132
      transform(B0, B1, B2, B3);
17,157✔
133
      key_xor(21, B0, B1, B2, B3);
17,157✔
134
      SBoxE5(B0, B1, B2, B3);
17,157✔
135
      transform(B0, B1, B2, B3);
17,157✔
136
      key_xor(22, B0, B1, B2, B3);
17,157✔
137
      SBoxE6(B0, B1, B2, B3);
17,157✔
138
      transform(B0, B1, B2, B3);
17,157✔
139
      key_xor(23, B0, B1, B2, B3);
17,157✔
140
      SBoxE7(B0, B1, B2, B3);
17,157✔
141
      transform(B0, B1, B2, B3);
17,157✔
142
      key_xor(24, B0, B1, B2, B3);
17,157✔
143
      SBoxE0(B0, B1, B2, B3);
17,157✔
144
      transform(B0, B1, B2, B3);
17,157✔
145
      key_xor(25, B0, B1, B2, B3);
17,157✔
146
      SBoxE1(B0, B1, B2, B3);
17,157✔
147
      transform(B0, B1, B2, B3);
17,157✔
148
      key_xor(26, B0, B1, B2, B3);
17,157✔
149
      SBoxE2(B0, B1, B2, B3);
17,157✔
150
      transform(B0, B1, B2, B3);
17,157✔
151
      key_xor(27, B0, B1, B2, B3);
17,157✔
152
      SBoxE3(B0, B1, B2, B3);
17,157✔
153
      transform(B0, B1, B2, B3);
17,157✔
154
      key_xor(28, B0, B1, B2, B3);
17,157✔
155
      SBoxE4(B0, B1, B2, B3);
17,157✔
156
      transform(B0, B1, B2, B3);
17,157✔
157
      key_xor(29, B0, B1, B2, B3);
17,157✔
158
      SBoxE5(B0, B1, B2, B3);
17,157✔
159
      transform(B0, B1, B2, B3);
17,157✔
160
      key_xor(30, B0, B1, B2, B3);
17,157✔
161
      SBoxE6(B0, B1, B2, B3);
17,157✔
162
      transform(B0, B1, B2, B3);
17,157✔
163
      key_xor(31, B0, B1, B2, B3);
17,157✔
164
      SBoxE7(B0, B1, B2, B3);
17,157✔
165
      key_xor(32, B0, B1, B2, B3);
17,157✔
166

167
      store_le(out + 16 * i, B0, B1, B2, B3);
17,157✔
168
   }
169
}
18,392✔
170

171
/*
172
* Serpent Decryption
173
*/
174
void Serpent::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const {
17,128✔
175
   using namespace Botan::Serpent_F;
17,128✔
176

177
   assert_key_material_set();
17,128✔
178

179
#if defined(BOTAN_HAS_SERPENT_AVX512)
180
   if(CPUID::has(CPUID::Feature::AVX512)) {
10,846✔
181
      while(blocks >= 16) {
×
182
         avx512_decrypt_16(in, out);
×
183
         in += 16 * BLOCK_SIZE;
×
184
         out += 16 * BLOCK_SIZE;
×
185
         blocks -= 16;
×
186
      }
187
   }
188
#endif
189

190
#if defined(BOTAN_HAS_SERPENT_AVX2)
191
   if(CPUID::has(CPUID::Feature::AVX2)) {
10,846✔
192
      while(blocks >= 8) {
7,071✔
193
         avx2_decrypt_8(in, out);
413✔
194
         in += 8 * BLOCK_SIZE;
413✔
195
         out += 8 * BLOCK_SIZE;
413✔
196
         blocks -= 8;
413✔
197
      }
198
   }
199
#endif
200

201
#if defined(BOTAN_HAS_SERPENT_SIMD)
202
   if(CPUID::has(CPUID::Feature::SIMD_4X32)) {
10,846✔
203
      while(blocks >= 4) {
11,311✔
204
         simd_decrypt_4(in, out);
465✔
205
         in += 4 * BLOCK_SIZE;
465✔
206
         out += 4 * BLOCK_SIZE;
465✔
207
         blocks -= 4;
465✔
208
      }
209
   }
210
#endif
211

212
   const Key_Inserter key_xor(m_round_key.data());
10,846✔
213

214
   for(size_t i = 0; i < blocks; ++i) {
22,012✔
215
      uint32_t B0 = 0;
11,166✔
216
      uint32_t B1 = 0;
11,166✔
217
      uint32_t B2 = 0;
11,166✔
218
      uint32_t B3 = 0;
11,166✔
219
      load_le(in + 16 * i, B0, B1, B2, B3);
11,166✔
220

221
      key_xor(32, B0, B1, B2, B3);
11,166✔
222
      SBoxD7(B0, B1, B2, B3);
11,166✔
223
      key_xor(31, B0, B1, B2, B3);
11,166✔
224
      i_transform(B0, B1, B2, B3);
11,166✔
225
      SBoxD6(B0, B1, B2, B3);
11,166✔
226
      key_xor(30, B0, B1, B2, B3);
11,166✔
227
      i_transform(B0, B1, B2, B3);
11,166✔
228
      SBoxD5(B0, B1, B2, B3);
11,166✔
229
      key_xor(29, B0, B1, B2, B3);
11,166✔
230
      i_transform(B0, B1, B2, B3);
11,166✔
231
      SBoxD4(B0, B1, B2, B3);
11,166✔
232
      key_xor(28, B0, B1, B2, B3);
11,166✔
233
      i_transform(B0, B1, B2, B3);
11,166✔
234
      SBoxD3(B0, B1, B2, B3);
11,166✔
235
      key_xor(27, B0, B1, B2, B3);
11,166✔
236
      i_transform(B0, B1, B2, B3);
11,166✔
237
      SBoxD2(B0, B1, B2, B3);
11,166✔
238
      key_xor(26, B0, B1, B2, B3);
11,166✔
239
      i_transform(B0, B1, B2, B3);
11,166✔
240
      SBoxD1(B0, B1, B2, B3);
11,166✔
241
      key_xor(25, B0, B1, B2, B3);
11,166✔
242
      i_transform(B0, B1, B2, B3);
11,166✔
243
      SBoxD0(B0, B1, B2, B3);
11,166✔
244
      key_xor(24, B0, B1, B2, B3);
11,166✔
245
      i_transform(B0, B1, B2, B3);
11,166✔
246
      SBoxD7(B0, B1, B2, B3);
11,166✔
247
      key_xor(23, B0, B1, B2, B3);
11,166✔
248
      i_transform(B0, B1, B2, B3);
11,166✔
249
      SBoxD6(B0, B1, B2, B3);
11,166✔
250
      key_xor(22, B0, B1, B2, B3);
11,166✔
251
      i_transform(B0, B1, B2, B3);
11,166✔
252
      SBoxD5(B0, B1, B2, B3);
11,166✔
253
      key_xor(21, B0, B1, B2, B3);
11,166✔
254
      i_transform(B0, B1, B2, B3);
11,166✔
255
      SBoxD4(B0, B1, B2, B3);
11,166✔
256
      key_xor(20, B0, B1, B2, B3);
11,166✔
257
      i_transform(B0, B1, B2, B3);
11,166✔
258
      SBoxD3(B0, B1, B2, B3);
11,166✔
259
      key_xor(19, B0, B1, B2, B3);
11,166✔
260
      i_transform(B0, B1, B2, B3);
11,166✔
261
      SBoxD2(B0, B1, B2, B3);
11,166✔
262
      key_xor(18, B0, B1, B2, B3);
11,166✔
263
      i_transform(B0, B1, B2, B3);
11,166✔
264
      SBoxD1(B0, B1, B2, B3);
11,166✔
265
      key_xor(17, B0, B1, B2, B3);
11,166✔
266
      i_transform(B0, B1, B2, B3);
11,166✔
267
      SBoxD0(B0, B1, B2, B3);
11,166✔
268
      key_xor(16, B0, B1, B2, B3);
11,166✔
269
      i_transform(B0, B1, B2, B3);
11,166✔
270
      SBoxD7(B0, B1, B2, B3);
11,166✔
271
      key_xor(15, B0, B1, B2, B3);
11,166✔
272
      i_transform(B0, B1, B2, B3);
11,166✔
273
      SBoxD6(B0, B1, B2, B3);
11,166✔
274
      key_xor(14, B0, B1, B2, B3);
11,166✔
275
      i_transform(B0, B1, B2, B3);
11,166✔
276
      SBoxD5(B0, B1, B2, B3);
11,166✔
277
      key_xor(13, B0, B1, B2, B3);
11,166✔
278
      i_transform(B0, B1, B2, B3);
11,166✔
279
      SBoxD4(B0, B1, B2, B3);
11,166✔
280
      key_xor(12, B0, B1, B2, B3);
11,166✔
281
      i_transform(B0, B1, B2, B3);
11,166✔
282
      SBoxD3(B0, B1, B2, B3);
11,166✔
283
      key_xor(11, B0, B1, B2, B3);
11,166✔
284
      i_transform(B0, B1, B2, B3);
11,166✔
285
      SBoxD2(B0, B1, B2, B3);
11,166✔
286
      key_xor(10, B0, B1, B2, B3);
11,166✔
287
      i_transform(B0, B1, B2, B3);
11,166✔
288
      SBoxD1(B0, B1, B2, B3);
11,166✔
289
      key_xor(9, B0, B1, B2, B3);
11,166✔
290
      i_transform(B0, B1, B2, B3);
11,166✔
291
      SBoxD0(B0, B1, B2, B3);
11,166✔
292
      key_xor(8, B0, B1, B2, B3);
11,166✔
293
      i_transform(B0, B1, B2, B3);
11,166✔
294
      SBoxD7(B0, B1, B2, B3);
11,166✔
295
      key_xor(7, B0, B1, B2, B3);
11,166✔
296
      i_transform(B0, B1, B2, B3);
11,166✔
297
      SBoxD6(B0, B1, B2, B3);
11,166✔
298
      key_xor(6, B0, B1, B2, B3);
11,166✔
299
      i_transform(B0, B1, B2, B3);
11,166✔
300
      SBoxD5(B0, B1, B2, B3);
11,166✔
301
      key_xor(5, B0, B1, B2, B3);
11,166✔
302
      i_transform(B0, B1, B2, B3);
11,166✔
303
      SBoxD4(B0, B1, B2, B3);
11,166✔
304
      key_xor(4, B0, B1, B2, B3);
11,166✔
305
      i_transform(B0, B1, B2, B3);
11,166✔
306
      SBoxD3(B0, B1, B2, B3);
11,166✔
307
      key_xor(3, B0, B1, B2, B3);
11,166✔
308
      i_transform(B0, B1, B2, B3);
11,166✔
309
      SBoxD2(B0, B1, B2, B3);
11,166✔
310
      key_xor(2, B0, B1, B2, B3);
11,166✔
311
      i_transform(B0, B1, B2, B3);
11,166✔
312
      SBoxD1(B0, B1, B2, B3);
11,166✔
313
      key_xor(1, B0, B1, B2, B3);
11,166✔
314
      i_transform(B0, B1, B2, B3);
11,166✔
315
      SBoxD0(B0, B1, B2, B3);
11,166✔
316
      key_xor(0, B0, B1, B2, B3);
11,166✔
317

318
      store_le(out + 16 * i, B0, B1, B2, B3);
11,166✔
319
   }
320
}
10,846✔
321

322
bool Serpent::has_keying_material() const {
60,093✔
323
   return !m_round_key.empty();
60,093✔
324
}
325

326
/*
327
* Serpent Key Schedule
328
*/
329
void Serpent::key_schedule(std::span<const uint8_t> key) {
12,064✔
330
   using namespace Botan::Serpent_F;
12,064✔
331

332
   const uint32_t PHI = 0x9E3779B9;
12,064✔
333

334
   secure_vector<uint32_t> W(140);
12,064✔
335
   for(size_t i = 0; i != key.size() / 4; ++i) {
103,418✔
336
      W[i] = load_le<uint32_t>(key.data(), i);
91,354✔
337
   }
338

339
   W[key.size() / 4] |= uint32_t(1) << ((key.size() % 4) * 8);
12,064✔
340

341
   for(size_t i = 8; i != 140; ++i) {
1,604,512✔
342
      const uint32_t wi = W[i - 8] ^ W[i - 5] ^ W[i - 3] ^ W[i - 1] ^ PHI ^ uint32_t(i - 8);
1,592,448✔
343
      W[i] = rotl<11>(wi);
1,592,448✔
344
   }
345

346
   SBoxE0(W[20], W[21], W[22], W[23]);
12,064✔
347
   SBoxE0(W[52], W[53], W[54], W[55]);
12,064✔
348
   SBoxE0(W[84], W[85], W[86], W[87]);
12,064✔
349
   SBoxE0(W[116], W[117], W[118], W[119]);
12,064✔
350

351
   SBoxE1(W[16], W[17], W[18], W[19]);
12,064✔
352
   SBoxE1(W[48], W[49], W[50], W[51]);
12,064✔
353
   SBoxE1(W[80], W[81], W[82], W[83]);
12,064✔
354
   SBoxE1(W[112], W[113], W[114], W[115]);
12,064✔
355

356
   SBoxE2(W[12], W[13], W[14], W[15]);
12,064✔
357
   SBoxE2(W[44], W[45], W[46], W[47]);
12,064✔
358
   SBoxE2(W[76], W[77], W[78], W[79]);
12,064✔
359
   SBoxE2(W[108], W[109], W[110], W[111]);
12,064✔
360

361
   SBoxE3(W[8], W[9], W[10], W[11]);
12,064✔
362
   SBoxE3(W[40], W[41], W[42], W[43]);
12,064✔
363
   SBoxE3(W[72], W[73], W[74], W[75]);
12,064✔
364
   SBoxE3(W[104], W[105], W[106], W[107]);
12,064✔
365
   SBoxE3(W[136], W[137], W[138], W[139]);
12,064✔
366

367
   SBoxE4(W[36], W[37], W[38], W[39]);
12,064✔
368
   SBoxE4(W[68], W[69], W[70], W[71]);
12,064✔
369
   SBoxE4(W[100], W[101], W[102], W[103]);
12,064✔
370
   SBoxE4(W[132], W[133], W[134], W[135]);
12,064✔
371

372
   SBoxE5(W[32], W[33], W[34], W[35]);
12,064✔
373
   SBoxE5(W[64], W[65], W[66], W[67]);
12,064✔
374
   SBoxE5(W[96], W[97], W[98], W[99]);
12,064✔
375
   SBoxE5(W[128], W[129], W[130], W[131]);
12,064✔
376

377
   SBoxE6(W[28], W[29], W[30], W[31]);
12,064✔
378
   SBoxE6(W[60], W[61], W[62], W[63]);
12,064✔
379
   SBoxE6(W[92], W[93], W[94], W[95]);
12,064✔
380
   SBoxE6(W[124], W[125], W[126], W[127]);
12,064✔
381

382
   SBoxE7(W[24], W[25], W[26], W[27]);
12,064✔
383
   SBoxE7(W[56], W[57], W[58], W[59]);
12,064✔
384
   SBoxE7(W[88], W[89], W[90], W[91]);
12,064✔
385
   SBoxE7(W[120], W[121], W[122], W[123]);
12,064✔
386

387
   m_round_key.assign(W.begin() + 8, W.end());
12,064✔
388
}
12,064✔
389

390
void Serpent::clear() {
7,437✔
391
   zap(m_round_key);
7,437✔
392
}
7,437✔
393

394
std::string Serpent::provider() const {
3,141✔
395
#if defined(BOTAN_HAS_SERPENT_AVX512)
396
   if(auto feat = CPUID::check(CPUID::Feature::AVX512)) {
3,141✔
397
      return *feat;
×
398
   }
×
399
#endif
400

401
#if defined(BOTAN_HAS_SERPENT_AVX2)
402
   if(auto feat = CPUID::check(CPUID::Feature::AVX2)) {
3,141✔
403
      return *feat;
2,094✔
404
   }
1,047✔
405
#endif
406

407
#if defined(BOTAN_HAS_SERPENT_SIMD)
408
   if(auto feat = CPUID::check(CPUID::Feature::SIMD_4X32)) {
2,094✔
409
      return *feat;
4,188✔
410
   }
2,094✔
411
#endif
412

413
   return "base";
×
414
}
415

416
}  // namespace Botan
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc