Botan 2.1.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

threefish.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.h>
9 #include <botan/loadstor.h>
10 #include <botan/cpuid.h>
11
12 namespace Botan {
13
14 #define THREEFISH_ROUND(X0,X1,X2,X3,X4,X5,X6,X7,ROT1,ROT2,ROT3,ROT4) \
15 do { \
16 X0 += X4; \
17 X1 += X5; \
18 X2 += X6; \
19 X3 += X7; \
20 X4 = rotate_left(X4, ROT1); \
21 X5 = rotate_left(X5, ROT2); \
22 X6 = rotate_left(X6, ROT3); \
23 X7 = rotate_left(X7, ROT4); \
24 X4 ^= X0; \
25 X5 ^= X1; \
26 X6 ^= X2; \
27 X7 ^= X3; \
28 } while(0)
29
30 #define THREEFISH_INJECT_KEY(r) \
31 do { \
32 X0 += m_K[(r ) % 9]; \
33 X1 += m_K[(r+1) % 9]; \
34 X2 += m_K[(r+2) % 9]; \
35 X3 += m_K[(r+3) % 9]; \
36 X4 += m_K[(r+4) % 9]; \
37 X5 += m_K[(r+5) % 9] + m_T[(r ) % 3]; \
38 X6 += m_K[(r+6) % 9] + m_T[(r+1) % 3]; \
39 X7 += m_K[(r+7) % 9] + (r); \
40 } while(0)
41
42 #define THREEFISH_ENC_8_ROUNDS(R1,R2) \
43 do { \
44 THREEFISH_ROUND(X0,X2,X4,X6, X1,X3,X5,X7, 46,36,19,37); \
45 THREEFISH_ROUND(X2,X4,X6,X0, X1,X7,X5,X3, 33,27,14,42); \
46 THREEFISH_ROUND(X4,X6,X0,X2, X1,X3,X5,X7, 17,49,36,39); \
47 THREEFISH_ROUND(X6,X0,X2,X4, X1,X7,X5,X3, 44, 9,54,56); \
48 THREEFISH_INJECT_KEY(R1); \
49 \
50 THREEFISH_ROUND(X0,X2,X4,X6, X1,X3,X5,X7, 39,30,34,24); \
51 THREEFISH_ROUND(X2,X4,X6,X0, X1,X7,X5,X3, 13,50,10,17); \
52 THREEFISH_ROUND(X4,X6,X0,X2, X1,X3,X5,X7, 25,29,39,43); \
53 THREEFISH_ROUND(X6,X0,X2,X4, X1,X7,X5,X3, 8,35,56,22); \
54 THREEFISH_INJECT_KEY(R2); \
55 } while(0)
56
57 void Threefish_512::skein_feedfwd(const secure_vector<uint64_t>& M,
58 const secure_vector<uint64_t>& T)
59 {
60 BOTAN_ASSERT(m_K.size() == 9, "Key was set");
61 BOTAN_ASSERT(M.size() == 8, "Single block");
62
63 m_T[0] = T[0];
64 m_T[1] = T[1];
65 m_T[2] = T[0] ^ T[1];
66
67 uint64_t X0 = M[0];
68 uint64_t X1 = M[1];
69 uint64_t X2 = M[2];
70 uint64_t X3 = M[3];
71 uint64_t X4 = M[4];
72 uint64_t X5 = M[5];
73 uint64_t X6 = M[6];
74 uint64_t X7 = M[7];
75
76 THREEFISH_INJECT_KEY(0);
77
78 THREEFISH_ENC_8_ROUNDS(1,2);
79 THREEFISH_ENC_8_ROUNDS(3,4);
80 THREEFISH_ENC_8_ROUNDS(5,6);
81 THREEFISH_ENC_8_ROUNDS(7,8);
82 THREEFISH_ENC_8_ROUNDS(9,10);
83 THREEFISH_ENC_8_ROUNDS(11,12);
84 THREEFISH_ENC_8_ROUNDS(13,14);
85 THREEFISH_ENC_8_ROUNDS(15,16);
86 THREEFISH_ENC_8_ROUNDS(17,18);
87
88 m_K[0] = M[0] ^ X0;
89 m_K[1] = M[1] ^ X1;
90 m_K[2] = M[2] ^ X2;
91 m_K[3] = M[3] ^ X3;
92 m_K[4] = M[4] ^ X4;
93 m_K[5] = M[5] ^ X5;
94 m_K[6] = M[6] ^ X6;
95 m_K[7] = M[7] ^ X7;
96
97 m_K[8] = m_K[0] ^ m_K[1] ^ m_K[2] ^ m_K[3] ^
98 m_K[4] ^ m_K[5] ^ m_K[6] ^ m_K[7] ^ 0x1BD11BDAA9FC1A22;
99 }
100
101 std::string Threefish_512::provider() const
102 {
103 #if defined(BOTAN_HAS_THREEFISH_512_AVX2)
104 if(CPUID::has_avx2())
105 {
106 return "avx2";
107 }
108 #endif
109
110 return "base";
111 }
112
113 void Threefish_512::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
114 {
115 BOTAN_ASSERT(m_K.size() == 9, "Key was set");
116 BOTAN_ASSERT(m_T.size() == 3, "Tweak was set");
117
118 #if defined(BOTAN_HAS_THREEFISH_512_AVX2)
119 if(CPUID::has_avx2())
120 {
121 return avx2_encrypt_n(in, out, blocks);
122 }
123 #endif
124
125 BOTAN_PARALLEL_FOR(size_t i = 0; i < blocks; ++i)
126 {
127 uint64_t X0, X1, X2, X3, X4, X5, X6, X7;
128 load_le(in + BLOCK_SIZE*i, X0, X1, X2, X3, X4, X5, X6, X7);
129
130 THREEFISH_INJECT_KEY(0);
131
132 THREEFISH_ENC_8_ROUNDS(1,2);
133 THREEFISH_ENC_8_ROUNDS(3,4);
134 THREEFISH_ENC_8_ROUNDS(5,6);
135 THREEFISH_ENC_8_ROUNDS(7,8);
136 THREEFISH_ENC_8_ROUNDS(9,10);
137 THREEFISH_ENC_8_ROUNDS(11,12);
138 THREEFISH_ENC_8_ROUNDS(13,14);
139 THREEFISH_ENC_8_ROUNDS(15,16);
140 THREEFISH_ENC_8_ROUNDS(17,18);
141
142 store_le(out + BLOCK_SIZE*i, X0, X1, X2, X3, X4, X5, X6, X7);
143 }
144 }
145
146 #undef THREEFISH_ENC_8_ROUNDS
147 #undef THREEFISH_INJECT_KEY
148 #undef THREEFISH_ROUND
149
150 void Threefish_512::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
151 {
152 BOTAN_ASSERT(m_K.size() == 9, "Key was set");
153 BOTAN_ASSERT(m_T.size() == 3, "Tweak was set");
154
155 #if defined(BOTAN_HAS_THREEFISH_512_AVX2)
156 if(CPUID::has_avx2())
157 {
158 return avx2_decrypt_n(in, out, blocks);
159 }
160 #endif
161
162 #define THREEFISH_ROUND(X0,X1,X2,X3,X4,X5,X6,X7,ROT1,ROT2,ROT3,ROT4) \
163 do { \
164 X4 ^= X0; \
165 X5 ^= X1; \
166 X6 ^= X2; \
167 X7 ^= X3; \
168 X4 = rotate_right(X4, ROT1); \
169 X5 = rotate_right(X5, ROT2); \
170 X6 = rotate_right(X6, ROT3); \
171 X7 = rotate_right(X7, ROT4); \
172 X0 -= X4; \
173 X1 -= X5; \
174 X2 -= X6; \
175 X3 -= X7; \
176 } while(0)
177
178 #define THREEFISH_INJECT_KEY(r) \
179 do { \
180 X0 -= m_K[(r ) % 9]; \
181 X1 -= m_K[(r+1) % 9]; \
182 X2 -= m_K[(r+2) % 9]; \
183 X3 -= m_K[(r+3) % 9]; \
184 X4 -= m_K[(r+4) % 9]; \
185 X5 -= m_K[(r+5) % 9] + m_T[(r ) % 3]; \
186 X6 -= m_K[(r+6) % 9] + m_T[(r+1) % 3]; \
187 X7 -= m_K[(r+7) % 9] + (r); \
188 } while(0)
189
190 #define THREEFISH_DEC_8_ROUNDS(R1,R2) \
191 do { \
192 THREEFISH_ROUND(X6,X0,X2,X4, X1,X7,X5,X3, 8,35,56,22); \
193 THREEFISH_ROUND(X4,X6,X0,X2, X1,X3,X5,X7, 25,29,39,43); \
194 THREEFISH_ROUND(X2,X4,X6,X0, X1,X7,X5,X3, 13,50,10,17); \
195 THREEFISH_ROUND(X0,X2,X4,X6, X1,X3,X5,X7, 39,30,34,24); \
196 THREEFISH_INJECT_KEY(R1); \
197 \
198 THREEFISH_ROUND(X6,X0,X2,X4, X1,X7,X5,X3, 44, 9,54,56); \
199 THREEFISH_ROUND(X4,X6,X0,X2, X1,X3,X5,X7, 17,49,36,39); \
200 THREEFISH_ROUND(X2,X4,X6,X0, X1,X7,X5,X3, 33,27,14,42); \
201 THREEFISH_ROUND(X0,X2,X4,X6, X1,X3,X5,X7, 46,36,19,37); \
202 THREEFISH_INJECT_KEY(R2); \
203 } while(0)
204
205 BOTAN_PARALLEL_FOR(size_t i = 0; i < blocks; ++i)
206 {
207 uint64_t X0, X1, X2, X3, X4, X5, X6, X7;
208 load_le(in + BLOCK_SIZE*i, X0, X1, X2, X3, X4, X5, X6, X7);
209
210 THREEFISH_INJECT_KEY(18);
211
212 THREEFISH_DEC_8_ROUNDS(17,16);
213 THREEFISH_DEC_8_ROUNDS(15,14);
214 THREEFISH_DEC_8_ROUNDS(13,12);
215 THREEFISH_DEC_8_ROUNDS(11,10);
216 THREEFISH_DEC_8_ROUNDS(9,8);
217 THREEFISH_DEC_8_ROUNDS(7,6);
218 THREEFISH_DEC_8_ROUNDS(5,4);
219 THREEFISH_DEC_8_ROUNDS(3,2);
220 THREEFISH_DEC_8_ROUNDS(1,0);
221
222 store_le(out + BLOCK_SIZE*i, X0, X1, X2, X3, X4, X5, X6, X7);
223 }
224
225 #undef THREEFISH_DEC_8_ROUNDS
226 #undef THREEFISH_INJECT_KEY
227 #undef THREEFISH_ROUND
228 }
229
230 void Threefish_512::set_tweak(const uint8_t tweak[], size_t len)
231 {
232 if(len != 16)
233 throw Exception("Threefish-512 requires 128 bit tweak");
234 m_T.resize(3);
235 m_T[0] = load_le<uint64_t>(tweak, 0);
236 m_T[1] = load_le<uint64_t>(tweak, 1);
237 m_T[2] = m_T[0] ^ m_T[1];
238 }
239
240 void Threefish_512::key_schedule(const uint8_t key[], size_t)
241 {
242 // todo: define key schedule for smaller keys
243 m_K.resize(9);
244
245 for(size_t i = 0; i != 8; ++i)
246 m_K[i] = load_le<uint64_t>(key, i);
247
248 m_K[8] = m_K[0] ^ m_K[1] ^ m_K[2] ^ m_K[3] ^
249 m_K[4] ^ m_K[5] ^ m_K[6] ^ m_K[7] ^ 0x1BD11BDAA9FC1A22;
250
251 // Reset tweak to all zeros on key reset
252 m_T.resize(3);
253 zeroise(m_T);
254 }
255
256 void Threefish_512::clear()
257 {
258 zap(m_K);
259 zap(m_T);
260 }
261
262 }
Botan::Threefish_512::provider
std::string provider() const override
Definition: threefish.cpp:101
Botan::Exception
Definition: exceptn.h:21
Botan::Block_Cipher_Fixed_Params< 64, 64 >::BLOCK_SIZE
Definition: block_cipher.h:186
Botan::zap
void zap(std::vector< T, Alloc > &vec)
Definition: secmem.h:221
THREEFISH_INJECT_KEY
#define THREEFISH_INJECT_KEY(r)
Definition: threefish.cpp:30
Botan::Threefish_512::encrypt_n
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
Definition: threefish.cpp:113
BOTAN_PARALLEL_FOR
#define BOTAN_PARALLEL_FOR
Definition: compiler.h:129
BOTAN_ASSERT
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:27
Botan::Threefish_512::decrypt_n
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override
Definition: threefish.cpp:150
Botan::load_le< uint64_t >
uint64_t load_le< uint64_t >(const uint8_t in[], size_t off)
Definition: loadstor.h:243
Botan::load_le
T load_le(const uint8_t in[], size_t off)
Definition: loadstor.h:129
Botan
Definition: alg_id.cpp:13
THREEFISH_DEC_8_ROUNDS
#define THREEFISH_DEC_8_ROUNDS(R1, R2)
Botan::Threefish_512::set_tweak
void set_tweak(const uint8_t tweak[], size_t len)
Definition: threefish.cpp:230
THREEFISH_ENC_8_ROUNDS
#define THREEFISH_ENC_8_ROUNDS(R1, R2)
Definition: threefish.cpp:42
Botan::store_le
void store_le(uint16_t in, uint8_t out[2])
Definition: loadstor.h:457
Botan::Threefish_512::clear
void clear() override
Definition: threefish.cpp:256
Botan::zeroise
void zeroise(std::vector< T, Alloc > &vec)
Definition: secmem.h:211