2020-11-30 13:54:34 +00:00
# Fuzz Testing trezor-crypto
2020-07-01 12:04:02 +00:00
Selected functions can be fuzzed via specific libFuzzer harnesses for increased test coverage and issue detection.
Note: the following commands are relative to the trezor-crypto main directory.
## Build
A modern C compiler with built-in libFuzzer support is required. The build process will use `clang` by default.
Set the `CC=` environment variable if you want to use a special compiler variant.
```bash
make clean
2022-08-12 12:04:15 +00:00
FUZZER=1 make fuzzer -j$(nproc)
2020-07-01 12:04:02 +00:00
```
### Sanitizers
Recommended: ASAN / UBSAN / MSAN flags for error detection can be specified via the special `SANFLAGS` .
Examples:
2021-12-08 12:11:13 +00:00
* `SANFLAGS="-fsanitize=address,undefined"`
* `SANFLAGS="-fsanitize=memory -fsanitize-memory-track-origins"`
2020-11-30 13:54:34 +00:00
2020-07-01 12:04:02 +00:00
### Optimizations
Override `OPTFLAGS` to test the library at different optimization levels or simplify the debugging of detected issues.
2020-11-30 13:54:34 +00:00
Examples:
2020-07-01 12:04:02 +00:00
2021-12-08 12:11:13 +00:00
* `OPTFLAGS="-O0 -ggdb3"`
2022-08-12 12:04:15 +00:00
* `OPTFLAGS="-O3 -march=native -fno-omit-frame-pointer -gline-tables-only"`
2020-07-01 12:04:02 +00:00
2021-12-08 12:11:13 +00:00
To be determined:
2022-08-12 12:04:15 +00:00
* semi-automatic use of `-fsanitize-ignorelist` to reduce sanitizer overhead on hot functions
2021-12-08 12:11:13 +00:00
* `-flto` and `-flto=thin` link time optimization
2021-11-13 13:25:32 +00:00
2021-12-08 12:11:13 +00:00
Advanced usage:
* [Profile guided optimization ](https://clang.llvm.org/docs/UsersManual.html#profile-guided-optimization )
2022-08-12 12:04:15 +00:00
### Fuzzer-specific Configuration Flags
* `-DFUZZ_ALLOW_SLOW` to enable optional fuzzing targets of slow functions
2023-02-08 11:08:11 +00:00
* select a specific fuzz testing harness with `-DFUZZ_EXCLUSIVE_TARGET=` to disable the use of all other targets
2022-08-12 12:04:15 +00:00
2021-07-25 21:23:31 +00:00
### Other Flags
To be determined:
2021-12-08 12:11:13 +00:00
2021-07-25 21:23:31 +00:00
* `-DNDEBUG`
2022-08-12 12:04:15 +00:00
* `-DUSE_BIP39_CACHE=0 -DUSE_BIP32_CACHE=0` to explicitly disable the cache, a workaround for automatic cache clearing is used otherwise
2021-12-08 12:11:13 +00:00
* `-D_FORTIFY_SOURCE=2` together with optimization flag -O2 or above
2020-11-30 13:54:34 +00:00
* `-fstack-protector-strong` or `-fstack-protector-all`
2022-08-12 12:04:15 +00:00
* `-m32` to closer emulate the 32-bit environment present on microcontroller platforms
* manually adjust Makefile `DSECP256K1_CONTEXT_SIZE=` for 32-bit values, see `legacy/firmware/Makefile`
* this flag requires 32-bit build support for gcc-multilib, libc and others
* switching from 64-bit to 32-bit has some effects on sanitizer internals such as Address Sanitizer
2022-01-01 13:04:56 +00:00
* `-DSHA2_UNROLL_TRANSFORM` SHA2 optimization flags
* `-fsanitize-coverage=edge,trace-cmp,trace-div,indirect-calls,trace-gep,no-prune` to add program counter granularity
2022-08-12 12:04:15 +00:00
* starting with clang-15, the additional `trace-loads` and `trace-stores` sanitizer coverage options are also available
2021-07-25 21:23:31 +00:00
2023-02-08 11:08:11 +00:00
### Architecture-specific Configuration
* aarch64 supports Hardware-assisted AddressSanitizer via `-fsanitize=hwaddress`
* initial testing suggests that this is usable but slower than Address Sanitizer on some systems
* use `lld` instead of the default linker
2020-07-01 12:04:02 +00:00
## Operation
See the [libFuzzer documentation ](https://llvm.org/docs/LibFuzzer.html#options ) for valid options and usage. Detailed fuzzer usage and relevant considerations are out of scope of this document.
**Warning**: fuzzing is resource-intensive and can have a negative impact on your system stability.
Basic fuzzer call:
```bash
./fuzzer/fuzzer
```
Here is a more sophisticated multithreading example with a persistent input corpus and other optimizations:
```bash
mkdir fuzzer/fuzzer_corpus
2022-08-12 12:04:15 +00:00
./fuzzer/fuzzer -max_len=2048 -use_value_profile=1 -workers=16 -jobs=16 -timeout=1 -reload=5 -print_pcs=1 -print_funcs=42 fuzzer/fuzzer_corpus
2020-07-01 12:04:02 +00:00
```
2020-11-30 13:54:34 +00:00
Hint: for more permanent setups, consider invoking the fuzzer from outside of the source directory to avoid cluttering it with logfiles and crash inputs. Similarly, it is recommended to store the fuzzer corpus in another location.
2020-07-01 12:04:02 +00:00
2020-11-30 13:54:34 +00:00
## Automated Fuzzer Dictionary Generation
2020-07-01 12:04:02 +00:00
[Dictionaries ](https://llvm.org/docs/LibFuzzer.html#dictionaries ) are a useful mechanism to augment the capabilities of the fuzzer. Specify them via the `-dict=` flag.
2020-11-30 13:54:34 +00:00
### Collect Interesting Strings From Unit Tests
```bash
cd fuzzer
./extract_fuzzer_dictionary.sh fuzzer_crypto_tests_strings_dictionary1.txt
2020-07-01 12:04:02 +00:00
```
2020-11-30 13:54:34 +00:00
The resulting file can be used as a fuzzer dictionary.
## Evaluate Source Coverage
2020-07-01 12:04:02 +00:00
1. build the fuzzer binary with `CFLAGS="-fprofile-instr-generate -fcoverage-mapping"`
1. run with suitable `-runs=` or `-max_total_time=` limits
1. convert the recorded data `llvm-profdata merge -output=default.profdata -instr default.profraw`
1. render the data `llvm-cov show fuzzer/fuzzer -instr-profile=default.profdata -format=html -output-dir=coverage-report`
1. analyze report at `coverage-report/index.html`
1. (optional) remove artifacts with `rm default.profraw default.profdata && rm -r coverage-report`
2021-12-08 12:11:13 +00:00
## Using Honggfuzz Fuzzer
2023-02-08 11:08:11 +00:00
Although this code is designed primarily for libFuzzer, it can also be used with [Honggfuzz ](https://honggfuzz.dev ) in a hybrid Honggfuzz/libFuzzer mode. The setup and usage details are mostly out of scope of this document, but here are some helpful pointers:
* compile with a clang-based `hfuzz_cc` Honggfuzz compiler variant
* set `-DFUZZ_HONGGFUZZ=1` to suppress compatibility issues