LCOV - code coverage report
Current view: top level - src/bls - bls.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 231 269 85.9 %
Date: 2026-06-25 07:23:43 Functions: 29 29 100.0 %

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

Generated by: LCOV version 1.16