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