From 89bdf3b0b9376204b039f38f8bebffa92cb30d4e Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Tue, 23 Jan 2018 23:05:47 +0800 Subject: add fuzzer-preauth_nomaths --HG-- branch : fuzz --- Makefile.in | 6 ++++- common-kex.c | 4 +--- debug.h | 2 ++ fuzz-common.c | 62 ++++++++++++++++++++++++++++++++++++++++++++---- fuzz.h | 12 +++++++--- fuzzer-preauth.c | 51 ++------------------------------------- fuzzer-preauth_nomaths.c | 6 +++++ fuzzer-pubkey.c | 4 ++-- fuzzer-verify.c | 4 ++-- kex.h | 1 + svr-kex.c | 7 ++++++ 11 files changed, 95 insertions(+), 64 deletions(-) create mode 100644 fuzzer-preauth_nomaths.c diff --git a/Makefile.in b/Makefile.in index 1d0a858..2a32549 100644 --- a/Makefile.in +++ b/Makefile.in @@ -247,7 +247,7 @@ default_options.h: default_options.h.in ## 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 @@ fuzz-targets: $(FUZZ_TARGETS) $(FUZZER_OPTIONS) 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 --git a/common-kex.c b/common-kex.c index fc2daad..195ffc1 100644 --- a/common-kex.c +++ b/common-kex.c @@ -48,7 +48,6 @@ static void read_kex_algos(void); /* 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 @@ void kexcurve25519_comb_key(struct kex_curve25519_param *param, buffer *buf_pub_ #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 --git a/debug.h b/debug.h index 0cd611d..ce7af53 100644 --- a/debug.h +++ b/debug.h @@ -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 --git a/fuzz-common.c b/fuzz-common.c index ac42def..d98043e 100644 --- a/fuzz-common.c +++ b/fuzz-common.c @@ -14,7 +14,7 @@ struct dropbear_fuzz_options fuzz; 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 @@ void common_setup_fuzzer(void) { 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 @@ static void fuzz_dropbear_log(int UNUSED(priority), const char* format, va_list #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 @@ void fuzz_get_socket_address(int UNUSED(fd), char **local_host, char **local_por *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 --git a/fuzz.h b/fuzz.h index e3bcb7f..7569130 100644 --- a/fuzz.h +++ b/fuzz.h @@ -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 @@ extern const char * const * fuzz_signkey_names; 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_fuzz_options { 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 --git a/fuzzer-preauth.c b/fuzzer-preauth.c index f7ced9d..3ac49f4 100644 --- a/fuzzer-preauth.c +++ b/fuzzer-preauth.c @@ -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 - - // 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; + return fuzz_run_preauth(Data, Size, 0); } + diff --git a/fuzzer-preauth_nomaths.c b/fuzzer-preauth_nomaths.c new file mode 100644 index 0000000..efdc2c3 --- /dev/null +++ b/fuzzer-preauth_nomaths.c @@ -0,0 +1,6 @@ +#include "fuzz.h" + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + return fuzz_run_preauth(Data, Size, 1); +} + diff --git a/fuzzer-pubkey.c b/fuzzer-pubkey.c index 0b7c0f3..511357b 100644 --- a/fuzzer-pubkey.c +++ b/fuzzer-pubkey.c @@ -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 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { once = 1; } - if (fuzzer_set_input(Data, Size) == DROPBEAR_FAILURE) { + if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) { return 0; } diff --git a/fuzzer-verify.c b/fuzzer-verify.c index 7e23bc9..ed4a9f7 100644 --- a/fuzzer-verify.c +++ b/fuzzer-verify.c @@ -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 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { once = 1; } - if (fuzzer_set_input(Data, Size) == DROPBEAR_FAILURE) { + if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) { return 0; } diff --git a/kex.h b/kex.h index 7b98cd5..3d66ab6 100644 --- a/kex.h +++ b/kex.h @@ -34,6 +34,7 @@ void recv_msg_kexinit(void); 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 --git a/svr-kex.c b/svr-kex.c index 7108f64..daed9d4 100644 --- a/svr-kex.c +++ b/svr-kex.c @@ -179,6 +179,13 @@ static void send_msg_kexdh_reply(mp_int *dh_e, buffer *ecdh_qs) { } #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); -- cgit v1.2.3