add fuzzer-preauth_nomaths

--HG--
branch : fuzz
This commit is contained in:
Matt Johnston 2018-01-23 23:05:47 +08:00
parent 597f7eb5e9
commit 89bdf3b0b9
11 changed files with 95 additions and 64 deletions

View File

@ -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@

View File

@ -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;

View File

@ -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.

View File

@ -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;
}

12
fuzz.h
View File

@ -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;

View File

@ -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);
}

6
fuzzer-preauth_nomaths.c Normal file
View File

@ -0,0 +1,6 @@
#include "fuzz.h"
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
return fuzz_run_preauth(Data, Size, 1);
}

View File

@ -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;
}

View File

@ -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;
}

1
kex.h
View File

@ -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);

View File

@ -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);