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