# HG changeset patch # User Matt Johnston # Date 1516719947 -28800 # Node ID a90fdd2d2ed83701733c084ab8e983131260211f # Parent 4afde04f0607d7cdabe6a2b98c6616b3ad739ca5 add fuzzer-preauth_nomaths diff -r 4afde04f0607 -r a90fdd2d2ed8 Makefile.in --- a/Makefile.in Tue Jan 23 22:46:07 2018 +0800 +++ b/Makefile.in Tue Jan 23 23:05:47 2018 +0800 @@ -247,7 +247,7 @@ ## Fuzzing targets # list of fuzz targets -FUZZ_TARGETS=fuzzer-preauth fuzzer-pubkey fuzzer-verify +FUZZ_TARGETS=fuzzer-preauth fuzzer-pubkey fuzzer-verify fuzzer-preauth_nomaths FUZZER_OPTIONS = $(addsuffix .options, $(FUZZ_TARGETS)) @@ -269,6 +269,10 @@ fuzzer-preauth: fuzzer-preauth.o $(HEADERS) $(LIBTOM_DEPS) Makefile $(svrfuzzobjs) $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ +fuzzer-preauth_nomaths: fuzzer-preauth_nomaths.o $(HEADERS) $(LIBTOM_DEPS) Makefile $(svrfuzzobjs) + $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ + + fuzzer-pubkey: fuzzer-pubkey.o $(HEADERS) $(LIBTOM_DEPS) Makefile $(svrfuzzobjs) $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ diff -r 4afde04f0607 -r a90fdd2d2ed8 common-kex.c --- a/common-kex.c Tue Jan 23 22:46:07 2018 +0800 +++ b/common-kex.c Tue Jan 23 23:05:47 2018 +0800 @@ -48,7 +48,6 @@ /* helper function for gen_new_keys */ static void hashkeys(unsigned char *out, unsigned int outlen, const hash_state * hs, const unsigned char X); -static void finish_kexhashbuf(void); /* Send our list of algorithms we can use */ @@ -769,8 +768,7 @@ #endif /* DROPBEAR_CURVE25519 */ - -static void finish_kexhashbuf(void) { +void finish_kexhashbuf(void) { hash_state hs; const struct ltc_hash_descriptor *hash_desc = ses.newkeys->algo_kex->hash_desc; diff -r 4afde04f0607 -r a90fdd2d2ed8 debug.h --- a/debug.h Tue Jan 23 22:46:07 2018 +0800 +++ b/debug.h Tue Jan 23 23:05:47 2018 +0800 @@ -49,7 +49,9 @@ /*#define CHECKCLEARTOWRITE() assert(ses.writepayload->len == 0 && \ ses.writepayload->pos == 0)*/ +#ifndef CHECKCLEARTOWRITE #define CHECKCLEARTOWRITE() +#endif /* Define this, compile with -pg and set GMON_OUT_PREFIX=gmon to get gmon * output when Dropbear forks. This will allow it gprof to be used. diff -r 4afde04f0607 -r a90fdd2d2ed8 fuzz-common.c --- a/fuzz-common.c Tue Jan 23 22:46:07 2018 +0800 +++ b/fuzz-common.c Tue Jan 23 23:05:47 2018 +0800 @@ -14,7 +14,7 @@ static void fuzz_dropbear_log(int UNUSED(priority), const char* format, va_list param); static void load_fixed_hostkeys(void); -void common_setup_fuzzer(void) { +void fuzz_common_setup(void) { fuzz.fuzzing = 1; fuzz.wrapfds = 1; fuzz.do_jmp = 1; @@ -23,7 +23,7 @@ crypto_init(); } -int fuzzer_set_input(const uint8_t *Data, size_t Size) { +int fuzz_set_input(const uint8_t *Data, size_t Size) { fuzz.input->data = (unsigned char*)Data; fuzz.input->size = Size; @@ -51,10 +51,10 @@ #endif } -void svr_setup_fuzzer(void) { +void fuzz_svr_setup(void) { struct passwd *pw; - common_setup_fuzzer(); + fuzz_common_setup(); _dropbear_exit = svr_dropbear_exit; @@ -130,3 +130,57 @@ *remote_port = m_strdup("9876"); } } + +/* cut down version of svr_send_msg_kexdh_reply() that skips slow maths. Still populates structures */ +void fuzz_fake_send_kexdh_reply(void) { + assert(!ses.dh_K); + m_mp_alloc_init_multi(&ses.dh_K, NULL); + mp_set_int(ses.dh_K, 12345678); + finish_kexhashbuf(); + assert(!ses.dh_K); +} + +int fuzz_run_preauth(const uint8_t *Data, size_t Size, int skip_kexmaths) { + static int once = 0; + if (!once) { + fuzz_svr_setup(); + fuzz.skip_kexmaths = skip_kexmaths; + once = 1; + } + + if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) { + return 0; + } + + // get prefix. input format is + // string prefix + // uint32 wrapfd seed + // ... to be extended later + // [bytes] ssh input stream + + // be careful to avoid triggering buffer.c assertions + if (fuzz.input->len < 8) { + return 0; + } + size_t prefix_size = buf_getint(fuzz.input); + if (prefix_size != 4) { + return 0; + } + uint32_t wrapseed = buf_getint(fuzz.input); + wrapfd_setseed(wrapseed); + + int fakesock = 20; + wrapfd_add(fakesock, fuzz.input, PLAIN); + + m_malloc_set_epoch(1); + if (setjmp(fuzz.jmp) == 0) { + svr_session(fakesock, fakesock); + m_malloc_free_epoch(1, 0); + } else { + m_malloc_free_epoch(1, 1); + TRACE(("dropbear_exit longjmped")) + // dropbear_exit jumped here + } + + return 0; +} diff -r 4afde04f0607 -r a90fdd2d2ed8 fuzz.h --- a/fuzz.h Tue Jan 23 22:46:07 2018 +0800 +++ b/fuzz.h Tue Jan 23 23:05:47 2018 +0800 @@ -10,12 +10,14 @@ #include "fuzz-wrapfd.h" // once per process -void common_setup_fuzzer(void); -void svr_setup_fuzzer(void); +void fuzz_common_setup(void); +void fuzz_svr_setup(void); // must be called once per fuzz iteration. // returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE -int fuzzer_set_input(const uint8_t *Data, size_t Size); +int fuzz_set_input(const uint8_t *Data, size_t Size); + +int fuzz_run_preauth(const uint8_t *Data, size_t Size, int skip_kexmaths); // fuzzer functions that intrude into general code void fuzz_kex_fakealgos(void); @@ -26,6 +28,7 @@ void fuzz_seed(void); void fuzz_get_socket_address(int fd, char **local_host, char **local_port, char **remote_host, char **remote_port, int host_lookup); +void fuzz_fake_send_kexdh_reply(void); // fake IO wrappers #ifndef FUZZ_SKIP_WRAP @@ -48,6 +51,9 @@ struct dropbear_hash recv_mac; int wrapfds; + // whether to skip slow bignum maths + int skip_kexmaths; + // dropbear_exit() jumps back int do_jmp; sigjmp_buf jmp; diff -r 4afde04f0607 -r a90fdd2d2ed8 fuzzer-preauth.c --- a/fuzzer-preauth.c Tue Jan 23 22:46:07 2018 +0800 +++ b/fuzzer-preauth.c Tue Jan 23 23:05:47 2018 +0800 @@ -1,53 +1,6 @@ #include "fuzz.h" -#include "session.h" -#include "fuzz-wrapfd.h" -#include "debug.h" - -static void setup_fuzzer(void) { - svr_setup_fuzzer(); - //debug_trace = 1; -} int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { - static int once = 0; - if (!once) { - setup_fuzzer(); - once = 1; - } - - if (fuzzer_set_input(Data, Size) == DROPBEAR_FAILURE) { - return 0; - } - - // get prefix. input format is - // string prefix - // uint32 wrapfd seed - // ... to be extended later - // [bytes] ssh input stream + return fuzz_run_preauth(Data, Size, 0); +} - // be careful to avoid triggering buffer.c assertions - if (fuzz.input->len < 8) { - return 0; - } - size_t prefix_size = buf_getint(fuzz.input); - if (prefix_size != 4) { - return 0; - } - uint32_t wrapseed = buf_getint(fuzz.input); - wrapfd_setseed(wrapseed); - - int fakesock = 20; - wrapfd_add(fakesock, fuzz.input, PLAIN); - - m_malloc_set_epoch(1); - if (setjmp(fuzz.jmp) == 0) { - svr_session(fakesock, fakesock); - m_malloc_free_epoch(1, 0); - } else { - m_malloc_free_epoch(1, 1); - TRACE(("dropbear_exit longjmped")) - // dropbear_exit jumped here - } - - return 0; -} diff -r 4afde04f0607 -r a90fdd2d2ed8 fuzzer-preauth_nomaths.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fuzzer-preauth_nomaths.c Tue Jan 23 23:05:47 2018 +0800 @@ -0,0 +1,6 @@ +#include "fuzz.h" + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + return fuzz_run_preauth(Data, Size, 1); +} + diff -r 4afde04f0607 -r a90fdd2d2ed8 fuzzer-pubkey.c --- a/fuzzer-pubkey.c Tue Jan 23 22:46:07 2018 +0800 +++ b/fuzzer-pubkey.c Tue Jan 23 23:05:47 2018 +0800 @@ -4,7 +4,7 @@ #include "debug.h" static void setup_fuzzer(void) { - common_setup_fuzzer(); + fuzz_common_setup(); } int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { @@ -14,7 +14,7 @@ once = 1; } - if (fuzzer_set_input(Data, Size) == DROPBEAR_FAILURE) { + if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) { return 0; } diff -r 4afde04f0607 -r a90fdd2d2ed8 fuzzer-verify.c --- a/fuzzer-verify.c Tue Jan 23 22:46:07 2018 +0800 +++ b/fuzzer-verify.c Tue Jan 23 23:05:47 2018 +0800 @@ -4,7 +4,7 @@ #include "debug.h" static void setup_fuzzer(void) { - common_setup_fuzzer(); + fuzz_common_setup(); } static buffer *verifydata; @@ -19,7 +19,7 @@ once = 1; } - if (fuzzer_set_input(Data, Size) == DROPBEAR_FAILURE) { + if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) { return 0; } diff -r 4afde04f0607 -r a90fdd2d2ed8 kex.h --- a/kex.h Tue Jan 23 22:46:07 2018 +0800 +++ b/kex.h Tue Jan 23 23:05:47 2018 +0800 @@ -34,6 +34,7 @@ void send_msg_newkeys(void); void recv_msg_newkeys(void); void kexfirstinitialise(void); +void finish_kexhashbuf(void); struct kex_dh_param *gen_kexdh_param(void); void free_kexdh_param(struct kex_dh_param *param); diff -r 4afde04f0607 -r a90fdd2d2ed8 svr-kex.c --- a/svr-kex.c Tue Jan 23 22:46:07 2018 +0800 +++ b/svr-kex.c Tue Jan 23 23:05:47 2018 +0800 @@ -179,6 +179,13 @@ } #endif +#ifdef DROPBEAR_FUZZ + if (fuzz.fuzzing && fuzz.skip_kexmaths) { + fuzz_fake_send_kexdh_reply(); + return; + } +#endif + buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_REPLY); buf_put_pub_key(ses.writepayload, svr_opts.hostkey, ses.newkeys->algo_hostkey);