diff --git a/.gitignore b/.gitignore index 3b945338..305bc79b 100644 --- a/.gitignore +++ b/.gitignore @@ -55,3 +55,6 @@ copyright pkcs11-helper.spec doc/api/Doxyfile + +fuzz/output +fuzz/fuzz_deserialize_cert diff --git a/fuzz/README.md b/fuzz/README.md new file mode 100644 index 00000000..bf4402e7 --- /dev/null +++ b/fuzz/README.md @@ -0,0 +1,25 @@ +## Prerequisites +Install AFL++ (and it's pre-requisites such as clang) +https://github.com/AFLplusplus/AFLplusplus/blob/stable/docs/INSTALL.md + +## Building the harness +1. Run ``build_fuzzer.sh`` from the fuzz directory + +## Running +1. Extract the corpus +``` +tar -xvf deserialize_cert_corpus.tar.gz +``` +2. Run the fuzzer +``AFL_SKIP_CPUFREQ=1 afl-fuzz -i ./corpus -o ./output ./fuzz_deserialize_cert`` +3. Wait for crashes to show up +![crashes from afl](crashes.png "Title") + +IMPORTANT NOTE: +For an effective fuzzing campaign: +1. You'd orchestrate the fuzzing campaign with multiple cores +2. You'd run the fuzzer for several hours (if you do not get crashes in the meantime) +3. You'd omit AFL_SKIP_CPUFREQ and run the scripts to increase fuzzing performance +## Debugging crashes +To run all crashes: +```find ./output/*/crashes/* -exec ./fuzz_deserialize_cert {} \;``` diff --git a/fuzz/build_fuzzer.sh b/fuzz/build_fuzzer.sh new file mode 100755 index 00000000..f0c3c4ab --- /dev/null +++ b/fuzz/build_fuzzer.sh @@ -0,0 +1,8 @@ +#!/bin/bash +cd .. +autoreconf -ivf +make clean +CXXFLAGS="-fsanitize=address" CFLAGS="-fsanitize=address" CC=afl-clang-fast CXX=afl-clang-fast++ ./configure +CFLAGS="-fsanitize=address" CC=afl-clang-fast CXX=afl-clang-fast++ make -j16 +afl-clang-fast++ ./fuzz/fuzz_deserialize_cert.c -fsanitize=fuzzer -I ./include/ ./lib/.libs/libpkcs11-helper.a -lssl -lcrypto -o ./fuzz/fuzz_deserialize_cert -fsanitize=address +cd fuzz diff --git a/fuzz/crashes.png b/fuzz/crashes.png new file mode 100644 index 00000000..d2d44ce7 Binary files /dev/null and b/fuzz/crashes.png differ diff --git a/fuzz/deserialize_cert_corpus.tar.gz b/fuzz/deserialize_cert_corpus.tar.gz new file mode 100644 index 00000000..52d806f9 Binary files /dev/null and b/fuzz/deserialize_cert_corpus.tar.gz differ diff --git a/fuzz/fuzz_deserialize_cert.c b/fuzz/fuzz_deserialize_cert.c new file mode 100644 index 00000000..61172287 --- /dev/null +++ b/fuzz/fuzz_deserialize_cert.c @@ -0,0 +1,31 @@ +#include +#include +#include +#include +#include +#include + +extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) { + (void)argc; + (void)argv; + CK_RV rv = pkcs11h_initialize(); + if (rv != CKR_OK) { + return -1; + } + pkcs11h_setLogLevel(PKCS11H_LOG_ERROR); + return 0; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *d, size_t s) { + if (s == 0 || s > 8092) { + return 0; + } + std::vector serialized_input(d, d + s); + serialized_input.push_back('\0'); // null-terminate + + pkcs11h_certificate_id_t certificate_id = NULL; + pkcs11h_certificate_deserializeCertificateId(&certificate_id, serialized_input.data()); + return 0; +} + +