changeset 1456:a90fdd2d2ed8 fuzz

add fuzzer-preauth_nomaths
author Matt Johnston <matt@ucc.asn.au>
date Tue, 23 Jan 2018 23:05:47 +0800
parents 4afde04f0607
children 32f990cc96b1
files Makefile.in common-kex.c debug.h fuzz-common.c fuzz.h fuzzer-preauth.c fuzzer-preauth_nomaths.c fuzzer-pubkey.c fuzzer-verify.c kex.h svr-kex.c
diffstat 11 files changed, 95 insertions(+), 64 deletions(-) [+]
line wrap: on
line diff
--- 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) [email protected] $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
 
+fuzzer-preauth_nomaths: fuzzer-preauth_nomaths.o $(HEADERS) $(LIBTOM_DEPS) Makefile $(svrfuzzobjs)
+	$(CXX) $(CXXFLAGS) [email protected] $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
+
+
 fuzzer-pubkey: fuzzer-pubkey.o $(HEADERS) $(LIBTOM_DEPS) Makefile $(svrfuzzobjs)
 	$(CXX) $(CXXFLAGS) [email protected] $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@
 
--- 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;
 
--- 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.
--- 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;
+}
--- 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;
--- 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;
-}
--- /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);
+}
+
--- 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;
 	}
 
--- 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;
 	}
 
--- 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);
--- 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);