Botan  2.11.0
Crypto and TLS for C++11
threefish_512.cpp
Go to the documentation of this file.
1 /*
2 * Threefish-512
3 * (C) 2013,2014,2016 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/threefish_512.h>
9 #include <botan/loadstor.h>
10 #include <botan/rotate.h>
11 #include <botan/cpuid.h>
12 
13 namespace Botan {
14 
15 #define THREEFISH_ROUND(X0,X1,X2,X3,X4,X5,X6,X7,ROT1,ROT2,ROT3,ROT4) \
16  do { \
17  X0 += X4; \
18  X1 += X5; \
19  X2 += X6; \
20  X3 += X7; \
21  X4 = rotl<ROT1>(X4); \
22  X5 = rotl<ROT2>(X5); \
23  X6 = rotl<ROT3>(X6); \
24  X7 = rotl<ROT4>(X7); \
25  X4 ^= X0; \
26  X5 ^= X1; \
27  X6 ^= X2; \
28  X7 ^= X3; \
29  } while(0)
30 
31 #define THREEFISH_INJECT_KEY(r) \
32  do { \
33  X0 += m_K[(r ) % 9]; \
34  X1 += m_K[(r+1) % 9]; \
35  X2 += m_K[(r+2) % 9]; \
36  X3 += m_K[(r+3) % 9]; \
37  X4 += m_K[(r+4) % 9]; \
38  X5 += m_K[(r+5) % 9] + m_T[(r ) % 3]; \
39  X6 += m_K[(r+6) % 9] + m_T[(r+1) % 3]; \
40  X7 += m_K[(r+7) % 9] + (r); \
41  } while(0)
42 
43 #define THREEFISH_ENC_8_ROUNDS(R1,R2) \
44  do { \
45  THREEFISH_ROUND(X0,X2,X4,X6, X1,X3,X5,X7, 46,36,19,37); \
46  THREEFISH_ROUND(X2,X4,X6,X0, X1,X7,X5,X3, 33,27,14,42); \
47  THREEFISH_ROUND(X4,X6,X0,X2, X1,X3,X5,X7, 17,49,36,39); \
48  THREEFISH_ROUND(X6,X0,X2,X4, X1,X7,X5,X3, 44, 9,54,56); \
49  THREEFISH_INJECT_KEY(R1); \
50  \
51  THREEFISH_ROUND(X0,X2,X4,X6, X1,X3,X5,X7, 39,30,34,24); \
52  THREEFISH_ROUND(X2,X4,X6,X0, X1,X7,X5,X3, 13,50,10,17); \
53  THREEFISH_ROUND(X4,X6,X0,X2, X1,X3,X5,X7, 25,29,39,43); \
54  THREEFISH_ROUND(X6,X0,X2,X4, X1,X7,X5,X3, 8,35,56,22); \
55  THREEFISH_INJECT_KEY(R2); \
56  } while(0)
57 
58 void Threefish_512::skein_feedfwd(const secure_vector<uint64_t>& M,
59  const secure_vector<uint64_t>& T)
60  {
61  BOTAN_ASSERT(m_K.size() == 9, "Key was set");
62  BOTAN_ASSERT(M.size() == 8, "Single block");
63 
64  m_T[0] = T[0];
65  m_T[1] = T[1];
66  m_T[2] = T[0] ^ T[1];
67 
68  uint64_t X0 = M[0];
69  uint64_t X1 = M[1];
70  uint64_t X2 = M[2];
71  uint64_t X3 = M[3];
72  uint64_t X4 = M[4];
73  uint64_t X5 = M[5];
74  uint64_t X6 = M[6];
75  uint64_t X7 = M[7];
76 
78 
88 
89  m_K[0] = M[0] ^ X0;
90  m_K[1] = M[1] ^ X1;
91  m_K[2] = M[2] ^ X2;
92  m_K[3] = M[3] ^ X3;
93  m_K[4] = M[4] ^ X4;
94  m_K[5] = M[5] ^ X5;
95  m_K[6] = M[6] ^ X6;
96  m_K[7] = M[7] ^ X7;
97 
98  m_K[8] = m_K[0] ^ m_K[1] ^ m_K[2] ^ m_K[3] ^
99  m_K[4] ^ m_K[5] ^ m_K[6] ^ m_K[7] ^ 0x1BD11BDAA9FC1A22;
100  }
101 
103  {
104 #if defined(BOTAN_HAS_THREEFISH_512_AVX2)
105  if(CPUID::has_avx2())
106  {
107  return 2;
108  }
109 #endif
110 
111  return 1;
112  }
113 
114 std::string Threefish_512::provider() const
115  {
116 #if defined(BOTAN_HAS_THREEFISH_512_AVX2)
117  if(CPUID::has_avx2())
118  {
119  return "avx2";
120  }
121 #endif
122 
123  return "base";
124  }
125 
126 void Threefish_512::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
127  {
128  verify_key_set(m_K.empty() == false);
129 
130 #if defined(BOTAN_HAS_THREEFISH_512_AVX2)
131  if(CPUID::has_avx2())
132  {
133  return avx2_encrypt_n(in, out, blocks);
134  }
135 #endif
136 
137  BOTAN_PARALLEL_SIMD_FOR(size_t i = 0; i < blocks; ++i)
138  {
139  uint64_t X0, X1, X2, X3, X4, X5, X6, X7;
140  load_le(in + BLOCK_SIZE*i, X0, X1, X2, X3, X4, X5, X6, X7);
141 
143 
149  THREEFISH_ENC_8_ROUNDS(11,12);
150  THREEFISH_ENC_8_ROUNDS(13,14);
151  THREEFISH_ENC_8_ROUNDS(15,16);
152  THREEFISH_ENC_8_ROUNDS(17,18);
153 
154  store_le(out + BLOCK_SIZE*i, X0, X1, X2, X3, X4, X5, X6, X7);
155  }
156  }
157 
158 #undef THREEFISH_ENC_8_ROUNDS
159 #undef THREEFISH_INJECT_KEY
160 #undef THREEFISH_ROUND
161 
162 void Threefish_512::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
163  {
164  verify_key_set(m_K.empty() == false);
165 
166 #if defined(BOTAN_HAS_THREEFISH_512_AVX2)
167  if(CPUID::has_avx2())
168  {
169  return avx2_decrypt_n(in, out, blocks);
170  }
171 #endif
172 
173 #define THREEFISH_ROUND(X0,X1,X2,X3,X4,X5,X6,X7,ROT1,ROT2,ROT3,ROT4) \
174  do { \
175  X4 ^= X0; \
176  X5 ^= X1; \
177  X6 ^= X2; \
178  X7 ^= X3; \
179  X4 = rotr<ROT1>(X4); \
180  X5 = rotr<ROT2>(X5); \
181  X6 = rotr<ROT3>(X6); \
182  X7 = rotr<ROT4>(X7); \
183  X0 -= X4; \
184  X1 -= X5; \
185  X2 -= X6; \
186  X3 -= X7; \
187  } while(0)
188 
189 #define THREEFISH_INJECT_KEY(r) \
190  do { \
191  X0 -= m_K[(r ) % 9]; \
192  X1 -= m_K[(r+1) % 9]; \
193  X2 -= m_K[(r+2) % 9]; \
194  X3 -= m_K[(r+3) % 9]; \
195  X4 -= m_K[(r+4) % 9]; \
196  X5 -= m_K[(r+5) % 9] + m_T[(r ) % 3]; \
197  X6 -= m_K[(r+6) % 9] + m_T[(r+1) % 3]; \
198  X7 -= m_K[(r+7) % 9] + (r); \
199  } while(0)
200 
201 #define THREEFISH_DEC_8_ROUNDS(R1,R2) \
202  do { \
203  THREEFISH_ROUND(X6,X0,X2,X4, X1,X7,X5,X3, 8,35,56,22); \
204  THREEFISH_ROUND(X4,X6,X0,X2, X1,X3,X5,X7, 25,29,39,43); \
205  THREEFISH_ROUND(X2,X4,X6,X0, X1,X7,X5,X3, 13,50,10,17); \
206  THREEFISH_ROUND(X0,X2,X4,X6, X1,X3,X5,X7, 39,30,34,24); \
207  THREEFISH_INJECT_KEY(R1); \
208  \
209  THREEFISH_ROUND(X6,X0,X2,X4, X1,X7,X5,X3, 44, 9,54,56); \
210  THREEFISH_ROUND(X4,X6,X0,X2, X1,X3,X5,X7, 17,49,36,39); \
211  THREEFISH_ROUND(X2,X4,X6,X0, X1,X7,X5,X3, 33,27,14,42); \
212  THREEFISH_ROUND(X0,X2,X4,X6, X1,X3,X5,X7, 46,36,19,37); \
213  THREEFISH_INJECT_KEY(R2); \
214  } while(0)
215 
216  BOTAN_PARALLEL_SIMD_FOR(size_t i = 0; i < blocks; ++i)
217  {
218  uint64_t X0, X1, X2, X3, X4, X5, X6, X7;
219  load_le(in + BLOCK_SIZE*i, X0, X1, X2, X3, X4, X5, X6, X7);
220 
222 
223  THREEFISH_DEC_8_ROUNDS(17,16);
224  THREEFISH_DEC_8_ROUNDS(15,14);
225  THREEFISH_DEC_8_ROUNDS(13,12);
226  THREEFISH_DEC_8_ROUNDS(11,10);
232 
233  store_le(out + BLOCK_SIZE*i, X0, X1, X2, X3, X4, X5, X6, X7);
234  }
235 
236 #undef THREEFISH_DEC_8_ROUNDS
237 #undef THREEFISH_INJECT_KEY
238 #undef THREEFISH_ROUND
239  }
240 
241 void Threefish_512::set_tweak(const uint8_t tweak[], size_t len)
242  {
243  BOTAN_ARG_CHECK(len == 16, "Threefish-512 requires 128 bit tweak");
244 
245  m_T.resize(3);
246  m_T[0] = load_le<uint64_t>(tweak, 0);
247  m_T[1] = load_le<uint64_t>(tweak, 1);
248  m_T[2] = m_T[0] ^ m_T[1];
249  }
250 
251 void Threefish_512::key_schedule(const uint8_t key[], size_t)
252  {
253  // todo: define key schedule for smaller keys
254  m_K.resize(9);
255 
256  for(size_t i = 0; i != 8; ++i)
257  m_K[i] = load_le<uint64_t>(key, i);
258 
259  m_K[8] = m_K[0] ^ m_K[1] ^ m_K[2] ^ m_K[3] ^
260  m_K[4] ^ m_K[5] ^ m_K[6] ^ m_K[7] ^ 0x1BD11BDAA9FC1A22;
261 
262  // Reset tweak to all zeros on key reset
263  m_T.resize(3);
264  zeroise(m_T);
265  }
266 
268  {
269  zap(m_K);
270  zap(m_T);
271  }
272 
273 }
std::string provider() const override
void verify_key_set(bool cond) const
Definition: sym_algo.h:89
void zap(std::vector< T, Alloc > &vec)
Definition: secmem.h:170
#define THREEFISH_ENC_8_ROUNDS(R1, R2)
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:55
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
uint64_t load_le< uint64_t >(const uint8_t in[], size_t off)
Definition: loadstor.h:235
T load_le(const uint8_t in[], size_t off)
Definition: loadstor.h:121
Definition: alg_id.cpp:13
#define BOTAN_ARG_CHECK(expr, msg)
Definition: assert.h:37
size_t parallelism() const override
#define THREEFISH_DEC_8_ROUNDS(R1, R2)
void set_tweak(const uint8_t tweak[], size_t len) override
#define THREEFISH_INJECT_KEY(r)
fe T
Definition: ge.cpp:37
#define BOTAN_PARALLEL_SIMD_FOR
Definition: compiler.h:188
void store_le(uint16_t in, uint8_t out[2])
Definition: loadstor.h:452
void clear() override
void zeroise(std::vector< T, Alloc > &vec)
Definition: secmem.h:160