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