1 /*
2 * (C) 2018 Jack Lloyd
3 *
4 * Botan is released under the Simplified BSD License (see license.txt)
5 */
6 
7 #include <botan/serpent.h>
8 #include <botan/internal/serpent_sbox.h>
9 #include <botan/internal/simd_avx2.h>
10 
11 namespace Botan {
12 
13 
14 #define key_xor(round, B0, B1, B2, B3)                             \
15    do {                                                            \
16       B0 ^= SIMD_8x32::splat(m_round_key[4*round  ]);              \
17       B1 ^= SIMD_8x32::splat(m_round_key[4*round+1]);              \
18       B2 ^= SIMD_8x32::splat(m_round_key[4*round+2]);              \
19       B3 ^= SIMD_8x32::splat(m_round_key[4*round+3]);              \
20    } while(0)
21 
22 /*
23 * Serpent's linear transformations
24 */
25 #define transform(B0, B1, B2, B3)                                  \
26    do {                                                            \
27       B0 = B0.rotl<13>();                                          \
28       B2 = B2.rotl<3>();                                           \
29       B1 ^= B0 ^ B2;                                               \
30       B3 ^= B2 ^ B0.shl<3>();                                      \
31       B1 = B1.rotl<1>();                                           \
32       B3 = B3.rotl<7>();                                           \
33       B0 ^= B1 ^ B3;                                               \
34       B2 ^= B3 ^ B1.shl<7>();                                      \
35       B0 = B0.rotl<5>();                                           \
36       B2 = B2.rotl<22>();                                          \
37    } while(0)
38 
39 #define i_transform(B0, B1, B2, B3)                                \
40    do {                                                            \
41       B2 = B2.rotr<22>();                                          \
42       B0 = B0.rotr<5>();                                           \
43       B2 ^= B3 ^ B1.shl<7>();                                      \
44       B0 ^= B1 ^ B3;                                               \
45       B3 = B3.rotr<7>();                                           \
46       B1 = B1.rotr<1>();                                           \
47       B3 ^= B2 ^ B0.shl<3>();                                      \
48       B1 ^= B0 ^ B2;                                               \
49       B2 = B2.rotr<3>();                                           \
50       B0 = B0.rotr<13>();                                          \
51    } while(0)
52 
53 BOTAN_FUNC_ISA("avx2")
avx2_encrypt_8(const uint8_t in[128],uint8_t out[128]) const54 void Serpent::avx2_encrypt_8(const uint8_t in[128], uint8_t out[128]) const
55    {
56    SIMD_8x32::reset_registers();
57 
58    SIMD_8x32 B0 = SIMD_8x32::load_le(in);
59    SIMD_8x32 B1 = SIMD_8x32::load_le(in + 32);
60    SIMD_8x32 B2 = SIMD_8x32::load_le(in + 64);
61    SIMD_8x32 B3 = SIMD_8x32::load_le(in + 96);
62 
63    SIMD_8x32::transpose(B0, B1, B2, B3);
64 
65    key_xor( 0,B0,B1,B2,B3); SBoxE0(B0,B1,B2,B3); transform(B0,B1,B2,B3);
66    key_xor( 1,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3);
67    key_xor( 2,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3);
68    key_xor( 3,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3);
69    key_xor( 4,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3);
70    key_xor( 5,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3);
71    key_xor( 6,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3);
72    key_xor( 7,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3);
73    key_xor( 8,B0,B1,B2,B3); SBoxE0(B0,B1,B2,B3); transform(B0,B1,B2,B3);
74    key_xor( 9,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3);
75    key_xor(10,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3);
76    key_xor(11,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3);
77    key_xor(12,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3);
78    key_xor(13,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3);
79    key_xor(14,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3);
80    key_xor(15,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3);
81    key_xor(16,B0,B1,B2,B3); SBoxE0(B0,B1,B2,B3); transform(B0,B1,B2,B3);
82    key_xor(17,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3);
83    key_xor(18,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3);
84    key_xor(19,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3);
85    key_xor(20,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3);
86    key_xor(21,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3);
87    key_xor(22,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3);
88    key_xor(23,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); transform(B0,B1,B2,B3);
89    key_xor(24,B0,B1,B2,B3); SBoxE0(B0,B1,B2,B3); transform(B0,B1,B2,B3);
90    key_xor(25,B0,B1,B2,B3); SBoxE1(B0,B1,B2,B3); transform(B0,B1,B2,B3);
91    key_xor(26,B0,B1,B2,B3); SBoxE2(B0,B1,B2,B3); transform(B0,B1,B2,B3);
92    key_xor(27,B0,B1,B2,B3); SBoxE3(B0,B1,B2,B3); transform(B0,B1,B2,B3);
93    key_xor(28,B0,B1,B2,B3); SBoxE4(B0,B1,B2,B3); transform(B0,B1,B2,B3);
94    key_xor(29,B0,B1,B2,B3); SBoxE5(B0,B1,B2,B3); transform(B0,B1,B2,B3);
95    key_xor(30,B0,B1,B2,B3); SBoxE6(B0,B1,B2,B3); transform(B0,B1,B2,B3);
96    key_xor(31,B0,B1,B2,B3); SBoxE7(B0,B1,B2,B3); key_xor(32,B0,B1,B2,B3);
97 
98    SIMD_8x32::transpose(B0, B1, B2, B3);
99    B0.store_le(out);
100    B1.store_le(out + 32);
101    B2.store_le(out + 64);
102    B3.store_le(out + 96);
103 
104    SIMD_8x32::zero_registers();
105    }
106 
107 BOTAN_FUNC_ISA("avx2")
avx2_decrypt_8(const uint8_t in[128],uint8_t out[128]) const108 void Serpent::avx2_decrypt_8(const uint8_t in[128], uint8_t out[128]) const
109    {
110    SIMD_8x32::reset_registers();
111 
112    SIMD_8x32 B0 = SIMD_8x32::load_le(in);
113    SIMD_8x32 B1 = SIMD_8x32::load_le(in + 32);
114    SIMD_8x32 B2 = SIMD_8x32::load_le(in + 64);
115    SIMD_8x32 B3 = SIMD_8x32::load_le(in + 96);
116 
117    SIMD_8x32::transpose(B0, B1, B2, B3);
118 
119    key_xor(32,B0,B1,B2,B3);  SBoxD7(B0,B1,B2,B3); key_xor(31,B0,B1,B2,B3);
120    i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(30,B0,B1,B2,B3);
121    i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(29,B0,B1,B2,B3);
122    i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(28,B0,B1,B2,B3);
123    i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(27,B0,B1,B2,B3);
124    i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor(26,B0,B1,B2,B3);
125    i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor(25,B0,B1,B2,B3);
126    i_transform(B0,B1,B2,B3); SBoxD0(B0,B1,B2,B3); key_xor(24,B0,B1,B2,B3);
127 
128    i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(23,B0,B1,B2,B3);
129    i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(22,B0,B1,B2,B3);
130    i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(21,B0,B1,B2,B3);
131    i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(20,B0,B1,B2,B3);
132    i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(19,B0,B1,B2,B3);
133    i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor(18,B0,B1,B2,B3);
134    i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor(17,B0,B1,B2,B3);
135    i_transform(B0,B1,B2,B3); SBoxD0(B0,B1,B2,B3); key_xor(16,B0,B1,B2,B3);
136 
137    i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor(15,B0,B1,B2,B3);
138    i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor(14,B0,B1,B2,B3);
139    i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor(13,B0,B1,B2,B3);
140    i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor(12,B0,B1,B2,B3);
141    i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor(11,B0,B1,B2,B3);
142    i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor(10,B0,B1,B2,B3);
143    i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor( 9,B0,B1,B2,B3);
144    i_transform(B0,B1,B2,B3); SBoxD0(B0,B1,B2,B3); key_xor( 8,B0,B1,B2,B3);
145 
146    i_transform(B0,B1,B2,B3); SBoxD7(B0,B1,B2,B3); key_xor( 7,B0,B1,B2,B3);
147    i_transform(B0,B1,B2,B3); SBoxD6(B0,B1,B2,B3); key_xor( 6,B0,B1,B2,B3);
148    i_transform(B0,B1,B2,B3); SBoxD5(B0,B1,B2,B3); key_xor( 5,B0,B1,B2,B3);
149    i_transform(B0,B1,B2,B3); SBoxD4(B0,B1,B2,B3); key_xor( 4,B0,B1,B2,B3);
150    i_transform(B0,B1,B2,B3); SBoxD3(B0,B1,B2,B3); key_xor( 3,B0,B1,B2,B3);
151    i_transform(B0,B1,B2,B3); SBoxD2(B0,B1,B2,B3); key_xor( 2,B0,B1,B2,B3);
152    i_transform(B0,B1,B2,B3); SBoxD1(B0,B1,B2,B3); key_xor( 1,B0,B1,B2,B3);
153    i_transform(B0,B1,B2,B3); SBoxD0(B0,B1,B2,B3); key_xor( 0,B0,B1,B2,B3);
154 
155    SIMD_8x32::transpose(B0, B1, B2, B3);
156 
157    B0.store_le(out);
158    B1.store_le(out + 32);
159    B2.store_le(out + 64);
160    B3.store_le(out + 96);
161 
162    SIMD_8x32::zero_registers();
163    }
164 
165 #undef key_xor
166 #undef transform
167 #undef i_transform
168 
169 }
170