8#include <botan/internal/serpent.h>
10#include <botan/internal/loadstor.h>
11#include <botan/internal/rotate.h>
12#include <botan/internal/serpent_sbox.h>
14#if defined(BOTAN_HAS_CPUID)
15 #include <botan/internal/cpuid.h>
28#if defined(BOTAN_HAS_SERPENT_AVX512)
31 avx512_encrypt_16(in, out);
39#if defined(BOTAN_HAS_SERPENT_AVX2)
42 avx2_encrypt_8(in, out);
50#if defined(BOTAN_HAS_SERPENT_SIMD)
53 simd_encrypt_4(in, out);
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);
67 key_xor(0, B0, B1, B2, B3);
70 key_xor(1, B0, B1, B2, B3);
73 key_xor(2, B0, B1, B2, B3);
76 key_xor(3, B0, B1, B2, B3);
79 key_xor(4, B0, B1, B2, B3);
82 key_xor(5, B0, B1, B2, B3);
85 key_xor(6, B0, B1, B2, B3);
88 key_xor(7, B0, B1, B2, B3);
91 key_xor(8, B0, B1, B2, B3);
94 key_xor(9, B0, B1, B2, B3);
97 key_xor(10, B0, B1, B2, B3);
100 key_xor(11, B0, B1, B2, B3);
103 key_xor(12, B0, B1, B2, B3);
106 key_xor(13, B0, B1, B2, B3);
109 key_xor(14, B0, B1, B2, B3);
112 key_xor(15, B0, B1, B2, B3);
115 key_xor(16, B0, B1, B2, B3);
118 key_xor(17, B0, B1, B2, B3);
121 key_xor(18, B0, B1, B2, B3);
124 key_xor(19, B0, B1, B2, B3);
127 key_xor(20, B0, B1, B2, B3);
130 key_xor(21, B0, B1, B2, B3);
133 key_xor(22, B0, B1, B2, B3);
136 key_xor(23, B0, B1, B2, B3);
139 key_xor(24, B0, B1, B2, B3);
142 key_xor(25, B0, B1, B2, B3);
145 key_xor(26, B0, B1, B2, B3);
148 key_xor(27, B0, B1, B2, B3);
151 key_xor(28, B0, B1, B2, B3);
154 key_xor(29, B0, B1, B2, B3);
157 key_xor(30, B0, B1, B2, B3);
160 key_xor(31, B0, B1, B2, B3);
162 key_xor(32, B0, B1, B2, B3);
164 store_le(out + 16 * i, B0, B1, B2, B3);
176#if defined(BOTAN_HAS_SERPENT_AVX512)
178 while(blocks >= 16) {
179 avx512_decrypt_16(in, out);
187#if defined(BOTAN_HAS_SERPENT_AVX2)
190 avx2_decrypt_8(in, out);
198#if defined(BOTAN_HAS_SERPENT_SIMD)
201 simd_decrypt_4(in, out);
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);
215 key_xor(32, B0, B1, B2, B3);
217 key_xor(31, B0, B1, B2, B3);
220 key_xor(30, B0, B1, B2, B3);
223 key_xor(29, B0, B1, B2, B3);
226 key_xor(28, B0, B1, B2, B3);
229 key_xor(27, B0, B1, B2, B3);
232 key_xor(26, B0, B1, B2, B3);
235 key_xor(25, B0, B1, B2, B3);
238 key_xor(24, B0, B1, B2, B3);
241 key_xor(23, B0, B1, B2, B3);
244 key_xor(22, B0, B1, B2, B3);
247 key_xor(21, B0, B1, B2, B3);
250 key_xor(20, B0, B1, B2, B3);
253 key_xor(19, B0, B1, B2, B3);
256 key_xor(18, B0, B1, B2, B3);
259 key_xor(17, B0, B1, B2, B3);
262 key_xor(16, B0, B1, B2, B3);
265 key_xor(15, B0, B1, B2, B3);
268 key_xor(14, B0, B1, B2, B3);
271 key_xor(13, B0, B1, B2, B3);
274 key_xor(12, B0, B1, B2, B3);
277 key_xor(11, B0, B1, B2, B3);
280 key_xor(10, B0, B1, B2, B3);
283 key_xor(9, B0, B1, B2, B3);
286 key_xor(8, B0, B1, B2, B3);
289 key_xor(7, B0, B1, B2, B3);
292 key_xor(6, B0, B1, B2, B3);
295 key_xor(5, B0, B1, B2, B3);
298 key_xor(4, B0, B1, B2, B3);
301 key_xor(3, B0, B1, B2, B3);
304 key_xor(2, B0, B1, B2, B3);
307 key_xor(1, B0, B1, B2, B3);
310 key_xor(0, B0, B1, B2, B3);
312 store_le(out + 16 * i, B0, B1, B2, B3);
317 return !m_round_key.empty();
323void Serpent::key_schedule(std::span<const uint8_t> key) {
326 const uint32_t PHI = 0x9E3779B9;
329 for(
size_t i = 0; i != key.size() / 4; ++i) {
333 W[key.size() / 4] |= uint32_t(1) << ((key.size() % 4) * 8);
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);
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]);
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]);
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]);
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]);
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]);
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]);
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]);
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]);
381 m_round_key.assign(W.begin() + 8, W.end());
389#if defined(BOTAN_HAS_SERPENT_AVX512)
395#if defined(BOTAN_HAS_SERPENT_AVX2)
401#if defined(BOTAN_HAS_SERPENT_SIMD)
static std::optional< std::string > check(CPUID::Feature feat)
static bool has(CPUID::Feature feat)
bool has_keying_material() const override
std::string provider() const override
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
void assert_key_material_set() const
BOTAN_FORCE_INLINE void transform(T &B0, T &B1, T &B2, T &B3)
BOTAN_FORCE_INLINE void SBoxD5(T &a, T &b, T &c, T &d)
BOTAN_FORCE_INLINE void SBoxD4(T &a, T &b, T &c, T &d)
BOTAN_FORCE_INLINE void SBoxE0(T &a, T &b, T &c, T &d)
BOTAN_FORCE_INLINE void SBoxE1(T &a, T &b, T &c, T &d)
BOTAN_FORCE_INLINE void SBoxE3(T &a, T &b, T &c, T &d)
BOTAN_FORCE_INLINE void SBoxD0(T &a, T &b, T &c, T &d)
BOTAN_FORCE_INLINE void SBoxE5(T &a, T &b, T &c, T &d)
BOTAN_FORCE_INLINE void SBoxD6(T &a, T &b, T &c, T &d)
BOTAN_FORCE_INLINE void SBoxD3(T &a, T &b, T &c, T &d)
BOTAN_FORCE_INLINE void i_transform(T &B0, T &B1, T &B2, T &B3)
BOTAN_FORCE_INLINE void SBoxD2(T &a, T &b, T &c, T &d)
BOTAN_FORCE_INLINE void SBoxE6(T &a, T &b, T &c, T &d)
BOTAN_FORCE_INLINE void SBoxE2(T &a, T &b, T &c, T &d)
BOTAN_FORCE_INLINE void SBoxE4(T &a, T &b, T &c, T &d)
BOTAN_FORCE_INLINE void SBoxD1(T &a, T &b, T &c, T &d)
BOTAN_FORCE_INLINE void SBoxE7(T &a, T &b, T &c, T &d)
BOTAN_FORCE_INLINE void SBoxD7(T &a, T &b, T &c, T &d)
void zap(std::vector< T, Alloc > &vec)
constexpr T rotl(T input)
constexpr auto store_le(ParamTs &&... params)
constexpr auto load_le(ParamTs &&... params)
std::vector< T, secure_allocator< T > > secure_vector