digestpp 1.0
C++11 header-only message digest library
Loading...
Searching...
No Matches
esch_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_ESCH_HPP
6#define DIGESTPP_PROVIDERS_ESCH_HPP
7
12#include <array>
13
14namespace digestpp
15{
16
17namespace detail
18{
19
20namespace esch_functions
21{
22
23template<size_t N>
24static inline void sparkle(std::array<uint32_t, N>& H, int rounds, int ns)
25{
26 for(int s = 0; s < ns; s++)
27 {
28 H[1] ^= esch_constants<void>::C[s % 8];
29 H[3] ^= s;
30 for (int j = 0, px = 0, py = 1; j < rounds; j++, px += 2, py += 2)
31 {
32 H[px] += rotate_right(H[py], 31);
33 H[py] ^= rotate_right(H[px], 24);
34 H[px] ^= esch_constants<void>::C[j];
35 H[px] += rotate_right(H[py], 17);
36 H[py] ^= rotate_right(H[px], 17);
37 H[px] ^= esch_constants<void>::C[j];
38 H[px] += H[py];
39 H[py] ^= rotate_right(H[px], 31);
40 H[px] ^= esch_constants<void>::C[j];
41 H[px] += rotate_right(H[py], 24);
42 H[py] ^= rotate_right(H[px], 16);
43 H[px] ^= esch_constants<void>::C[j];
44 }
45 uint32_t x = H[0] ^ H[2] ^ H[4];
46 uint32_t y = H[1] ^ H[3] ^ H[5];
47 if (rounds > 6)
48 {
49 x ^= H[6];
50 y ^= H[7];
51 }
52 x = rotate_right(x ^ (x << 16), 16);
53 y = rotate_right(y ^ (y << 16), 16);
54
55 for (int i = 0, j = rounds; i < rounds; i+=2, j+=2)
56 {
57 H[j] ^= H[i] ^ y;
58 H[j + 1] ^= H[i + 1] ^ x;
59 }
60 x = H[rounds];
61 y = H[rounds + 1];
62 for (int i = 0; i < rounds - 2; i++)
63 {
64 H[i + rounds] = H[i];
65 H[i] = H[i + rounds + 2];
66 }
67 H[rounds * 2 - 2] = H[rounds - 2];
68 H[rounds * 2 - 1] = H[rounds - 1];
69 H[rounds - 2] = x;
70 H[rounds - 1] = y;
71 }
72}
73
74}
75
76template<size_t N, bool XOF, size_t HS = 0>
78{
79public:
80 static const bool is_xof = XOF;
81
82 template<bool xof=XOF, size_t hss = HS, typename std::enable_if<!xof && hss == 0>::type* = nullptr>
83 esch_provider(size_t hashsize)
84 : hs(hashsize), squeezing(false)
85 {
86 static_assert(N == 384 || N == 512, "Esch only supports 384 and 512 bits state size");
87 validate_hash_size(hashsize, {256, 384});
88 }
89
90 template<bool xof=XOF, size_t hss = HS, typename std::enable_if<!xof && hss != 0>::type* = nullptr>
92 : hs(hss), squeezing(false)
93 {
94 static_assert(N == 384 || N == 512, "Esch only supports 384 and 512 bits state size");
95 static_assert(hss == 256 || hss == 384, "Esch only supports output size of 256 and 384 bits");
96 }
97
98 template<bool xof=XOF, typename std::enable_if<xof>::type* = nullptr>
99 esch_provider() : hs(N - 128), squeezing(false)
100 {
101 static_assert(N == 384 || N == 512, "Esch only supports 384 and 512 bits state size");
102 }
103
105 {
106 clear();
107 }
108
109 inline void init()
110 {
111 pos = 0;
112 total = 0;
113 squeezing = false;
114 zero_memory(H);
115 zero_memory(m);
116 }
117
118 inline void update(const unsigned char* data, size_t len)
119 {
120 detail::absorb_bytes(data, len, 16, 16 + 1, m.data(), pos, total,
121 [this](const unsigned char* data, size_t len) { transform(data, len, false); });
122 }
123
124 inline void squeeze(unsigned char* hash, size_t hss)
125 {
126 size_t processed = 0;
127 if (!squeezing)
128 {
129 total = 1;
130 squeezing = true;
131 if (pos < 16)
132 {
133 memset(&m[pos], 0, 16 - pos);
134 m[pos] = 0x80;
135 H[(hs+128)/64 - 1] ^= (XOF ? 0x5000000 : 0x1000000);
136 }
137 else
138 H[(hs+128)/64 - 1] ^= (XOF ? 0x6000000 : 0x2000000);
139
140 transform(m.data(), 1, true);
141 }
142 else if (pos < 16)
143 {
144 size_t to_copy = std::min(hss, 16 - pos);
145 memcpy(hash, reinterpret_cast<unsigned char*>(H.data()) + pos, to_copy);
146 processed += to_copy;
147 pos += to_copy;
148 total = 0;
149 }
150
151 while (processed < hss)
152 {
153 if (!total)
154 esch_functions::sparkle(H, hs > 256 ? 8 : 6, hs > 256 ? 8 : 7);
155 pos = std::min(hss - processed, static_cast<size_t>(16));
156 memcpy(hash + processed, H.data(), pos);
157 processed += pos;
158 total = 0;
159 }
160 }
161
162 inline void final(unsigned char* hash)
163 {
164 return squeeze(hash, hs / 8);
165 }
166
167 inline void clear()
168 {
169 zero_memory(H);
170 zero_memory(m);
171 }
172
173 inline size_t hash_size() const { return hs; }
174
175private:
176
177 inline void transform(const unsigned char* data, size_t num_blks, bool lastBlock)
178 {
179 for (size_t blk = 0; blk < num_blks; blk++)
180 {
181 uint32_t M[4];
182 for (int i = 0; i < 4; i++)
183 M[i] = reinterpret_cast<const uint32_t*>(data)[blk * 4 + i];
184 uint32_t x = M[0] ^ M[2];
185 uint32_t y = M[1] ^ M[3];
186 x = rotate_right(x ^ (x << 16), 16);
187 y = rotate_right(y ^ (y << 16), 16);
188 H[0] = H[0] ^ M[0] ^ y;
189 H[1] = H[1] ^ M[1] ^ x;
190 H[2] = H[2] ^ M[2] ^ y;
191 H[3] = H[3] ^ M[3] ^ x;
192 H[4] ^= y;
193 H[5] ^= x;
194 if (hs > 256)
195 {
196 H[6] ^= y;
197 H[7] ^= x;
198 }
199 int steps = lastBlock ? 11 : 7;
200 if (hs > 256)
201 steps++;
202 esch_functions::sparkle(H, hs > 256 ? 8 : 6, steps);
203 }
204 }
205
206
207 std::array<uint32_t, N / 32> H;
208 std::array<unsigned char, 128> m;
209 size_t pos;
210 uint64_t total;
211 size_t hs;
212 bool squeezing;
213};
214
215} // namespace detail
216
217} // namespace digestpp
218
219#endif
Definition esch_provider.hpp:78
void init()
Definition esch_provider.hpp:109
void squeeze(unsigned char *hash, size_t hss)
Definition esch_provider.hpp:124
void update(const unsigned char *data, size_t len)
Definition esch_provider.hpp:118
void clear()
Definition esch_provider.hpp:167
esch_provider()
Definition esch_provider.hpp:99
size_t hash_size() const
Definition esch_provider.hpp:173
esch_provider(size_t hashsize)
Definition esch_provider.hpp:83
esch_provider()
Definition esch_provider.hpp:91
~esch_provider()
Definition esch_provider.hpp:104
static void sparkle(std::array< uint32_t, N > &H, int rounds, int ns)
Definition esch_provider.hpp:24
uint32_t rotate_right(uint32_t x, unsigned n)
Definition functions.hpp:61
void validate_hash_size(size_t hs, std::initializer_list< size_t > set)
Definition validate_hash_size.hpp:14
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 esch_constants.hpp:16
Definition traits.hpp:17