summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--Makefile.in6
-rw-r--r--common-kex.c4
-rw-r--r--debug.h2
-rw-r--r--fuzz-common.c62
-rw-r--r--fuzz.h12
-rw-r--r--fuzzer-preauth.c51
-rw-r--r--fuzzer-preauth_nomaths.c6
-rw-r--r--fuzzer-pubkey.c4
-rw-r--r--fuzzer-verify.c4
-rw-r--r--kex.h1
-rw-r--r--svr-kex.c7
11 files changed, 95 insertions, 64 deletions
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);