LCOV - code coverage report
Current view: top level - src/test/fuzz - key.cpp (source / functions) Hit Total Coverage
Test: fuzz_coverage.info Lines: 6 245 2.4 %
Date: 2023-11-10 23:46:46 Functions: 3 14 21.4 %
Branches: 5 670 0.7 %

           Branch data     Line data    Source code
       1                 :            : // Copyright (c) 2020-2022 The Bitcoin 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 <chainparams.h>
       6                 :            : #include <key.h>
       7                 :            : #include <key_io.h>
       8                 :            : #include <outputtype.h>
       9                 :            : #include <policy/policy.h>
      10                 :            : #include <pubkey.h>
      11                 :            : #include <rpc/util.h>
      12                 :            : #include <script/keyorigin.h>
      13                 :            : #include <script/script.h>
      14                 :            : #include <script/sign.h>
      15                 :            : #include <script/signingprovider.h>
      16                 :            : #include <script/solver.h>
      17         [ +  - ]:          2 : #include <streams.h>
      18         [ +  - ]:          2 : #include <test/fuzz/FuzzedDataProvider.h>
      19                 :            : #include <test/fuzz/fuzz.h>
      20                 :            : #include <test/fuzz/util.h>
      21                 :            : #include <util/chaintype.h>
      22                 :            : #include <util/strencodings.h>
      23                 :            : 
      24                 :            : #include <array>
      25                 :            : #include <cassert>
      26                 :            : #include <cstddef>
      27                 :          2 : #include <cstdint>
      28                 :            : #include <numeric>
      29                 :            : #include <optional>
      30                 :            : #include <string>
      31                 :            : #include <vector>
      32                 :            : 
      33                 :          0 : void initialize_key()
      34                 :            : {
      35                 :          0 :     ECC_Start();
      36                 :          0 :     SelectParams(ChainType::REGTEST);
      37                 :          0 : }
      38                 :            : 
      39         [ +  - ]:          4 : FUZZ_TARGET(key, .init = initialize_key)
      40                 :            : {
      41                 :          0 :     const CKey key = [&] {
      42                 :          0 :         CKey k;
      43         [ #  # ]:          0 :         k.Set(buffer.begin(), buffer.end(), true);
      44                 :          0 :         return k;
      45         [ #  # ]:          0 :     }();
      46 [ #  # ][ #  # ]:          0 :     if (!key.IsValid()) {
      47                 :          0 :         return;
      48                 :            :     }
      49                 :            : 
      50                 :            :     {
      51 [ #  # ][ #  # ]:          0 :         assert(key.begin() + key.size() == key.end());
         [ #  # ][ #  # ]
      52 [ #  # ][ #  # ]:          0 :         assert(key.IsCompressed());
      53 [ #  # ][ #  # ]:          0 :         assert(key.size() == 32);
      54 [ #  # ][ #  # ]:          0 :         assert(DecodeSecret(EncodeSecret(key)) == key);
         [ #  # ][ #  # ]
      55                 :            :     }
      56                 :            : 
      57                 :            :     {
      58                 :          0 :         CKey invalid_key;
      59 [ #  # ][ #  # ]:          0 :         assert(!(invalid_key == key));
      60 [ #  # ][ #  # ]:          0 :         assert(!invalid_key.IsCompressed());
      61 [ #  # ][ #  # ]:          0 :         assert(!invalid_key.IsValid());
      62 [ #  # ][ #  # ]:          0 :         assert(invalid_key.size() == 0);
      63                 :          0 :     }
      64                 :            : 
      65                 :            :     {
      66                 :          0 :         CKey uncompressed_key;
      67         [ #  # ]:          0 :         uncompressed_key.Set(buffer.begin(), buffer.end(), false);
      68 [ #  # ][ #  # ]:          0 :         assert(!(uncompressed_key == key));
      69 [ #  # ][ #  # ]:          0 :         assert(!uncompressed_key.IsCompressed());
      70 [ #  # ][ #  # ]:          0 :         assert(key.size() == 32);
      71 [ #  # ][ #  # ]:          0 :         assert(uncompressed_key.begin() + uncompressed_key.size() == uncompressed_key.end());
         [ #  # ][ #  # ]
      72 [ #  # ][ #  # ]:          0 :         assert(uncompressed_key.IsValid());
      73                 :          0 :     }
      74                 :            : 
      75                 :            :     {
      76                 :          0 :         CKey copied_key;
      77 [ #  # ][ #  # ]:          0 :         copied_key.Set(key.begin(), key.end(), key.IsCompressed());
         [ #  # ][ #  # ]
      78 [ #  # ][ #  # ]:          0 :         assert(copied_key == key);
      79                 :          0 :     }
      80                 :            : 
      81                 :            :     {
      82         [ #  # ]:          0 :         CKey negated_key = key;
      83         [ #  # ]:          0 :         negated_key.Negate();
      84 [ #  # ][ #  # ]:          0 :         assert(negated_key.IsValid());
      85 [ #  # ][ #  # ]:          0 :         assert(!(negated_key == key));
      86                 :            : 
      87         [ #  # ]:          0 :         negated_key.Negate();
      88 [ #  # ][ #  # ]:          0 :         assert(negated_key == key);
      89                 :          0 :     }
      90                 :            : 
      91         [ #  # ]:          0 :     const uint256 random_uint256 = Hash(buffer);
      92                 :            : 
      93                 :            :     {
      94                 :          0 :         CKey child_key;
      95         [ #  # ]:          0 :         ChainCode child_chaincode;
      96         [ #  # ]:          0 :         const bool ok = key.Derive(child_key, child_chaincode, 0, random_uint256);
      97         [ #  # ]:          0 :         assert(ok);
      98 [ #  # ][ #  # ]:          0 :         assert(child_key.IsValid());
      99 [ #  # ][ #  # ]:          0 :         assert(!(child_key == key));
     100 [ #  # ][ #  # ]:          0 :         assert(child_chaincode != random_uint256);
     101                 :          0 :     }
     102                 :            : 
     103         [ #  # ]:          0 :     const CPubKey pubkey = key.GetPubKey();
     104                 :            : 
     105                 :            :     {
     106 [ #  # ][ #  # ]:          0 :         assert(pubkey.size() == 33);
     107 [ #  # ][ #  # ]:          0 :         assert(key.VerifyPubKey(pubkey));
     108 [ #  # ][ #  # ]:          0 :         assert(pubkey.GetHash() != random_uint256);
                 [ #  # ]
     109 [ #  # ][ #  # ]:          0 :         assert(pubkey.begin() + pubkey.size() == pubkey.end());
         [ #  # ][ #  # ]
     110 [ #  # ][ #  # ]:          0 :         assert(pubkey.data() == pubkey.begin());
                 [ #  # ]
     111 [ #  # ][ #  # ]:          0 :         assert(pubkey.IsCompressed());
     112 [ #  # ][ #  # ]:          0 :         assert(pubkey.IsValid());
     113 [ #  # ][ #  # ]:          0 :         assert(pubkey.IsFullyValid());
     114 [ #  # ][ #  # ]:          0 :         assert(HexToPubKey(HexStr(pubkey)) == pubkey);
         [ #  # ][ #  # ]
                 [ #  # ]
     115 [ #  # ][ #  # ]:          0 :         assert(GetAllDestinationsForKey(pubkey).size() == 3);
     116                 :            :     }
     117                 :            : 
     118                 :            :     {
     119         [ #  # ]:          0 :         DataStream data_stream{};
     120         [ #  # ]:          0 :         pubkey.Serialize(data_stream);
     121                 :            : 
     122         [ #  # ]:          0 :         CPubKey pubkey_deserialized;
     123         [ #  # ]:          0 :         pubkey_deserialized.Unserialize(data_stream);
     124 [ #  # ][ #  # ]:          0 :         assert(pubkey_deserialized == pubkey);
     125                 :          0 :     }
     126                 :            : 
     127                 :            :     {
     128         [ #  # ]:          0 :         const CScript tx_pubkey_script = GetScriptForRawPubKey(pubkey);
     129 [ #  # ][ #  # ]:          0 :         assert(!tx_pubkey_script.IsPayToScriptHash());
     130 [ #  # ][ #  # ]:          0 :         assert(!tx_pubkey_script.IsPayToWitnessScriptHash());
     131 [ #  # ][ #  # ]:          0 :         assert(!tx_pubkey_script.IsPushOnly());
     132 [ #  # ][ #  # ]:          0 :         assert(!tx_pubkey_script.IsUnspendable());
     133 [ #  # ][ #  # ]:          0 :         assert(tx_pubkey_script.HasValidOps());
     134 [ #  # ][ #  # ]:          0 :         assert(tx_pubkey_script.size() == 35);
     135                 :            : 
     136 [ #  # ][ #  # ]:          0 :         const CScript tx_multisig_script = GetScriptForMultisig(1, {pubkey});
     137 [ #  # ][ #  # ]:          0 :         assert(!tx_multisig_script.IsPayToScriptHash());
     138 [ #  # ][ #  # ]:          0 :         assert(!tx_multisig_script.IsPayToWitnessScriptHash());
     139 [ #  # ][ #  # ]:          0 :         assert(!tx_multisig_script.IsPushOnly());
     140 [ #  # ][ #  # ]:          0 :         assert(!tx_multisig_script.IsUnspendable());
     141 [ #  # ][ #  # ]:          0 :         assert(tx_multisig_script.HasValidOps());
     142 [ #  # ][ #  # ]:          0 :         assert(tx_multisig_script.size() == 37);
     143                 :            : 
     144                 :          0 :         FillableSigningProvider fillable_signing_provider;
     145 [ #  # ][ #  # ]:          0 :         assert(!IsSegWitOutput(fillable_signing_provider, tx_pubkey_script));
     146 [ #  # ][ #  # ]:          0 :         assert(!IsSegWitOutput(fillable_signing_provider, tx_multisig_script));
     147 [ #  # ][ #  # ]:          0 :         assert(fillable_signing_provider.GetKeys().size() == 0);
     148 [ #  # ][ #  # ]:          0 :         assert(!fillable_signing_provider.HaveKey(pubkey.GetID()));
                 [ #  # ]
     149                 :            : 
     150         [ #  # ]:          0 :         const bool ok_add_key = fillable_signing_provider.AddKey(key);
     151         [ #  # ]:          0 :         assert(ok_add_key);
     152 [ #  # ][ #  # ]:          0 :         assert(fillable_signing_provider.HaveKey(pubkey.GetID()));
                 [ #  # ]
     153                 :            : 
     154                 :          0 :         FillableSigningProvider fillable_signing_provider_pub;
     155 [ #  # ][ #  # ]:          0 :         assert(!fillable_signing_provider_pub.HaveKey(pubkey.GetID()));
                 [ #  # ]
     156                 :            : 
     157         [ #  # ]:          0 :         const bool ok_add_key_pubkey = fillable_signing_provider_pub.AddKeyPubKey(key, pubkey);
     158         [ #  # ]:          0 :         assert(ok_add_key_pubkey);
     159 [ #  # ][ #  # ]:          0 :         assert(fillable_signing_provider_pub.HaveKey(pubkey.GetID()));
                 [ #  # ]
     160                 :            : 
     161                 :            :         TxoutType which_type_tx_pubkey;
     162         [ #  # ]:          0 :         const bool is_standard_tx_pubkey = IsStandard(tx_pubkey_script, std::nullopt, which_type_tx_pubkey);
     163         [ #  # ]:          0 :         assert(is_standard_tx_pubkey);
     164         [ #  # ]:          0 :         assert(which_type_tx_pubkey == TxoutType::PUBKEY);
     165                 :            : 
     166                 :            :         TxoutType which_type_tx_multisig;
     167         [ #  # ]:          0 :         const bool is_standard_tx_multisig = IsStandard(tx_multisig_script, std::nullopt, which_type_tx_multisig);
     168         [ #  # ]:          0 :         assert(is_standard_tx_multisig);
     169         [ #  # ]:          0 :         assert(which_type_tx_multisig == TxoutType::MULTISIG);
     170                 :            : 
     171                 :          0 :         std::vector<std::vector<unsigned char>> v_solutions_ret_tx_pubkey;
     172         [ #  # ]:          0 :         const TxoutType outtype_tx_pubkey = Solver(tx_pubkey_script, v_solutions_ret_tx_pubkey);
     173         [ #  # ]:          0 :         assert(outtype_tx_pubkey == TxoutType::PUBKEY);
     174         [ #  # ]:          0 :         assert(v_solutions_ret_tx_pubkey.size() == 1);
     175         [ #  # ]:          0 :         assert(v_solutions_ret_tx_pubkey[0].size() == 33);
     176                 :            : 
     177                 :          0 :         std::vector<std::vector<unsigned char>> v_solutions_ret_tx_multisig;
     178         [ #  # ]:          0 :         const TxoutType outtype_tx_multisig = Solver(tx_multisig_script, v_solutions_ret_tx_multisig);
     179         [ #  # ]:          0 :         assert(outtype_tx_multisig == TxoutType::MULTISIG);
     180         [ #  # ]:          0 :         assert(v_solutions_ret_tx_multisig.size() == 3);
     181         [ #  # ]:          0 :         assert(v_solutions_ret_tx_multisig[0].size() == 1);
     182         [ #  # ]:          0 :         assert(v_solutions_ret_tx_multisig[1].size() == 33);
     183         [ #  # ]:          0 :         assert(v_solutions_ret_tx_multisig[2].size() == 1);
     184                 :            : 
     185                 :          0 :         OutputType output_type{};
     186         [ #  # ]:          0 :         const CTxDestination tx_destination = GetDestinationForKey(pubkey, output_type);
     187         [ #  # ]:          0 :         assert(output_type == OutputType::LEGACY);
     188 [ #  # ][ #  # ]:          0 :         assert(IsValidDestination(tx_destination));
     189 [ #  # ][ #  # ]:          0 :         assert(PKHash{pubkey} == *std::get_if<PKHash>(&tx_destination));
     190                 :            : 
     191         [ #  # ]:          0 :         const CScript script_for_destination = GetScriptForDestination(tx_destination);
     192 [ #  # ][ #  # ]:          0 :         assert(script_for_destination.size() == 25);
     193                 :            : 
     194         [ #  # ]:          0 :         const std::string destination_address = EncodeDestination(tx_destination);
     195 [ #  # ][ #  # ]:          0 :         assert(DecodeDestination(destination_address) == tx_destination);
                 [ #  # ]
     196                 :            : 
     197         [ #  # ]:          0 :         const CPubKey pubkey_from_address_string = AddrToPubKey(fillable_signing_provider, destination_address);
     198 [ #  # ][ #  # ]:          0 :         assert(pubkey_from_address_string == pubkey);
     199                 :            : 
     200         [ #  # ]:          0 :         CKeyID key_id = pubkey.GetID();
     201 [ #  # ][ #  # ]:          0 :         assert(!key_id.IsNull());
     202 [ #  # ][ #  # ]:          0 :         assert(key_id == CKeyID{key_id});
     203 [ #  # ][ #  # ]:          0 :         assert(key_id == GetKeyForDestination(fillable_signing_provider, tx_destination));
                 [ #  # ]
     204                 :            : 
     205         [ #  # ]:          0 :         CPubKey pubkey_out;
     206         [ #  # ]:          0 :         const bool ok_get_pubkey = fillable_signing_provider.GetPubKey(key_id, pubkey_out);
     207         [ #  # ]:          0 :         assert(ok_get_pubkey);
     208                 :            : 
     209                 :          0 :         CKey key_out;
     210         [ #  # ]:          0 :         const bool ok_get_key = fillable_signing_provider.GetKey(key_id, key_out);
     211         [ #  # ]:          0 :         assert(ok_get_key);
     212 [ #  # ][ #  # ]:          0 :         assert(fillable_signing_provider.GetKeys().size() == 1);
     213 [ #  # ][ #  # ]:          0 :         assert(fillable_signing_provider.HaveKey(key_id));
     214                 :            : 
     215                 :          0 :         KeyOriginInfo key_origin_info;
     216         [ #  # ]:          0 :         const bool ok_get_key_origin = fillable_signing_provider.GetKeyOrigin(key_id, key_origin_info);
     217         [ #  # ]:          0 :         assert(!ok_get_key_origin);
     218                 :          0 :     }
     219                 :            : 
     220                 :            :     {
     221 [ #  # ][ #  # ]:          0 :         const std::vector<unsigned char> vch_pubkey{pubkey.begin(), pubkey.end()};
                 [ #  # ]
     222 [ #  # ][ #  # ]:          0 :         assert(CPubKey::ValidSize(vch_pubkey));
     223 [ #  # ][ #  # ]:          0 :         assert(!CPubKey::ValidSize({pubkey.begin(), pubkey.begin() + pubkey.size() - 1}));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     224                 :            : 
     225 [ #  # ][ #  # ]:          0 :         const CPubKey pubkey_ctor_1{vch_pubkey};
     226 [ #  # ][ #  # ]:          0 :         assert(pubkey == pubkey_ctor_1);
     227                 :            : 
     228         [ #  # ]:          0 :         const CPubKey pubkey_ctor_2{vch_pubkey.begin(), vch_pubkey.end()};
     229 [ #  # ][ #  # ]:          0 :         assert(pubkey == pubkey_ctor_2);
     230                 :            : 
     231         [ #  # ]:          0 :         CPubKey pubkey_set;
     232         [ #  # ]:          0 :         pubkey_set.Set(vch_pubkey.begin(), vch_pubkey.end());
     233 [ #  # ][ #  # ]:          0 :         assert(pubkey == pubkey_set);
     234                 :          0 :     }
     235                 :            : 
     236                 :            :     {
     237         [ #  # ]:          0 :         const CPubKey invalid_pubkey{};
     238 [ #  # ][ #  # ]:          0 :         assert(!invalid_pubkey.IsValid());
     239 [ #  # ][ #  # ]:          0 :         assert(!invalid_pubkey.IsFullyValid());
     240 [ #  # ][ #  # ]:          0 :         assert(!(pubkey == invalid_pubkey));
     241 [ #  # ][ #  # ]:          0 :         assert(pubkey != invalid_pubkey);
     242 [ #  # ][ #  # ]:          0 :         assert(pubkey < invalid_pubkey);
     243                 :            :     }
     244                 :            : 
     245                 :            :     {
     246                 :            :         // Cover CPubKey's operator[](unsigned int pos)
     247                 :          0 :         unsigned int sum = 0;
     248 [ #  # ][ #  # ]:          0 :         for (size_t i = 0; i < pubkey.size(); ++i) {
     249         [ #  # ]:          0 :             sum += pubkey[i];
     250                 :          0 :         }
     251 [ #  # ][ #  # ]:          0 :         assert(std::accumulate(pubkey.begin(), pubkey.end(), 0U) == sum);
         [ #  # ][ #  # ]
     252                 :            :     }
     253                 :            : 
     254                 :            :     {
     255                 :          0 :         CPubKey decompressed_pubkey = pubkey;
     256 [ #  # ][ #  # ]:          0 :         assert(decompressed_pubkey.IsCompressed());
     257                 :            : 
     258         [ #  # ]:          0 :         const bool ok = decompressed_pubkey.Decompress();
     259         [ #  # ]:          0 :         assert(ok);
     260 [ #  # ][ #  # ]:          0 :         assert(!decompressed_pubkey.IsCompressed());
     261 [ #  # ][ #  # ]:          0 :         assert(decompressed_pubkey.size() == 65);
     262                 :            :     }
     263                 :            : 
     264                 :            :     {
     265                 :          0 :         std::vector<unsigned char> vch_sig;
     266         [ #  # ]:          0 :         const bool ok = key.Sign(random_uint256, vch_sig, false);
     267         [ #  # ]:          0 :         assert(ok);
     268 [ #  # ][ #  # ]:          0 :         assert(pubkey.Verify(random_uint256, vch_sig));
     269 [ #  # ][ #  # ]:          0 :         assert(CPubKey::CheckLowS(vch_sig));
     270                 :            : 
     271         [ #  # ]:          0 :         const std::vector<unsigned char> vch_invalid_sig{vch_sig.begin(), vch_sig.begin() + vch_sig.size() - 1};
     272 [ #  # ][ #  # ]:          0 :         assert(!pubkey.Verify(random_uint256, vch_invalid_sig));
     273 [ #  # ][ #  # ]:          0 :         assert(!CPubKey::CheckLowS(vch_invalid_sig));
     274                 :          0 :     }
     275                 :            : 
     276                 :            :     {
     277                 :          0 :         std::vector<unsigned char> vch_compact_sig;
     278         [ #  # ]:          0 :         const bool ok_sign_compact = key.SignCompact(random_uint256, vch_compact_sig);
     279         [ #  # ]:          0 :         assert(ok_sign_compact);
     280                 :            : 
     281         [ #  # ]:          0 :         CPubKey recover_pubkey;
     282         [ #  # ]:          0 :         const bool ok_recover_compact = recover_pubkey.RecoverCompact(random_uint256, vch_compact_sig);
     283         [ #  # ]:          0 :         assert(ok_recover_compact);
     284 [ #  # ][ #  # ]:          0 :         assert(recover_pubkey == pubkey);
     285                 :          0 :     }
     286                 :            : 
     287                 :            :     {
     288         [ #  # ]:          0 :         CPubKey child_pubkey;
     289         [ #  # ]:          0 :         ChainCode child_chaincode;
     290         [ #  # ]:          0 :         const bool ok = pubkey.Derive(child_pubkey, child_chaincode, 0, random_uint256);
     291         [ #  # ]:          0 :         assert(ok);
     292 [ #  # ][ #  # ]:          0 :         assert(child_pubkey != pubkey);
     293 [ #  # ][ #  # ]:          0 :         assert(child_pubkey.IsCompressed());
     294 [ #  # ][ #  # ]:          0 :         assert(child_pubkey.IsFullyValid());
     295 [ #  # ][ #  # ]:          0 :         assert(child_pubkey.IsValid());
     296 [ #  # ][ #  # ]:          0 :         assert(child_pubkey.size() == 33);
     297 [ #  # ][ #  # ]:          0 :         assert(child_chaincode != random_uint256);
     298                 :            :     }
     299                 :            : 
     300         [ #  # ]:          0 :     const CPrivKey priv_key = key.GetPrivKey();
     301                 :            : 
     302                 :            :     {
     303         [ #  # ]:          0 :         for (const bool skip_check : {true, false}) {
     304                 :          0 :             CKey loaded_key;
     305         [ #  # ]:          0 :             const bool ok = loaded_key.Load(priv_key, pubkey, skip_check);
     306         [ #  # ]:          0 :             assert(ok);
     307 [ #  # ][ #  # ]:          0 :             assert(key == loaded_key);
     308                 :          0 :         }
     309                 :            :     }
     310         [ #  # ]:          0 : }
     311                 :            : 
     312         [ +  - ]:          4 : FUZZ_TARGET(ellswift_roundtrip, .init = initialize_key)
     313                 :            : {
     314                 :          0 :     FuzzedDataProvider fdp{buffer.data(), buffer.size()};
     315                 :            : 
     316                 :          0 :     CKey key = ConsumePrivateKey(fdp, /*compressed=*/true);
     317 [ #  # ][ #  # ]:          0 :     if (!key.IsValid()) return;
     318                 :            : 
     319         [ #  # ]:          0 :     auto ent32 = fdp.ConsumeBytes<std::byte>(32);
     320         [ #  # ]:          0 :     ent32.resize(32);
     321                 :            : 
     322 [ #  # ][ #  # ]:          0 :     auto encoded_ellswift = key.EllSwiftCreate(ent32);
     323         [ #  # ]:          0 :     auto decoded_pubkey = encoded_ellswift.Decode();
     324                 :            : 
     325 [ #  # ][ #  # ]:          0 :     assert(key.VerifyPubKey(decoded_pubkey));
     326         [ #  # ]:          0 : }
     327                 :            : 
     328         [ +  - ]:          4 : FUZZ_TARGET(bip324_ecdh, .init = initialize_key)
     329                 :            : {
     330                 :          0 :     FuzzedDataProvider fdp{buffer.data(), buffer.size()};
     331                 :            : 
     332                 :            :     // We generate private key, k1.
     333                 :          0 :     CKey k1 = ConsumePrivateKey(fdp, /*compressed=*/true);
     334 [ #  # ][ #  # ]:          0 :     if (!k1.IsValid()) return;
     335                 :            : 
     336                 :            :     // They generate private key, k2.
     337                 :          0 :     CKey k2 = ConsumePrivateKey(fdp, /*compressed=*/true);
     338 [ #  # ][ #  # ]:          0 :     if (!k2.IsValid()) return;
     339                 :            : 
     340                 :            :     // We construct an ellswift encoding for our key, k1_ellswift.
     341         [ #  # ]:          0 :     auto ent32_1 = fdp.ConsumeBytes<std::byte>(32);
     342         [ #  # ]:          0 :     ent32_1.resize(32);
     343 [ #  # ][ #  # ]:          0 :     auto k1_ellswift = k1.EllSwiftCreate(ent32_1);
     344                 :            : 
     345                 :            :     // They construct an ellswift encoding for their key, k2_ellswift.
     346         [ #  # ]:          0 :     auto ent32_2 = fdp.ConsumeBytes<std::byte>(32);
     347         [ #  # ]:          0 :     ent32_2.resize(32);
     348 [ #  # ][ #  # ]:          0 :     auto k2_ellswift = k2.EllSwiftCreate(ent32_2);
     349                 :            : 
     350                 :            :     // They construct another (possibly distinct) ellswift encoding for their key, k2_ellswift_bad.
     351         [ #  # ]:          0 :     auto ent32_2_bad = fdp.ConsumeBytes<std::byte>(32);
     352         [ #  # ]:          0 :     ent32_2_bad.resize(32);
     353 [ #  # ][ #  # ]:          0 :     auto k2_ellswift_bad = k2.EllSwiftCreate(ent32_2_bad);
     354 [ #  # ][ #  # ]:          0 :     assert((ent32_2_bad == ent32_2) == (k2_ellswift_bad == k2_ellswift));
                 [ #  # ]
     355                 :            : 
     356                 :            :     // Determine who is who.
     357         [ #  # ]:          0 :     bool initiating = fdp.ConsumeBool();
     358                 :            : 
     359                 :            :     // We compute our shared secret using our key and their public key.
     360         [ #  # ]:          0 :     auto ecdh_secret_1 = k1.ComputeBIP324ECDHSecret(k2_ellswift, k1_ellswift, initiating);
     361                 :            :     // They compute their shared secret using their key and our public key.
     362         [ #  # ]:          0 :     auto ecdh_secret_2 = k2.ComputeBIP324ECDHSecret(k1_ellswift, k2_ellswift, !initiating);
     363                 :            :     // Those must match, as everyone is behaving correctly.
     364 [ #  # ][ #  # ]:          0 :     assert(ecdh_secret_1 == ecdh_secret_2);
     365                 :            : 
     366 [ #  # ][ #  # ]:          0 :     if (k1_ellswift != k2_ellswift) {
     367                 :            :         // Unless the two keys are exactly identical, acting as the wrong party breaks things.
     368         [ #  # ]:          0 :         auto ecdh_secret_bad = k1.ComputeBIP324ECDHSecret(k2_ellswift, k1_ellswift, !initiating);
     369 [ #  # ][ #  # ]:          0 :         assert(ecdh_secret_bad != ecdh_secret_1);
     370                 :          0 :     }
     371                 :            : 
     372 [ #  # ][ #  # ]:          0 :     if (k2_ellswift_bad != k2_ellswift) {
     373                 :            :         // Unless both encodings created by them are identical, using the second one breaks things.
     374         [ #  # ]:          0 :         auto ecdh_secret_bad = k1.ComputeBIP324ECDHSecret(k2_ellswift_bad, k1_ellswift, initiating);
     375 [ #  # ][ #  # ]:          0 :         assert(ecdh_secret_bad != ecdh_secret_1);
     376                 :          0 :     }
     377         [ #  # ]:          0 : }

Generated by: LCOV version 1.14