diff options
author | Ava Chow <github@achow101.com> | 2024-06-04 21:26:42 -0400 |
---|---|---|
committer | Ava Chow <github@achow101.com> | 2024-06-04 21:26:42 -0400 |
commit | b3a61bd7b10211124613d18a524ec86781a30e9e (patch) | |
tree | 4311401fd8dd326243593a38df534d7d4293f4e4 /src | |
parent | 55cf34a5c30f1aee0737b48fa2814996359eca89 (diff) | |
parent | d7290d662f494503f28e087dd728b492c0bb2c5f (diff) |
Merge bitcoin/bitcoin#28074: fuzz: wallet, add target for `Crypter`
d7290d662f494503f28e087dd728b492c0bb2c5f fuzz: wallet, add target for Crypter (Ayush Singh)
Pull request description:
This PR adds fuzz coverage for `wallet/crypter`.
Motivation: Issue [27272](https://github.com/bitcoin/bitcoin/issues/27272#issue-1628327906)
I ran this for a long time with Sanitizers on and had no crashes; the average `exec/sec` also looks good to me. However, I would really appreciate it if some of the reviewers could try it on their machines too, and give their feedback.
ACKs for top commit:
maflcko:
utACK d7290d662f494503f28e087dd728b492c0bb2c5f
achow101:
ACK d7290d662f494503f28e087dd728b492c0bb2c5f
brunoerg:
utACK d7290d662f494503f28e087dd728b492c0bb2c5f
Tree-SHA512: f5c496cabdd3263a7e1ad49eeff702725336f76bf19a82e5dbbead082e990889dd43c851d0d2d6ab740f44b8ec2aa06defd9ff6b02be68b5f8b4eaf963f88599
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.test.include | 1 | ||||
-rw-r--r-- | src/wallet/test/fuzz/crypter.cpp | 92 |
2 files changed, 93 insertions, 0 deletions
diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 0cb3b185ad..742022ca93 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -203,6 +203,7 @@ endif FUZZ_WALLET_SRC = \ wallet/test/fuzz/coincontrol.cpp \ wallet/test/fuzz/coinselection.cpp \ + wallet/test/fuzz/crypter.cpp \ wallet/test/fuzz/fees.cpp \ wallet/test/fuzz/parse_iso8601.cpp \ wallet/test/fuzz/wallet_bdb_parser.cpp diff --git a/src/wallet/test/fuzz/crypter.cpp b/src/wallet/test/fuzz/crypter.cpp new file mode 100644 index 0000000000..62dd1bfde0 --- /dev/null +++ b/src/wallet/test/fuzz/crypter.cpp @@ -0,0 +1,92 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <test/fuzz/FuzzedDataProvider.h> +#include <test/fuzz/fuzz.h> +#include <test/fuzz/util.h> +#include <test/util/setup_common.h> +#include <wallet/crypter.h> + +namespace wallet { +namespace { + +const TestingSetup* g_setup; +void initialize_crypter() +{ + static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>(); + g_setup = testing_setup.get(); +} + +FUZZ_TARGET(crypter, .init = initialize_crypter) +{ + FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); + bool good_data{true}; + + CCrypter crypt; + // These values are regularly updated within `CallOneOf` + std::vector<unsigned char> cipher_text_ed; + CKeyingMaterial plain_text_ed; + const std::vector<unsigned char> random_key = ConsumeRandomLengthByteVector(fuzzed_data_provider); + + LIMITED_WHILE(good_data && fuzzed_data_provider.ConsumeBool(), 10000) + { + CallOneOf( + fuzzed_data_provider, + [&] { + const std::string random_string = fuzzed_data_provider.ConsumeRandomLengthString(); + SecureString secure_string(random_string.begin(), random_string.end()); + + const unsigned int derivation_method = fuzzed_data_provider.ConsumeBool() ? 0 : fuzzed_data_provider.ConsumeIntegral<unsigned int>(); + + // Limiting the value of nRounds since it is otherwise uselessly expensive and causes a timeout when fuzzing. + crypt.SetKeyFromPassphrase(/*strKeyData=*/secure_string, + /*chSalt=*/ConsumeRandomLengthByteVector(fuzzed_data_provider), + /*nRounds=*/fuzzed_data_provider.ConsumeIntegralInRange<unsigned int>(0, 25000), + /*nDerivationMethod=*/derivation_method); + }, + [&] { + const std::vector<unsigned char> random_vector = ConsumeFixedLengthByteVector(fuzzed_data_provider, 32); + const CKeyingMaterial new_key(random_vector.begin(), random_vector.end()); + const std::vector<unsigned char>& new_IV = ConsumeFixedLengthByteVector(fuzzed_data_provider, 16); + crypt.SetKey(new_key, new_IV); + }, + [&] { + const std::vector<unsigned char> random_vector = ConsumeRandomLengthByteVector(fuzzed_data_provider); + plain_text_ed = CKeyingMaterial(random_vector.begin(), random_vector.end()); + }, + [&] { + cipher_text_ed = ConsumeRandomLengthByteVector(fuzzed_data_provider); + }, + [&] { + (void)crypt.Encrypt(plain_text_ed, cipher_text_ed); + }, + [&] { + (void)crypt.Decrypt(cipher_text_ed, plain_text_ed); + }, + [&] { + const CKeyingMaterial master_key(random_key.begin(), random_key.end()); + const uint256 iv = ConsumeUInt256(fuzzed_data_provider); + EncryptSecret(master_key, plain_text_ed, iv, cipher_text_ed); + }, + [&] { + const CKeyingMaterial master_key(random_key.begin(), random_key.end()); + const uint256 iv = ConsumeUInt256(fuzzed_data_provider); + DecryptSecret(master_key, cipher_text_ed, iv, plain_text_ed); + }, + [&] { + std::optional<CPubKey> random_pub_key = ConsumeDeserializable<CPubKey>(fuzzed_data_provider); + if (!random_pub_key) { + good_data = false; + return; + } + const CPubKey pub_key = *random_pub_key; + const CKeyingMaterial master_key(random_key.begin(), random_key.end()); + const std::vector<unsigned char> crypted_secret = ConsumeRandomLengthByteVector(fuzzed_data_provider); + CKey key; + DecryptKey(master_key, crypted_secret, pub_key, key); + }); + } +} +} // namespace +} // namespace wallet |