Botan 2.19.3
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/threefish_512.h>
9#include <botan/loadstor.h>
10#include <botan/rotate.h>
11#include <botan/cpuid.h>
12
13namespace 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
58void 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
114std::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
126void 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
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
162void 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
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
241void 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
251void 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}
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:37
#define BOTAN_ASSERT(expr, assertion_made)
Definition assert.h:55
void verify_key_set(bool cond) const
Definition sym_algo.h:171
size_t parallelism() const override
void set_tweak(const uint8_t tweak[], size_t len) override
std::string provider() const 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_PARALLEL_SIMD_FOR
Definition compiler.h:220
fe T
Definition ge.cpp:37
void zeroise(std::vector< T, Alloc > &vec)
Definition secmem.h:114
void zap(std::vector< T, Alloc > &vec)
Definition secmem.h:124
T load_le(const uint8_t in[], size_t off)
Definition loadstor.h:123
void store_le(uint16_t in, uint8_t out[2])
Definition loadstor.h:454
uint64_t load_le< uint64_t >(const uint8_t in[], size_t off)
Definition loadstor.h:237
#define THREEFISH_ENC_8_ROUNDS(R1, R2)
#define THREEFISH_DEC_8_ROUNDS(R1, R2)
#define THREEFISH_INJECT_KEY(r)