bip324.cpp raw

   1  // Copyright (c) 2023-present 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 <bip324.h>
   6  #include <chainparams.h>
   7  #include <random.h>
   8  #include <span.h>
   9  #include <test/fuzz/FuzzedDataProvider.h>
  10  #include <test/fuzz/fuzz.h>
  11  #include <test/fuzz/util.h>
  12  
  13  #include <algorithm>
  14  #include <cstdint>
  15  #include <vector>
  16  
  17  namespace {
  18  
  19  void Initialize()
  20  {
  21      static ECC_Context ecc_context{};
  22      SelectParams(ChainType::MAIN);
  23  }
  24  
  25  }  // namespace
  26  
  27  FUZZ_TARGET(bip324_cipher_roundtrip, .init=Initialize)
  28  {
  29      // Test that BIP324Cipher's encryption and decryption agree.
  30  
  31      // Load keys from fuzzer.
  32      FuzzedDataProvider provider(buffer.data(), buffer.size());
  33      // Initiator key
  34      CKey init_key = ConsumePrivateKey(provider, /*compressed=*/true);
  35      if (!init_key.IsValid()) return;
  36      // Initiator entropy
  37      auto init_ent = provider.ConsumeBytes<std::byte>(32);
  38      init_ent.resize(32);
  39      // Responder key
  40      CKey resp_key = ConsumePrivateKey(provider, /*compressed=*/true);
  41      if (!resp_key.IsValid()) return;
  42      // Responder entropy
  43      auto resp_ent = provider.ConsumeBytes<std::byte>(32);
  44      resp_ent.resize(32);
  45  
  46      // Initialize ciphers by exchanging public keys.
  47      BIP324Cipher initiator(init_key, init_ent);
  48      assert(!initiator);
  49      BIP324Cipher responder(resp_key, resp_ent);
  50      assert(!responder);
  51      initiator.Initialize(responder.GetOurPubKey(), true);
  52      assert(initiator);
  53      responder.Initialize(initiator.GetOurPubKey(), false);
  54      assert(responder);
  55  
  56      // Initialize RNG deterministically, to generate contents and AAD. We assume that there are no
  57      // (potentially buggy) edge cases triggered by specific values of contents/AAD, so we can avoid
  58      // reading the actual data for those from the fuzzer input (which would need large amounts of
  59      // data).
  60      InsecureRandomContext rng(provider.ConsumeIntegral<uint64_t>());
  61  
  62      // Compare session IDs and garbage terminators.
  63      assert(std::ranges::equal(initiator.GetSessionID(), responder.GetSessionID()));
  64      assert(std::ranges::equal(initiator.GetSendGarbageTerminator(), responder.GetReceiveGarbageTerminator()));
  65      assert(std::ranges::equal(initiator.GetReceiveGarbageTerminator(), responder.GetSendGarbageTerminator()));
  66  
  67      LIMITED_WHILE(provider.remaining_bytes(), 1000) {
  68          // Mode:
  69          // - Bit 0: whether the ignore bit is set in message
  70          // - Bit 1: whether the responder (0) or initiator (1) sends
  71          // - Bit 2: whether this ciphertext will be corrupted (making it the last sent one)
  72          // - Bit 3-4: controls the maximum aad length (max 4095 bytes)
  73          // - Bit 5-7: controls the maximum content length (max 16383 bytes, for performance reasons)
  74          unsigned mode = provider.ConsumeIntegral<uint8_t>();
  75          bool ignore = mode & 1;
  76          bool from_init = mode & 2;
  77          bool damage = mode & 4;
  78          unsigned aad_length_bits = 4 * ((mode >> 3) & 3);
  79          unsigned aad_length = provider.ConsumeIntegralInRange<unsigned>(0, (1 << aad_length_bits) - 1);
  80          unsigned length_bits = 2 * ((mode >> 5) & 7);
  81          unsigned length = provider.ConsumeIntegralInRange<unsigned>(0, (1 << length_bits) - 1);
  82          // Generate aad and content.
  83          auto aad = rng.randbytes<std::byte>(aad_length);
  84          auto contents = rng.randbytes<std::byte>(length);
  85  
  86          // Pick sides.
  87          auto& sender{from_init ? initiator : responder};
  88          auto& receiver{from_init ? responder : initiator};
  89  
  90          // Encrypt
  91          std::vector<std::byte> ciphertext(length + initiator.EXPANSION);
  92          sender.Encrypt(contents, aad, ignore, ciphertext);
  93  
  94          // Optionally damage 1 bit in either the ciphertext (corresponding to a change in transit)
  95          // or the aad (to make sure that decryption will fail if the AAD mismatches).
  96          if (damage) {
  97              unsigned damage_bit = provider.ConsumeIntegralInRange<unsigned>(0,
  98                  (ciphertext.size() + aad.size()) * 8U - 1U);
  99              unsigned damage_pos = damage_bit >> 3;
 100              std::byte damage_val{(uint8_t)(1U << (damage_bit & 7))};
 101              if (damage_pos >= ciphertext.size()) {
 102                  aad[damage_pos - ciphertext.size()] ^= damage_val;
 103              } else {
 104                  ciphertext[damage_pos] ^= damage_val;
 105              }
 106          }
 107  
 108          // Decrypt length
 109          uint32_t dec_length = receiver.DecryptLength(std::span{ciphertext}.first(initiator.LENGTH_LEN));
 110          if (!damage) {
 111              assert(dec_length == length);
 112          } else {
 113              // For performance reasons, don't try to decode if length got increased too much.
 114              if (dec_length > 16384 + length) break;
 115              // Otherwise, just append zeros if dec_length > length.
 116              ciphertext.resize(dec_length + initiator.EXPANSION);
 117          }
 118  
 119          // Decrypt
 120          std::vector<std::byte> decrypt(dec_length);
 121          bool dec_ignore{false};
 122          bool ok = receiver.Decrypt(std::span{ciphertext}.subspan(initiator.LENGTH_LEN), aad, dec_ignore, decrypt);
 123          // Decryption *must* fail if the packet was damaged, and succeed if it wasn't.
 124          assert(!ok == damage);
 125          if (!ok) break;
 126          assert(ignore == dec_ignore);
 127          assert(decrypt == contents);
 128      }
 129  }
 130