digestpp 1.0
C++11 header-only message digest library
Loading...
Searching...
No Matches
skein_provider.hpp
Go to the documentation of this file.
1/*
2This code is written by kerukuro and released into public domain.
3*/
4
5#ifndef DIGESTPP_PROVIDERS_SKEIN_HPP
6#define DIGESTPP_PROVIDERS_SKEIN_HPP
7
12#include <array>
13
14namespace digestpp
15{
16
17namespace detail
18{
19
20template<size_t N>
22{
23};
24
25template<>
27{
37
38 template<size_t r>
39 static inline void KStRv4(uint64_t* G, uint64_t* keys, uint64_t* tweaks)
40 {
41 G[0] += keys[(r + 0 + 1) % 5];
42 G[1] += keys[(r + 1 + 1) % 5] + tweaks[(r + 1) % 3];
43 G[2] += keys[(r + 2 + 1) % 5] + tweaks[(r + 2) % 3];
44 G[3] += keys[(r + 3 + 1) % 5] + r + 1;
45 }
46
47 template<size_t r>
48 static inline void G8(uint64_t* G, uint64_t* keys, uint64_t* tweaks)
49 {
50 GTv4<0>(G);
51 GTv4<1>(G);
52 GTv4<2>(G);
53 GTv4<3>(G);
54 KStRv4<r>(G, keys, tweaks);
55 GTv4<4>(G);
56 GTv4<5>(G);
57 GTv4<6>(G);
58 GTv4<7>(G);
59 KStRv4<r + 1>(G, keys, tweaks);
60 }
61};
62
63template<>
65{
81
82 template<size_t r>
83 static inline void KStRv4(uint64_t* G, uint64_t* keys, uint64_t* tweaks)
84 {
85 G[0] += keys[(r + 0 + 1) % 9];
86 G[1] += keys[(r + 1 + 1) % 9];
87 G[2] += keys[(r + 2 + 1) % 9];
88 G[3] += keys[(r + 3 + 1) % 9];
89 G[4] += keys[(r + 4 + 1) % 9];
90 G[5] += keys[(r + 5 + 1) % 9] + tweaks[(r + 1) % 3];
91 G[6] += keys[(r + 6 + 1) % 9] + tweaks[(r + 2) % 3];
92 G[7] += keys[(r + 7 + 1) % 9] + r + 1;
93 }
94
95 template<size_t r>
96 static inline void G8(uint64_t* G, uint64_t* keys, uint64_t* tweaks)
97 {
98 GTv4<0>(G);
99 GTv4<1>(G);
100 GTv4<2>(G);
101 GTv4<3>(G);
102 KStRv4<r>(G, keys, tweaks);
103 GTv4<4>(G);
104 GTv4<5>(G);
105 GTv4<6>(G);
106 GTv4<7>(G);
107 KStRv4<r + 1>(G, keys, tweaks);
108 }
109};
110
111template<>
113{
114
115 template<size_t r> static inline void GTv4(uint64_t* G)
116 {
141 }
142
143 template<size_t r>
144 static inline void KStRv4(uint64_t* G, uint64_t* keys, uint64_t* tweaks)
145 {
146 G[0] += keys[(r + 0 + 1) % 17];
147 G[1] += keys[(r + 1 + 1) % 17];
148 G[2] += keys[(r + 2 + 1) % 17];
149 G[3] += keys[(r + 3 + 1) % 17];
150 G[4] += keys[(r + 4 + 1) % 17];
151 G[5] += keys[(r + 5 + 1) % 17];
152 G[6] += keys[(r + 6 + 1) % 17];
153 G[7] += keys[(r + 7 + 1) % 17];
154 G[8] += keys[(r + 8 + 1) % 17];
155 G[9] += keys[(r + 9 + 1) % 17];
156 G[10] += keys[(r + 10 + 1) % 17];
157 G[11] += keys[(r + 11 + 1) % 17];
158 G[12] += keys[(r + 12 + 1) % 17];
159 G[13] += keys[(r + 13 + 1) % 17] + tweaks[(r + 1) % 3];
160 G[14] += keys[(r + 14 + 1) % 17] + tweaks[(r + 2) % 3];
161 G[15] += keys[(r + 15 + 1) % 17] + r + 1;
162 }
163
164 template<size_t r>
165 static inline void G8(uint64_t* G, uint64_t* keys, uint64_t* tweaks)
166 {
167 GTv4<0>(G);
168 GTv4<1>(G);
169 GTv4<2>(G);
170 GTv4<3>(G);
171 KStRv4<r>(G, keys, tweaks);
172 GTv4<4>(G);
173 GTv4<5>(G);
174 GTv4<6>(G);
175 GTv4<7>(G);
176 KStRv4<r + 1>(G, keys, tweaks);
177 }
178};
179
180template<size_t N, bool XOF, size_t HS = 0>
182{
183public:
184 static const bool is_xof = XOF;
185
186 template<size_t hss=HS, typename std::enable_if<hss == 0>::type* = nullptr>
187 skein_provider(size_t hashsize = N)
188 : hs(hashsize)
189 {
190 validate_hash_size(hashsize, SIZE_MAX);
191 }
192
193 template<size_t hss=HS, typename std::enable_if<hss != 0>::type* = nullptr>
194 skein_provider(size_t hashsize = N)
195 : hs(hss)
196 {
197 static_assert(hss > 0 && hss % 8 == 0);
198 }
199
201 {
202 clear();
203 }
204
205 inline void set_personalization(const std::string& personalization)
206 {
207 p = personalization;
208 }
209
210 inline void set_nonce(const std::string& nonce)
211 {
212 n = nonce;
213 }
214
215 inline void set_key(const std::string& key)
216 {
217 k = key;
218 }
219
220 inline void init()
221 {
222 squeezing = false;
223 tweak[0] = 0ULL;
224 pos = 0;
225 total = 0;
226 zero_memory(H);
227 inject_parameter(k, 0ULL);
228 tweak[1] = (1ULL << 62) | (4ULL << 56) | (1ULL << 63);
229 zero_memory(m);
230 m[0] = 0x53;
231 m[1] = 0x48;
232 m[2] = 0x41;
233 m[3] = 0x33;
234 m[4] = 0x01;
235 uint64_t size64 = XOF ? static_cast<uint64_t>(-1) : hs;
236 memcpy(&m[8], &size64, 8);
237 transform(m.data(), 1, 32);
238 pos = 0;
239 total = 0;
240 tweak[0] = 0ULL;
241 tweak[1] = (1ULL << 62) | (48ULL << 56);
242 inject_parameter(p, 8ULL);
243 inject_parameter(n, 20ULL);
244
245 }
246
247 inline void update(const unsigned char* data, size_t len)
248 {
249 detail::absorb_bytes(data, len, N / 8, N / 8 + 1, m.data(), pos, total,
250 [this](const unsigned char* data, size_t len) { transform(data, len, N / 8); });
251 }
252
253 inline void squeeze(unsigned char* hash, size_t hs)
254 {
255 size_t processed = 0;
256 if (!squeezing)
257 {
258 squeezing = true;
259 tweak[1] |= 1ull << 63; // last block
260 if (pos < N / 8)
261 memset(&m[pos], 0, N / 8 - pos);
262
263 transform(m.data(), 1, pos);
264 memset(&m[0], 0, N / 8);
265 memcpy(&hbk[0], H.data(), N / 8);
266 pos = 0;
267 total = 0;
268 }
269 else if (pos < N / 8)
270 {
271 size_t to_copy = std::min(hs, N / 8 - pos);
272 memcpy(hash, reinterpret_cast<unsigned char*>(H.data()) + pos, to_copy);
273 processed += to_copy;
274 pos += to_copy;
275 }
276 while (processed < hs)
277 {
278 pos = std::min(hs - processed, N / 8);
279 tweak[0] = 0;
280 tweak[1] = 255ULL << 56;
281 memcpy(&m[0], &total, 8);
282 memcpy(&H[0], hbk.data(), N / 8);
283 transform(m.data(), 1, 8);
284 memcpy(hash + processed, H.data(), pos);
285 processed += pos;
286 ++total;
287 }
288 }
289
290 inline void final(unsigned char* hash)
291 {
292 return squeeze(hash, hs / 8);
293 }
294
295 inline size_t hash_size() const
296 {
297 return hs;
298 }
299
300 inline void clear()
301 {
302 zero_memory(H);
303 zero_memory(hbk);
304 zero_memory(m);
305 zero_memory(tweak);
306 zero_memory(p);
307 zero_memory(n);
308 zero_memory(k);
309 p.clear();
310 n.clear();
311 k.clear();
312 }
313
314private:
315 inline void transform(const unsigned char* mp, uint64_t num_blks, size_t reallen)
316 {
317 uint64_t keys[N / 64 + 1];
318 uint64_t tweaks[3];
319
320 for (uint64_t b = 0; b < num_blks; b++)
321 {
322 uint64_t M[N / 64];
323 uint64_t G[N / 64];
324 for (uint64_t i = 0; i < N / 64; i++)
325 {
326 M[i] = (reinterpret_cast<const uint64_t*>(mp)[b * N / 64 + i]);
327 }
328 memcpy(keys, H.data(), sizeof(uint64_t) * N / 64);
329 memcpy(tweaks, tweak.data(), sizeof(uint64_t) * 2);
330 tweaks[0] += reallen;
331 tweaks[2] = tweaks[0] ^ tweaks[1];
332 keys[N / 64] = 0x1BD11BDAA9FC1A22ULL;
333 for (int i = 0; i < N / 64; i++)
334 {
335 keys[N / 64] ^= keys[i];
336 G[i] = M[i] + keys[i];
337 }
338 G[N / 64 - 3] += tweaks[0];
339 G[N / 64 - 2] += tweaks[1];
340
341 skein_functions<N / 64>::template G8<0>(G, keys, tweaks);
342 skein_functions<N / 64>::template G8<2>(G, keys, tweaks);
343 skein_functions<N / 64>::template G8<4>(G, keys, tweaks);
344 skein_functions<N / 64>::template G8<6>(G, keys, tweaks);
345 skein_functions<N / 64>::template G8<8>(G, keys, tweaks);
346 skein_functions<N / 64>::template G8<10>(G, keys, tweaks);
347 skein_functions<N / 64>::template G8<12>(G, keys, tweaks);
348 skein_functions<N / 64>::template G8<14>(G, keys, tweaks);
349 skein_functions<N / 64>::template G8<16>(G, keys, tweaks);
350 if (N == 1024)
351 skein_functions<N / 64>::template G8<18>(G, keys, tweaks);
352
353 tweaks[1] &= ~(64ULL << 56);
354 tweak[0] = tweaks[0];
355 tweak[1] = tweaks[1];
356
357 for (int i = 0; i < N / 64; i++)
358 H[i] = G[i] ^ M[i];
359 }
360 }
361
362 inline void inject_parameter(const std::string& p, uint64_t code)
363 {
364 if (p.empty())
365 return;
366
367 tweak[1] = (1ULL << 62) | (code << 56);
368 update(reinterpret_cast<const unsigned char*>(p.data()), p.length());
369 tweak[1] |= 1ull << 63; // last block
370 if (pos < N / 8)
371 memset(&m[pos], 0, N / 8 - pos);
372 transform(m.data(), 1, pos);
373 squeezing = false;
374 pos = 0;
375 total = 0;
376 tweak[0] = 0ULL;
377 tweak[1] = (1ULL << 62) | (48ULL << 56);
378 }
379
380 std::array<uint64_t, N / 64> H, hbk;
381 std::array<unsigned char, N / 8> m;
382 size_t pos;
383 uint64_t total;
384 std::array<uint64_t, 2> tweak;
385 size_t hs;
386 bool squeezing;
387 std::string p, n, k;
388};
389
390
391} // namespace detail
392
393} // namespace digestpp
394
395#endif
Definition skein_provider.hpp:182
void update(const unsigned char *data, size_t len)
Definition skein_provider.hpp:247
void squeeze(unsigned char *hash, size_t hs)
Definition skein_provider.hpp:253
skein_provider(size_t hashsize=N)
Definition skein_provider.hpp:187
void set_key(const std::string &key)
Definition skein_provider.hpp:215
size_t hash_size() const
Definition skein_provider.hpp:295
void clear()
Definition skein_provider.hpp:300
void set_nonce(const std::string &nonce)
Definition skein_provider.hpp:210
void set_personalization(const std::string &personalization)
Definition skein_provider.hpp:205
void init()
Definition skein_provider.hpp:220
~skein_provider()
Definition skein_provider.hpp:200
void validate_hash_size(size_t hs, std::initializer_list< size_t > set)
Definition validate_hash_size.hpp:14
uint32_t rotate_left(uint32_t x, unsigned n)
Definition functions.hpp:67
void zero_memory(void *v, size_t n)
Definition functions.hpp:85
void absorb_bytes(const unsigned char *data, size_t len, size_t bs, size_t bschk, unsigned char *m, size_t &pos, T &total, TF transform)
Definition absorb_data.hpp:16
digestpp namespace
Definition ascon.hpp:14
Definition traits.hpp:17
Definition skein_constants.hpp:16
static void GTv4(uint64_t *G)
Definition skein_provider.hpp:115
static void KStRv4(uint64_t *G, uint64_t *keys, uint64_t *tweaks)
Definition skein_provider.hpp:144
static void G8(uint64_t *G, uint64_t *keys, uint64_t *tweaks)
Definition skein_provider.hpp:165
static void GTv4(uint64_t *G)
Definition skein_provider.hpp:28
static void G8(uint64_t *G, uint64_t *keys, uint64_t *tweaks)
Definition skein_provider.hpp:48
static void KStRv4(uint64_t *G, uint64_t *keys, uint64_t *tweaks)
Definition skein_provider.hpp:39
static void GTv4(uint64_t *G)
Definition skein_provider.hpp:66
static void G8(uint64_t *G, uint64_t *keys, uint64_t *tweaks)
Definition skein_provider.hpp:96
static void KStRv4(uint64_t *G, uint64_t *keys, uint64_t *tweaks)
Definition skein_provider.hpp:83
Definition skein_provider.hpp:22