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