digestpp 1.0
C++11 header-only message digest library
Loading...
Searching...
No Matches
echo_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_ECHO_HPP
6#define DIGESTPP_PROVIDERS_ECHO_HPP
7
12#include <array>
13
14namespace digestpp
15{
16
17namespace detail
18{
19
20namespace echo_functions
21{
22 static inline void shift_rows(uint64_t* w)
23 {
24 std::swap(w[2], w[10]);
25 std::swap(w[3], w[11]);
26 std::swap(w[4], w[20]);
27 std::swap(w[5], w[21]);
28 std::swap(w[6], w[30]);
29 std::swap(w[7], w[31]);
30 std::swap(w[12], w[28]);
31 std::swap(w[13], w[29]);
32 std::swap(w[22], w[14]);
33 std::swap(w[23], w[15]);
34 std::swap(w[30], w[14]);
35 std::swap(w[31], w[15]);
36 std::swap(w[26], w[18]);
37 std::swap(w[27], w[19]);
38 std::swap(w[26], w[10]);
39 std::swap(w[27], w[11]);
40 }
41
42 static inline void mix_columns(uint64_t* w)
43 {
44 for (int i = 0; i < 4; i++)
45 {
46 for (int j = 0; j < 2; j++)
47 {
48 const uint64_t firstbits = 0xfefefefefefefefeull;
49 const uint64_t lastbit = 0x0101010101010101ull;
50 size_t idx = i * 4 * 2 + j;
51 uint64_t a = w[idx];
52 uint64_t b = w[idx + 2];
53 uint64_t c = w[idx + 4];
54 uint64_t d = w[idx + 6];
55
56 uint64_t dblA = ((a << 1) & firstbits) ^ (((a >> 7) & lastbit) * 0x1b);
57 uint64_t dblB = ((b << 1) & firstbits) ^ (((b >> 7) & lastbit) * 0x1b);
58 uint64_t dblC = ((c << 1) & firstbits) ^ (((c >> 7) & lastbit) * 0x1b);
59 uint64_t dblD = ((d << 1) & firstbits) ^ (((d >> 7) & lastbit) * 0x1b);
60
61 w[idx] = dblA ^ dblB ^ b ^ c ^ d;
62 w[idx + 2] = dblB ^ dblC ^ c ^ d ^ a;
63 w[idx + 4] = dblC ^ dblD ^ d ^ a ^ b;
64 w[idx + 6] = dblD ^ dblA ^ a ^ b ^ c;
65 }
66 }
67 }
68
69 static inline void sub_words(uint64_t* w, uint64_t* salt, uint64_t& counter)
70 {
71 for (int r = 0; r < 16; r++)
72 {
73 size_t idx = r * 2;
74 size_t idx1 = r * 2 + 1;
75 uint32_t t0 = static_cast<uint32_t>(counter)
76 ^ echo_constants<void>::T[0][(unsigned char)(w[idx])]
77 ^ echo_constants<void>::T[1][(unsigned char)(w[idx] >> 40)]
78 ^ echo_constants<void>::T[2][(unsigned char)(w[idx1] >> 16)]
79 ^ echo_constants<void>::T[3][(unsigned char)(w[idx1] >> 56)];
80 uint32_t t1 = (counter >> 32)
81 ^ echo_constants<void>::T[0][(unsigned char)(w[idx] >> 32)]
82 ^ echo_constants<void>::T[1][(unsigned char)(w[idx1] >> 8)]
83 ^ echo_constants<void>::T[2][(unsigned char)(w[idx1] >> 48)]
84 ^ echo_constants<void>::T[3][(unsigned char)(w[idx] >> 24)];
85 uint32_t t2 = echo_constants<void>::T[0][(unsigned char)(w[idx1])]
86 ^ echo_constants<void>::T[1][(unsigned char)(w[idx1] >> 40)]
87 ^ echo_constants<void>::T[2][(unsigned char)(w[idx] >> 16)]
88 ^ echo_constants<void>::T[3][(unsigned char)(w[idx] >> 56)];
89 uint32_t t3 = echo_constants<void>::T[0][(unsigned char)(w[idx1] >> 32)]
90 ^ echo_constants<void>::T[1][(unsigned char)(w[idx] >> 8)]
91 ^ echo_constants<void>::T[2][(unsigned char)(w[idx] >> 48)]
92 ^ echo_constants<void>::T[3][(unsigned char)(w[idx1] >> 24)];
93
94 ++counter;
95
96 w[idx] = static_cast<uint64_t>(echo_constants<void>::T[0][(unsigned char)(t0)]
97 ^ echo_constants<void>::T[1][(unsigned char)(t1 >> 8)]
98 ^ echo_constants<void>::T[2][(unsigned char)(t2 >> 16)]
99 ^ echo_constants<void>::T[3][(unsigned char)(t3 >> 24)])
100 ^ (
101 static_cast<uint64_t>(echo_constants<void>::T[0][(unsigned char)(t1)]
102 ^ echo_constants<void>::T[1][(unsigned char)(t2 >> 8)]
103 ^ echo_constants<void>::T[2][(unsigned char)(t3 >> 16)]
104 ^ echo_constants<void>::T[3][(unsigned char)(t0 >> 24)])
105 << 32)
106 ^ salt[0];
107 w[idx + 1] = static_cast<uint64_t>(echo_constants<void>::T[0][(unsigned char)(t2)]
108 ^ echo_constants<void>::T[1][(unsigned char)(t3 >> 8)]
109 ^ echo_constants<void>::T[2][(unsigned char)(t0 >> 16)]
110 ^ echo_constants<void>::T[3][(unsigned char)(t1 >> 24)])
111 ^ (
112 static_cast<uint64_t>(echo_constants<void>::T[0][(unsigned char)(t3)]
113 ^ echo_constants<void>::T[1][(unsigned char)(t0 >> 8)]
114 ^ echo_constants<void>::T[2][(unsigned char)(t1 >> 16)]
115 ^ echo_constants<void>::T[3][(unsigned char)(t2 >> 24)])
116 << 32)
117 ^ salt[1];
118 }
119 }
120
121
122 static inline void final256(uint64_t* h, uint64_t* w)
123 {
124 h[0] = h[0] ^ h[8] ^ h[16] ^ h[24] ^ w[0] ^ w[8] ^ w[16] ^ w[24];
125 h[1] = h[1] ^ h[9] ^ h[17] ^ h[25] ^ w[1] ^ w[9] ^ w[17] ^ w[25];
126 h[2] = h[2] ^ h[10] ^ h[18] ^ h[26] ^ w[2] ^ w[10] ^ w[18] ^ w[26];
127 h[3] = h[3] ^ h[11] ^ h[19] ^ h[27] ^ w[3] ^ w[11] ^ w[19] ^ w[27];
128 h[4] = h[4] ^ h[12] ^ h[20] ^ h[28] ^ w[4] ^ w[12] ^ w[20] ^ w[28];
129 h[5] = h[5] ^ h[13] ^ h[21] ^ h[29] ^ w[5] ^ w[13] ^ w[21] ^ w[29];
130 h[6] = h[6] ^ h[14] ^ h[22] ^ h[30] ^ w[6] ^ w[14] ^ w[22] ^ w[30];
131 h[7] = h[7] ^ h[15] ^ h[23] ^ h[31] ^ w[7] ^ w[15] ^ w[23] ^ w[31];
132 }
133
134 static inline void final512(uint64_t* h, uint64_t* w)
135 {
136 h[0] = h[0] ^ h[16] ^ w[0] ^ w[16];
137 h[1] = h[1] ^ h[17] ^ w[1] ^ w[17];
138 h[2] = h[2] ^ h[18] ^ w[2] ^ w[18];
139 h[3] = h[3] ^ h[19] ^ w[3] ^ w[19];
140 h[4] = h[4] ^ h[20] ^ w[4] ^ w[20];
141 h[5] = h[5] ^ h[21] ^ w[5] ^ w[21];
142 h[6] = h[6] ^ h[22] ^ w[6] ^ w[22];
143 h[7] = h[7] ^ h[23] ^ w[7] ^ w[23];
144 h[8] = h[8] ^ h[24] ^ w[8] ^ w[24];
145 h[9] = h[9] ^ h[25] ^ w[9] ^ w[25];
146 h[10] = h[10] ^ h[26] ^ w[10] ^ w[26];
147 h[11] = h[11] ^ h[27] ^ w[11] ^ w[27];
148 h[12] = h[12] ^ h[28] ^ w[12] ^ w[28];
149 h[13] = h[13] ^ h[29] ^ w[13] ^ w[29];
150 h[14] = h[14] ^ h[30] ^ w[14] ^ w[30];
151 h[15] = h[15] ^ h[31] ^ w[15] ^ w[31];
152 }
153
154}
155
156template<size_t HS = 0>
158{
159public:
160 static const bool is_xof = false;
161
162 template<size_t hss=HS, typename std::enable_if<hss == 0>::type* = nullptr>
163 echo_provider(size_t hashsize)
164 : hs(hashsize)
165 {
166 validate_hash_size(hashsize, 512);
167 zero_memory(salt);
168 }
169
170 template<size_t hss=HS, typename std::enable_if<hss != 0>::type* = nullptr>
172 : hs(hss)
173 {
174 static_assert(hss <= 512 && hss > 0 && hss % 8 == 0);
175 zero_memory(salt);
176 }
177
179 {
180 clear();
181 }
182
183 inline void init()
184 {
185 pos = 0;
186 total = 0;
187 memset(&h[0], 0, sizeof(uint64_t)*32);
188
189 for (int i = 0; i < (hs > 256 ? 8 : 4); i++)
190 {
191 h[2 * i] = hs;
192 h[2 * i + 1] = 0;
193 }
194 }
195
196 inline void set_salt(const unsigned char* salt, size_t salt_len)
197 {
198 if (salt_len && salt_len != 16)
199 throw std::runtime_error("invalid salt length");
200
201 if (salt_len)
202 memcpy(this->salt.data(), salt, salt_len);
203 else
204 memset(this->salt.data(), 0, 16);
205 }
206
207 inline void update(const unsigned char* data, size_t len)
208 {
209 detail::absorb_bytes(data, len, block_bytes(), block_bytes(), reinterpret_cast<unsigned char*>(h.data()) + 256 - block_bytes(), pos, total,
210 [this](const unsigned char* data, size_t num_blks) { transform(data, num_blks, true, block_bytes() * num_blks); });
211 }
212
213 inline void final(unsigned char* hash)
214 {
215 unsigned char* m = reinterpret_cast<unsigned char*>(h.data()) + 256 - block_bytes();
216 total += pos * 8;
217 m[pos++] = 0x80;
218 size_t limit = block_bytes();
219 if (pos > limit - 18)
220 {
221 if (limit != pos)
222 memset(&m[pos], 0, limit - pos);
223 transform(m, 1, true, 0);
224 pos = 0;
225 }
226 memset(&m[pos], 0, limit - 18 - pos);
227 uint16_t hsize = static_cast<uint16_t>(hs);
228 memcpy(&m[limit - 18], &hsize, sizeof(hsize));
229 memcpy(&m[limit - 16], &total, sizeof(total));
230 memset(&m[limit - 8], 0, 8);
231 transform(m, 1, pos > 1, 0);
232
233 memcpy(hash, reinterpret_cast<unsigned char*>(h.data()), hash_size() / 8);
234 }
235
236 inline void clear()
237 {
238 zero_memory(h);
239 zero_memory(salt);
240 }
241
242 inline size_t hash_size() const { return hs; }
243
244private:
245 inline size_t block_bytes() const { return (hs > 256 ? 1024 : 1536) / 8; }
246
247 inline void transform(const unsigned char* mp, size_t num_blks, bool addedbits, uint64_t addtototal)
248 {
249 unsigned char* m = reinterpret_cast<unsigned char*>(h.data()) + 256 - block_bytes();
250 for (size_t blk = 0; blk < num_blks; blk++)
251 {
252 uint64_t w[32];
253
254 uint64_t counter = 0;
255 if (addedbits)
256 {
257 uint64_t delta = std::min(addtototal, static_cast<uint64_t>(block_bytes()));
258 counter = total + (blk * block_bytes() + delta) * 8;
259 addtototal -= delta;
260
261 if (m != mp)
262 memcpy(m, mp + block_bytes() * blk, delta);
263 }
264 memcpy(w, h.data(), sizeof(w));
265 int rounds = hs > 256 ? 10 : 8;
266 for (int l = 0; l < rounds; l++)
267 {
268 echo_functions::sub_words(w, salt.data(), counter);
271 }
272
273 if (hs <= 256)
274 echo_functions::final256(h.data(), w);
275 else
276 echo_functions::final512(h.data(), w);
277 }
278 }
279
280 std::array<uint64_t, 32> h;
281 std::array<uint64_t, 2> salt;
282 size_t hs;
283 size_t pos;
284 uint64_t total;
285
286};
287
288} // namespace detail
289
290} // namespace digestpp
291
292#endif
Definition echo_provider.hpp:158
void init()
Definition echo_provider.hpp:183
size_t hash_size() const
Definition echo_provider.hpp:242
~echo_provider()
Definition echo_provider.hpp:178
void set_salt(const unsigned char *salt, size_t salt_len)
Definition echo_provider.hpp:196
void clear()
Definition echo_provider.hpp:236
echo_provider()
Definition echo_provider.hpp:171
echo_provider(size_t hashsize)
Definition echo_provider.hpp:163
void update(const unsigned char *data, size_t len)
Definition echo_provider.hpp:207
static void mix_columns(uint64_t *w)
Definition echo_provider.hpp:42
static void final256(uint64_t *h, uint64_t *w)
Definition echo_provider.hpp:122
static void shift_rows(uint64_t *w)
Definition echo_provider.hpp:22
static void final512(uint64_t *h, uint64_t *w)
Definition echo_provider.hpp:134
static void sub_words(uint64_t *w, uint64_t *salt, uint64_t &counter)
Definition echo_provider.hpp:69
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 echo_constants.hpp:16
Definition traits.hpp:17