aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorstratospher <44024636+stratospher@users.noreply.github.com>2021-08-07 10:55:33 +0000
committerstratospher <ruhiasap@gmail.com>2021-12-11 08:29:34 +0530
commit4d0ac72f3ae78e3c6a0d5dc4f7e809583abd0546 (patch)
tree779ad16c51b2986d070a1bd80658f662f386dd7b
parent65ef93203cc6a977c8e96f07cb9155f46faf5004 (diff)
downloadbitcoin-4d0ac72f3ae78e3c6a0d5dc4f7e809583abd0546.tar.xz
[fuzz] Add fuzzing harness to compare both implementations of ChaCha20
Co-authored-by: Prakash Choudhary <44579179+prakash1512@users.noreply.github.com>
-rw-r--r--src/Makefile.test.include1
-rw-r--r--src/test/fuzz/crypto_diff_fuzz_chacha20.cpp75
2 files changed, 76 insertions, 0 deletions
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index 06d195aaaf..6313ab13df 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -238,6 +238,7 @@ test_fuzz_fuzz_SOURCES = \
test/fuzz/crypto_chacha20.cpp \
test/fuzz/crypto_chacha20_poly1305_aead.cpp \
test/fuzz/crypto_common.cpp \
+ test/fuzz/crypto_diff_fuzz_chacha20.cpp \
test/fuzz/crypto_hkdf_hmac_sha256_l32.cpp \
test/fuzz/crypto_poly1305.cpp \
test/fuzz/cuckoocache.cpp \
diff --git a/src/test/fuzz/crypto_diff_fuzz_chacha20.cpp b/src/test/fuzz/crypto_diff_fuzz_chacha20.cpp
index 7725606de9..96681a121a 100644
--- a/src/test/fuzz/crypto_diff_fuzz_chacha20.cpp
+++ b/src/test/fuzz/crypto_diff_fuzz_chacha20.cpp
@@ -1,3 +1,15 @@
+// Copyright (c) 2020-2021 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 <crypto/chacha20.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+
+#include <cstdint>
+#include <vector>
+
/*
From https://cr.yp.to/chacha.html
chacha-merged.c version 20080118
@@ -253,3 +265,66 @@ void ECRYPT_keystream_bytes(ECRYPT_ctx* x, u8* stream, u32 bytes)
ECRYPT_encrypt_bytes(x, stream, stream, bytes);
}
+FUZZ_TARGET(crypto_diff_fuzz_chacha20)
+{
+ FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
+
+ ChaCha20 chacha20;
+ ECRYPT_ctx ctx;
+ // D. J. Bernstein doesn't initialise ctx to 0 while Bitcoin Core initialises chacha20 to 0 in the constructor
+ for (int i = 0; i < 16; i++) {
+ ctx.input[i] = 0;
+ }
+
+ if (fuzzed_data_provider.ConsumeBool()) {
+ const std::vector<unsigned char> key = ConsumeFixedLengthByteVector(fuzzed_data_provider, fuzzed_data_provider.ConsumeIntegralInRange<size_t>(16, 32));
+ chacha20 = ChaCha20{key.data(), key.size()};
+ ECRYPT_keysetup(&ctx, key.data(), key.size() * 8, 0);
+ // ECRYPT_keysetup() doesn't set the counter and nonce to 0 while SetKey() does
+ uint8_t iv[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+ ECRYPT_ivsetup(&ctx, iv);
+ }
+
+ LIMITED_WHILE (fuzzed_data_provider.ConsumeBool(), 3000) {
+ CallOneOf(
+ fuzzed_data_provider,
+ [&] {
+ const std::vector<unsigned char> key = ConsumeFixedLengthByteVector(fuzzed_data_provider, fuzzed_data_provider.ConsumeIntegralInRange<size_t>(16, 32));
+ chacha20.SetKey(key.data(), key.size());
+ ECRYPT_keysetup(&ctx, key.data(), key.size() * 8, 0);
+ // ECRYPT_keysetup() doesn't set the counter and nonce to 0 while SetKey() does
+ uint8_t iv[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+ ECRYPT_ivsetup(&ctx, iv);
+ },
+ [&] {
+ uint64_t iv = fuzzed_data_provider.ConsumeIntegral<uint64_t>();
+ chacha20.SetIV(iv);
+ ctx.input[14] = iv;
+ ctx.input[15] = iv >> 32;
+ },
+ [&] {
+ uint64_t counter = fuzzed_data_provider.ConsumeIntegral<uint64_t>();
+ chacha20.Seek(counter);
+ ctx.input[12] = counter;
+ ctx.input[13] = counter >> 32;
+ },
+ [&] {
+ uint32_t integralInRange = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 4096);
+ std::vector<uint8_t> output(integralInRange);
+ chacha20.Keystream(output.data(), output.size());
+ std::vector<uint8_t> djb_output(integralInRange);
+ ECRYPT_keystream_bytes(&ctx, djb_output.data(), djb_output.size());
+ if (output.data() != NULL && djb_output.data() != NULL) {
+ assert(memcmp(output.data(), djb_output.data(), integralInRange) == 0);
+ }
+ },
+ [&] {
+ uint32_t integralInRange = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 4096);
+ std::vector<uint8_t> output(integralInRange);
+ const std::vector<uint8_t> input = ConsumeFixedLengthByteVector(fuzzed_data_provider, output.size());
+ chacha20.Crypt(input.data(), output.data(), input.size());
+ std::vector<uint8_t> djb_output(integralInRange);
+ ECRYPT_encrypt_bytes(&ctx, input.data(), djb_output.data(), input.size());
+ });
+ }
+}