Botan 3.0.0
Crypto and TLS for C&
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/internal/threefish_512.h>
9#include <botan/internal/loadstor.h>
10#include <botan/internal/rotate.h>
11#include <botan/internal/cpuid.h>
12
13namespace Botan {
14
15namespace Threefish_F {
16
17template<size_t R1, size_t R2, size_t R3, size_t R4>
19 uint64_t& X0, uint64_t& X1, uint64_t& X2, uint64_t& X3,
20 uint64_t& X4, uint64_t& X5, uint64_t& X6, uint64_t& X7)
21 {
22 X0 += X4;
23 X1 += X5;
24 X2 += X6;
25 X3 += X7;
26 X4 = rotl<R1>(X4);
27 X5 = rotl<R2>(X5);
28 X6 = rotl<R3>(X6);
29 X7 = rotl<R4>(X7);
30 X4 ^= X0;
31 X5 ^= X1;
32 X6 ^= X2;
33 X7 ^= X3;
34 }
35
36template<size_t R1, size_t R2, size_t R3, size_t R4>
38 uint64_t& X0, uint64_t& X1, uint64_t& X2, uint64_t& X3,
39 uint64_t& X4, uint64_t& X5, uint64_t& X6, uint64_t& X7)
40 {
41 X4 ^= X0;
42 X5 ^= X1;
43 X6 ^= X2;
44 X7 ^= X3;
45 X4 = rotr<R1>(X4);
46 X5 = rotr<R2>(X5);
47 X6 = rotr<R3>(X6);
48 X7 = rotr<R4>(X7);
49 X0 -= X4;
50 X1 -= X5;
51 X2 -= X6;
52 X3 -= X7;
53 }
54
55class Key_Inserter
56 {
57 public:
58 Key_Inserter(const uint64_t* K, const uint64_t* T) :
59 m_K(K), m_T(T) {}
60
61 inline void e_add(
62 size_t R,
63 uint64_t& X0, uint64_t& X1, uint64_t& X2, uint64_t& X3,
64 uint64_t& X4, uint64_t& X5, uint64_t& X6, uint64_t& X7) const
65 {
66 X0 += m_K[(R ) % 9];
67 X1 += m_K[(R+1) % 9];
68 X2 += m_K[(R+2) % 9];
69 X3 += m_K[(R+3) % 9];
70 X4 += m_K[(R+4) % 9];
71 X5 += m_K[(R+5) % 9] + m_T[(R ) % 3];
72 X6 += m_K[(R+6) % 9] + m_T[(R+1) % 3];
73 X7 += m_K[(R+7) % 9] + R;
74 }
75
76 inline void d_add(
77 size_t R,
78 uint64_t& X0, uint64_t& X1, uint64_t& X2, uint64_t& X3,
79 uint64_t& X4, uint64_t& X5, uint64_t& X6, uint64_t& X7) const
80 {
81 X0 -= m_K[(R ) % 9];
82 X1 -= m_K[(R+1) % 9];
83 X2 -= m_K[(R+2) % 9];
84 X3 -= m_K[(R+3) % 9];
85 X4 -= m_K[(R+4) % 9];
86 X5 -= m_K[(R+5) % 9] + m_T[(R ) % 3];
87 X6 -= m_K[(R+6) % 9] + m_T[(R+1) % 3];
88 X7 -= m_K[(R+7) % 9] + R;
89 }
90
91 private:
92 const uint64_t* m_K;
93 const uint64_t* m_T;
94 };
95
96template<size_t R1, size_t R2>
98 uint64_t& X0, uint64_t& X1, uint64_t& X2, uint64_t& X3,
99 uint64_t& X4, uint64_t& X5, uint64_t& X6, uint64_t& X7,
100 const Key_Inserter& key)
101 {
102 e_round<46,36,19,37>(X0,X2,X4,X6, X1,X3,X5,X7);
103 e_round<33,27,14,42>(X2,X4,X6,X0, X1,X7,X5,X3);
104 e_round<17,49,36,39>(X4,X6,X0,X2, X1,X3,X5,X7);
105 e_round<44, 9,54,56>(X6,X0,X2,X4, X1,X7,X5,X3);
106 key.e_add(R1, X0, X1, X2, X3, X4, X5, X6, X7);
107
108 e_round<39,30,34,24>(X0,X2,X4,X6, X1,X3,X5,X7);
109 e_round<13,50,10,17>(X2,X4,X6,X0, X1,X7,X5,X3);
110 e_round<25,29,39,43>(X4,X6,X0,X2, X1,X3,X5,X7);
111 e_round< 8,35,56,22>(X6,X0,X2,X4, X1,X7,X5,X3);
112 key.e_add(R2, X0, X1, X2, X3, X4, X5, X6, X7);
113 }
114
115template<size_t R1, size_t R2>
117 uint64_t& X0, uint64_t& X1, uint64_t& X2, uint64_t& X3,
118 uint64_t& X4, uint64_t& X5, uint64_t& X6, uint64_t& X7,
119 const Key_Inserter& key)
120 {
121 d_round< 8,35,56,22>(X6,X0,X2,X4, X1,X7,X5,X3);
122 d_round<25,29,39,43>(X4,X6,X0,X2, X1,X3,X5,X7);
123 d_round<13,50,10,17>(X2,X4,X6,X0, X1,X7,X5,X3);
124 d_round<39,30,34,24>(X0,X2,X4,X6, X1,X3,X5,X7);
125 key.d_add(R1, X0, X1, X2, X3, X4, X5, X6, X7);
126
127 d_round<44, 9,54,56>(X6,X0,X2,X4, X1,X7,X5,X3);
128 d_round<17,49,36,39>(X4,X6,X0,X2, X1,X3,X5,X7);
129 d_round<33,27,14,42>(X2,X4,X6,X0, X1,X7,X5,X3);
130 d_round<46,36,19,37>(X0,X2,X4,X6, X1,X3,X5,X7);
131 key.d_add(R2, X0, X1, X2, X3, X4, X5, X6, X7);
132 }
133
134}
135
136void Threefish_512::skein_feedfwd(const secure_vector<uint64_t>& M,
137 const secure_vector<uint64_t>& T)
138 {
139 using namespace Threefish_F;
140
141 BOTAN_ASSERT(m_K.size() == 9, "Key was set");
142 BOTAN_ASSERT(M.size() == 8, "Single block");
143
144 m_T[0] = T[0];
145 m_T[1] = T[1];
146 m_T[2] = T[0] ^ T[1];
147
148 const Key_Inserter key(m_K.data(), m_T.data());
149
150 uint64_t X0 = M[0];
151 uint64_t X1 = M[1];
152 uint64_t X2 = M[2];
153 uint64_t X3 = M[3];
154 uint64_t X4 = M[4];
155 uint64_t X5 = M[5];
156 uint64_t X6 = M[6];
157 uint64_t X7 = M[7];
158
159 key.e_add(0, X0, X1, X2, X3, X4, X5, X6, X7);
160
161 e8_rounds< 1, 2>(X0, X1, X2, X3, X4, X5, X6, X7, key);
162 e8_rounds< 3, 4>(X0, X1, X2, X3, X4, X5, X6, X7, key);
163 e8_rounds< 5, 6>(X0, X1, X2, X3, X4, X5, X6, X7, key);
164 e8_rounds< 7, 8>(X0, X1, X2, X3, X4, X5, X6, X7, key);
165 e8_rounds< 9,10>(X0, X1, X2, X3, X4, X5, X6, X7, key);
166 e8_rounds<11,12>(X0, X1, X2, X3, X4, X5, X6, X7, key);
167 e8_rounds<13,14>(X0, X1, X2, X3, X4, X5, X6, X7, key);
168 e8_rounds<15,16>(X0, X1, X2, X3, X4, X5, X6, X7, key);
169 e8_rounds<17,18>(X0, X1, X2, X3, X4, X5, X6, X7, key);
170
171 m_K[0] = M[0] ^ X0;
172 m_K[1] = M[1] ^ X1;
173 m_K[2] = M[2] ^ X2;
174 m_K[3] = M[3] ^ X3;
175 m_K[4] = M[4] ^ X4;
176 m_K[5] = M[5] ^ X5;
177 m_K[6] = M[6] ^ X6;
178 m_K[7] = M[7] ^ X7;
179
180 m_K[8] = m_K[0] ^ m_K[1] ^ m_K[2] ^ m_K[3] ^
181 m_K[4] ^ m_K[5] ^ m_K[6] ^ m_K[7] ^ 0x1BD11BDAA9FC1A22;
182 }
183
184void Threefish_512::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
185 {
186 using namespace Threefish_F;
187
189
190 const Key_Inserter key(m_K.data(), m_T.data());
191
192 BOTAN_PARALLEL_SIMD_FOR(size_t i = 0; i < blocks; ++i)
193 {
194 uint64_t X0, X1, X2, X3, X4, X5, X6, X7;
195 load_le(in + BLOCK_SIZE*i, X0, X1, X2, X3, X4, X5, X6, X7);
196
197 key.e_add(0, X0, X1, X2, X3, X4, X5, X6, X7);
198
199 e8_rounds< 1, 2>(X0, X1, X2, X3, X4, X5, X6, X7, key);
200 e8_rounds< 3, 4>(X0, X1, X2, X3, X4, X5, X6, X7, key);
201 e8_rounds< 5, 6>(X0, X1, X2, X3, X4, X5, X6, X7, key);
202 e8_rounds< 7, 8>(X0, X1, X2, X3, X4, X5, X6, X7, key);
203 e8_rounds< 9,10>(X0, X1, X2, X3, X4, X5, X6, X7, key);
204 e8_rounds<11,12>(X0, X1, X2, X3, X4, X5, X6, X7, key);
205 e8_rounds<13,14>(X0, X1, X2, X3, X4, X5, X6, X7, key);
206 e8_rounds<15,16>(X0, X1, X2, X3, X4, X5, X6, X7, key);
207 e8_rounds<17,18>(X0, X1, X2, X3, X4, X5, X6, X7, key);
208
209 store_le(out + BLOCK_SIZE*i, X0, X1, X2, X3, X4, X5, X6, X7);
210 }
211 }
212
213#undef THREEFISH_ENC_8_ROUNDS
214
215void Threefish_512::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
216 {
217 using namespace Threefish_F;
218
220
221 const Key_Inserter key(m_K.data(), m_T.data());
222
223 BOTAN_PARALLEL_SIMD_FOR(size_t i = 0; i < blocks; ++i)
224 {
225 uint64_t X0, X1, X2, X3, X4, X5, X6, X7;
226 load_le(in + BLOCK_SIZE*i, X0, X1, X2, X3, X4, X5, X6, X7);
227
228 key.d_add(18, X0, X1, X2, X3, X4, X5, X6, X7);
229
230 d8_rounds<17,16>(X0, X1, X2, X3, X4, X5, X6, X7, key);
231 d8_rounds<15,14>(X0, X1, X2, X3, X4, X5, X6, X7, key);
232 d8_rounds<13,12>(X0, X1, X2, X3, X4, X5, X6, X7, key);
233 d8_rounds<11,10>(X0, X1, X2, X3, X4, X5, X6, X7, key);
234 d8_rounds< 9, 8>(X0, X1, X2, X3, X4, X5, X6, X7, key);
235 d8_rounds< 7, 6>(X0, X1, X2, X3, X4, X5, X6, X7, key);
236 d8_rounds< 5, 4>(X0, X1, X2, X3, X4, X5, X6, X7, key);
237 d8_rounds< 3, 2>(X0, X1, X2, X3, X4, X5, X6, X7, key);
238 d8_rounds< 1, 0>(X0, X1, X2, X3, X4, X5, X6, X7, key);
239
240 store_le(out + BLOCK_SIZE*i, X0, X1, X2, X3, X4, X5, X6, X7);
241 }
242
243}
244
245void Threefish_512::set_tweak(const uint8_t tweak[], size_t len)
246 {
247 BOTAN_ARG_CHECK(len == 16, "Threefish-512 requires 128 bit tweak");
248
249 m_T.resize(3);
250 m_T[0] = load_le<uint64_t>(tweak, 0);
251 m_T[1] = load_le<uint64_t>(tweak, 1);
252 m_T[2] = m_T[0] ^ m_T[1];
253 }
254
256 {
257 return !m_K.empty();
258 }
259
260void Threefish_512::key_schedule(const uint8_t key[], size_t /*length*/)
261 {
262 // todo: define key schedule for smaller keys
263 m_K.resize(9);
264
265 for(size_t i = 0; i != 8; ++i)
266 m_K[i] = load_le<uint64_t>(key, i);
267
268 m_K[8] = m_K[0] ^ m_K[1] ^ m_K[2] ^ m_K[3] ^
269 m_K[4] ^ m_K[5] ^ m_K[6] ^ m_K[7] ^ 0x1BD11BDAA9FC1A22;
270
271 // Reset tweak to all zeros on key reset
272 m_T.resize(3);
273 zeroise(m_T);
274 }
275
277 {
278 zap(m_K);
279 zap(m_T);
280 }
281
282}
#define BOTAN_ARG_CHECK(expr, msg)
Definition: assert.h:36
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:54
void assert_key_material_set() const
Definition: sym_algo.h:182
bool has_keying_material() const override
void set_tweak(const uint8_t tweak[], size_t len) 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 clear() override
#define BOTAN_FORCE_INLINE
Definition: compiler.h:167
#define BOTAN_PARALLEL_SIMD_FOR
Definition: compiler.h:180
FE_25519 T
Definition: ge.cpp:36
BOTAN_FORCE_INLINE void d_round(uint64_t &X0, uint64_t &X1, uint64_t &X2, uint64_t &X3, uint64_t &X4, uint64_t &X5, uint64_t &X6, uint64_t &X7)
BOTAN_FORCE_INLINE void d8_rounds(uint64_t &X0, uint64_t &X1, uint64_t &X2, uint64_t &X3, uint64_t &X4, uint64_t &X5, uint64_t &X6, uint64_t &X7, const Key_Inserter &key)
BOTAN_FORCE_INLINE void e8_rounds(uint64_t &X0, uint64_t &X1, uint64_t &X2, uint64_t &X3, uint64_t &X4, uint64_t &X5, uint64_t &X6, uint64_t &X7, const Key_Inserter &key)
BOTAN_FORCE_INLINE void e_round(uint64_t &X0, uint64_t &X1, uint64_t &X2, uint64_t &X3, uint64_t &X4, uint64_t &X5, uint64_t &X6, uint64_t &X7)
Definition: alg_id.cpp:12
constexpr void store_le(uint16_t in, uint8_t out[2])
Definition: loadstor.h:465
void zeroise(std::vector< T, Alloc > &vec)
Definition: secmem.h:119
void zap(std::vector< T, Alloc > &vec)
Definition: secmem.h:129
constexpr T load_le(const uint8_t in[], size_t off)
Definition: loadstor.h:134
constexpr uint64_t load_le< uint64_t >(const uint8_t in[], size_t off)
Definition: loadstor.h:248