Line data Source code
1 : // Copyright (c) 2018 The Dash Core developers
2 : // Copyright (c) 2021 The PIVX Core developers
3 : // Distributed under the MIT software license, see the accompanying
4 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 :
6 : #include "bls/bls_wrapper.h"
7 :
8 : #include "random.h"
9 : #include "tinyformat.h"
10 :
11 : #ifndef BUILD_BITCOIN_INTERNAL
12 : #include "support/allocators/mt_pooled_secure.h"
13 : #endif
14 :
15 : #include <assert.h>
16 : #include <string.h>
17 :
18 : static std::unique_ptr<bls::CoreMPL> pScheme(new bls::BasicSchemeMPL);
19 :
20 1595 : CBLSId::CBLSId(const uint256& nHash) : CBLSWrapper<CBLSIdImplicit, BLS_CURVE_ID_SIZE, CBLSId>()
21 : {
22 1595 : impl = nHash;
23 1595 : fValid = true;
24 1595 : cachedHash.SetNull();
25 1595 : }
26 :
27 1877 : void CBLSSecretKey::AggregateInsecure(const CBLSSecretKey& o)
28 : {
29 1877 : assert(IsValid() && o.IsValid());
30 5631 : impl = bls::PrivateKey::Aggregate({impl, o.impl});
31 1877 : cachedHash.SetNull();
32 1877 : }
33 :
34 5 : CBLSSecretKey CBLSSecretKey::AggregateInsecure(const std::vector<CBLSSecretKey>& sks)
35 : {
36 5 : if (sks.empty()) {
37 5 : return CBLSSecretKey();
38 : }
39 :
40 5 : std::vector<bls::PrivateKey> v;
41 5 : v.reserve(sks.size());
42 17 : for (auto& sk : sks) {
43 12 : v.emplace_back(sk.impl);
44 : }
45 :
46 10 : CBLSSecretKey ret;
47 5 : ret.impl = bls::PrivateKey::Aggregate(v);
48 5 : ret.fValid = true;
49 5 : ret.cachedHash.SetNull();
50 5 : return ret;
51 : }
52 :
53 : #ifndef BUILD_BITCOIN_INTERNAL
54 1628 : void CBLSSecretKey::MakeNewKey()
55 : {
56 3638 : unsigned char buf[32];
57 3638 : while (true) {
58 3638 : GetStrongRandBytes(buf, sizeof(buf));
59 3638 : try {
60 3638 : impl = bls::PrivateKey::FromBytes(bls::Bytes((const uint8_t*)buf, SerSize));
61 1628 : break;
62 2010 : } catch (...) {
63 : }
64 : }
65 1628 : fValid = true;
66 1628 : cachedHash.SetNull();
67 1628 : }
68 : #endif
69 :
70 1798 : bool CBLSSecretKey::SecretKeyShare(const std::vector<CBLSSecretKey>& msk, const CBLSId& _id)
71 : {
72 1798 : fValid = false;
73 1798 : cachedHash.SetNull();
74 :
75 1798 : if (!_id.IsValid()) {
76 : return false;
77 : }
78 :
79 3596 : std::vector<bls::PrivateKey> mskVec;
80 1798 : mskVec.reserve(msk.size());
81 50194 : for (const CBLSSecretKey& sk : msk) {
82 48396 : if (!sk.IsValid()) {
83 0 : return false;
84 : }
85 48396 : mskVec.emplace_back(sk.impl);
86 : }
87 :
88 1798 : try {
89 1798 : impl = bls::Threshold::PrivateKeyShare(mskVec, bls::Bytes(_id.impl.begin(), _id.impl.size()));
90 0 : } catch (...) {
91 0 : return false;
92 : }
93 :
94 1798 : fValid = true;
95 1798 : cachedHash.SetNull();
96 1798 : return true;
97 : }
98 :
99 5073 : CBLSPublicKey CBLSSecretKey::GetPublicKey() const
100 : {
101 5073 : if (!IsValid()) {
102 0 : return CBLSPublicKey();
103 : }
104 :
105 5073 : CBLSPublicKey pubKey;
106 5073 : pubKey.impl = impl.GetG1Element();
107 5073 : pubKey.fValid = true;
108 5073 : pubKey.cachedHash.SetNull();
109 5073 : return pubKey;
110 : }
111 :
112 1198 : CBLSSignature CBLSSecretKey::Sign(const uint256& hash) const
113 : {
114 1198 : if (!IsValid()) {
115 0 : return CBLSSignature();
116 : }
117 :
118 1198 : CBLSSignature sigRet;
119 1198 : sigRet.impl = pScheme->Sign(impl, bls::Bytes(hash.begin(), hash.size()));
120 :
121 1198 : sigRet.fValid = true;
122 1198 : sigRet.cachedHash.SetNull();
123 :
124 1198 : return sigRet;
125 : }
126 :
127 1 : bool CBLSSecretKey::Recover(const std::vector<CBLSSecretKey>& keys, const std::vector<CBLSId>& ids)
128 : {
129 1 : fValid = false;
130 1 : cachedHash.SetNull();
131 :
132 1 : if (keys.empty() || ids.empty() || keys.size() != ids.size()) {
133 : return false;
134 : }
135 :
136 1 : std::vector<bls::PrivateKey> keysVec;
137 1 : std::vector<bls::Bytes> idsVec;
138 1 : keysVec.reserve(keys.size());
139 1 : idsVec.reserve(keys.size());
140 :
141 31 : for (size_t i = 0; i < keys.size(); i++) {
142 30 : if (!keys[i].IsValid() || !ids[i].IsValid()) {
143 : return false;
144 : }
145 30 : keysVec.emplace_back(keys[i].impl);
146 30 : idsVec.emplace_back(ids[i].impl.begin(), ids[i].impl.size());
147 : }
148 :
149 1 : try {
150 1 : impl = bls::Threshold::PrivateKeyRecover(keysVec, idsVec);
151 0 : } catch (...) {
152 0 : return false;
153 : }
154 :
155 1 : fValid = true;
156 1 : cachedHash.SetNull();
157 1 : return true;
158 : }
159 :
160 3472 : void CBLSPublicKey::AggregateInsecure(const CBLSPublicKey& o)
161 : {
162 3472 : assert(IsValid() && o.IsValid());
163 3472 : impl = pScheme->Aggregate({impl, o.impl});
164 3472 : cachedHash.SetNull();
165 3472 : }
166 :
167 5 : CBLSPublicKey CBLSPublicKey::AggregateInsecure(const std::vector<CBLSPublicKey>& pks)
168 : {
169 5 : if (pks.empty()) {
170 5 : return CBLSPublicKey();
171 : }
172 :
173 10 : std::vector<bls::G1Element> vecPublicKeys;
174 5 : vecPublicKeys.reserve(pks.size());
175 17 : for (auto& pk : pks) {
176 12 : vecPublicKeys.emplace_back(pk.impl);
177 : }
178 :
179 5 : CBLSPublicKey ret;
180 5 : ret.impl = pScheme->Aggregate(vecPublicKeys);
181 5 : ret.fValid = true;
182 5 : ret.cachedHash.SetNull();
183 5 : return ret;
184 : }
185 :
186 3625 : bool CBLSPublicKey::PublicKeyShare(const std::vector<CBLSPublicKey>& mpk, const CBLSId& _id)
187 : {
188 3625 : fValid = false;
189 3625 : cachedHash.SetNull();
190 :
191 3625 : if (!_id.IsValid()) {
192 : return false;
193 : }
194 :
195 7250 : std::vector<bls::G1Element> mpkVec;
196 3625 : mpkVec.reserve(mpk.size());
197 100475 : for (const CBLSPublicKey& pk : mpk) {
198 96850 : if (!pk.IsValid()) {
199 0 : return false;
200 : }
201 96850 : mpkVec.emplace_back(pk.impl);
202 : }
203 :
204 3625 : try {
205 3625 : impl = bls::Threshold::PublicKeyShare(mpkVec, bls::Bytes(_id.impl.begin(), _id.impl.size()));
206 0 : } catch (...) {
207 0 : return false;
208 : }
209 :
210 3625 : fValid = true;
211 3625 : cachedHash.SetNull();
212 3625 : return true;
213 : }
214 :
215 3590 : bool CBLSPublicKey::DHKeyExchange(const CBLSSecretKey& sk, const CBLSPublicKey& pk)
216 : {
217 3590 : fValid = false;
218 3590 : cachedHash.SetNull();
219 :
220 3590 : if (!sk.IsValid() || !pk.IsValid()) {
221 : return false;
222 : }
223 3590 : impl = sk.impl * pk.impl;
224 3590 : fValid = true;
225 3590 : cachedHash.SetNull();
226 3590 : return true;
227 : }
228 :
229 779 : void CBLSSignature::AggregateInsecure(const CBLSSignature& o)
230 : {
231 779 : assert(IsValid() && o.IsValid());
232 779 : impl = pScheme->Aggregate({impl, o.impl});
233 779 : cachedHash.SetNull();
234 779 : }
235 :
236 0 : CBLSSignature CBLSSignature::AggregateInsecure(const std::vector<CBLSSignature>& sigs)
237 : {
238 0 : if (sigs.empty()) {
239 0 : return CBLSSignature();
240 : }
241 :
242 0 : std::vector<bls::G2Element> v;
243 0 : v.reserve(sigs.size());
244 0 : for (auto& pk : sigs) {
245 0 : v.emplace_back(pk.impl);
246 : }
247 :
248 0 : CBLSSignature ret;
249 0 : ret.impl = pScheme->Aggregate(v);
250 0 : ret.fValid = true;
251 0 : ret.cachedHash.SetNull();
252 0 : return ret;
253 : }
254 :
255 64 : CBLSSignature CBLSSignature::AggregateSecure(const std::vector<CBLSSignature>& sigs,
256 : const std::vector<CBLSPublicKey>& pks,
257 : const uint256& hash)
258 : {
259 64 : if (sigs.size() != pks.size() || sigs.empty()) {
260 64 : return CBLSSignature();
261 : }
262 :
263 128 : std::vector<bls::G1Element> vecPublicKeys;
264 64 : vecPublicKeys.reserve(pks.size());
265 239 : for (auto& pk : pks) {
266 175 : vecPublicKeys.push_back(pk.impl);
267 : }
268 :
269 128 : std::vector<bls::G2Element> vecSignatures;
270 64 : vecSignatures.reserve(pks.size());
271 239 : for (auto& sig : sigs) {
272 175 : vecSignatures.push_back(sig.impl);
273 : }
274 :
275 64 : CBLSSignature ret;
276 64 : ret.impl = pScheme->AggregateSecure(vecPublicKeys, vecSignatures, bls::Bytes(hash.begin(), hash.size()));
277 64 : ret.fValid = true;
278 64 : ret.cachedHash.SetNull();
279 64 : return ret;
280 : }
281 :
282 0 : void CBLSSignature::SubInsecure(const CBLSSignature& o)
283 : {
284 0 : assert(IsValid() && o.IsValid());
285 0 : impl = impl + o.impl.Negate();
286 0 : cachedHash.SetNull();
287 0 : }
288 :
289 2326 : bool CBLSSignature::VerifyInsecure(const CBLSPublicKey& pubKey, const uint256& hash) const
290 : {
291 2326 : if (!IsValid() || !pubKey.IsValid()) {
292 : return false;
293 : }
294 :
295 2323 : try {
296 2323 : return pScheme->Verify(pubKey.impl, bls::Bytes(hash.begin(), hash.size()), impl);
297 0 : } catch (...) {
298 0 : return false;
299 : }
300 : }
301 :
302 1342 : bool CBLSSignature::VerifyInsecureAggregated(const std::vector<CBLSPublicKey>& pubKeys, const std::vector<uint256>& hashes) const
303 : {
304 1342 : if (!IsValid()) {
305 : return false;
306 : }
307 1342 : assert(!pubKeys.empty() && !hashes.empty() && pubKeys.size() == hashes.size());
308 :
309 2684 : std::vector<bls::G1Element> pubKeyVec;
310 1342 : std::vector<bls::Bytes> hashes2;
311 1342 : hashes2.reserve(hashes.size());
312 1342 : pubKeyVec.reserve(pubKeys.size());
313 3327 : for (size_t i = 0; i < pubKeys.size(); i++) {
314 1985 : auto& p = pubKeys[i];
315 1985 : if (!p.IsValid()) {
316 : return false;
317 : }
318 1985 : pubKeyVec.push_back(p.impl);
319 1985 : hashes2.emplace_back(hashes[i].begin(), hashes[i].size());
320 : }
321 :
322 1342 : try {
323 1342 : return pScheme->AggregateVerify(pubKeyVec, hashes2, impl);
324 0 : } catch (...) {
325 0 : return false;
326 : }
327 : }
328 :
329 354 : bool CBLSSignature::VerifySecureAggregated(const std::vector<CBLSPublicKey>& pks, const uint256& hash) const
330 : {
331 354 : if (pks.empty()) {
332 : return false;
333 : }
334 :
335 708 : std::vector<bls::G1Element> vecPublicKeys;
336 354 : vecPublicKeys.reserve(pks.size());
337 1307 : for (const auto& pk : pks) {
338 953 : vecPublicKeys.push_back(pk.impl);
339 : }
340 :
341 354 : return pScheme->VerifySecure(vecPublicKeys, impl, bls::Bytes(hash.begin(), hash.size()));
342 : }
343 :
344 279 : bool CBLSSignature::Recover(const std::vector<CBLSSignature>& sigs, const std::vector<CBLSId>& ids)
345 : {
346 279 : fValid = false;
347 279 : cachedHash.SetNull();
348 :
349 279 : if (sigs.empty() || ids.empty() || sigs.size() != ids.size()) {
350 : return false;
351 : }
352 :
353 558 : std::vector<bls::G2Element> sigsVec;
354 279 : std::vector<bls::Bytes> idsVec;
355 279 : sigsVec.reserve(sigs.size());
356 279 : idsVec.reserve(sigs.size());
357 :
358 938 : for (size_t i = 0; i < sigs.size(); i++) {
359 659 : if (!sigs[i].IsValid() || !ids[i].IsValid()) {
360 : return false;
361 : }
362 659 : sigsVec.emplace_back(sigs[i].impl);
363 659 : idsVec.emplace_back(ids[i].impl.begin(), ids[i].impl.size());
364 : }
365 :
366 279 : try {
367 279 : impl = bls::Threshold::SignatureRecover(sigsVec, idsVec);
368 0 : } catch (...) {
369 0 : return false;
370 : }
371 :
372 279 : fValid = true;
373 279 : cachedHash.SetNull();
374 279 : return true;
375 : }
376 :
377 : #ifndef BUILD_BITCOIN_INTERNAL
378 :
379 : static std::once_flag init_flag;
380 : static mt_pooled_secure_allocator<uint8_t>* secure_allocator_instance;
381 77 : static void create_secure_allocator()
382 : {
383 : // make sure LockedPoolManager is initialized first (ensures destruction order)
384 77 : LockedPoolManager::Instance();
385 :
386 : // static variable in function scope ensures it's initialized when first accessed
387 : // and destroyed before LockedPoolManager
388 77 : static mt_pooled_secure_allocator<uint8_t> a(sizeof(bn_t) + sizeof(size_t));
389 77 : secure_allocator_instance = &a;
390 77 : }
391 :
392 746324 : static mt_pooled_secure_allocator<uint8_t>& get_secure_allocator()
393 : {
394 746324 : std::call_once(init_flag, create_secure_allocator);
395 746324 : return *secure_allocator_instance;
396 : }
397 :
398 373162 : static void* secure_allocate(size_t n)
399 : {
400 373162 : uint8_t* ptr = get_secure_allocator().allocate(n + sizeof(size_t));
401 373162 : *(size_t*)ptr = n;
402 373162 : return ptr + sizeof(size_t);
403 : }
404 :
405 373162 : static void secure_free(void* p)
406 : {
407 373162 : if (!p) {
408 : return;
409 : }
410 :
411 373162 : uint8_t* ptr = (uint8_t*)p - sizeof(size_t);
412 373162 : size_t n = *(size_t*)ptr;
413 373162 : return get_secure_allocator().deallocate(ptr, n);
414 : }
415 : #endif
416 :
417 794 : bool BLSInit()
418 : {
419 794 : if (!bls::BLS::Init()) {
420 : return false;
421 : }
422 : #ifndef BUILD_BITCOIN_INTERNAL
423 794 : bls::BLS::SetSecureAllocator(secure_allocate, secure_free);
424 : #endif
425 794 : return true;
426 : }
|