Botan 3.11.1
Crypto and TLS for C&
seed.cpp
Go to the documentation of this file.
1/*
2* SEED
3* (C) 1999-2007,2020 Jack Lloyd
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#include <botan/internal/seed.h>
9
10#include <botan/internal/loadstor.h>
11#include <botan/internal/prefetch.h>
12
13#if defined(BOTAN_HAS_CPUID)
14 #include <botan/internal/cpuid.h>
15#endif
16
17namespace Botan {
18
19namespace {
20
21alignas(256) const uint8_t SEED_S0[256] = {
22 0xA9, 0x85, 0xD6, 0xD3, 0x54, 0x1D, 0xAC, 0x25, 0x5D, 0x43, 0x18, 0x1E, 0x51, 0xFC, 0xCA, 0x63, 0x28, 0x44, 0x20,
23 0x9D, 0xE0, 0xE2, 0xC8, 0x17, 0xA5, 0x8F, 0x03, 0x7B, 0xBB, 0x13, 0xD2, 0xEE, 0x70, 0x8C, 0x3F, 0xA8, 0x32, 0xDD,
24 0xF6, 0x74, 0xEC, 0x95, 0x0B, 0x57, 0x5C, 0x5B, 0xBD, 0x01, 0x24, 0x1C, 0x73, 0x98, 0x10, 0xCC, 0xF2, 0xD9, 0x2C,
25 0xE7, 0x72, 0x83, 0x9B, 0xD1, 0x86, 0xC9, 0x60, 0x50, 0xA3, 0xEB, 0x0D, 0xB6, 0x9E, 0x4F, 0xB7, 0x5A, 0xC6, 0x78,
26 0xA6, 0x12, 0xAF, 0xD5, 0x61, 0xC3, 0xB4, 0x41, 0x52, 0x7D, 0x8D, 0x08, 0x1F, 0x99, 0x00, 0x19, 0x04, 0x53, 0xF7,
27 0xE1, 0xFD, 0x76, 0x2F, 0x27, 0xB0, 0x8B, 0x0E, 0xAB, 0xA2, 0x6E, 0x93, 0x4D, 0x69, 0x7C, 0x09, 0x0A, 0xBF, 0xEF,
28 0xF3, 0xC5, 0x87, 0x14, 0xFE, 0x64, 0xDE, 0x2E, 0x4B, 0x1A, 0x06, 0x21, 0x6B, 0x66, 0x02, 0xF5, 0x92, 0x8A, 0x0C,
29 0xB3, 0x7E, 0xD0, 0x7A, 0x47, 0x96, 0xE5, 0x26, 0x80, 0xAD, 0xDF, 0xA1, 0x30, 0x37, 0xAE, 0x36, 0x15, 0x22, 0x38,
30 0xF4, 0xA7, 0x45, 0x4C, 0x81, 0xE9, 0x84, 0x97, 0x35, 0xCB, 0xCE, 0x3C, 0x71, 0x11, 0xC7, 0x89, 0x75, 0xFB, 0xDA,
31 0xF8, 0x94, 0x59, 0x82, 0xC4, 0xFF, 0x49, 0x39, 0x67, 0xC0, 0xCF, 0xD7, 0xB8, 0x0F, 0x8E, 0x42, 0x23, 0x91, 0x6C,
32 0xDB, 0xA4, 0x34, 0xF1, 0x48, 0xC2, 0x6F, 0x3D, 0x2D, 0x40, 0xBE, 0x3E, 0xBC, 0xC1, 0xAA, 0xBA, 0x4E, 0x55, 0x3B,
33 0xDC, 0x68, 0x7F, 0x9C, 0xD8, 0x4A, 0x56, 0x77, 0xA0, 0xED, 0x46, 0xB5, 0x2B, 0x65, 0xFA, 0xE3, 0xB9, 0xB1, 0x9F,
34 0x5E, 0xF9, 0xE6, 0xB2, 0x31, 0xEA, 0x6D, 0x5F, 0xE4, 0xF0, 0xCD, 0x88, 0x16, 0x3A, 0x58, 0xD4, 0x62, 0x29, 0x07,
35 0x33, 0xE8, 0x1B, 0x05, 0x79, 0x90, 0x6A, 0x2A, 0x9A,
36};
37
38alignas(256) const uint8_t SEED_S1[256] = {
39 0x38, 0xE8, 0x2D, 0xA6, 0xCF, 0xDE, 0xB3, 0xB8, 0xAF, 0x60, 0x55, 0xC7, 0x44, 0x6F, 0x6B, 0x5B, 0xC3, 0x62, 0x33,
40 0xB5, 0x29, 0xA0, 0xE2, 0xA7, 0xD3, 0x91, 0x11, 0x06, 0x1C, 0xBC, 0x36, 0x4B, 0xEF, 0x88, 0x6C, 0xA8, 0x17, 0xC4,
41 0x16, 0xF4, 0xC2, 0x45, 0xE1, 0xD6, 0x3F, 0x3D, 0x8E, 0x98, 0x28, 0x4E, 0xF6, 0x3E, 0xA5, 0xF9, 0x0D, 0xDF, 0xD8,
42 0x2B, 0x66, 0x7A, 0x27, 0x2F, 0xF1, 0x72, 0x42, 0xD4, 0x41, 0xC0, 0x73, 0x67, 0xAC, 0x8B, 0xF7, 0xAD, 0x80, 0x1F,
43 0xCA, 0x2C, 0xAA, 0x34, 0xD2, 0x0B, 0xEE, 0xE9, 0x5D, 0x94, 0x18, 0xF8, 0x57, 0xAE, 0x08, 0xC5, 0x13, 0xCD, 0x86,
44 0xB9, 0xFF, 0x7D, 0xC1, 0x31, 0xF5, 0x8A, 0x6A, 0xB1, 0xD1, 0x20, 0xD7, 0x02, 0x22, 0x04, 0x68, 0x71, 0x07, 0xDB,
45 0x9D, 0x99, 0x61, 0xBE, 0xE6, 0x59, 0xDD, 0x51, 0x90, 0xDC, 0x9A, 0xA3, 0xAB, 0xD0, 0x81, 0x0F, 0x47, 0x1A, 0xE3,
46 0xEC, 0x8D, 0xBF, 0x96, 0x7B, 0x5C, 0xA2, 0xA1, 0x63, 0x23, 0x4D, 0xC8, 0x9E, 0x9C, 0x3A, 0x0C, 0x2E, 0xBA, 0x6E,
47 0x9F, 0x5A, 0xF2, 0x92, 0xF3, 0x49, 0x78, 0xCC, 0x15, 0xFB, 0x70, 0x75, 0x7F, 0x35, 0x10, 0x03, 0x64, 0x6D, 0xC6,
48 0x74, 0xD5, 0xB4, 0xEA, 0x09, 0x76, 0x19, 0xFE, 0x40, 0x12, 0xE0, 0xBD, 0x05, 0xFA, 0x01, 0xF0, 0x2A, 0x5E, 0xA9,
49 0x56, 0x43, 0x85, 0x14, 0x89, 0x9B, 0xB0, 0xE5, 0x48, 0x79, 0x97, 0xFC, 0x1E, 0x82, 0x21, 0x8C, 0x1B, 0x5F, 0x77,
50 0x54, 0xB2, 0x1D, 0x25, 0x4F, 0x00, 0x46, 0xED, 0x58, 0x52, 0xEB, 0x7E, 0xDA, 0xC9, 0xFD, 0x30, 0x95, 0x65, 0x3C,
51 0xB6, 0xE4, 0xBB, 0x7C, 0x0E, 0x50, 0x39, 0x26, 0x32, 0x84, 0x69, 0x93, 0x37, 0xE7, 0x24, 0xA4, 0xCB, 0x53, 0x0A,
52 0x87, 0xD9, 0x4C, 0x83, 0x8F, 0xCE, 0x3B, 0x4A, 0xB7,
53};
54
55/*
56* SEED G Function
57*/
58BOTAN_FORCE_INLINE uint32_t SEED_G(uint32_t X) {
59 const uint32_t M = 0x01010101;
60 const uint32_t s0 = M * SEED_S0[get_byte<3>(X)];
61 const uint32_t s1 = M * SEED_S1[get_byte<2>(X)];
62 const uint32_t s2 = M * SEED_S0[get_byte<1>(X)];
63 const uint32_t s3 = M * SEED_S1[get_byte<0>(X)];
64
65 const uint32_t M0 = 0x3FCFF3FC;
66 const uint32_t M1 = 0xFC3FCFF3;
67 const uint32_t M2 = 0xF3FC3FCF;
68 const uint32_t M3 = 0xCFF3FC3F;
69
70 return (s0 & M0) ^ (s1 & M1) ^ (s2 & M2) ^ (s3 & M3);
71}
72
73} // namespace
74
75/*
76* SEED Encryption
77*/
78void SEED::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const {
80
81#if defined(BOTAN_HAS_SEED_AVX512_GFNI)
83 return avx512_gfni_encrypt(in, out, blocks);
84 }
85#endif
86
87#if defined(BOTAN_HAS_SEED_HWAES)
89 return hwaes_encrypt(in, out, blocks);
90 }
91#endif
92
93 prefetch_arrays(SEED_S0, SEED_S1);
94
95 while(blocks >= 2) {
96 uint32_t B00 = load_be<uint32_t>(in, 0);
97 uint32_t B01 = load_be<uint32_t>(in, 1);
98 uint32_t B02 = load_be<uint32_t>(in, 2);
99 uint32_t B03 = load_be<uint32_t>(in, 3);
100 uint32_t B10 = load_be<uint32_t>(in, 4);
101 uint32_t B11 = load_be<uint32_t>(in, 5);
102 uint32_t B12 = load_be<uint32_t>(in, 6);
103 uint32_t B13 = load_be<uint32_t>(in, 7);
104
105 for(size_t j = 0; j != 16; j += 2) {
106 uint32_t T00 = B02 ^ m_K[2 * j];
107 uint32_t T10 = B12 ^ m_K[2 * j];
108 uint32_t T01 = SEED_G(B02 ^ B03 ^ m_K[2 * j + 1]);
109 uint32_t T11 = SEED_G(B12 ^ B13 ^ m_K[2 * j + 1]);
110 T00 = SEED_G(T01 + T00);
111 T10 = SEED_G(T11 + T10);
112 T01 = SEED_G(T01 + T00);
113 T11 = SEED_G(T11 + T10);
114 B01 ^= T01;
115 B11 ^= T11;
116 B00 ^= T00 + T01;
117 B10 ^= T10 + T11;
118
119 T00 = B00 ^ m_K[2 * j + 2];
120 T10 = B10 ^ m_K[2 * j + 2];
121 T01 = SEED_G(B00 ^ B01 ^ m_K[2 * j + 3]);
122 T11 = SEED_G(B10 ^ B11 ^ m_K[2 * j + 3]);
123 T10 = SEED_G(T11 + T10);
124 T00 = SEED_G(T01 + T00);
125 T01 = SEED_G(T01 + T00);
126 T11 = SEED_G(T11 + T10);
127 B03 ^= T01;
128 B13 ^= T11;
129 B02 ^= T00 + T01;
130 B12 ^= T10 + T11;
131 }
132
133 store_be(out, B02, B03, B00, B01, B12, B13, B10, B11);
134
135 in += 2 * BLOCK_SIZE;
136 out += 2 * BLOCK_SIZE;
137
138 blocks -= 2;
139 }
140
141 for(size_t i = 0; i != blocks; ++i) {
142 uint32_t B0 = load_be<uint32_t>(in, 0);
143 uint32_t B1 = load_be<uint32_t>(in, 1);
144 uint32_t B2 = load_be<uint32_t>(in, 2);
145 uint32_t B3 = load_be<uint32_t>(in, 3);
146
147 for(size_t j = 0; j != 16; j += 2) {
148 uint32_t T0 = B2 ^ m_K[2 * j];
149 uint32_t T1 = SEED_G(B2 ^ B3 ^ m_K[2 * j + 1]);
150 T0 = SEED_G(T1 + T0);
151 T1 = SEED_G(T1 + T0);
152 B1 ^= T1;
153 B0 ^= T0 + T1;
154
155 T0 = B0 ^ m_K[2 * j + 2];
156 T1 = SEED_G(B0 ^ B1 ^ m_K[2 * j + 3]);
157 T0 = SEED_G(T1 + T0);
158 T1 = SEED_G(T1 + T0);
159 B3 ^= T1;
160 B2 ^= T0 + T1;
161 }
162
163 store_be(out, B2, B3, B0, B1);
164
165 in += BLOCK_SIZE;
166 out += BLOCK_SIZE;
167 }
168}
169
170/*
171* SEED Decryption
172*/
173void SEED::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const {
175
176#if defined(BOTAN_HAS_SEED_AVX512_GFNI)
178 return avx512_gfni_decrypt(in, out, blocks);
179 }
180#endif
181
182#if defined(BOTAN_HAS_SEED_HWAES)
184 return hwaes_decrypt(in, out, blocks);
185 }
186#endif
187
188 prefetch_arrays(SEED_S0, SEED_S1);
189
190 while(blocks >= 2) {
191 uint32_t B00 = load_be<uint32_t>(in, 0);
192 uint32_t B01 = load_be<uint32_t>(in, 1);
193 uint32_t B02 = load_be<uint32_t>(in, 2);
194 uint32_t B03 = load_be<uint32_t>(in, 3);
195 uint32_t B10 = load_be<uint32_t>(in, 4);
196 uint32_t B11 = load_be<uint32_t>(in, 5);
197 uint32_t B12 = load_be<uint32_t>(in, 6);
198 uint32_t B13 = load_be<uint32_t>(in, 7);
199
200 for(size_t j = 0; j != 16; j += 2) {
201 uint32_t T00 = B02 ^ m_K[30 - 2 * j];
202 uint32_t T10 = B12 ^ m_K[30 - 2 * j];
203 uint32_t T01 = SEED_G(B02 ^ B03 ^ m_K[31 - 2 * j]);
204 uint32_t T11 = SEED_G(B12 ^ B13 ^ m_K[31 - 2 * j]);
205 T00 = SEED_G(T01 + T00);
206 T10 = SEED_G(T11 + T10);
207 T01 = SEED_G(T01 + T00);
208 T11 = SEED_G(T11 + T10);
209 B01 ^= T01;
210 B11 ^= T11;
211 B00 ^= T00 + T01;
212 B10 ^= T10 + T11;
213
214 T00 = B00 ^ m_K[28 - 2 * j];
215 T10 = B10 ^ m_K[28 - 2 * j];
216 T01 = SEED_G(B00 ^ B01 ^ m_K[29 - 2 * j]);
217 T11 = SEED_G(B10 ^ B11 ^ m_K[29 - 2 * j]);
218 T00 = SEED_G(T01 + T00);
219 T10 = SEED_G(T11 + T10);
220 T01 = SEED_G(T01 + T00);
221 T11 = SEED_G(T11 + T10);
222 B03 ^= T01;
223 B13 ^= T11;
224 B02 ^= T00 + T01;
225 B12 ^= T10 + T11;
226 }
227
228 store_be(out, B02, B03, B00, B01, B12, B13, B10, B11);
229
230 in += 2 * BLOCK_SIZE;
231 out += 2 * BLOCK_SIZE;
232 blocks -= 2;
233 }
234
235 for(size_t i = 0; i != blocks; ++i) {
236 uint32_t B0 = load_be<uint32_t>(in, 0);
237 uint32_t B1 = load_be<uint32_t>(in, 1);
238 uint32_t B2 = load_be<uint32_t>(in, 2);
239 uint32_t B3 = load_be<uint32_t>(in, 3);
240
241 for(size_t j = 0; j != 16; j += 2) {
242 uint32_t T0 = B2 ^ m_K[30 - 2 * j];
243 uint32_t T1 = SEED_G(B2 ^ B3 ^ m_K[31 - 2 * j]);
244 T0 = SEED_G(T1 + T0);
245 T1 = SEED_G(T1 + T0);
246 B1 ^= T1;
247 B0 ^= T0 + T1;
248
249 T0 = B0 ^ m_K[28 - 2 * j];
250 T1 = SEED_G(B0 ^ B1 ^ m_K[29 - 2 * j]);
251 T0 = SEED_G(T1 + T0);
252 T1 = SEED_G(T1 + T0);
253 B3 ^= T1;
254 B2 ^= T0 + T1;
255 }
256
257 store_be(out, B2, B3, B0, B1);
258
259 in += BLOCK_SIZE;
260 out += BLOCK_SIZE;
261 }
262}
263
265 return !m_K.empty();
266}
267
268/*
269* SEED Key Schedule
270*/
271void SEED::key_schedule(std::span<const uint8_t> key) {
272 const uint32_t RC[16] = {0x9E3779B9,
273 0x3C6EF373,
274 0x78DDE6E6,
275 0xF1BBCDCC,
276 0xE3779B99,
277 0xC6EF3733,
278 0x8DDE6E67,
279 0x1BBCDCCF,
280 0x3779B99E,
281 0x6EF3733C,
282 0xDDE6E678,
283 0xBBCDCCF1,
284 0x779B99E3,
285 0xEF3733C6,
286 0xDE6E678D,
287 0xBCDCCF1B};
288
290
291 for(size_t i = 0; i != 4; ++i) {
292 WK[i] = load_be<uint32_t>(key.data(), i);
293 }
294
295 m_K.resize(32);
296
297 for(size_t i = 0; i != 16; i += 2) {
298 m_K[2 * i] = SEED_G(WK[0] + WK[2] - RC[i]);
299 m_K[2 * i + 1] = SEED_G(WK[1] - WK[3] + RC[i]) ^ m_K[2 * i];
300
301 uint32_t T = (WK[0] & 0xFF) << 24;
302 WK[0] = (WK[0] >> 8) | (get_byte<3>(WK[1]) << 24);
303 WK[1] = (WK[1] >> 8) | T;
304
305 m_K[2 * i + 2] = SEED_G(WK[0] + WK[2] - RC[i + 1]);
306 m_K[2 * i + 3] = SEED_G(WK[1] - WK[3] + RC[i + 1]) ^ m_K[2 * i + 2];
307
308 T = get_byte<0>(WK[3]);
309 WK[3] = (WK[3] << 8) | get_byte<0>(WK[2]);
310 WK[2] = (WK[2] << 8) | T;
311 }
312}
313
315 zap(m_K);
316}
317
318size_t SEED::parallelism() const {
319#if defined(BOTAN_HAS_SEED_AVX512_GFNI)
321 return 16;
322 }
323#endif
324
325#if defined(BOTAN_HAS_SEED_HWAES)
327 return 4;
328 }
329#endif
330
331 return 1;
332}
333
334std::string SEED::provider() const {
335#if defined(BOTAN_HAS_SEED_AVX512_GFNI)
337 return *feat;
338 }
339#endif
340
341#if defined(BOTAN_HAS_SEED_HWAES)
342 if(auto feat = CPUID::check(CPUID::Feature::HW_AES)) {
343 return *feat;
344 }
345#endif
346
347 return "base";
348}
349
350} // namespace Botan
static std::optional< std::string > check(CPUID::Feature feat)
Definition cpuid.h:67
static bool has(CPUID::Feature feat)
Definition cpuid.h:94
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
Definition seed.cpp:78
bool has_keying_material() const override
Definition seed.cpp:264
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
Definition seed.cpp:173
size_t parallelism() const override
Definition seed.cpp:318
std::string provider() const override
Definition seed.cpp:334
void clear() override
Definition seed.cpp:314
#define BOTAN_FORCE_INLINE
Definition compiler.h:87
constexpr uint8_t get_byte(T input)
Definition loadstor.h:79
void zap(std::vector< T, Alloc > &vec)
Definition secmem.h:133
T prefetch_arrays(T(&... arr)[Ns]) noexcept
Definition prefetch.h:34
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:68
constexpr auto store_be(ParamTs &&... params)
Definition loadstor.h:745
constexpr auto load_be(ParamTs &&... params)
Definition loadstor.h:504