summaryrefslogtreecommitdiffhomepage
path: root/FUZZER-NOTES.md
diff options
context:
space:
mode:
authorMatt Johnston <matt@ucc.asn.au>2018-03-05 14:07:11 +0800
committerMatt Johnston <matt@ucc.asn.au>2018-03-05 14:07:11 +0800
commit366fc8f335e134be447ed77b6923b085857dc7f3 (patch)
tree49f4a43e628b6824b6f7ef068a4147ed613deb22 /FUZZER-NOTES.md
parent35f479bd87e16e7370aceda3da65bacdcce0c362 (diff)
notes on the fuzzer
Diffstat (limited to 'FUZZER-NOTES.md')
-rw-r--r--FUZZER-NOTES.md72
1 files changed, 72 insertions, 0 deletions
diff --git a/FUZZER-NOTES.md b/FUZZER-NOTES.md
new file mode 100644
index 0000000..b5b5c97
--- /dev/null
+++ b/FUZZER-NOTES.md
@@ -0,0 +1,72 @@
+# Fuzzing Dropbear
+
+Dropbear is process-per-session so it assumes calling `dropbear_exit()`
+is fine at any point to clean up. This makes fuzzing a bit trickier.
+A few pieces of wrapping infrastructure are used to work around this.
+
+The [libfuzzer](http://llvm.org/docs/LibFuzzer.html#fuzz-target) harness
+expects a long running process to continually run a test function with
+a string of crafted input. That process should not leak resources or exit.
+
+## longjmp
+
+When dropbear runs in fuzz mode it sets up a
+[`setjmp()`](http://man7.org/linux/man-pages/man3/setjmp.3.html) target prior
+to launching the code to be fuzzed, and then [`dropbear_exit()`](dbutil.c#L125)
+calls `longjmp()` back there. This avoids exiting though it doesn't free
+memory or other resources.
+
+## malloc Wrapper
+
+Dropbear normally uses a [`m_malloc()`](dbmalloc.c) function that is the same as `malloc()` but
+exits if allocation fails. In fuzzing mode this is replaced with a tracking allocator
+that stores all allocations in a linked list. After the `longjmp()` occurs the fuzzer target
+calls [`m_malloc_free_epoch(1, 1)`](dbmalloc.c) to clean up any unreleased memory.
+
+If the fuzz target runs to completion it calls `m_malloc_free_epoch(1, 0)` which will reset
+the tracked allocations but will not free memory - that allows libfuzzer's leak checking
+to detect leaks in normal operation.
+
+## File Descriptor Input
+
+As a network process Dropbear reads and writes from a socket. The wrappers for
+`read()`/`write()`/`select()` in [fuzz-wrapfd.c](fuzz-wrapfd.c) will read from the
+fuzzer input that has been set up with `wrapfd_add()`. `write()` output is
+currently discarded.
+These also test error paths such as EINTR and short reads with certain probabilities.
+
+This allows running the entire dropbear server process with network input provided by the
+fuzzer, without many modifications to the main code. At the time of writing this
+only runs the pre-authentication stages, though post-authentication could be run similarly.
+
+## Encryption and Randomness
+
+When running in fuzzing mode Dropbear uses a [fixed seed](dbrandom.c#L185)
+every time so that failures can be reproduced.
+
+Since the fuzzer cannot generate valid encrypted input the packet decryption and
+message authentication calls are disabled, see (packet.c)[packet.c].
+MAC failures are set to occur with a low probability to test that error path.
+
+## Fuzzers
+
+Current fuzzers are
+
+- fuzzer-preauth - the fuzzer input is treated as a stream of session input. This will
+ test key exchange, packet ordering, authentication attempts etc.
+
+- fuzzer-preauth_nomaths - the same as fuzzer-preauth but with asymmetric crypto
+ routines replaced with dummies for faster runtime. corpora are shared
+ between fuzzers by [oss-fuzz](https://github.com/google/oss-fuzz) so this
+ will help fuzzer-preauth too.
+
+- fuzzer-verify - read a key and signature from fuzzer input and verify that signature.
+ It would not be expected to pass, though some keys with bad parameters are
+ able to validate with a trivial signature - extra checks are added for that.
+
+- fuzzer-pubkey - test parsing of an `authorized_keys` line.
+
+- fuzzer-kexdh - test Diffie-Hellman key exchange where the fuzz input is the
+ public key that would be received over the network.
+
+- fuzzer-kexecdh - test Elliptic Curve Diffie-Hellman key exchange like fuzzer-kexdh