LCOV - code coverage report
Current view: top level - src/bls - bls_wrapper.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 201 234 85.9 %
Date: 2025-02-23 09:33:43 Functions: 23 25 92.0 %

          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        2092 : CBLSId::CBLSId(const uint256& nHash) : CBLSWrapper<CBLSIdImplicit, BLS_CURVE_ID_SIZE, CBLSId>()
      21             : {
      22        2092 :     impl = nHash;
      23        2092 :     fValid = true;
      24        2092 :     cachedHash.SetNull();
      25        2092 : }
      26             : 
      27        1856 : void CBLSSecretKey::AggregateInsecure(const CBLSSecretKey& o)
      28             : {
      29        1856 :     assert(IsValid() && o.IsValid());
      30        5568 :     impl = bls::PrivateKey::Aggregate({impl, o.impl});
      31        1856 :     cachedHash.SetNull();
      32        1856 : }
      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        3533 :     unsigned char buf[32];
      57        3533 :     while (true) {
      58        3533 :         GetStrongRandBytes(buf, sizeof(buf));
      59        3533 :         try {
      60        3533 :             impl = bls::PrivateKey::FromBytes(bls::Bytes((const uint8_t*)buf, SerSize));
      61        1636 :             break;
      62        1897 :         } 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        5076 : CBLSPublicKey CBLSSecretKey::GetPublicKey() const
     100             : {
     101        5076 :     if (!IsValid()) {
     102           0 :         return CBLSPublicKey();
     103             :     }
     104             : 
     105        5076 :     CBLSPublicKey pubKey;
     106        5076 :     pubKey.impl = impl.GetG1Element();
     107        5076 :     pubKey.fValid = true;
     108        5076 :     pubKey.cachedHash.SetNull();
     109        5076 :     return pubKey;
     110             : }
     111             : 
     112        1586 : CBLSSignature CBLSSecretKey::Sign(const uint256& hash) const
     113             : {
     114        1586 :     if (!IsValid()) {
     115           0 :         return CBLSSignature();
     116             :     }
     117             : 
     118        1586 :     CBLSSignature sigRet;
     119        1586 :     sigRet.impl = pScheme->Sign(impl, bls::Bytes(hash.begin(), hash.size()));
     120             : 
     121        1586 :     sigRet.fValid = true;
     122        1586 :     sigRet.cachedHash.SetNull();
     123             : 
     124        1586 :     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        3482 : void CBLSPublicKey::AggregateInsecure(const CBLSPublicKey& o)
     161             : {
     162        3482 :     assert(IsValid() && o.IsValid());
     163        3482 :     impl = pScheme->Aggregate({impl, o.impl});
     164        3482 :     cachedHash.SetNull();
     165        3482 : }
     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        3607 : bool CBLSPublicKey::PublicKeyShare(const std::vector<CBLSPublicKey>& mpk, const CBLSId& _id)
     187             : {
     188        3607 :     fValid = false;
     189        3607 :     cachedHash.SetNull();
     190             : 
     191        3607 :     if (!_id.IsValid()) {
     192             :         return false;
     193             :     }
     194             : 
     195        7214 :     std::vector<bls::G1Element> mpkVec;
     196        3607 :     mpkVec.reserve(mpk.size());
     197      100421 :     for (const CBLSPublicKey& pk : mpk) {
     198       96814 :         if (!pk.IsValid()) {
     199           0 :             return false;
     200             :         }
     201       96814 :         mpkVec.emplace_back(pk.impl);
     202             :     }
     203             : 
     204        3607 :     try {
     205        3607 :         impl = bls::Threshold::PublicKeyShare(mpkVec, bls::Bytes(_id.impl.begin(), _id.impl.size()));
     206           0 :     } catch (...) {
     207           0 :         return false;
     208             :     }
     209             : 
     210        3607 :     fValid = true;
     211        3607 :     cachedHash.SetNull();
     212        3607 :     return true;
     213             : }
     214             : 
     215        3596 : bool CBLSPublicKey::DHKeyExchange(const CBLSSecretKey& sk, const CBLSPublicKey& pk)
     216             : {
     217        3596 :     fValid = false;
     218        3596 :     cachedHash.SetNull();
     219             : 
     220        3596 :     if (!sk.IsValid() || !pk.IsValid()) {
     221             :         return false;
     222             :     }
     223        3596 :     impl = sk.impl * pk.impl;
     224        3596 :     fValid = true;
     225        3596 :     cachedHash.SetNull();
     226        3596 :     return true;
     227             : }
     228             : 
     229        1301 : void CBLSSignature::AggregateInsecure(const CBLSSignature& o)
     230             : {
     231        1301 :     assert(IsValid() && o.IsValid());
     232        1301 :     impl = pScheme->Aggregate({impl, o.impl});
     233        1301 :     cachedHash.SetNull();
     234        1301 : }
     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          62 : CBLSSignature CBLSSignature::AggregateSecure(const std::vector<CBLSSignature>& sigs,
     256             :                                              const std::vector<CBLSPublicKey>& pks,
     257             :                                              const uint256& hash)
     258             : {
     259          62 :     if (sigs.size() != pks.size() || sigs.empty()) {
     260          62 :         return CBLSSignature();
     261             :     }
     262             : 
     263         124 :     std::vector<bls::G1Element> vecPublicKeys;
     264          62 :     vecPublicKeys.reserve(pks.size());
     265         233 :     for (auto& pk : pks) {
     266         171 :         vecPublicKeys.push_back(pk.impl);
     267             :     }
     268             : 
     269         124 :     std::vector<bls::G2Element> vecSignatures;
     270          62 :     vecSignatures.reserve(pks.size());
     271         233 :     for (auto& sig : sigs) {
     272         171 :         vecSignatures.push_back(sig.impl);
     273             :     }
     274             : 
     275          62 :     CBLSSignature ret;
     276          62 :     ret.impl = pScheme->AggregateSecure(vecPublicKeys, vecSignatures, bls::Bytes(hash.begin(), hash.size()));
     277          62 :     ret.fValid = true;
     278          62 :     ret.cachedHash.SetNull();
     279          62 :     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        2344 : bool CBLSSignature::VerifyInsecure(const CBLSPublicKey& pubKey, const uint256& hash) const
     290             : {
     291        2344 :     if (!IsValid() || !pubKey.IsValid()) {
     292             :         return false;
     293             :     }
     294             : 
     295        2341 :     try {
     296        2341 :         return pScheme->Verify(pubKey.impl, bls::Bytes(hash.begin(), hash.size()), impl);
     297           0 :     } catch (...) {
     298           0 :         return false;
     299             :     }
     300             : }
     301             : 
     302        1711 : bool CBLSSignature::VerifyInsecureAggregated(const std::vector<CBLSPublicKey>& pubKeys, const std::vector<uint256>& hashes) const
     303             : {
     304        1711 :     if (!IsValid()) {
     305             :         return false;
     306             :     }
     307        1711 :     assert(!pubKeys.empty() && !hashes.empty() && pubKeys.size() == hashes.size());
     308             : 
     309        3422 :     std::vector<bls::G1Element> pubKeyVec;
     310        1711 :     std::vector<bls::Bytes> hashes2;
     311        1711 :     hashes2.reserve(hashes.size());
     312        1711 :     pubKeyVec.reserve(pubKeys.size());
     313        4546 :     for (size_t i = 0; i < pubKeys.size(); i++) {
     314        2835 :         auto& p = pubKeys[i];
     315        2835 :         if (!p.IsValid()) {
     316             :             return false;
     317             :         }
     318        2835 :         pubKeyVec.push_back(p.impl);
     319        2835 :         hashes2.emplace_back(hashes[i].begin(), hashes[i].size());
     320             :     }
     321             : 
     322        1711 :     try {
     323        1711 :         return pScheme->AggregateVerify(pubKeyVec, hashes2, impl);
     324           0 :     } catch (...) {
     325           0 :         return false;
     326             :     }
     327             : }
     328             : 
     329         332 : bool CBLSSignature::VerifySecureAggregated(const std::vector<CBLSPublicKey>& pks, const uint256& hash) const
     330             : {
     331         332 :     if (pks.empty()) {
     332             :         return false;
     333             :     }
     334             : 
     335         664 :     std::vector<bls::G1Element> vecPublicKeys;
     336         332 :     vecPublicKeys.reserve(pks.size());
     337        1239 :     for (const auto& pk : pks) {
     338         907 :         vecPublicKeys.push_back(pk.impl);
     339             :     }
     340             : 
     341         332 :     return pScheme->VerifySecure(vecPublicKeys, impl, bls::Bytes(hash.begin(), hash.size()));
     342             : }
     343             : 
     344         448 : bool CBLSSignature::Recover(const std::vector<CBLSSignature>& sigs, const std::vector<CBLSId>& ids)
     345             : {
     346         448 :     fValid = false;
     347         448 :     cachedHash.SetNull();
     348             : 
     349         448 :     if (sigs.empty() || ids.empty() || sigs.size() != ids.size()) {
     350             :         return false;
     351             :     }
     352             : 
     353         896 :     std::vector<bls::G2Element> sigsVec;
     354         448 :     std::vector<bls::Bytes> idsVec;
     355         448 :     sigsVec.reserve(sigs.size());
     356         448 :     idsVec.reserve(sigs.size());
     357             : 
     358        1445 :     for (size_t i = 0; i < sigs.size(); i++) {
     359         997 :         if (!sigs[i].IsValid() || !ids[i].IsValid()) {
     360             :             return false;
     361             :         }
     362         997 :         sigsVec.emplace_back(sigs[i].impl);
     363         997 :         idsVec.emplace_back(ids[i].impl.begin(), ids[i].impl.size());
     364             :     }
     365             : 
     366         448 :     try {
     367         448 :         impl = bls::Threshold::SignatureRecover(sigsVec, idsVec);
     368           0 :     } catch (...) {
     369           0 :         return false;
     370             :     }
     371             : 
     372         448 :     fValid = true;
     373         448 :     cachedHash.SetNull();
     374         448 :     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      747174 : static mt_pooled_secure_allocator<uint8_t>& get_secure_allocator()
     393             : {
     394      747174 :     std::call_once(init_flag, create_secure_allocator);
     395      747174 :     return *secure_allocator_instance;
     396             : }
     397             : 
     398      373587 : static void* secure_allocate(size_t n)
     399             : {
     400      373587 :     uint8_t* ptr = get_secure_allocator().allocate(n + sizeof(size_t));
     401      373587 :     *(size_t*)ptr = n;
     402      373587 :     return ptr + sizeof(size_t);
     403             : }
     404             : 
     405      373587 : static void secure_free(void* p)
     406             : {
     407      373587 :     if (!p) {
     408             :         return;
     409             :     }
     410             : 
     411      373587 :     uint8_t* ptr = (uint8_t*)p - sizeof(size_t);
     412      373587 :     size_t n = *(size_t*)ptr;
     413      373587 :     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             : }

Generated by: LCOV version 1.14