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 2004 : CBLSId::CBLSId(const uint256& nHash) : CBLSWrapper<CBLSIdImplicit, BLS_CURVE_ID_SIZE, CBLSId>()
21 : {
22 2004 : impl = nHash;
23 2004 : fValid = true;
24 2004 : cachedHash.SetNull();
25 2004 : }
26 :
27 1825 : void CBLSSecretKey::AggregateInsecure(const CBLSSecretKey& o)
28 : {
29 1825 : assert(IsValid() && o.IsValid());
30 5475 : impl = bls::PrivateKey::Aggregate({impl, o.impl});
31 1825 : cachedHash.SetNull();
32 1825 : }
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 1636 : void CBLSSecretKey::MakeNewKey()
55 : {
56 3587 : unsigned char buf[32];
57 3587 : while (true) {
58 3587 : GetStrongRandBytes(buf, sizeof(buf));
59 3587 : try {
60 3587 : impl = bls::PrivateKey::FromBytes(bls::Bytes((const uint8_t*)buf, SerSize));
61 1636 : break;
62 1951 : } catch (...) {
63 : }
64 : }
65 1636 : fValid = true;
66 1636 : cachedHash.SetNull();
67 1636 : }
68 : #endif
69 :
70 1807 : bool CBLSSecretKey::SecretKeyShare(const std::vector<CBLSSecretKey>& msk, const CBLSId& _id)
71 : {
72 1807 : fValid = false;
73 1807 : cachedHash.SetNull();
74 :
75 1807 : if (!_id.IsValid()) {
76 : return false;
77 : }
78 :
79 3614 : std::vector<bls::PrivateKey> mskVec;
80 1807 : mskVec.reserve(msk.size());
81 50221 : for (const CBLSSecretKey& sk : msk) {
82 48414 : if (!sk.IsValid()) {
83 0 : return false;
84 : }
85 48414 : mskVec.emplace_back(sk.impl);
86 : }
87 :
88 1807 : try {
89 1807 : impl = bls::Threshold::PrivateKeyShare(mskVec, bls::Bytes(_id.impl.begin(), _id.impl.size()));
90 0 : } catch (...) {
91 0 : return false;
92 : }
93 :
94 1807 : fValid = true;
95 1807 : cachedHash.SetNull();
96 1807 : return true;
97 : }
98 :
99 5067 : CBLSPublicKey CBLSSecretKey::GetPublicKey() const
100 : {
101 5067 : if (!IsValid()) {
102 0 : return CBLSPublicKey();
103 : }
104 :
105 5067 : CBLSPublicKey pubKey;
106 5067 : pubKey.impl = impl.GetG1Element();
107 5067 : pubKey.fValid = true;
108 5067 : pubKey.cachedHash.SetNull();
109 5067 : return pubKey;
110 : }
111 :
112 1540 : CBLSSignature CBLSSecretKey::Sign(const uint256& hash) const
113 : {
114 1540 : if (!IsValid()) {
115 0 : return CBLSSignature();
116 : }
117 :
118 1540 : CBLSSignature sigRet;
119 1540 : sigRet.impl = pScheme->Sign(impl, bls::Bytes(hash.begin(), hash.size()));
120 :
121 1540 : sigRet.fValid = true;
122 1540 : sigRet.cachedHash.SetNull();
123 :
124 1540 : 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 3402 : void CBLSPublicKey::AggregateInsecure(const CBLSPublicKey& o)
161 : {
162 3402 : assert(IsValid() && o.IsValid());
163 3402 : impl = pScheme->Aggregate({impl, o.impl});
164 3402 : cachedHash.SetNull();
165 3402 : }
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 3560 : bool CBLSPublicKey::PublicKeyShare(const std::vector<CBLSPublicKey>& mpk, const CBLSId& _id)
187 : {
188 3560 : fValid = false;
189 3560 : cachedHash.SetNull();
190 :
191 3560 : if (!_id.IsValid()) {
192 : return false;
193 : }
194 :
195 7120 : std::vector<bls::G1Element> mpkVec;
196 3560 : mpkVec.reserve(mpk.size());
197 100280 : for (const CBLSPublicKey& pk : mpk) {
198 96720 : if (!pk.IsValid()) {
199 0 : return false;
200 : }
201 96720 : mpkVec.emplace_back(pk.impl);
202 : }
203 :
204 3560 : try {
205 3560 : impl = bls::Threshold::PublicKeyShare(mpkVec, bls::Bytes(_id.impl.begin(), _id.impl.size()));
206 0 : } catch (...) {
207 0 : return false;
208 : }
209 :
210 3560 : fValid = true;
211 3560 : cachedHash.SetNull();
212 3560 : return true;
213 : }
214 :
215 3584 : bool CBLSPublicKey::DHKeyExchange(const CBLSSecretKey& sk, const CBLSPublicKey& pk)
216 : {
217 3584 : fValid = false;
218 3584 : cachedHash.SetNull();
219 :
220 3584 : if (!sk.IsValid() || !pk.IsValid()) {
221 : return false;
222 : }
223 3584 : impl = sk.impl * pk.impl;
224 3584 : fValid = true;
225 3584 : cachedHash.SetNull();
226 3584 : return true;
227 : }
228 :
229 1304 : void CBLSSignature::AggregateInsecure(const CBLSSignature& o)
230 : {
231 1304 : assert(IsValid() && o.IsValid());
232 1304 : impl = pScheme->Aggregate({impl, o.impl});
233 1304 : cachedHash.SetNull();
234 1304 : }
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 54 : CBLSSignature CBLSSignature::AggregateSecure(const std::vector<CBLSSignature>& sigs,
256 : const std::vector<CBLSPublicKey>& pks,
257 : const uint256& hash)
258 : {
259 54 : if (sigs.size() != pks.size() || sigs.empty()) {
260 54 : return CBLSSignature();
261 : }
262 :
263 108 : std::vector<bls::G1Element> vecPublicKeys;
264 54 : vecPublicKeys.reserve(pks.size());
265 203 : for (auto& pk : pks) {
266 149 : vecPublicKeys.push_back(pk.impl);
267 : }
268 :
269 108 : std::vector<bls::G2Element> vecSignatures;
270 54 : vecSignatures.reserve(pks.size());
271 203 : for (auto& sig : sigs) {
272 149 : vecSignatures.push_back(sig.impl);
273 : }
274 :
275 54 : CBLSSignature ret;
276 54 : ret.impl = pScheme->AggregateSecure(vecPublicKeys, vecSignatures, bls::Bytes(hash.begin(), hash.size()));
277 54 : ret.fValid = true;
278 54 : ret.cachedHash.SetNull();
279 54 : 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 2174 : bool CBLSSignature::VerifyInsecure(const CBLSPublicKey& pubKey, const uint256& hash) const
290 : {
291 2174 : if (!IsValid() || !pubKey.IsValid()) {
292 : return false;
293 : }
294 :
295 2171 : try {
296 2171 : return pScheme->Verify(pubKey.impl, bls::Bytes(hash.begin(), hash.size()), impl);
297 0 : } catch (...) {
298 0 : return false;
299 : }
300 : }
301 :
302 1593 : bool CBLSSignature::VerifyInsecureAggregated(const std::vector<CBLSPublicKey>& pubKeys, const std::vector<uint256>& hashes) const
303 : {
304 1593 : if (!IsValid()) {
305 : return false;
306 : }
307 1593 : assert(!pubKeys.empty() && !hashes.empty() && pubKeys.size() == hashes.size());
308 :
309 3186 : std::vector<bls::G1Element> pubKeyVec;
310 1593 : std::vector<bls::Bytes> hashes2;
311 1593 : hashes2.reserve(hashes.size());
312 1593 : pubKeyVec.reserve(pubKeys.size());
313 4331 : for (size_t i = 0; i < pubKeys.size(); i++) {
314 2738 : auto& p = pubKeys[i];
315 2738 : if (!p.IsValid()) {
316 : return false;
317 : }
318 2738 : pubKeyVec.push_back(p.impl);
319 2738 : hashes2.emplace_back(hashes[i].begin(), hashes[i].size());
320 : }
321 :
322 1593 : try {
323 1593 : return pScheme->AggregateVerify(pubKeyVec, hashes2, impl);
324 0 : } catch (...) {
325 0 : return false;
326 : }
327 : }
328 :
329 287 : bool CBLSSignature::VerifySecureAggregated(const std::vector<CBLSPublicKey>& pks, const uint256& hash) const
330 : {
331 287 : if (pks.empty()) {
332 : return false;
333 : }
334 :
335 574 : std::vector<bls::G1Element> vecPublicKeys;
336 287 : vecPublicKeys.reserve(pks.size());
337 1074 : for (const auto& pk : pks) {
338 787 : vecPublicKeys.push_back(pk.impl);
339 : }
340 :
341 287 : return pScheme->VerifySecure(vecPublicKeys, impl, bls::Bytes(hash.begin(), hash.size()));
342 : }
343 :
344 436 : bool CBLSSignature::Recover(const std::vector<CBLSSignature>& sigs, const std::vector<CBLSId>& ids)
345 : {
346 436 : fValid = false;
347 436 : cachedHash.SetNull();
348 :
349 436 : if (sigs.empty() || ids.empty() || sigs.size() != ids.size()) {
350 : return false;
351 : }
352 :
353 872 : std::vector<bls::G2Element> sigsVec;
354 436 : std::vector<bls::Bytes> idsVec;
355 436 : sigsVec.reserve(sigs.size());
356 436 : idsVec.reserve(sigs.size());
357 :
358 1403 : for (size_t i = 0; i < sigs.size(); i++) {
359 967 : if (!sigs[i].IsValid() || !ids[i].IsValid()) {
360 : return false;
361 : }
362 967 : sigsVec.emplace_back(sigs[i].impl);
363 967 : idsVec.emplace_back(ids[i].impl.begin(), ids[i].impl.size());
364 : }
365 :
366 436 : try {
367 436 : impl = bls::Threshold::SignatureRecover(sigsVec, idsVec);
368 0 : } catch (...) {
369 0 : return false;
370 : }
371 :
372 436 : fValid = true;
373 436 : cachedHash.SetNull();
374 436 : 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 745584 : static mt_pooled_secure_allocator<uint8_t>& get_secure_allocator()
393 : {
394 745584 : std::call_once(init_flag, create_secure_allocator);
395 745584 : return *secure_allocator_instance;
396 : }
397 :
398 372792 : static void* secure_allocate(size_t n)
399 : {
400 372792 : uint8_t* ptr = get_secure_allocator().allocate(n + sizeof(size_t));
401 372792 : *(size_t*)ptr = n;
402 372792 : return ptr + sizeof(size_t);
403 : }
404 :
405 372792 : static void secure_free(void* p)
406 : {
407 372792 : if (!p) {
408 : return;
409 : }
410 :
411 372792 : uint8_t* ptr = (uint8_t*)p - sizeof(size_t);
412 372792 : size_t n = *(size_t*)ptr;
413 372792 : 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 : }
|