1# Fuzz testing 2 3Modern fuzz testers are very effective and we wish to use them to ensure that no silly bugs creep into BoringSSL. 4 5We primarily use Clang's [libFuzzer](http://llvm.org/docs/LibFuzzer.html) for fuzz testing and there are a number of fuzz testing functions in `fuzz/`. They are not built by default because they require libFuzzer at build time. 6 7In order to build the fuzz tests you will need at least Clang 3.7. Pass `-DFUZZ=1` on the CMake command line to enable building BoringSSL with coverage and AddressSanitizer, and to build the fuzz test binaries. You'll probably need to set the `CC` and `CXX` environment variables too, like this: 8 9``` 10CC=clang CXX=clang++ cmake -GNinja -DFUZZ=1 .. 11``` 12 13In order for the fuzz tests to link, the linker needs to find libFuzzer. This is not commonly provided and you may need to download the [Clang source code](http://llvm.org/releases/download.html) and do the following: 14 15``` 16svn co http://llvm.org/svn/llvm-project/llvm/trunk/lib/Fuzzer 17clang++ -c -g -O2 -std=c++11 Fuzzer/*.cpp -IFuzzer 18ar ruv libFuzzer.a Fuzzer*.o 19``` 20 21Then copy `libFuzzer.a` to the top-level of your BoringSSL source directory. 22 23From the `build/` directory, you can then run the fuzzers. For example: 24 25``` 26./fuzz/cert -max_len=10000 -jobs=32 -workers=32 ../fuzz/cert_corpus/ 27``` 28 29The arguments to `jobs` and `workers` should be the number of cores that you wish to dedicate to fuzzing. By default, libFuzzer uses the largest test in the corpus (or 64 if empty) as the maximum test case length. The `max_len` argument overrides this. 30 31The recommended values of `max_len` for each test are: 32 33| Test | `max_len` value | 34|---------------|-----------------| 35| `cert` | 10000 | 36| `client` | 20000 | 37| `pkcs8` | 2048 | 38| `privkey` | 2048 | 39| `server` | 4096 | 40| `session` | 8192 | 41| `spki` | 1024 | 42| `read_pem` | 512 | 43| `ssl_ctx_api` | 256 | 44 45These were determined by rounding up the length of the largest case in the corpus. 46 47There are directories in `fuzz/` for each of the fuzzing tests which contain seed files for fuzzing. Some of the seed files were generated manually but many of them are “interesting” results generated by the fuzzing itself. (Where “interesting” means that it triggered a previously unknown path in the code.) 48 49## Minimising the corpuses 50 51When a large number of new seeds are available, it's a good idea to minimise the corpus so that different seeds that trigger the same code paths can be deduplicated. 52 53In order to minimise all the corpuses, build for fuzzing and run `./fuzz/minimise_corpuses.sh`. Note that minimisation is, oddly, often not idempotent for unknown reasons. 54 55## Fuzzer mode 56 57When `-DFUZZ=1` is passed into CMake, BoringSSL builds with `BORINGSSL_UNSAFE_FUZZER_MODE` and `BORINGSSL_UNSAFE_DETERMINISTIC_MODE` defined. This modifies the library to be more friendly to fuzzers. If `BORINGSSL_UNSAFE_DETERMINISTIC_MODE` is set, BoringSSL will: 58 59* Replace `RAND_bytes` with a deterministic PRNG. Call `RAND_reset_for_fuzzing()` at the start of fuzzers which use `RAND_bytes` to reset the PRNG state. 60 61* Use a hard-coded time instead of the actual time. 62 63Additionally, if `BORINGSSL_UNSAFE_FUZZER_MODE` is set, BoringSSL will: 64 65* Modify the TLS stack to perform all signature checks (CertificateVerify and ServerKeyExchange) and the Finished check, but always act as if the check succeeded. 66 67* Treat every cipher as the NULL cipher. 68 69* Tickets are unencrypted and the MAC check is performed but ignored. 70 71This is to prevent the fuzzer from getting stuck at a cryptographic invariant in the protocol. 72 73## TLS transcripts 74 75The `client` and `server` corpora are seeded from the test suite. The test suite has a `-fuzzer` flag which mirrors the fuzzer mode changes above and a `-deterministic` flag which removes all non-determinism on the Go side. Not all tests pass, so `ssl/test/runner/fuzzer_mode.json` contains the necessary suppressions. The `run_tests` target will pass appropriate command-line flags. 76 77There are separate corpora, `client_corpus_no_fuzzer_mode` and `server_corpus_no_fuzzer_mode`. These are transcripts for fuzzers with only `BORINGSSL_UNSAFE_DETERMINISTIC_MODE` defined. To build in this mode, pass `-DNO_FUZZER_MODE=1` into CMake. This configuration is run in the same way but without `-fuzzer` and `-shim-path` flags. 78 79If both sets of tests pass, refresh the fuzzer corpora with `refresh_ssl_corpora.sh`: 80 81``` 82cd fuzz 83./refresh_fuzzer_corpora.sh /path/to/fuzzer/mode/build /path/to/non/fuzzer/mode/build 84``` 85