# HG changeset patch # User Matt Johnston # Date 1495122310 -28800 # Node ID 3fdd8c5a019597f0cee2755d66e2474210100773 # Parent 7618759e9327a4f5e18dfd01f0094559d261406e# Parent bbc0a0ee3843acf69ad14f1924c68a8679c83f7c merge main to fuzz diff -r bbc0a0ee3843 -r 3fdd8c5a0195 .hgignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Thu May 18 23:45:10 2017 +0800 @@ -0,0 +1,2 @@ +.*\.o +.*~ diff -r bbc0a0ee3843 -r 3fdd8c5a0195 Makefile.in --- a/Makefile.in Thu May 18 23:00:12 2017 +0800 +++ b/Makefile.in Thu May 18 23:45:10 2017 +0800 @@ -34,7 +34,7 @@ queue.o \ atomicio.o compat.o fake-rfc2553.o \ ltc_prng.o ecc.o ecdsa.o crypto_desc.o \ - gensignkey.o gendss.o genrsa.o + gensignkey.o gendss.o genrsa.o fuzz-common.o SVROBJS=svr-kex.o svr-auth.o sshpty.o \ svr-authpasswd.o svr-authpubkey.o svr-authpubkeyoptions.o svr-session.o svr-service.o \ @@ -220,7 +220,7 @@ thisclean: -rm -f dropbear dbclient dropbearkey dropbearconvert scp scp-progress \ - dropbearmulti *.o *.da *.bb *.bbg *.prof + dropbearmulti *.o *.da *.bb *.bbg *.prof distclean: clean tidy -rm -f config.h @@ -236,3 +236,37 @@ echo >> $@.tmp $(srcdir)/ifndef_wrapper.sh < $^ > $@.tmp mv $@.tmp $@ + +## Fuzzing targets + +# list of fuzz targets +FUZZ_TARGETS=fuzzer-preauth + +list-fuzz-targets: + @echo $(FUZZ_TARGETS) + +# fuzzers that don't use libfuzzer, just a standalone harness that feeds inputs +fuzzstandalone: FUZZLIB=fuzz-harness.o +fuzzstandalone: fuzz-harness.o fuzz-targets + +# exclude svr-main.o to avoid duplicate main +svrfuzzobjs=$(subst svr-main.o, ,$(dropbearobjs)) + +# build all the fuzzers. This will require fail to link unless built with +# make fuzzers LIBS=-lFuzzer.a +# or similar - the library provides main(). +fuzz-targets: $(FUZZ_TARGETS) + +fuzzer-preauth: fuzzer-preauth.o $(HEADERS) $(LIBTOM_DEPS) Makefile $(svrfuzzobjs) + $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ + +# run this to update hardcoded hostkeys for for fuzzing. +# hostkeys.c is checked in to hg. +fuzz-hostkeys: + dropbearkey -t rsa -f keyr + dropbearkey -t dss -f keyd + dropbearkey -t ecdsa -size 256 -f keye + echo > hostkeys.c + /usr/bin/xxd -i -a keyr >> hostkeys.c + /usr/bin/xxd -i -a keye >> hostkeys.c + /usr/bin/xxd -i -a keyd >> hostkeys.c diff -r bbc0a0ee3843 -r 3fdd8c5a0195 buffer.c diff -r bbc0a0ee3843 -r 3fdd8c5a0195 common-kex.c --- a/common-kex.c Thu May 18 23:00:12 2017 +0800 +++ b/common-kex.c Thu May 18 23:45:10 2017 +0800 @@ -943,6 +943,17 @@ ses.newkeys->trans.algo_comp = s2c_comp_algo->val; } +#ifdef DROPBEAR_FUZZ + ses.newkeys->recv.algo_crypt = &dropbear_nocipher; + ses.newkeys->trans.algo_crypt = &dropbear_nocipher; + ses.newkeys->recv.crypt_mode = &dropbear_mode_none; + ses.newkeys->trans.crypt_mode = &dropbear_mode_none; + ses.newkeys->recv.algo_mac = &dropbear_nohash; + ses.newkeys->trans.algo_mac = &dropbear_nohash; + ses.newkeys->recv.algo_comp = DROPBEAR_COMP_NONE; + ses.newkeys->trans.algo_comp = DROPBEAR_COMP_NONE; +#endif + /* reserved for future extensions */ buf_getint(ses.payload); diff -r bbc0a0ee3843 -r 3fdd8c5a0195 configure.ac --- a/configure.ac Thu May 18 23:00:12 2017 +0800 +++ b/configure.ac Thu May 18 23:45:10 2017 +0800 @@ -217,6 +217,15 @@ AC_MSG_NOTICE(Using shadow passwords if available) ] ) + +AC_ARG_ENABLE(fuzz, + [ --enable-fuzz Build fuzzing], + [ + AC_DEFINE(DROPBEAR_FUZZ, 1, Fuzzing) + AC_MSG_NOTICE(Enabling fuzzing) + ] +) + # Checks for header files. diff -r bbc0a0ee3843 -r 3fdd8c5a0195 dbrandom.c --- a/dbrandom.c Thu May 18 23:00:12 2017 +0800 +++ b/dbrandom.c Thu May 18 23:45:10 2017 +0800 @@ -27,6 +27,8 @@ #include "dbutil.h" #include "bignum.h" #include "dbrandom.h" +#include "runopts.h" +#include "fuzz.h" /* this is used to generate unique output from the same hashpool */ @@ -145,6 +147,12 @@ { hash_state hs; +#ifdef DROPBEAR_FUZZ + if (fuzz.fuzzing || fuzz.recordf) { + return; + } +#endif + /* hash in the new seed data */ sha1_init(&hs); /* existing state (zeroes on startup) */ @@ -157,6 +165,11 @@ static void write_urandom() { +#ifdef DROPBEAR_FUZZ + if (fuzz.fuzzing || fuzz.recordf) { + return; + } +#endif #ifndef DROPBEAR_PRNGD_SOCKET /* This is opportunistic, don't worry about failure */ unsigned char buf[INIT_SEED_SIZE]; @@ -170,6 +183,16 @@ #endif } +static void seedfuzz(void) { + hash_state hs; + sha1_init(&hs); + sha1_process(&hs, "fuzzfuzzfuzz", strlen("fuzzfuzzfuzz")); + sha1_done(&hs, hashpool); + + counter = 0; + donerandinit = 1; +} + /* Initialise the prng from /dev/urandom or prngd. This function can * be called multiple times */ void seedrandom() { @@ -180,8 +203,16 @@ struct timeval tv; clock_t clockval; +#ifdef DROPBEAR_FUZZ + if (fuzz.fuzzing || fuzz.recordf) { + seedfuzz(); + return; + } +#endif + /* hash in the new seed data */ sha1_init(&hs); + /* existing state */ sha1_process(&hs, (void*)hashpool, sizeof(hashpool)); diff -r bbc0a0ee3843 -r 3fdd8c5a0195 fuzz-common.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fuzz-common.c Thu May 18 23:45:10 2017 +0800 @@ -0,0 +1,84 @@ +#include "includes.h" + +#ifdef DROPBEAR_FUZZ + +#include "includes.h" +#include "fuzz.h" +#include "dbutil.h" +#include "runopts.h" +#include "crypto_desc.h" +#include "session.h" + +struct dropbear_fuzz_options fuzz; + +static void load_fixed_hostkeys(void); + +static void common_setup_fuzzer(void) { + fuzz.fuzzing = 1; + crypto_init(); +} + +void svr_setup_fuzzer(void) { + struct passwd *pw; + + common_setup_fuzzer(); + + _dropbear_exit = svr_dropbear_exit; + _dropbear_log = svr_dropbear_log; + + char *argv[] = { + "-E", + }; + + int argc = sizeof(argv) / sizeof(*argv); + svr_getopts(argc, argv); + + /* user lookups might be slow, cache it */ + pw = getpwuid(getuid()); + dropbear_assert(pw); + fuzz.pw_name = m_strdup(pw->pw_name); + fuzz.pw_dir = m_strdup(pw->pw_dir); + fuzz.pw_shell = m_strdup(pw->pw_shell); + fuzz.pw_passwd = m_strdup("!!zzznope"); + + load_fixed_hostkeys(); +} + +static void load_fixed_hostkeys(void) { +#include "fuzz-hostkeys.c" + + buffer *b = buf_new(3000); + enum signkey_type type; + + TRACE(("load fixed hostkeys")) + + svr_opts.hostkey = new_sign_key(); + + buf_setlen(b, 0); + buf_putbytes(b, keyr, keyr_len); + buf_setpos(b, 0); + type = DROPBEAR_SIGNKEY_RSA; + if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) { + dropbear_exit("failed fixed rsa hostkey"); + } + + buf_setlen(b, 0); + buf_putbytes(b, keyd, keyd_len); + buf_setpos(b, 0); + type = DROPBEAR_SIGNKEY_DSS; + if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) { + dropbear_exit("failed fixed dss hostkey"); + } + + buf_setlen(b, 0); + buf_putbytes(b, keye, keye_len); + buf_setpos(b, 0); + type = DROPBEAR_SIGNKEY_ECDSA_NISTP256; + if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) { + dropbear_exit("failed fixed ecdsa hostkey"); + } + + buf_free(b); +} + +#endif /* DROPBEAR_FUZZ */ diff -r bbc0a0ee3843 -r 3fdd8c5a0195 fuzz-harness.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fuzz-harness.c Thu May 18 23:45:10 2017 +0800 @@ -0,0 +1,25 @@ +#include "includes.h" +#include "buffer.h" +#include "dbutil.h" + +extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size); + +int main(int argc, char ** argv) { + int i; + buffer *input = buf_new(100000); + + for (i = 1; i < argc; i++) { + char* fn = argv[i]; + buf_setlen(input, 0); + buf_readfile(input, fn); + buf_setpos(input, 0); + + printf("Running %s\n", fn); + LLVMFuzzerTestOneInput(input->data, input->len); + printf("Done %s\n", fn); + } + + printf("Finished\n"); + + return 0; +} diff -r bbc0a0ee3843 -r 3fdd8c5a0195 fuzz-hostkeys.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fuzz-hostkeys.c Thu May 18 23:45:10 2017 +0800 @@ -0,0 +1,129 @@ + +unsigned char keyr[] = { + 0x00, 0x00, 0x00, 0x07, 0x73, 0x73, 0x68, 0x2d, 0x72, 0x73, 0x61, 0x00, + 0x00, 0x00, 0x03, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0xb1, + 0x06, 0x95, 0xc9, 0xa8, 0x38, 0xb9, 0x99, 0x91, 0xb5, 0x17, 0x39, 0xb9, + 0xfa, 0xa4, 0x49, 0xf8, 0x2a, 0x4c, 0x14, 0xbd, 0xb6, 0x85, 0xdb, 0x38, + 0x99, 0x44, 0xfa, 0xd6, 0xaa, 0x67, 0xef, 0x00, 0x75, 0x2b, 0x6a, 0x5c, + 0x1b, 0x50, 0xa8, 0x52, 0xf9, 0xa7, 0xee, 0xe2, 0xb3, 0x80, 0x38, 0x92, + 0x20, 0x86, 0x7c, 0xe5, 0x89, 0xb3, 0x06, 0xe4, 0x3b, 0xd1, 0xe2, 0x45, + 0xea, 0xc1, 0xd5, 0x8e, 0x05, 0xfb, 0x90, 0x29, 0xd9, 0x41, 0xb3, 0x05, + 0x31, 0x1e, 0xcc, 0xeb, 0x89, 0xdc, 0xd2, 0x6a, 0x99, 0x23, 0xbd, 0x7a, + 0xbe, 0x8c, 0xe3, 0x3f, 0xa1, 0xe8, 0xf5, 0xb4, 0x51, 0x40, 0xb4, 0xb1, + 0xc1, 0x16, 0x9f, 0x07, 0xbb, 0x99, 0xaa, 0x4b, 0x8f, 0x11, 0x19, 0x3c, + 0x18, 0xbd, 0x6e, 0xce, 0x14, 0x54, 0x2c, 0x16, 0x4a, 0x5f, 0x89, 0xe4, + 0x6b, 0x9f, 0x55, 0x68, 0xcc, 0x09, 0x8e, 0x4b, 0x92, 0xc8, 0x87, 0xfe, + 0x09, 0xed, 0x53, 0x6e, 0xff, 0x5f, 0x15, 0x0d, 0x19, 0x9d, 0xa6, 0x54, + 0xd2, 0xea, 0x59, 0x4f, 0xa1, 0x7c, 0xf6, 0xf5, 0x7f, 0x32, 0x23, 0xed, + 0x72, 0xa8, 0x96, 0x17, 0x87, 0x06, 0xf2, 0xc7, 0xcd, 0xda, 0x4a, 0x10, + 0xd1, 0xfd, 0xb8, 0xf1, 0xaf, 0x25, 0x55, 0x32, 0x45, 0x39, 0x95, 0xec, + 0x0c, 0xa9, 0xf0, 0x47, 0x8b, 0x66, 0xe0, 0xb7, 0xa2, 0xf6, 0x35, 0x50, + 0x27, 0xe7, 0x2f, 0x90, 0x35, 0x5b, 0xd5, 0x62, 0x19, 0xb4, 0x41, 0xd4, + 0x52, 0xe7, 0x7f, 0x97, 0xfc, 0x5b, 0x4a, 0x5b, 0x19, 0x06, 0x65, 0x2d, + 0x23, 0x29, 0x15, 0x8b, 0x05, 0xaf, 0xbe, 0xd3, 0x4a, 0x27, 0x5b, 0xc9, + 0xc0, 0xd0, 0xd2, 0xba, 0x8b, 0x00, 0x7a, 0x2f, 0x39, 0xa0, 0x13, 0xb9, + 0xe6, 0xf5, 0x4b, 0x21, 0x54, 0x57, 0xb3, 0xf9, 0x6c, 0x6f, 0xd0, 0x17, + 0xf4, 0x50, 0x9d, 0x00, 0x00, 0x01, 0x00, 0x01, 0xf2, 0xda, 0x5f, 0xfb, + 0xe2, 0xda, 0xfc, 0xe0, 0xdf, 0x3a, 0x0e, 0x14, 0x18, 0xc1, 0xd9, 0x1f, + 0x43, 0xe3, 0x65, 0x3e, 0x07, 0xe7, 0x8d, 0xdc, 0x1d, 0x11, 0xc1, 0xd6, + 0xc0, 0xd8, 0xda, 0x53, 0xf5, 0x04, 0x73, 0x51, 0x1b, 0x26, 0xef, 0x4e, + 0xf5, 0xce, 0x3d, 0x77, 0x21, 0x94, 0xd0, 0xc7, 0xc1, 0xda, 0x19, 0x7d, + 0xf8, 0xc5, 0x4c, 0xc8, 0xee, 0x7d, 0xd1, 0xbb, 0x02, 0x90, 0x2b, 0xff, + 0x4e, 0x4d, 0xd7, 0x9d, 0x72, 0x0c, 0x60, 0x0f, 0x4b, 0x83, 0xf5, 0xc2, + 0x26, 0xd6, 0x22, 0xb8, 0x60, 0x3a, 0xf9, 0x2f, 0x92, 0x2a, 0x2e, 0x14, + 0xa7, 0x56, 0x1c, 0x56, 0x05, 0x41, 0x92, 0xac, 0xb1, 0x4e, 0x44, 0x1e, + 0x70, 0x42, 0xda, 0xc7, 0xc8, 0x9c, 0xae, 0x29, 0x2d, 0x0c, 0x3a, 0xff, + 0x9b, 0xb6, 0xad, 0xb4, 0xfb, 0x49, 0x28, 0x96, 0x74, 0xf5, 0x94, 0x74, + 0xb7, 0x40, 0x93, 0x2b, 0x34, 0x29, 0xd2, 0x8a, 0xf3, 0x99, 0xf9, 0xe9, + 0xd8, 0xcc, 0x48, 0x1d, 0x3e, 0xc1, 0x82, 0x35, 0x4f, 0xef, 0xb1, 0x81, + 0x3c, 0xe1, 0xa1, 0x03, 0x65, 0xac, 0x21, 0x21, 0x40, 0x61, 0xfb, 0xd3, + 0x54, 0xac, 0xa1, 0xf2, 0xf0, 0x61, 0xd9, 0x01, 0x4e, 0xc2, 0x28, 0xb1, + 0x7c, 0x27, 0x6e, 0x56, 0x68, 0x69, 0x8f, 0xc5, 0xfd, 0xca, 0x39, 0x6e, + 0x22, 0x09, 0xf1, 0xb4, 0xd5, 0xac, 0xb8, 0xe0, 0x1b, 0x21, 0x86, 0xf4, + 0xc8, 0x15, 0xc6, 0x1f, 0x21, 0xae, 0xcb, 0xab, 0x5a, 0x09, 0x30, 0x9e, + 0xdd, 0x6c, 0x38, 0x59, 0xec, 0x59, 0x3a, 0x08, 0xee, 0x46, 0x7b, 0x78, + 0x23, 0xbc, 0xfc, 0xe2, 0xda, 0xe8, 0x1a, 0x65, 0xe6, 0xe0, 0x78, 0xd3, + 0xb0, 0x03, 0x2e, 0xf1, 0xb8, 0xca, 0x8e, 0x90, 0x75, 0xaf, 0xf7, 0xa8, + 0x48, 0xed, 0x82, 0xc9, 0xcf, 0x44, 0x56, 0xfc, 0x05, 0xfd, 0x6b, 0x00, + 0x00, 0x00, 0x81, 0x00, 0xfc, 0x94, 0xdf, 0x42, 0xc7, 0x9a, 0xa2, 0xff, + 0x32, 0xdf, 0x06, 0xb6, 0x4d, 0x90, 0x31, 0x28, 0x28, 0xdb, 0x03, 0xf9, + 0xa6, 0xb3, 0xa2, 0x91, 0x4c, 0xdf, 0x6e, 0xf6, 0xb9, 0x44, 0x3b, 0xdd, + 0x17, 0xc1, 0xc8, 0x1d, 0xd1, 0xc0, 0xc0, 0x30, 0x22, 0xbe, 0x24, 0x2e, + 0x0e, 0xdf, 0xe0, 0x18, 0x37, 0x3e, 0xb8, 0x7f, 0xb2, 0x50, 0x34, 0xc4, + 0x08, 0x5e, 0x69, 0x1f, 0xd5, 0xc9, 0xce, 0x47, 0x7d, 0x75, 0x5e, 0x3b, + 0x87, 0xdd, 0x46, 0x35, 0x01, 0x0f, 0x17, 0x8a, 0xf1, 0xf1, 0xc4, 0xa9, + 0x94, 0xa7, 0x6e, 0xce, 0x80, 0xe3, 0x17, 0x2e, 0xb0, 0xef, 0x63, 0xa7, + 0x11, 0x86, 0x96, 0x4a, 0x63, 0x2d, 0x9e, 0x92, 0x62, 0x43, 0x43, 0x72, + 0xa5, 0xdc, 0xa0, 0xcd, 0x19, 0x93, 0xd7, 0xe0, 0x80, 0x41, 0x27, 0xea, + 0xe4, 0xe8, 0xc1, 0x91, 0x9e, 0x13, 0xb3, 0x9c, 0xd1, 0xed, 0xcb, 0xbf, + 0x00, 0x00, 0x00, 0x81, 0x00, 0xb3, 0x6b, 0xee, 0xa4, 0x70, 0x4e, 0xfb, + 0xf9, 0x7e, 0x2e, 0x74, 0x5d, 0x3e, 0x8b, 0x3f, 0xff, 0x8c, 0xde, 0x68, + 0x38, 0xda, 0xce, 0xc0, 0x66, 0x4b, 0xca, 0x35, 0xc3, 0x97, 0xa8, 0xf0, + 0x00, 0x8e, 0xb3, 0x46, 0x60, 0xd0, 0x4d, 0x7e, 0x7b, 0xdf, 0x17, 0x7b, + 0x2f, 0xc4, 0x16, 0xee, 0x45, 0xdb, 0xa5, 0x5d, 0xc0, 0x72, 0xe9, 0xc6, + 0x91, 0x0f, 0xd9, 0x30, 0x74, 0x6c, 0xde, 0x93, 0xb5, 0xb6, 0xaf, 0x52, + 0x53, 0x3c, 0x08, 0x55, 0xea, 0xb8, 0x66, 0x07, 0xbe, 0xce, 0xf9, 0x80, + 0x8d, 0xe0, 0xca, 0xdc, 0x63, 0xe8, 0x58, 0x94, 0x22, 0x4f, 0x08, 0x66, + 0x13, 0x9e, 0x63, 0x2e, 0x92, 0x7a, 0xb6, 0x66, 0x94, 0x9b, 0x71, 0x66, + 0xd3, 0x08, 0xc9, 0x89, 0xea, 0x78, 0x35, 0x0d, 0xf2, 0x25, 0x55, 0xd4, + 0xb0, 0x9b, 0xea, 0x18, 0x77, 0xf6, 0x25, 0x02, 0xb4, 0x5e, 0x71, 0xea, + 0xa3 +}; +unsigned int keyr_len = 805; +unsigned char keye[] = { + 0x00, 0x00, 0x00, 0x13, 0x65, 0x63, 0x64, 0x73, 0x61, 0x2d, 0x73, 0x68, + 0x61, 0x32, 0x2d, 0x6e, 0x69, 0x73, 0x74, 0x70, 0x32, 0x35, 0x36, 0x00, + 0x00, 0x00, 0x08, 0x6e, 0x69, 0x73, 0x74, 0x70, 0x32, 0x35, 0x36, 0x00, + 0x00, 0x00, 0x41, 0x04, 0x0a, 0x00, 0x6c, 0x7c, 0x1c, 0xc4, 0x03, 0x44, + 0x46, 0x70, 0xba, 0x00, 0x7c, 0x79, 0x89, 0x7b, 0xc3, 0xd6, 0x32, 0x98, + 0x34, 0xe7, 0x1c, 0x60, 0x04, 0x73, 0xd9, 0xb5, 0x7e, 0x94, 0x04, 0x04, + 0xea, 0xc8, 0xb8, 0xfb, 0xd4, 0x70, 0x9f, 0x29, 0xa7, 0x8d, 0x9a, 0x64, + 0x3a, 0x8c, 0x45, 0x23, 0x37, 0x5a, 0x2b, 0x4f, 0x54, 0x91, 0x80, 0xf1, + 0xac, 0x3a, 0xf5, 0x6d, 0xfa, 0xe8, 0x76, 0x20, 0x00, 0x00, 0x00, 0x21, + 0x00, 0xc2, 0xaf, 0xbe, 0xdc, 0x06, 0xff, 0x3d, 0x08, 0x9b, 0x73, 0xe0, + 0x3c, 0x58, 0x28, 0x70, 0x9b, 0x23, 0x39, 0x51, 0xd7, 0xbc, 0xa7, 0x1a, + 0xf5, 0xb4, 0x23, 0xd3, 0xf6, 0x17, 0xa6, 0x9c, 0x02 +}; +unsigned int keye_len = 141; +unsigned char keyd[] = { + 0x00, 0x00, 0x00, 0x07, 0x73, 0x73, 0x68, 0x2d, 0x64, 0x73, 0x73, 0x00, + 0x00, 0x00, 0x81, 0x00, 0xb0, 0x02, 0x19, 0x8b, 0xf3, 0x46, 0xf9, 0xc5, + 0x47, 0x78, 0x3d, 0x7f, 0x04, 0x10, 0x0a, 0x43, 0x8e, 0x00, 0x9e, 0xa4, + 0x30, 0xfd, 0x47, 0xb9, 0x05, 0x9e, 0x95, 0xaa, 0x37, 0x9a, 0x91, 0xbf, + 0xf8, 0xb9, 0xe0, 0x8d, 0x97, 0x49, 0x87, 0xe2, 0xe6, 0x90, 0xc1, 0xe4, + 0x61, 0x57, 0x77, 0xfd, 0x91, 0x1d, 0xe1, 0x4b, 0xa0, 0xb2, 0xbc, 0xa1, + 0x6a, 0x6a, 0xdd, 0x31, 0xda, 0xe7, 0x54, 0x03, 0xfd, 0x48, 0x62, 0x8a, + 0x1d, 0x1d, 0xe2, 0x26, 0x76, 0x29, 0x08, 0xab, 0x65, 0x88, 0x74, 0x02, + 0x1e, 0xa9, 0x29, 0x1b, 0x69, 0x3b, 0xb4, 0x5f, 0x62, 0x80, 0xa3, 0xa6, + 0x4b, 0xc3, 0x0e, 0x89, 0x24, 0xe4, 0x8a, 0x31, 0xae, 0x89, 0x7a, 0x7a, + 0x58, 0x44, 0x46, 0x77, 0x62, 0x33, 0xa2, 0x5d, 0x17, 0x0e, 0x0b, 0x64, + 0xee, 0x1a, 0x02, 0xbd, 0xf8, 0x27, 0x86, 0xe1, 0x87, 0x92, 0x84, 0xc7, + 0x00, 0x00, 0x00, 0x15, 0x00, 0xb3, 0x8b, 0x81, 0x39, 0x9c, 0xba, 0xe1, + 0x1d, 0x9a, 0x8b, 0x89, 0xb3, 0x08, 0x9b, 0x12, 0xa8, 0x7b, 0xea, 0x25, + 0x8d, 0x00, 0x00, 0x00, 0x80, 0x76, 0x3f, 0x72, 0xb2, 0xef, 0xc3, 0x16, + 0xd8, 0x09, 0x36, 0x23, 0x03, 0xf9, 0x5c, 0xac, 0x8b, 0x51, 0x35, 0x2e, + 0x36, 0xba, 0x39, 0xd0, 0x57, 0x19, 0x4f, 0x14, 0x8b, 0xea, 0x32, 0xfc, + 0x86, 0x41, 0xea, 0x85, 0x71, 0x4d, 0x52, 0x0c, 0xff, 0xc1, 0xd3, 0xd5, + 0xcd, 0x2e, 0x37, 0xcc, 0xe1, 0xcc, 0x22, 0x38, 0xa8, 0x47, 0x16, 0x34, + 0x3b, 0x32, 0x9c, 0x2f, 0x0f, 0xcd, 0x5f, 0x7f, 0x06, 0x64, 0x89, 0xc5, + 0x02, 0x4f, 0x9a, 0x70, 0x11, 0xf0, 0xaa, 0xe1, 0x7a, 0x75, 0x49, 0x8d, + 0x0f, 0x8d, 0x5b, 0x54, 0xe2, 0xe7, 0x10, 0x6e, 0xe5, 0xbd, 0xb7, 0x62, + 0xf7, 0x40, 0x59, 0x39, 0x31, 0xd9, 0x13, 0x7b, 0xa3, 0xdf, 0x0d, 0x31, + 0x52, 0x43, 0xe0, 0xaf, 0x19, 0x12, 0x15, 0x12, 0x34, 0x01, 0x6f, 0xcf, + 0x62, 0x21, 0xe4, 0xc8, 0x34, 0x69, 0xc9, 0x85, 0xe3, 0xde, 0xd7, 0x0c, + 0xac, 0x00, 0x00, 0x00, 0x80, 0x41, 0xa3, 0xc5, 0xa4, 0x89, 0x86, 0xc8, + 0x17, 0xf3, 0x8e, 0x68, 0x72, 0xbe, 0x13, 0x8b, 0x63, 0xe3, 0x07, 0xe3, + 0xd5, 0xa4, 0xa2, 0xd3, 0x2c, 0x2f, 0xbe, 0x16, 0x71, 0xc9, 0x79, 0x64, + 0x5a, 0x1e, 0x19, 0x82, 0x07, 0xe2, 0x93, 0xda, 0x22, 0xcf, 0x6d, 0xdd, + 0x38, 0xcb, 0x6e, 0x6b, 0x0f, 0x95, 0x8d, 0xfa, 0x3f, 0xbb, 0xb8, 0x6a, + 0x7d, 0xc3, 0x22, 0x1e, 0x49, 0xcf, 0x98, 0x73, 0x05, 0x5d, 0x97, 0xfa, + 0x4c, 0xf2, 0x82, 0x3d, 0x98, 0x61, 0x4e, 0x96, 0x80, 0x26, 0x79, 0xda, + 0x24, 0xf8, 0xa1, 0x9c, 0x71, 0x82, 0xe6, 0xc7, 0xdc, 0xc2, 0xa5, 0xd0, + 0xf4, 0x36, 0xba, 0xaa, 0xee, 0xd3, 0x43, 0x46, 0x1d, 0xaa, 0x53, 0xea, + 0x85, 0x2c, 0x1b, 0xc8, 0x7c, 0x3c, 0xe7, 0x06, 0x44, 0xab, 0x16, 0xad, + 0xc6, 0x54, 0x91, 0x9a, 0xb9, 0xc0, 0xeb, 0x93, 0x8c, 0xca, 0x39, 0xcf, + 0x6f, 0x00, 0x00, 0x00, 0x15, 0x00, 0x90, 0x26, 0x0a, 0xfc, 0x15, 0x99, + 0x7b, 0xac, 0xaa, 0x0c, 0xa2, 0xca, 0x7b, 0xa8, 0xd4, 0xdf, 0x68, 0x56, + 0xf9, 0x39 +}; +unsigned int keyd_len = 458; diff -r bbc0a0ee3843 -r 3fdd8c5a0195 fuzz.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fuzz.h Thu May 18 23:45:10 2017 +0800 @@ -0,0 +1,35 @@ +#ifndef DROPBEAR_FUZZ_H +#define DROPBEAR_FUZZ_H + +#include "includes.h" +#include "buffer.h" + +#ifdef DROPBEAR_FUZZ + +void svr_setup_fuzzer(void); + +struct dropbear_fuzz_options { + int fuzzing; + + // to record an unencrypted stream + FILE* recordf; + + // fuzzing input + buffer input; + + // dropbear_exit() jumps back + sigjmp_buf jmp; + + uid_t pw_uid; + gid_t pw_gid; + char* pw_name; + char* pw_dir; + char* pw_shell; + char* pw_passwd; +}; + +extern struct dropbear_fuzz_options fuzz; + +#endif + +#endif /* DROPBEAR_FUZZ_H */ diff -r bbc0a0ee3843 -r 3fdd8c5a0195 fuzzer-preauth.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fuzzer-preauth.c Thu May 18 23:45:10 2017 +0800 @@ -0,0 +1,31 @@ +#include "fuzz.h" +#include "dbrandom.h" +#include "session.h" + +static int setup_fuzzer(void) { + svr_setup_fuzzer(); + return 0; +} + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + static int once = 0; + if (!once) { + setup_fuzzer(); + once = 1; + } + + fuzz.input.data = (unsigned char*)Data; + fuzz.input.size = Size; + fuzz.input.len = Size; + fuzz.input.pos = 0; + + seedrandom(); + + if (setjmp(fuzz.jmp) == 0) { + svr_session(-1, -1); + } else { + // dropbear_exit jumped here + } + + return 0; +} diff -r bbc0a0ee3843 -r 3fdd8c5a0195 includes.h --- a/includes.h Thu May 18 23:00:12 2017 +0800 +++ b/includes.h Thu May 18 23:45:10 2017 +0800 @@ -57,6 +57,7 @@ #include #include #include +#include #ifdef HAVE_UTMP_H #include diff -r bbc0a0ee3843 -r 3fdd8c5a0195 netio.c --- a/netio.c Thu May 18 23:00:12 2017 +0800 +++ b/netio.c Thu May 18 23:45:10 2017 +0800 @@ -485,14 +485,36 @@ if (local_host || local_port) { addrlen = sizeof(addr); if (getsockname(fd, (struct sockaddr*)&addr, &addrlen) < 0) { - dropbear_exit("Failed socket address: %s", strerror(errno)); + if (errno == ENOTSOCK) { + // FUZZ + if (local_host) { + *local_host = m_strdup("notsocket"); + } + if (local_port) { + *local_port = m_strdup("999"); + } + return; + } else { + dropbear_exit("Failed socket address: %s", strerror(errno)); + } } getaddrstring(&addr, local_host, local_port, host_lookup); } if (remote_host || remote_port) { addrlen = sizeof(addr); if (getpeername(fd, (struct sockaddr*)&addr, &addrlen) < 0) { - dropbear_exit("Failed socket address: %s", strerror(errno)); + if (errno == ENOTSOCK) { + // FUZZ + if (remote_host) { + *remote_host = m_strdup("notsocket"); + } + if (remote_port) { + *remote_port = m_strdup("999"); + } + return; + } else { + dropbear_exit("Failed socket address: %s", strerror(errno)); + } } getaddrstring(&addr, remote_host, remote_port, host_lookup); } @@ -546,6 +568,18 @@ return; } else { /* if we can't do a numeric lookup, something's gone terribly wrong */ + if (ret == EAI_FAMILY) { + // FUZZ + // Fake it for non-socket input + if (ret_host) { + *ret_host = m_strdup("0.0.0.0"); + } + if (ret_port) + { + *ret_port = m_strdup("999"); + } + return; + } dropbear_exit("Failed lookup: %s", gai_strerror(ret)); } } diff -r bbc0a0ee3843 -r 3fdd8c5a0195 packet.c --- a/packet.c Thu May 18 23:00:12 2017 +0800 +++ b/packet.c Thu May 18 23:45:10 2017 +0800 @@ -35,6 +35,8 @@ #include "auth.h" #include "channel.h" #include "netio.h" +#include "runopts.h" +#include "fuzz.h" static int read_packet_init(void); static void make_mac(unsigned int seqno, const struct key_context_directional * key_state, @@ -76,6 +78,15 @@ /* This may return EAGAIN. The main loop sometimes calls write_packet() without bothering to test with select() since it's likely to be necessary */ +#ifdef DROPBEAR_FUZZ + if (fuzz.fuzzing) { + // pretend to write one packet at a time + // TODO(fuzz): randomise amount written based on the fuzz input + written = iov[0].iov_len; + } + else +#endif + { written = writev(ses.sock_out, iov, iov_count); if (written < 0) { if (errno == EINTR || errno == EAGAIN) { @@ -85,6 +96,7 @@ dropbear_exit("Error writing: %s", strerror(errno)); } } + } packet_queue_consume(&ses.writequeue, written); ses.writequeue_len -= written; @@ -94,6 +106,9 @@ } #else /* No writev () */ +#ifdef DROPBEAR_FUZZ + _Static_assert(0, "No fuzzing code for no-writev writes"); +#endif /* Get the next buffer in the queue of encrypted packets to write*/ writebuf = (buffer*)examine(&ses.writequeue); diff -r bbc0a0ee3843 -r 3fdd8c5a0195 runopts.h diff -r bbc0a0ee3843 -r 3fdd8c5a0195 svr-auth.c --- a/svr-auth.c Thu May 18 23:00:12 2017 +0800 +++ b/svr-auth.c Thu May 18 23:45:10 2017 +0800 @@ -358,7 +358,11 @@ genrandom((unsigned char*)&delay, sizeof(delay)); /* We delay for 300ms +- 50ms */ delay = 250000 + (delay % 100000); - usleep(delay); +#ifndef DROPBEAR_FUZZ + if (!fuzz.fuzzing) { + usleep(delay); + } +#endif ses.authstate.failcount++; } diff -r bbc0a0ee3843 -r 3fdd8c5a0195 svr-runopts.c --- a/svr-runopts.c Thu May 18 23:00:12 2017 +0800 +++ b/svr-runopts.c Thu May 18 23:45:10 2017 +0800 @@ -480,6 +480,7 @@ svr_opts.num_hostkey_files++; } + void load_all_hostkeys() { int i; int disable_unset_keys = 1; diff -r bbc0a0ee3843 -r 3fdd8c5a0195 svr-session.c --- a/svr-session.c Thu May 18 23:00:12 2017 +0800 +++ b/svr-session.c Thu May 18 23:45:10 2017 +0800 @@ -40,6 +40,7 @@ #include "auth.h" #include "runopts.h" #include "crypto_desc.h" +#include "fuzz.h" static void svr_remoteclosed(void); @@ -182,6 +183,13 @@ session_cleanup(); } +#ifdef DROPBEAR_FUZZ + // longjmp before cleaning up svr_opts + if (fuzz.fuzzing) { + longjmp(fuzz.jmp, 1); + } +#endif + if (svr_opts.hostkey) { sign_key_free(svr_opts.hostkey); svr_opts.hostkey = NULL; @@ -191,6 +199,7 @@ m_free(svr_opts.ports[i]); } + exit(exitcode); }