Skip to content

Commit

Permalink
Libspark fuzzing harness (#1340)
Browse files Browse the repository at this point in the history
* Spark address/key serialization functions implemented

* CSparkWallet and mint db functions added

* Spark mint tx creation, GetAvailableSparkCoins() implemented

* Bind serial commitments to chain context

* Use default curve generator for spend component

* Completed merge

* Use default address when auto minting

* Adding domain separators when doing hashes

* Adding version and checksum in address serialization

* Saving serial_context into CSparkMintMeta

* Moving Spark related code into separate directory

* Embed KDF derived key size into hash instantiation

* Generalize range proofs to arbitrary set sizes

* Spark state implemented

* More state functionality implemented

* WIP: spend verification batching

* Adding Spark state into mempool

* Use a key-committing AEAD construction

* More spark state functionality implemented

* Spark balance proof fixed

* Adds an encoding method for address scrambling

* Switch from hex to `bech32m` encoding

* Add tests

* SpendTransaction refactored and added serialization for it

* Review comment applied and fixed a bug in mint generation

* Spark spend creation

* Spark spend verification

* More state functionality implemented and bug fixes

* Some bug fixes and cleanup

* Bug fixes and review comments resolved

* More review comments resolved

* Adding several rpc calls for spark

* Adding more rpc calls

* Failing unittests fixed

* Version bump

* Devnet Spark HF block

* Added fuzz folder for persistent fuzzing libspark fuzzing

* bech32 fuzzing harness for honggfuzz added

* fix bech32_fuzz.cpp

* Added f4grumble fuzzing harness

* Forgot to add return statement to f4grumble_fuzz.cpp

* Moved libspark related fuzzing to its own folder

* Added FuzzedDataProvider.h

* Integrated FuzzedDataProvider.h in bech32_fuzz.cpp

* Fixed fuzzing enum in bech32_fuzz.cpp

* missing semicolon

* Added fuzz folder for persistent fuzzing libspark fuzzing

bech32 fuzzing harness for honggfuzz added

Added f4grumble fuzzing harness

Revert "missing semicolon"

This reverts commit 330cff6.

Fuzzing directory cleanup

Added FuzzedDataProvider.h

* Added fuzzing utilities for group elements and scalars

* Added fuzzing for aead.cpp

* Added vector versions of GetGroupElement and GetScalar in fuzzing_utilities.cpp

* Added single proof fuzz test for bpplus_fuzz

* LelantusToSpark function implemented

* Refactoring of file paths

* lelantustospark rpc name refactored

* Adding check to stop lelantus on consensus level

* Added fuzz folder for persistent fuzzing libspark fuzzing

bech32 fuzzing harness for honggfuzz added

Added f4grumble fuzzing harness

Revert "missing semicolon"

This reverts commit 330cff6.

Fuzzing directory cleanup

Added FuzzedDataProvider.h

* Added fuzzing utilities for group elements and scalars

* Added fuzzing for aead.cpp

* Added vector versions of GetGroupElement and GetScalar in fuzzing_utilities.cpp

* Added single proof fuzz test for bpplus_fuzz

* Changed relative paths of dependencies in secp256k1/src/cpp

* More relative path changes in src/secp256k1

* Changed relative paths in crypto/common.h

* Removed FuzzedSecp256k1Object deconstructor

* Addedd aead_fuzz.cpp and other utilities

Adding check to stop lelantus on consensus level

Added fuzz folder for persistent fuzzing libspark fuzzing

bech32 fuzzing harness for honggfuzz added

Added f4grumble fuzzing harness

Revert "missing semicolon"

This reverts commit 330cff6.

Fuzzing directory cleanup

Added FuzzedDataProvider.h

Added fuzzing utilities for group elements and scalars

Added fuzzing for aead.cpp

* Added vector versions of GetGroupElement and GetScalar in fuzzing_utilities.cpp

* Added single proof fuzz test for bpplus_fuzz

* Changed relative paths of dependencies in secp256k1/src/cpp

* More relative path changes in src/secp256k1

* Changed relative paths in crypto/common.h

* Removed FuzzedSecp256k1Object deconstructor

* Added batch bpplus proofs fuzzing tests

* Changed relative paths in libspark/params.h

* Fixed errors in bpplus_fuzz.cpp

* Fixed more errors

* More fixes in bpplus.cpp

* Completed bpplus_fuzz tests

Added batch bpplus proofs fuzzing tests

Changed relative paths in libspark/params.h

Fixed errors in bpplus_fuzz.cpp

Fixed more errors

More fixes in bpplus.cpp

Changed type of sizes in bpplus_fuzz.cpp

* Added chaum_fuzz.cpp

* Changed relative paths in src/wallet/crypter.h

* Changed relative path in arith_uint256.h

exit

* Completed chaum fuzz tests

Added chaum_fuzz.cpp

Changed relative paths in src/wallet/crypter.h

Changed relative path in arith_uint256.h

exit

* Added schnorr_fuzz.cpp

* Addedd grootle_fuzz.cpp

* Added length to ConsumeBytes call

* Initialized sizes vector via a loop in grootle_fuzz.cpp

* Changed relative paths in support/allocator/secure.h

* Changed relative paths in support/allocator/secure.h again

* Added mint_transaction_fuzz.cpp

* Changed type of parameter in MintTransaction in mint_transaction_fuzz.cpp

* Changed relative path in params.cpp

* Changed relative paths in consensus/params.h

* Changed relative paths in primitives/block.h

* Changed relative paths in primitives/transaction.h

* Changed relative paths in src/script/script.h

* Changed more relative paths in src/script/script.h

* Changed relative paths in crypto/MerkleTreeProof/mtp.h

* Changed relative paths in crypto/MerkleTreeProof/mtp.h. Actually this time.

* Changed relative paths in crypto/progpow.h

* Completed mint_transaction_fuzz.cpp

Added mint_transaction_fuzz.cpp

Changed type of parameter in MintTransaction in mint_transaction_fuzz.cpp

Changed relative path in params.cpp

Changed relative paths in consensus/params.h

Changed relative paths in primitives/block.h

Changed relative paths in primitives/transaction.h

Changed relative paths in src/script/script.h

Changed more relative paths in src/script/script.h

Changed relative paths in crypto/MerkleTreeProof/mtp.h

Changed relative paths in crypto/MerkleTreeProof/mtp.h. Actually this time.

Changed relative paths in crypto/progpow.h

* Added spend_transaction_fuzz.cpp

* Fixed errors in spend_transaction_fuzz.cpp

* Completed spend_transaction_fuzz.cpp

Added spend_transaction_fuzz.cpp

Fixed errors in spend_transaction_fuzz.cpp

* Updated relative paths in MultiExponent.cpp

* fuzzing and coverage of different libspark files

* makefile and code-coverage for libspark

* spend transaction modified

* coverage, input, results removed

* empty and temporary files deleted

* empty files removed

* readme for fuzzing modified

* original paths restored and conflict resolved, flags added in fuzz makefile

* path fixed and merged latest spark

* path fixed

* instructions for installing dependencies added in fuzz readme

* binary removed and loop length resized

* readme modified & vetor size reserved in fuzzing_utilities

---------

Co-authored-by: levonpetrosyan93 <petrosyan.levon93@gmail.com>
Co-authored-by: Aaron Feickert <66188213+AaronFeickert@users.noreply.github.com>
Co-authored-by: Mikerah <mikerah@hashcloak.com>
Co-authored-by: Onur İnanç <e191322@metu.edu.tr>
Co-authored-by: HashCloak <info@hashcloak.com>
  • Loading branch information
6 people authored Nov 16, 2023
1 parent 3ba735d commit 92a2050
Show file tree
Hide file tree
Showing 22 changed files with 2,145 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/crypto/progpow.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,4 @@ uint256 progpow_hash_full(const CProgPowHeader& header, uint256& mix_hash);
/* Performs a light progpow hash (DAG loops excluded) provided header has mix_hash */
uint256 progpow_hash_light(const CProgPowHeader& header);

#endif // FIRO_PROGPOW_H
#endif // FIRO_PROGPOW_H
398 changes: 398 additions & 0 deletions src/fuzz/FuzzedDataProvider.h

Large diffs are not rendered by default.

134 changes: 134 additions & 0 deletions src/fuzz/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
CXX := hfuzz-clang++

CXXFLAGS := -DHAVE_CONFIG_H -I../../src/ -iquote ../../src/config/ -iquote ../secp256k1/ -iquote ../secp256k1/src/ -iquote ../secp256k1/include/
CXXFLAGS2 := -DHAVE_CONFIG_H

LIBS := -lcrypto -lstdc++ -lboost_thread -lboost_filesystem -lboost_program_options -lboost_chrono
LIBS2 := -lstdc++ -lcrypto

INCLUDE_HEADER := -include ../streams.h -include ../version.h

BPPLUS_SRCS := libspark/bpplus_fuzz.cpp ../libspark/bpplus.cpp ../libspark/util.cpp fuzzing_utilities.cpp ../libspark/hash.cpp ../libspark/kdf.cpp ../libspark/transcript.cpp ../crypto/aes.cpp ../crypto/chacha20.cpp ../crypto/sha512.cpp ../secp256k1/src/cpp/Scalar.cpp ../secp256k1/src/cpp/GroupElement.cpp ../secp256k1/src/cpp/MultiExponent.cpp ../support/cleanse.cpp ../util.cpp ../utiltime.cpp ../utilstrencodings.cpp ../random.cpp ../chainparamsbase.cpp
BPPLUS_OUTPUT := libspark/bpplus_hfuzz
BPPLUS_OUTPUT_DEBUG := libspark/bpplus_debug

BECH32_SRCS := libspark/bech32_fuzz_2.cpp ../libspark/bech32.cpp
BECH32_OUTPUT := libspark/bech32_hfuzz
BECH32_OUTPUT_DEBUG := libspark/bech32_debug

AEAD_SRCS := libspark/aead_fuzz.cpp ../libspark/aead.cpp ../libspark/util.cpp ../libspark/kdf.cpp ../libspark/hash.cpp ../fuzz/fuzzing_utilities.cpp ../crypto/aes.cpp ../support/lockedpool.cpp ../support/cleanse.cpp ../secp256k1/src/cpp/Scalar.cpp ../secp256k1/src/cpp/GroupElement.cpp
AEAD_OUTPUT := libspark/aead_hfuzz
AEAD_OUTPUT_DEBUG := libspark/aead_debug

GROOTLE_SRCS := libspark/grootle_fuzz.cpp ../libspark/grootle.cpp ../libspark/util.cpp fuzzing_utilities.cpp ../libspark/hash.cpp ../libspark/kdf.cpp ../libspark/transcript.cpp ../crypto/aes.cpp ../crypto/chacha20.cpp ../crypto/sha512.cpp ../secp256k1/src/cpp/Scalar.cpp ../secp256k1/src/cpp/GroupElement.cpp ../secp256k1/src/cpp/MultiExponent.cpp ../support/cleanse.cpp ../util.cpp ../utiltime.cpp ../utilstrencodings.cpp ../random.cpp ../chainparamsbase.cpp
GROOTLE_OUTPUT := libspark/grootle_hfuzz
GROOTLE_OUTPUT_DEBUG := libspark/grootle_debug

CHAUM_SRCS := libspark/chaum_fuzz.cpp ../libspark/chaum.cpp ../libspark/transcript.cpp fuzzing_utilities.cpp ../secp256k1/src/cpp/Scalar.cpp ../secp256k1/src/cpp/GroupElement.cpp ../secp256k1/src/cpp/MultiExponent.cpp ../support/cleanse.cpp
CHAUM_OUTPUT := libspark/chaum_hfuzz
CHAUM_OUTPUT_DEBUG := libspark/chaum_debug

SCHNORR_SRCS := libspark/schnorr_fuzz.cpp ../libspark/schnorr.cpp ../fuzz/fuzzing_utilities.cpp ../secp256k1/src/cpp/Scalar.cpp ../secp256k1/src/cpp/GroupElement.cpp ../secp256k1/src/cpp/MultiExponent.cpp ../libspark/transcript.cpp ../support/cleanse.cpp
SCHNORR_OUTPUT := libspark/schnorr_hfuzz
SCHNORR_OUTPUT_DEBUG := libspark/schnorr_debug

COIN_SRCS := libspark/coin_fuzz.cpp ../libspark/coin.cpp ../libspark/params.cpp ../crypto/aes.cpp ../crypto/ripemd160.cpp ../crypto/sha256.cpp ../secp256k1/src/cpp/Scalar.cpp ../secp256k1/src/cpp/GroupElement.cpp ../secp256k1/src/cpp/MultiExponent.cpp ../support/*.cpp ../uint256.cpp ../utilstrencodings.cpp fuzzing_utilities.cpp ../libspark/aead.cpp ../libspark/util.cpp ../libspark/keys.cpp ../libspark/f4grumble.cpp ../libspark/hash.cpp ../libspark/bech32.cpp ../libspark/kdf.cpp
COIN_OUTPUT := libspark/coin_hfuzz
COIN_OUTPUT_DEBUG := libspark/coin_debug

MINT_TRANSACTION_SRCS := libspark/mint_transaction_fuzz.cpp ../libspark/mint_transaction.cpp ../libspark/coin.cpp ../libspark/keys.cpp ../libspark/schnorr.cpp ../fuzz/fuzzing_utilities.cpp ../libspark/util.cpp ../libspark/hash.cpp ../libspark/kdf.cpp ../libspark/transcript.cpp ../libspark/f4grumble.cpp ../libspark/params.cpp ../libspark/bech32.cpp ../libspark/aead.cpp ../crypto/aes.cpp ../crypto/ripemd160.cpp ../crypto/sha256.cpp ../secp256k1/src/cpp/Scalar.cpp ../secp256k1/src/cpp/GroupElement.cpp ../secp256k1/src/cpp/MultiExponent.cpp ../support/cleanse.cpp ../uint256.cpp ../utilstrencodings.cpp
MINT_TRANSACTION_OUTPUT := libspark/mint_transaction_hfuzz
MINT_TRANSACTION_OUTPUT_DEBUG := libspark/mint_transaction_debug

SPEND_TRANSACTION_SRCS := libspark/spend_transaction_fuzz.cpp ../libspark/spend_transaction.cpp ../libspark/coin.cpp ../libspark/keys.cpp ../libspark/schnorr.cpp ../fuzz/fuzzing_utilities.cpp ../libspark/util.cpp ../libspark/hash.cpp ../libspark/kdf.cpp ../libspark/transcript.cpp ../libspark/f4grumble.cpp ../libspark/params.cpp ../libspark/bech32.cpp ../libspark/aead.cpp ../libspark/chaum.cpp ../libspark/bpplus.cpp ../libspark/grootle.cpp ../crypto/aes.cpp ../crypto/ripemd160.cpp ../crypto/sha256.cpp ../crypto/chacha20.cpp ../crypto/sha512.cpp ../secp256k1/src/cpp/Scalar.cpp ../secp256k1/src/cpp/GroupElement.cpp ../secp256k1/src/cpp/MultiExponent.cpp ../support/cleanse.cpp ../uint256.cpp ../utilstrencodings.cpp ../util.cpp ../utiltime.cpp ../chainparamsbase.cpp ../random.cpp
SPEND_TRANSACTION_OUTPUT := libspark/spend_transaction_hfuzz
SPEND_TRANSACTION_OUTPUT_DEBUG := libspark/spend_transaction_debug

F4GRUMBLE_SRCS := libspark/f4grumble_fuzz.cpp ../libspark/f4grumble.cpp ../libspark/util.cpp ../libspark/kdf.cpp ../libspark/hash.cpp ../crypto/aes.cpp ../support/lockedpool.cpp ../support/cleanse.cpp ../secp256k1/src/cpp/Scalar.cpp ../secp256k1/src/cpp/GroupElement.cpp
F4GRUMBLE_OUTPUT := libspark/f4grumble_hfuzz
F4GRUMBLE_OUTPUT_DEBUG := libspark/f4grumble_debug

DEBUG_FLAGS := -g -O0 -ggdb

bpplus: $(BPPLUS_OUTPUT)
$(BPPLUS_OUTPUT): $(BPPLUS_SRCS)
$(CXX) $(CXXFLAGS) $^ -o $@ $(LIBS)

bpplus_debug: $(BPPLUS_OUTPUT_DEBUG)
$(BPPLUS_OUTPUT_DEBUG): $(BPPLUS_SRCS)
$(CXX) $(DEBUG_FLAGS) $(CXXFLAGS) $^ -o $@ $(LIBS)

bech32: $(BECH32_OUTPUT)
$(BECH32_OUTPUT): $(BECH32_SRCS)
$(CXX) $(CXXFLAGS2) $^ -o $@ $(LIBS2)

bech32_debug: $(BECH32_OUTPUT_DEBUG)
$(BECH32_OUTPUT_DEBUG): $(BECH32_SRCS)
$(CXX) $(DEBUG_FLAGS) $(CXXFLAGS2) $^ -o $@ $(LIBS2)

aead: $(AEAD_OUTPUT)
$(AEAD_OUTPUT): $(AEAD_SRCS)
$(CXX) $(CXXFLAGS) $^ -o $@ $(LIBS2)

aead_debug: $(AEAD_OUTPUT_DEBUG)
$(AEAD_OUTPUT_DEBUG): $(AEAD_SRCS)
$(CXX) $(DEBUG_FLAGS) $(CXXFLAGS) $^ -o $@ $(LIBS2)

grootle: $(GROOTLE_OUTPUT)
$(GROOTLE_OUTPUT): $(GROOTLE_SRCS)
$(CXX) $(CXXFLAGS) $^ -o $@ $(LIBS)

grootle_debug: $(GROOTLE_OUTPUT_DEBUG)
$(GROOTLE_OUTPUT_DEBUG): $(GROOTLE_SRCS)
$(CXX) $(DEBUG_FLAGS) $(CXXFLAGS) $^ -o $@ $(LIBS)

chaum: $(CHAUM_OUTPUT)
$(CHAUM_OUTPUT): $(CHAUM_SRCS)
$(CXX) $(CXXFLAGS) $^ -o $@ $(INCLUDE_HEADER) $(LIBS)

chaum_debug: $(CHAUM_OUTPUT_DEBUG)
$(CHAUM_OUTPUT_DEBUG): $(CHAUM_SRCS)
$(CXX) $(DEBUG_FLAGS) $(CXXFLAGS2) $^ -o $@ $(INCLUDE_HEADER) $(LIBS)

schnorr: $(SCHNORR_OUTPUT)
$(SCHNORR_OUTPUT): $(SCHNORR_SRCS)
$(CXX) $(CXXFLAGS) $^ -o $@ $(INCLUDE_HEADER) $(LIBS)

schnorr_debug: $(SCHNORR_OUTPUT_DEBUG)
$(SCHNORR_OUTPUT_DEBUG): $(SCHNORR_SRCS)
$(CXX) $(DEBUG_FLAGS) $(CXXFLAGS) $^ -o $@ $(INCLUDE_HEADER) $(LIBS)

coin: $(COIN_OUTPUT)
$(COIN_OUTPUT): $(COIN_SRCS)
$(CXX) $(CXXFLAGS) $^ -o $@ $(LIBS)

coin_debug: $(COIN_OUTPUT_DEBUG)
$(COIN_OUTPUT_DEBUG): $(COIN_SRCS)
$(CXX) $(DEBUG_FLAGS) $(CXXFLAGS) $^ -o $@ $(LIBS)

mint_transaction: $(MINT_TRANSACTION_OUTPUT)
$(MINT_TRANSACTION_OUTPUT): $(MINT_TRANSACTION_SRCS)
$(CXX) $(CXXFLAGS) $^ -o $@ $(LIBS2)

mint_transaction_debug: $(MINT_TRANSACTION_OUTPUT_DEBUG)
$(MINT_TRANSACTION_OUTPUT_DEBUG): $(MINT_TRANSACTION_SRCS)
$(CXX) $(DEBUG_FLAGS) $(CXXFLAGS2) $^ -o $@ $(LIBS2)

spend_transaction: $(SPEND_TRANSACTION_OUTPUT)
$(SPEND_TRANSACTION_OUTPUT): $(SPEND_TRANSACTION_SRCS)
$(CXX) $(CXXFLAGS) $^ -o $@ $(LIBS)

spend_transaction_debug: $(SPEND_TRANSACTION_OUTPUT_DEBUG)
$(SPEND_TRANSACTION_OUTPUT_DEBUG): $(SPEND_TRANSACTION_SRCS)
$(CXX) $(DEBUG_FLAGS) $(CXXFLAGS) $^ -o $@ $(LIBS)

f4grumble: $(F4GRUMBLE_OUTPUT)
$(F4GRUMBLE_OUTPUT): $(F4GRUMBLE_SRCS)
$(CXX) $(CXXFLAGS) $^ -o $@ $(LIBS)

f4grumble_debug: $(F4GRUMBLE_OUTPUT_DEBUG)
$(F4GRUMBLE_OUTPUT_DEBUG): $(F4GRUMBLE_SRCS)
$(CXX) $(DEBUG_FLAGS) $(CXXFLAGS) $^ -o $@ $(LIBS)

clean:
rm -f $(BPPLUS_OUTPUT) $(BPPLUS_OUTPUT_DEBUG) $(BECH32_OUTPUT) $(BECH32_OUTPUT_DEBUG) $(AEAD_OUTPUT) $(AEAD_OUTPUT_DEBUG) $(GROOTLE_OUTPUT) $(GROOTLE_OUTPUT_DEBUG) $(CHAUM_OUTPUT) $(CHAUM_OUTPUT_DEBUG) $(SCHNORR_OUTPUT) $(SCHNORR_OUTPUT_DEBUG) $(COIN_OUTPUT) $(COIN_OUTPUT_DEBUG) $(MINT_TRANSACTION_OUTPUT) $(MINT_TRANSACTION_OUTPUT_DEBUG) $(SPEND_TRANSACTION_OUTPUT) $(SPEND_TRANSACTION_OUTPUT_DEBUG) *.o
142 changes: 142 additions & 0 deletions src/fuzz/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
# Fuzzing libspark

## Quickstart Guide
To quickly get started fuzzing libspark using honggfuzz:

### Build firo
- clone this repo:
```
git clone -b spark https://github.com/firoorg/firo.git
```
- Build firo: Follow instruction from https://github.com/firoorg/firo/tree/spark#readme

Once the build is successful, we have to install honggfuzz and required dependencies.

### Installing fuzzer and Dependencies
- Install honggfuzz (https://github.com/google/honggfuzz)
```
sudo apt-get install binutils-dev libunwind-dev libblocksruntime-dev clang
git clone https://github.com/google/honggfuzz.git
cd honggfuzz
make
sudo make install
```
For more information you can look at https://github.com/google/honggfuzz/blob/master/docs/USAGE.md

You might also need to install the following boost and ssl dependencies in order to compile the fuzzing harness:

```
sudo apt install libboost-dev
sudo apt install libssl-dev
sudo apt install libstdc++-12-dev
sudo apt install libboost-filesystem-dev
sudo apt install libboost-thread-dev
sudo apt install libboost-program-options-dev
sudo apt install libboost-chrono-dev
```

### Fuzzing using honggfuzz
* In order to fuzz `firo/src/libpark` using Honggfuzz:

```
cd firo/src/fuzz/
export CC=hfuzz-clang
export CXX=hfuzz-clang++
```

To compile with `hfuzz-clang++`, inside src/fuzz run:

```
make <filename>
```

For example(for bpplus):
```
make bpplus
```
The above command will generate an instrumented binary with name `<filename>_hfuzz` (eg: bpplus_hfuzz) inside src/fuzz/libspark.

The fuzzing harness of the following spark files is availabe: aead, bech32, bpplus, chaum, coin, f4grumble, grootle, mint_transaction, schnorr and spend_transaction.

* To start fuzzing:

1. create directories for input corpora and for saving all the crashes
```
mkdir input crashes
```
2. Inside the crashes directory run:
```
honggfuzz -i input -- ./libspark/<filename>_hfuzz ___FILE___
```

example:
1. `mkdir input crashes`
2. `cd crashes`
2. `honggfuzz -i ../input -- ./../libspark/bpplus_hfuzz ___FILE___`
3. To stop press `ctrl+c`

Here we are providing an empty corpora. In case of an already available corpora, we can provide the availabe corpora.
The flag `-i` is for the input folder which we are providing `./../<filename>_hfuzz>` is the target binary which we want to fuzz.

### Analyzing the crashes

If there is a crash, the reason for the crash can be found in HONGGFUZZ.REPORT.TXT or simply by running
```
./libspark/<binary_file> <input_file>
```

Example:
```
./libspark/bpplus_hfuzz SIGABRT.PC.7ffff7a8400b.STACK.1b5b5f0067.CODE.-6.ADDR.0.INSTR.mov____0x108(%rsp),%rax
```

To debug or to do the rootcause analysis, gdb debugger can be used. to debug using gdb debugger:

1. First compile the harness using gdb flags `-g -O0 -ggdb`. To compile using gdb debugger, inside `src/fuzz` run:
```
make <filename>_debug
```
Example:
```
make bpplus_debug
```

2. start the debugger by running:
```
gdb --args <filename_debug> <crashed_input>
```
Example:
```
gdb --args bpplus_debug SIGABRT.PC.7ffff7a8400b.STACK.1b5b5f0067.CODE.-6.ADDR.0.INSTR.mov____0x108(%rsp),%rax
```
This will start the debugger.

3. You can do heap analysis by running `heap-analysis` inside the debugger and/or `bt` for backtracing.


### Generating a Coverage Report using kcov
* Install kcov (https://github.com/SimonKagstrom/kcov/tree/master)
```
sudo apt-get install binutils-dev libssl-dev libcurl4-openssl-dev zlib1g-dev libdw-dev libiberty-dev
git clone https://github.com/SimonKagstrom/kcov.git
cd /path/to/kcov/source/dir
mkdir build
cd build
cmake ..
make
sudo make install
```
Once successfully installed, follow the below instructions to generate the code-coverage

1. First compile the harness with gdb flag. run `make <filename>_debug` inside src/fuzz to compile using gdb debugger.
2. take the input_folder as the input corpora from fuzzing or one can also create it by running: `honggfuzz -i <input_folder> -– ./<filename>_hfuzz ___FILE___ @@`. This will start the fuzzer. Kill it by `ctrl+C`. The fuzzer will generate some random inputs inside the input_folder. Since kcov will generate coverage for each input inside the input_folder, it's preffered to have only a few inputs, otherwise it will take a long time to generate the entire coverage.

3. inside the `generate_coverage.sh` replace the input_folder, output_folder and fuzz_exe by your inpur corpora, coverage output folder and harness binary.
4. run `./generate_coverage.sh`. This will generated a merged output for all the inputs present in the input_folder.
5. To view the result run run `firefox ./merged-output/index.html`.

6. alternatively or if you are on a VM, go inside coverage output folder and then merged-output
7. run `python3 -m http.server`. This will start a http server at http://0.0.0.0:8000/
8. open your browser and paste http://0.0.0.0:8000/ to see the result.

NOTE: to view the coverage for every dependent file, `generate_coverage.sh` should be in the root folder. Also, you should either delete the previous port or start the server on new port by running `python3 -m http.server <port_number>` for different files.
89 changes: 89 additions & 0 deletions src/fuzz/fuzzing_utilities.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#include "fuzzing_utilities.h"

FuzzedSecp256k1Object::FuzzedSecp256k1Object(FuzzedDataProvider *fdp) {
this->fdp = fdp;
}

secp_primitives::GroupElement FuzzedSecp256k1Object::GetGroupElement() {
char* x = (char *)this->fdp->ConsumeBytes<uint8_t>(256).data();
char* y = (char *)this->fdp->ConsumeBytes<uint8_t>(256).data();
secp_primitives::GroupElement ge = secp_primitives::GroupElement(x, y);

return ge;
}

secp_primitives::Scalar FuzzedSecp256k1Object::GetScalar() {
uint64_t value = this->fdp->ConsumeIntegral<uint64_t>();
secp_primitives::Scalar s = secp_primitives::Scalar(value);

return s;
}

secp_primitives::GroupElement FuzzedSecp256k1Object::GetMemberGroupElement() {
secp_primitives::GroupElement ge;
ge.randomize();
return ge;
}

std::vector<secp_primitives::GroupElement> FuzzedSecp256k1Object::GetMemberGroupElements(size_t len) {
std::vector<secp_primitives::GroupElement> ge_vec;
ge_vec.resize(len);
for (size_t i = 0; i < len; i++) {
ge_vec[i] = (GetMemberGroupElement());
}
return ge_vec;
}

std::vector<secp_primitives::GroupElement> FuzzedSecp256k1Object::GetRandomGroupVector(size_t len) {
std::vector<secp_primitives::GroupElement> result;
result.resize(len);
for (size_t i = 0; i < len; i++) {
result[i].randomize();
}
return result;
}

std::vector<secp_primitives::GroupElement> FuzzedSecp256k1Object::GetGroupElements(int len) {
std::vector<secp_primitives::GroupElement> ge_vec;
ge_vec.reserve(len);
for (int i = 0; i < len; i++) {
ge_vec.push_back(GetGroupElement());
}

return ge_vec;
}

std::vector<secp_primitives::Scalar> FuzzedSecp256k1Object::GetScalars(size_t len) {
std::vector<secp_primitives::Scalar> scalar_vec;
scalar_vec.reserve(len);
for (int i = 0; i < len; i++) {
scalar_vec.push_back(GetScalar());
}

return scalar_vec;
}

std::vector<secp_primitives::Scalar> FuzzedSecp256k1Object::GetScalarsVector(size_t len) {
std::vector<secp_primitives::Scalar> scalar_vec;
scalar_vec.reserve(len);
for (int i = 0; i < len; i++) {
scalar_vec.push_back(GetScalar());
}

return scalar_vec;
}

secp_primitives::Scalar FuzzedSecp256k1Object::GetScalar_modified() {
secp_primitives::Scalar s = secp_primitives::Scalar(this->fdp->ConsumeBytes<uint8_t>(256).data());
return s;
}

std::vector<secp_primitives::Scalar> FuzzedSecp256k1Object::GetScalars_modified(int len) {
std::vector<secp_primitives::Scalar> scalar_vec;
scalar_vec.reserve(len);
for (int i = 0; i < len; i++) {
scalar_vec.push_back(GetScalar_modified());
}

return scalar_vec;
}
Loading

0 comments on commit 92a2050

Please sign in to comment.