digestpp 1.0
C++11 header-only message digest library
Loading...
Searching...
No Matches
blake2p_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_BLAKE2P_HPP
6#define DIGESTPP_PROVIDERS_BLAKE2P_HPP
7
11#include "blake2_provider.hpp"
12#include <array>
13#include <limits>
14
15namespace digestpp
16{
17
18namespace detail
19{
20
21template<typename T, blake2_type type, size_t HS = 0>
23{
24public:
25 static const bool is_xof = type == blake2_type::xof;
26
27 template<size_t hss=HS, typename std::enable_if<hss == 0>::type* = nullptr>
28 blake2p_provider(size_t hashsize = N)
29 : main(hashsize), hs(hashsize), squeezing(false)
30 {
31 static_assert(sizeof(T) == 8 || sizeof(T) == 4, "Invalid T size");
32
33 if (type == blake2_type::hash)
34 detail::validate_hash_size(hashsize, N);
35 else if (type == blake2_type::x_hash)
36 detail::validate_hash_size(hashsize, N * sizeof(T) * 4 - 16);
37
38 main.set_blake2p_params(P, 1, 0);
39
40 for (size_t p = 0; p < P; p++)
41 {
42 leaf[p] = blake2_provider<T, type, HS>(hashsize);
43 leaf[p].set_blake2p_params(static_cast<uint8_t>(P), 0, static_cast<uint8_t>(p));
44 }
45 }
46
47 template<size_t hss=HS, typename std::enable_if<hss != 0>::type* = nullptr>
49 : main(), hs(hss), squeezing(false)
50 {
51 static_assert(sizeof(T) == 8 || sizeof(T) == 4, "Invalid T size");
52
53 const size_t limit = type == blake2_type::hash ? N : type == blake2_type::x_hash ? N * sizeof(T) * 4 - 16 : SIZE_MAX;
54 static_assert(hss <= limit && hss > 0 && hss % 8 == 0);
55
56 main.set_blake2p_params(P, 1, 0);
57
58 for (size_t p = 0; p < P; p++)
59 {
60 leaf[p].set_blake2p_params(static_cast<uint8_t>(P), 0, static_cast<uint8_t>(p));
61 }
62 }
63
65 {
66 clear();
67 }
68
69 inline void init()
70 {
71 pos = 0;
72 total = 0;
73 squeezing = false;
74
75 main.init();
76 for (size_t p = 0; p < P; p++)
77 {
78 leaf[p].init();
79 }
80 }
81
82 inline void update(const unsigned char* data, size_t len)
83 {
84 detail::absorb_bytes(data, len, m.size(), m.size(), m.data(), pos, total,
85 [this](const unsigned char* data, size_t len) { transform(data, len); });
86 }
87
88 inline void set_key(const std::string& key)
89 {
90 main.set_key(key);
91 for (size_t p = 0; p < P; p++)
92 leaf[p].set_key(key);
93 }
94
95 inline void set_salt(const unsigned char* salt, size_t salt_len)
96 {
97 main.set_salt(salt, salt_len);
98 for (size_t p = 0; p < P; p++)
99 leaf[p].set_salt(salt, salt_len);
100 }
101
102 inline void set_personalization(const unsigned char* personalization, size_t personalization_len)
103 {
104 main.set_personalization(personalization, personalization_len);
105 for (size_t p = 0; p < P; p++)
106 leaf[p].set_personalization(personalization, personalization_len);
107 }
108
109 inline void squeeze(unsigned char* hash, size_t hs)
110 {
111 size_t processed = 0;
112 if (!squeezing)
113 {
114 squeezing = true;
115 finalize();
116 }
117 main.squeeze(hash, hs);
118 }
119
120 inline void final(unsigned char* hash)
121 {
122 total += pos * 8;
123 if (type == blake2_type::hash)
124 {
125 finalize();
126 main.final(hash);
127 }
128 else
129 squeeze(hash, hs / 8);
130 }
131
132 inline void clear()
133 {
134 zero_memory(m);
135 main.clear();
136 for (size_t p = 0; p < P; p++)
137 leaf[p].clear();
138 }
139
140 inline size_t hash_size() const { return hs; }
141
142private:
143
144 inline void finalize()
145 {
146 if (512 != pos)
147 memset(&m[pos], 0, 512 - pos);
148 for (size_t i = 0; i < P; i++)
149 {
150 if (pos > i * sizeof(T) * 16)
151 {
152 size_t prev = i * sizeof(T) * 16;
153 size_t next = prev + sizeof(T) * 16;
154 size_t len = pos < next ? pos - prev : sizeof(T) * 16;
155 leaf[i].update(&m[i * sizeof(T) * 16], len);
156 }
157 uint8_t buf[N / 8];
158 leaf[i].final(buf, N);
159 main.update(buf, sizeof(buf));
160 }
161 }
162
163 inline void transform(const unsigned char* data, size_t num_blks)
164 {
165#ifdef _OPENMP
166#pragma omp parallel for
167#endif
168 for (int i = 0; i < static_cast<int>(P); i++)
169 {
170 for (size_t blk = 0; blk < num_blks; blk++)
171 {
172 leaf[i].update(data + blk * 512 + i * 16 * sizeof(T), sizeof(T) * 16);
173 }
174 }
175 }
176
177 constexpr static size_t N = sizeof(T) == 8 ? 512 : 256;
178 constexpr static size_t P = sizeof(T) == 8 ? 4 : 8;
179 blake2_provider<T, type, HS> main;
180 std::array<blake2_provider<T, type, HS>, P> leaf;
181 std::array<unsigned char, 512> m;
182 size_t pos;
183 uint64_t total;
184 size_t hs;
185 bool squeezing;
186};
187
188} // namespace detail
189
190} // namespace digestpp
191
192#endif
Definition blake2_provider.hpp:116
Definition blake2p_provider.hpp:23
void set_salt(const unsigned char *salt, size_t salt_len)
Definition blake2p_provider.hpp:95
void init()
Definition blake2p_provider.hpp:69
void set_personalization(const unsigned char *personalization, size_t personalization_len)
Definition blake2p_provider.hpp:102
blake2p_provider()
Definition blake2p_provider.hpp:48
~blake2p_provider()
Definition blake2p_provider.hpp:64
size_t hash_size() const
Definition blake2p_provider.hpp:140
blake2p_provider(size_t hashsize=N)
Definition blake2p_provider.hpp:28
void clear()
Definition blake2p_provider.hpp:132
void set_key(const std::string &key)
Definition blake2p_provider.hpp:88
void update(const unsigned char *data, size_t len)
Definition blake2p_provider.hpp:82
void squeeze(unsigned char *hash, size_t hs)
Definition blake2p_provider.hpp:109
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 traits.hpp:17