# HG changeset patch # User Matt Johnston # Date 1603633662 -28800 # Node ID 4c5599435084191674bb3a36244a4ae959834082 # Parent 1365661f6be67d02e1d7703a72ec039439ca4f49# Parent 064f5be2fc45c4842cbfc5fb4523dd5b3d680c8b merge from main diff -r 064f5be2fc45 -r 4c5599435084 Makefile.in --- a/Makefile.in Sat Oct 24 18:56:45 2020 +0800 +++ b/Makefile.in Sun Oct 25 21:47:42 2020 +0800 @@ -62,7 +62,7 @@ SCPOBJS=scp.o progressmeter.o atomicio.o scpmisc.o compat.o ifeq (@DROPBEAR_FUZZ@, 1) - allobjs = $(COMMONOBJS) fuzz-common.o fuzz-wrapfd.o $(CLISVROBJS) $(CLIOBJS) $(SVROBJS) @CRYPTLIB@ + allobjs = $(COMMONOBJS) fuzz/fuzz-common.o fuzz/fuzz-wrapfd.o $(CLISVROBJS) $(CLIOBJS) $(SVROBJS) @CRYPTLIB@ allobjs:=$(subst svr-main.o, ,$(allobjs)) allobjs:=$(subst cli-main.o, ,$(allobjs)) @@ -72,6 +72,7 @@ dropbearconvertobjs=$(allobjs) $(CONVERTOBJS) # CXX only set when fuzzing CXX=@CXX@ + FUZZ_CLEAN=fuzz-clean else dropbearobjs=$(COMMONOBJS) $(CLISVROBJS) $(SVROBJS) dbclientobjs=$(COMMONOBJS) $(CLISVROBJS) $(CLIOBJS) @@ -246,7 +247,7 @@ sizes: dropbear objdump -t dropbear|grep ".text"|cut -d "." -f 2|sort -rn -clean: $(LIBTOM_CLEAN) thisclean +clean: $(LIBTOM_CLEAN) $(FUZZ_CLEAN) thisclean thisclean: -rm -f dropbear$(EXEEXT) dbclient$(EXEEXT) dropbearkey$(EXEEXT) \ @@ -271,47 +272,24 @@ fuzzer-kexdh fuzzer-kexecdh fuzzer-kexcurve25519 fuzzer-client fuzzer-client_nomaths FUZZER_OPTIONS = $(addsuffix .options, $(FUZZ_TARGETS)) +FUZZ_OBJS = $(addprefix fuzz/,$(addsuffix .o,$(FUZZ_TARGETS))) list-fuzz-targets: @echo $(FUZZ_TARGETS) # fuzzers that don't use libfuzzer, just a standalone harness that feeds inputs -fuzzstandalone: FUZZLIB=fuzz-harness.o -fuzzstandalone: fuzz-harness.o fuzz-targets +fuzzstandalone: FUZZLIB=fuzz/fuzz-harness.o +fuzzstandalone: fuzz/fuzz-harness.o fuzz-targets -fuzz-harness.o: $(HEADERS) $(LIBTOM_DEPS) Makefile $(allobjs) fuzz-common.o - -# build all the fuzzers. This will require fail to link unless built with -# make fuzz-targets FUZZLIB=-lFuzzer.a -# or similar - the library provides main(). +# Build all the fuzzers. Usually like +# make fuzz-targets FUZZLIB=-lFuzzer.a +# the library provides main(). Otherwise +# make fuzzstandalone +# provides a main in fuzz-harness.c fuzz-targets: $(FUZZ_TARGETS) $(FUZZER_OPTIONS) -fuzzer-preauth: fuzzer-preauth.o fuzz-harness.o - $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(allobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ - -fuzzer-preauth_nomaths: fuzzer-preauth_nomaths.o fuzz-harness.o - $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(allobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ - -fuzzer-pubkey: fuzzer-pubkey.o fuzz-harness.o - $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(allobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ - -fuzzer-verify: fuzzer-verify.o fuzz-harness.o - $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(allobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ - -fuzzer-kexdh: fuzzer-kexdh.o fuzz-harness.o - $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(allobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ - -fuzzer-kexecdh: fuzzer-kexecdh.o fuzz-harness.o - $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(allobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ - -fuzzer-kexcurve25519: fuzzer-kexcurve25519.o fuzz-harness.o - $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(allobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ - -fuzzer-client: fuzzer-client.o fuzz-harness.o - $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(allobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ - -fuzzer-client_nomaths: fuzzer-client_nomaths.o fuzz-harness.o - $(CXX) $(CXXFLAGS) $@.o $(LDFLAGS) $(allobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) @CRYPTLIB@ +$(FUZZ_TARGETS): $(FUZZ_OBJS) $(allobjs) $(LIBTOM_DEPS) + $(CXX) $(CXXFLAGS) fuzz/$@.o $(LDFLAGS) $(allobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) $(FUZZLIB) -lcrypt fuzzer-%.options: Makefile echo "[libfuzzer]" > $@ @@ -329,3 +307,6 @@ /usr/bin/xxd -i -a keye >> hostkeys.c /usr/bin/xxd -i -a keyd >> hostkeys.c /usr/bin/xxd -i -a keyed25519 >> hostkeys.c + +fuzz-clean: + -rm -f fuzz/*.o $(FUZZ_TARGETS) $(FUZZER_OPTIONS) diff -r 064f5be2fc45 -r 4c5599435084 configure.ac --- a/configure.ac Sat Oct 24 18:56:45 2020 +0800 +++ b/configure.ac Sun Oct 25 21:47:42 2020 +0800 @@ -347,6 +347,7 @@ DROPBEAR_FUZZ=1 # libfuzzer needs linking with c++ libraries AC_PROG_CXX + mkdir -pv fuzz else AC_DEFINE(DROPBEAR_FUZZ, 0, Fuzzing) AC_MSG_NOTICE(Disabling fuzzing) diff -r 064f5be2fc45 -r 4c5599435084 dbrandom.c --- a/dbrandom.c Sat Oct 24 18:56:45 2020 +0800 +++ b/dbrandom.c Sun Oct 25 21:47:42 2020 +0800 @@ -150,10 +150,11 @@ } #if DROPBEAR_FUZZ -void fuzz_seed(void) { +void fuzz_seed(const unsigned char* dat, unsigned int len) { hash_state hs; sha1_init(&hs); sha1_process(&hs, "fuzzfuzzfuzz", strlen("fuzzfuzzfuzz")); + sha1_process(&hs, dat, len); sha1_done(&hs, hashpool); counter = 0; diff -r 064f5be2fc45 -r 4c5599435084 fuzz-common.c --- a/fuzz-common.c Sat Oct 24 18:56:45 2020 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,311 +0,0 @@ -#include "includes.h" - -#include "includes.h" -#include "fuzz.h" -#include "dbutil.h" -#include "runopts.h" -#include "crypto_desc.h" -#include "session.h" -#include "dbrandom.h" -#include "bignum.h" -#include "atomicio.h" -#include "fuzz-wrapfd.h" - -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); -static void load_fixed_client_key(void); - -void fuzz_common_setup(void) { - disallow_core(); - fuzz.fuzzing = 1; - fuzz.wrapfds = 1; - fuzz.do_jmp = 1; - fuzz.input = m_malloc(sizeof(buffer)); - _dropbear_log = fuzz_dropbear_log; - crypto_init(); - fuzz_seed(); - /* let any messages get flushed */ - setlinebuf(stdout); -} - -int fuzz_set_input(const uint8_t *Data, size_t Size) { - - fuzz.input->data = (unsigned char*)Data; - fuzz.input->size = Size; - fuzz.input->len = Size; - fuzz.input->pos = 0; - - memset(&ses, 0x0, sizeof(ses)); - memset(&svr_ses, 0x0, sizeof(svr_ses)); - memset(&cli_ses, 0x0, sizeof(cli_ses)); - wrapfd_setup(fuzz.input); - - fuzz_seed(); - - return DROPBEAR_SUCCESS; -} - -#if DEBUG_TRACE -static void fuzz_dropbear_log(int UNUSED(priority), const char* format, va_list param) { - if (debug_trace) { - char printbuf[1024]; - vsnprintf(printbuf, sizeof(printbuf), format, param); - fprintf(stderr, "%s\n", printbuf); - } -} -#else -static void fuzz_dropbear_log(int UNUSED(priority), const char* UNUSED(format), va_list UNUSED(param)) { - /* No print */ -} -#endif /* DEBUG_TRACE */ - -void fuzz_svr_setup(void) { - fuzz_common_setup(); - - _dropbear_exit = svr_dropbear_exit; - - char *argv[] = { - "dropbear", - "-E", - }; - - int argc = sizeof(argv) / sizeof(*argv); - svr_getopts(argc, argv); - - load_fixed_hostkeys(); -} - -void fuzz_cli_setup(void) { - fuzz_common_setup(); - - _dropbear_exit = cli_dropbear_exit; - _dropbear_log = cli_dropbear_log; - - char *argv[] = { - "dbclient", - "-y", - "localhost", - "uptime" - }; - - int argc = sizeof(argv) / sizeof(*argv); - cli_getopts(argc, argv); - - load_fixed_client_key(); - /* Avoid password prompt */ - setenv(DROPBEAR_PASSWORD_ENV, "password", 1); -} - -#include "fuzz-hostkeys.c" - -static void load_fixed_client_key(void) { - - buffer *b = buf_new(3000); - sign_key *key; - enum signkey_type keytype; - - key = new_sign_key(); - keytype = DROPBEAR_SIGNKEY_ANY; - buf_putbytes(b, keyed25519, keyed25519_len); - buf_setpos(b, 0); - if (buf_get_priv_key(b, key, &keytype) == DROPBEAR_FAILURE) { - dropbear_exit("failed fixed ed25519 hostkey"); - } - list_append(cli_opts.privkeys, key); - - buf_free(b); -} - -static void load_fixed_hostkeys(void) { - - buffer *b = buf_new(3000); - enum signkey_type type; - - TRACE(("load fixed hostkeys")) - - svr_opts.hostkey = new_sign_key(); - - buf_setlen(b, 0); - buf_putbytes(b, keyr, keyr_len); - buf_setpos(b, 0); - type = DROPBEAR_SIGNKEY_RSA; - if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) { - dropbear_exit("failed fixed rsa hostkey"); - } - - buf_setlen(b, 0); - buf_putbytes(b, keyd, keyd_len); - buf_setpos(b, 0); - type = DROPBEAR_SIGNKEY_DSS; - if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) { - dropbear_exit("failed fixed dss hostkey"); - } - - buf_setlen(b, 0); - buf_putbytes(b, keye, keye_len); - buf_setpos(b, 0); - type = DROPBEAR_SIGNKEY_ECDSA_NISTP256; - if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) { - dropbear_exit("failed fixed ecdsa hostkey"); - } - - buf_setlen(b, 0); - buf_putbytes(b, keyed25519, keyed25519_len); - buf_setpos(b, 0); - type = DROPBEAR_SIGNKEY_ED25519; - if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) { - dropbear_exit("failed fixed ed25519 hostkey"); - } - - buf_free(b); -} - -void fuzz_kex_fakealgos(void) { - ses.newkeys->recv.crypt_mode = &dropbear_mode_none; -} - -void fuzz_get_socket_address(int UNUSED(fd), char **local_host, char **local_port, - char **remote_host, char **remote_port, int UNUSED(host_lookup)) { - if (local_host) { - *local_host = m_strdup("fuzzlocalhost"); - } - if (local_port) { - *local_port = m_strdup("1234"); - } - if (remote_host) { - *remote_host = m_strdup("fuzzremotehost"); - } - if (remote_port) { - *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_ul(ses.dh_K, 12345678uL); - finish_kexhashbuf(); -} - -/* fake version of spawn_command() */ -int fuzz_spawn_command(int *ret_writefd, int *ret_readfd, int *ret_errfd, pid_t *ret_pid) { - *ret_writefd = wrapfd_new(); - *ret_readfd = wrapfd_new(); - if (ret_errfd) { - *ret_errfd = wrapfd_new(); - } - *ret_pid = 999; - return DROPBEAR_SUCCESS; -} - -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, allowing for future extensibility. 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 = wrapfd_new(); - - 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; -} - -int fuzz_run_client(const uint8_t *Data, size_t Size, int skip_kexmaths) { - static int once = 0; - if (!once) { - fuzz_cli_setup(); - fuzz.skip_kexmaths = skip_kexmaths; - once = 1; - } - - if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) { - return 0; - } - - /* - get prefix, allowing for future extensibility. 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 = wrapfd_new(); - - m_malloc_set_epoch(1); - if (setjmp(fuzz.jmp) == 0) { - cli_session(fakesock, fakesock, NULL, 0); - m_malloc_free_epoch(1, 0); - } else { - m_malloc_free_epoch(1, 1); - TRACE(("dropbear_exit longjmped")) - /* dropbear_exit jumped here */ - } - - return 0; -} - -const void* fuzz_get_algo(const algo_type *algos, const char* name) { - const algo_type *t; - for (t = algos; t->name; t++) { - if (strcmp(t->name, name) == 0) { - return t->data; - } - } - assert(0); -} - -void fuzz_dump(const unsigned char* data, size_t len) { - TRACE(("dump %zu", len)) - if (fuzz.dumping) { - assert(atomicio(vwrite, fuzz.recv_dumpfd, (void*)data, len) == len); - } -} diff -r 064f5be2fc45 -r 4c5599435084 fuzz-harness.c --- a/fuzz-harness.c Sat Oct 24 18:56:45 2020 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -#include "includes.h" -#include "buffer.h" -#include "dbutil.h" - -extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size); - -int main(int argc, char ** argv) { - int i; - buffer *input = buf_new(100000); - - for (i = 1; i < argc; i++) { -#if DEBUG_TRACE - if (strcmp(argv[i], "-v") == 0) { - debug_trace = 1; - TRACE(("debug printing on")) - } -#endif - } - - int old_fuzz_wrapfds = 0; - for (i = 1; i < argc; i++) { - if (argv[i][0] == '-') { - /* ignore arguments */ - continue; - } - - char* fn = argv[i]; - buf_setlen(input, 0); - buf_readfile(input, fn); - buf_setpos(input, 0); - - /* Run twice to catch problems with statefulness */ - fuzz.wrapfds = old_fuzz_wrapfds; - printf("Running %s once \n", fn); - LLVMFuzzerTestOneInput(input->data, input->len); - printf("Running %s twice \n", fn); - LLVMFuzzerTestOneInput(input->data, input->len); - printf("Done %s\n", fn); - - /* Disable wrapfd so it won't interfere with buf_readfile() above */ - old_fuzz_wrapfds = fuzz.wrapfds; - fuzz.wrapfds = 0; - } - - printf("Finished\n"); - - return 0; -} diff -r 064f5be2fc45 -r 4c5599435084 fuzz-hostkeys.c --- a/fuzz-hostkeys.c Sat Oct 24 18:56:45 2020 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,140 +0,0 @@ -/* To be included in fuzz-common.c */ - -static unsigned char keyr[] = { - 0x00, 0x00, 0x00, 0x07, 0x73, 0x73, 0x68, 0x2d, 0x72, 0x73, 0x61, 0x00, - 0x00, 0x00, 0x03, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0xb1, - 0x06, 0x95, 0xc9, 0xa8, 0x38, 0xb9, 0x99, 0x91, 0xb5, 0x17, 0x39, 0xb9, - 0xfa, 0xa4, 0x49, 0xf8, 0x2a, 0x4c, 0x14, 0xbd, 0xb6, 0x85, 0xdb, 0x38, - 0x99, 0x44, 0xfa, 0xd6, 0xaa, 0x67, 0xef, 0x00, 0x75, 0x2b, 0x6a, 0x5c, - 0x1b, 0x50, 0xa8, 0x52, 0xf9, 0xa7, 0xee, 0xe2, 0xb3, 0x80, 0x38, 0x92, - 0x20, 0x86, 0x7c, 0xe5, 0x89, 0xb3, 0x06, 0xe4, 0x3b, 0xd1, 0xe2, 0x45, - 0xea, 0xc1, 0xd5, 0x8e, 0x05, 0xfb, 0x90, 0x29, 0xd9, 0x41, 0xb3, 0x05, - 0x31, 0x1e, 0xcc, 0xeb, 0x89, 0xdc, 0xd2, 0x6a, 0x99, 0x23, 0xbd, 0x7a, - 0xbe, 0x8c, 0xe3, 0x3f, 0xa1, 0xe8, 0xf5, 0xb4, 0x51, 0x40, 0xb4, 0xb1, - 0xc1, 0x16, 0x9f, 0x07, 0xbb, 0x99, 0xaa, 0x4b, 0x8f, 0x11, 0x19, 0x3c, - 0x18, 0xbd, 0x6e, 0xce, 0x14, 0x54, 0x2c, 0x16, 0x4a, 0x5f, 0x89, 0xe4, - 0x6b, 0x9f, 0x55, 0x68, 0xcc, 0x09, 0x8e, 0x4b, 0x92, 0xc8, 0x87, 0xfe, - 0x09, 0xed, 0x53, 0x6e, 0xff, 0x5f, 0x15, 0x0d, 0x19, 0x9d, 0xa6, 0x54, - 0xd2, 0xea, 0x59, 0x4f, 0xa1, 0x7c, 0xf6, 0xf5, 0x7f, 0x32, 0x23, 0xed, - 0x72, 0xa8, 0x96, 0x17, 0x87, 0x06, 0xf2, 0xc7, 0xcd, 0xda, 0x4a, 0x10, - 0xd1, 0xfd, 0xb8, 0xf1, 0xaf, 0x25, 0x55, 0x32, 0x45, 0x39, 0x95, 0xec, - 0x0c, 0xa9, 0xf0, 0x47, 0x8b, 0x66, 0xe0, 0xb7, 0xa2, 0xf6, 0x35, 0x50, - 0x27, 0xe7, 0x2f, 0x90, 0x35, 0x5b, 0xd5, 0x62, 0x19, 0xb4, 0x41, 0xd4, - 0x52, 0xe7, 0x7f, 0x97, 0xfc, 0x5b, 0x4a, 0x5b, 0x19, 0x06, 0x65, 0x2d, - 0x23, 0x29, 0x15, 0x8b, 0x05, 0xaf, 0xbe, 0xd3, 0x4a, 0x27, 0x5b, 0xc9, - 0xc0, 0xd0, 0xd2, 0xba, 0x8b, 0x00, 0x7a, 0x2f, 0x39, 0xa0, 0x13, 0xb9, - 0xe6, 0xf5, 0x4b, 0x21, 0x54, 0x57, 0xb3, 0xf9, 0x6c, 0x6f, 0xd0, 0x17, - 0xf4, 0x50, 0x9d, 0x00, 0x00, 0x01, 0x00, 0x01, 0xf2, 0xda, 0x5f, 0xfb, - 0xe2, 0xda, 0xfc, 0xe0, 0xdf, 0x3a, 0x0e, 0x14, 0x18, 0xc1, 0xd9, 0x1f, - 0x43, 0xe3, 0x65, 0x3e, 0x07, 0xe7, 0x8d, 0xdc, 0x1d, 0x11, 0xc1, 0xd6, - 0xc0, 0xd8, 0xda, 0x53, 0xf5, 0x04, 0x73, 0x51, 0x1b, 0x26, 0xef, 0x4e, - 0xf5, 0xce, 0x3d, 0x77, 0x21, 0x94, 0xd0, 0xc7, 0xc1, 0xda, 0x19, 0x7d, - 0xf8, 0xc5, 0x4c, 0xc8, 0xee, 0x7d, 0xd1, 0xbb, 0x02, 0x90, 0x2b, 0xff, - 0x4e, 0x4d, 0xd7, 0x9d, 0x72, 0x0c, 0x60, 0x0f, 0x4b, 0x83, 0xf5, 0xc2, - 0x26, 0xd6, 0x22, 0xb8, 0x60, 0x3a, 0xf9, 0x2f, 0x92, 0x2a, 0x2e, 0x14, - 0xa7, 0x56, 0x1c, 0x56, 0x05, 0x41, 0x92, 0xac, 0xb1, 0x4e, 0x44, 0x1e, - 0x70, 0x42, 0xda, 0xc7, 0xc8, 0x9c, 0xae, 0x29, 0x2d, 0x0c, 0x3a, 0xff, - 0x9b, 0xb6, 0xad, 0xb4, 0xfb, 0x49, 0x28, 0x96, 0x74, 0xf5, 0x94, 0x74, - 0xb7, 0x40, 0x93, 0x2b, 0x34, 0x29, 0xd2, 0x8a, 0xf3, 0x99, 0xf9, 0xe9, - 0xd8, 0xcc, 0x48, 0x1d, 0x3e, 0xc1, 0x82, 0x35, 0x4f, 0xef, 0xb1, 0x81, - 0x3c, 0xe1, 0xa1, 0x03, 0x65, 0xac, 0x21, 0x21, 0x40, 0x61, 0xfb, 0xd3, - 0x54, 0xac, 0xa1, 0xf2, 0xf0, 0x61, 0xd9, 0x01, 0x4e, 0xc2, 0x28, 0xb1, - 0x7c, 0x27, 0x6e, 0x56, 0x68, 0x69, 0x8f, 0xc5, 0xfd, 0xca, 0x39, 0x6e, - 0x22, 0x09, 0xf1, 0xb4, 0xd5, 0xac, 0xb8, 0xe0, 0x1b, 0x21, 0x86, 0xf4, - 0xc8, 0x15, 0xc6, 0x1f, 0x21, 0xae, 0xcb, 0xab, 0x5a, 0x09, 0x30, 0x9e, - 0xdd, 0x6c, 0x38, 0x59, 0xec, 0x59, 0x3a, 0x08, 0xee, 0x46, 0x7b, 0x78, - 0x23, 0xbc, 0xfc, 0xe2, 0xda, 0xe8, 0x1a, 0x65, 0xe6, 0xe0, 0x78, 0xd3, - 0xb0, 0x03, 0x2e, 0xf1, 0xb8, 0xca, 0x8e, 0x90, 0x75, 0xaf, 0xf7, 0xa8, - 0x48, 0xed, 0x82, 0xc9, 0xcf, 0x44, 0x56, 0xfc, 0x05, 0xfd, 0x6b, 0x00, - 0x00, 0x00, 0x81, 0x00, 0xfc, 0x94, 0xdf, 0x42, 0xc7, 0x9a, 0xa2, 0xff, - 0x32, 0xdf, 0x06, 0xb6, 0x4d, 0x90, 0x31, 0x28, 0x28, 0xdb, 0x03, 0xf9, - 0xa6, 0xb3, 0xa2, 0x91, 0x4c, 0xdf, 0x6e, 0xf6, 0xb9, 0x44, 0x3b, 0xdd, - 0x17, 0xc1, 0xc8, 0x1d, 0xd1, 0xc0, 0xc0, 0x30, 0x22, 0xbe, 0x24, 0x2e, - 0x0e, 0xdf, 0xe0, 0x18, 0x37, 0x3e, 0xb8, 0x7f, 0xb2, 0x50, 0x34, 0xc4, - 0x08, 0x5e, 0x69, 0x1f, 0xd5, 0xc9, 0xce, 0x47, 0x7d, 0x75, 0x5e, 0x3b, - 0x87, 0xdd, 0x46, 0x35, 0x01, 0x0f, 0x17, 0x8a, 0xf1, 0xf1, 0xc4, 0xa9, - 0x94, 0xa7, 0x6e, 0xce, 0x80, 0xe3, 0x17, 0x2e, 0xb0, 0xef, 0x63, 0xa7, - 0x11, 0x86, 0x96, 0x4a, 0x63, 0x2d, 0x9e, 0x92, 0x62, 0x43, 0x43, 0x72, - 0xa5, 0xdc, 0xa0, 0xcd, 0x19, 0x93, 0xd7, 0xe0, 0x80, 0x41, 0x27, 0xea, - 0xe4, 0xe8, 0xc1, 0x91, 0x9e, 0x13, 0xb3, 0x9c, 0xd1, 0xed, 0xcb, 0xbf, - 0x00, 0x00, 0x00, 0x81, 0x00, 0xb3, 0x6b, 0xee, 0xa4, 0x70, 0x4e, 0xfb, - 0xf9, 0x7e, 0x2e, 0x74, 0x5d, 0x3e, 0x8b, 0x3f, 0xff, 0x8c, 0xde, 0x68, - 0x38, 0xda, 0xce, 0xc0, 0x66, 0x4b, 0xca, 0x35, 0xc3, 0x97, 0xa8, 0xf0, - 0x00, 0x8e, 0xb3, 0x46, 0x60, 0xd0, 0x4d, 0x7e, 0x7b, 0xdf, 0x17, 0x7b, - 0x2f, 0xc4, 0x16, 0xee, 0x45, 0xdb, 0xa5, 0x5d, 0xc0, 0x72, 0xe9, 0xc6, - 0x91, 0x0f, 0xd9, 0x30, 0x74, 0x6c, 0xde, 0x93, 0xb5, 0xb6, 0xaf, 0x52, - 0x53, 0x3c, 0x08, 0x55, 0xea, 0xb8, 0x66, 0x07, 0xbe, 0xce, 0xf9, 0x80, - 0x8d, 0xe0, 0xca, 0xdc, 0x63, 0xe8, 0x58, 0x94, 0x22, 0x4f, 0x08, 0x66, - 0x13, 0x9e, 0x63, 0x2e, 0x92, 0x7a, 0xb6, 0x66, 0x94, 0x9b, 0x71, 0x66, - 0xd3, 0x08, 0xc9, 0x89, 0xea, 0x78, 0x35, 0x0d, 0xf2, 0x25, 0x55, 0xd4, - 0xb0, 0x9b, 0xea, 0x18, 0x77, 0xf6, 0x25, 0x02, 0xb4, 0x5e, 0x71, 0xea, - 0xa3 -}; -static unsigned int keyr_len = 805; -static unsigned char keye[] = { - 0x00, 0x00, 0x00, 0x13, 0x65, 0x63, 0x64, 0x73, 0x61, 0x2d, 0x73, 0x68, - 0x61, 0x32, 0x2d, 0x6e, 0x69, 0x73, 0x74, 0x70, 0x32, 0x35, 0x36, 0x00, - 0x00, 0x00, 0x08, 0x6e, 0x69, 0x73, 0x74, 0x70, 0x32, 0x35, 0x36, 0x00, - 0x00, 0x00, 0x41, 0x04, 0x0a, 0x00, 0x6c, 0x7c, 0x1c, 0xc4, 0x03, 0x44, - 0x46, 0x70, 0xba, 0x00, 0x7c, 0x79, 0x89, 0x7b, 0xc3, 0xd6, 0x32, 0x98, - 0x34, 0xe7, 0x1c, 0x60, 0x04, 0x73, 0xd9, 0xb5, 0x7e, 0x94, 0x04, 0x04, - 0xea, 0xc8, 0xb8, 0xfb, 0xd4, 0x70, 0x9f, 0x29, 0xa7, 0x8d, 0x9a, 0x64, - 0x3a, 0x8c, 0x45, 0x23, 0x37, 0x5a, 0x2b, 0x4f, 0x54, 0x91, 0x80, 0xf1, - 0xac, 0x3a, 0xf5, 0x6d, 0xfa, 0xe8, 0x76, 0x20, 0x00, 0x00, 0x00, 0x21, - 0x00, 0xc2, 0xaf, 0xbe, 0xdc, 0x06, 0xff, 0x3d, 0x08, 0x9b, 0x73, 0xe0, - 0x3c, 0x58, 0x28, 0x70, 0x9b, 0x23, 0x39, 0x51, 0xd7, 0xbc, 0xa7, 0x1a, - 0xf5, 0xb4, 0x23, 0xd3, 0xf6, 0x17, 0xa6, 0x9c, 0x02 -}; -static unsigned int keye_len = 141; -static unsigned char keyd[] = { - 0x00, 0x00, 0x00, 0x07, 0x73, 0x73, 0x68, 0x2d, 0x64, 0x73, 0x73, 0x00, - 0x00, 0x00, 0x81, 0x00, 0xb0, 0x02, 0x19, 0x8b, 0xf3, 0x46, 0xf9, 0xc5, - 0x47, 0x78, 0x3d, 0x7f, 0x04, 0x10, 0x0a, 0x43, 0x8e, 0x00, 0x9e, 0xa4, - 0x30, 0xfd, 0x47, 0xb9, 0x05, 0x9e, 0x95, 0xaa, 0x37, 0x9a, 0x91, 0xbf, - 0xf8, 0xb9, 0xe0, 0x8d, 0x97, 0x49, 0x87, 0xe2, 0xe6, 0x90, 0xc1, 0xe4, - 0x61, 0x57, 0x77, 0xfd, 0x91, 0x1d, 0xe1, 0x4b, 0xa0, 0xb2, 0xbc, 0xa1, - 0x6a, 0x6a, 0xdd, 0x31, 0xda, 0xe7, 0x54, 0x03, 0xfd, 0x48, 0x62, 0x8a, - 0x1d, 0x1d, 0xe2, 0x26, 0x76, 0x29, 0x08, 0xab, 0x65, 0x88, 0x74, 0x02, - 0x1e, 0xa9, 0x29, 0x1b, 0x69, 0x3b, 0xb4, 0x5f, 0x62, 0x80, 0xa3, 0xa6, - 0x4b, 0xc3, 0x0e, 0x89, 0x24, 0xe4, 0x8a, 0x31, 0xae, 0x89, 0x7a, 0x7a, - 0x58, 0x44, 0x46, 0x77, 0x62, 0x33, 0xa2, 0x5d, 0x17, 0x0e, 0x0b, 0x64, - 0xee, 0x1a, 0x02, 0xbd, 0xf8, 0x27, 0x86, 0xe1, 0x87, 0x92, 0x84, 0xc7, - 0x00, 0x00, 0x00, 0x15, 0x00, 0xb3, 0x8b, 0x81, 0x39, 0x9c, 0xba, 0xe1, - 0x1d, 0x9a, 0x8b, 0x89, 0xb3, 0x08, 0x9b, 0x12, 0xa8, 0x7b, 0xea, 0x25, - 0x8d, 0x00, 0x00, 0x00, 0x80, 0x76, 0x3f, 0x72, 0xb2, 0xef, 0xc3, 0x16, - 0xd8, 0x09, 0x36, 0x23, 0x03, 0xf9, 0x5c, 0xac, 0x8b, 0x51, 0x35, 0x2e, - 0x36, 0xba, 0x39, 0xd0, 0x57, 0x19, 0x4f, 0x14, 0x8b, 0xea, 0x32, 0xfc, - 0x86, 0x41, 0xea, 0x85, 0x71, 0x4d, 0x52, 0x0c, 0xff, 0xc1, 0xd3, 0xd5, - 0xcd, 0x2e, 0x37, 0xcc, 0xe1, 0xcc, 0x22, 0x38, 0xa8, 0x47, 0x16, 0x34, - 0x3b, 0x32, 0x9c, 0x2f, 0x0f, 0xcd, 0x5f, 0x7f, 0x06, 0x64, 0x89, 0xc5, - 0x02, 0x4f, 0x9a, 0x70, 0x11, 0xf0, 0xaa, 0xe1, 0x7a, 0x75, 0x49, 0x8d, - 0x0f, 0x8d, 0x5b, 0x54, 0xe2, 0xe7, 0x10, 0x6e, 0xe5, 0xbd, 0xb7, 0x62, - 0xf7, 0x40, 0x59, 0x39, 0x31, 0xd9, 0x13, 0x7b, 0xa3, 0xdf, 0x0d, 0x31, - 0x52, 0x43, 0xe0, 0xaf, 0x19, 0x12, 0x15, 0x12, 0x34, 0x01, 0x6f, 0xcf, - 0x62, 0x21, 0xe4, 0xc8, 0x34, 0x69, 0xc9, 0x85, 0xe3, 0xde, 0xd7, 0x0c, - 0xac, 0x00, 0x00, 0x00, 0x80, 0x41, 0xa3, 0xc5, 0xa4, 0x89, 0x86, 0xc8, - 0x17, 0xf3, 0x8e, 0x68, 0x72, 0xbe, 0x13, 0x8b, 0x63, 0xe3, 0x07, 0xe3, - 0xd5, 0xa4, 0xa2, 0xd3, 0x2c, 0x2f, 0xbe, 0x16, 0x71, 0xc9, 0x79, 0x64, - 0x5a, 0x1e, 0x19, 0x82, 0x07, 0xe2, 0x93, 0xda, 0x22, 0xcf, 0x6d, 0xdd, - 0x38, 0xcb, 0x6e, 0x6b, 0x0f, 0x95, 0x8d, 0xfa, 0x3f, 0xbb, 0xb8, 0x6a, - 0x7d, 0xc3, 0x22, 0x1e, 0x49, 0xcf, 0x98, 0x73, 0x05, 0x5d, 0x97, 0xfa, - 0x4c, 0xf2, 0x82, 0x3d, 0x98, 0x61, 0x4e, 0x96, 0x80, 0x26, 0x79, 0xda, - 0x24, 0xf8, 0xa1, 0x9c, 0x71, 0x82, 0xe6, 0xc7, 0xdc, 0xc2, 0xa5, 0xd0, - 0xf4, 0x36, 0xba, 0xaa, 0xee, 0xd3, 0x43, 0x46, 0x1d, 0xaa, 0x53, 0xea, - 0x85, 0x2c, 0x1b, 0xc8, 0x7c, 0x3c, 0xe7, 0x06, 0x44, 0xab, 0x16, 0xad, - 0xc6, 0x54, 0x91, 0x9a, 0xb9, 0xc0, 0xeb, 0x93, 0x8c, 0xca, 0x39, 0xcf, - 0x6f, 0x00, 0x00, 0x00, 0x15, 0x00, 0x90, 0x26, 0x0a, 0xfc, 0x15, 0x99, - 0x7b, 0xac, 0xaa, 0x0c, 0xa2, 0xca, 0x7b, 0xa8, 0xd4, 0xdf, 0x68, 0x56, - 0xf9, 0x39 -}; -static unsigned int keyd_len = 458; -static unsigned char keyed25519[] = { - 0x00, 0x00, 0x00, 0x0b, 0x73, 0x73, 0x68, 0x2d, 0x65, 0x64, 0x32, 0x35, - 0x35, 0x31, 0x39, 0x00, 0x00, 0x00, 0x40, 0x10, 0xb3, 0x79, 0x06, 0xe5, - 0x9b, 0xe7, 0xe4, 0x6e, 0xec, 0xfe, 0xa5, 0x39, 0x21, 0x7c, 0xf6, 0x66, - 0x8c, 0x0b, 0x6a, 0x01, 0x09, 0x05, 0xc7, 0x4f, 0x64, 0xa8, 0x24, 0xd2, - 0x8d, 0xbd, 0xdd, 0xc6, 0x3c, 0x99, 0x1b, 0x2d, 0x3e, 0x33, 0x90, 0x19, - 0xa4, 0xd5, 0xe9, 0x23, 0xfe, 0x8e, 0xd6, 0xd4, 0xf9, 0xb1, 0x11, 0x69, - 0x7c, 0x57, 0x52, 0x0e, 0x41, 0xdb, 0x1b, 0x12, 0x87, 0xfa, 0xc9 -}; -static unsigned int keyed25519_len = 83; diff -r 064f5be2fc45 -r 4c5599435084 fuzz-wrapfd.c --- a/fuzz-wrapfd.c Sat Oct 24 18:56:45 2020 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,241 +0,0 @@ -#define FUZZ_SKIP_WRAP 1 -#include "includes.h" -#include "fuzz-wrapfd.h" - -#include "dbutil.h" - -#include "fuzz.h" - -#define IOWRAP_MAXFD (FD_SETSIZE-1) -static const int MAX_RANDOM_IN = 50000; -static const double CHANCE_CLOSE = 1.0 / 600; -static const double CHANCE_INTR = 1.0 / 900; -static const double CHANCE_READ1 = 0.96; -static const double CHANCE_READ2 = 0.5; -static const double CHANCE_WRITE1 = 0.96; -static const double CHANCE_WRITE2 = 0.5; - -struct fdwrap { - enum wrapfd_mode mode; - int closein; - int closeout; -}; - -static struct fdwrap wrap_fds[IOWRAP_MAXFD+1] = {{UNUSED, 0, 0}}; -static int wrapfd_maxfd = -1; -static unsigned short rand_state[3]; -static buffer *input_buf; -static int devnull_fd = -1; - -static void wrapfd_remove(int fd); - -void wrapfd_setup(buffer *buf) { - TRACE(("wrapfd_setup")) - - // clean old ones - int i; - for (i = 0; i <= wrapfd_maxfd; i++) { - if (wrap_fds[i].mode == COMMONBUF) { - wrapfd_remove(i); - } - } - wrapfd_maxfd = -1; - - memset(rand_state, 0x0, sizeof(rand_state)); - wrapfd_setseed(50); - input_buf = buf; -} - -void wrapfd_setseed(uint32_t seed) { - memcpy(rand_state, &seed, sizeof(seed)); - nrand48(rand_state); -} - -int wrapfd_new() { - if (devnull_fd == -1) { - devnull_fd = open("/dev/null", O_RDONLY); - assert(devnull_fd != -1); - } - - int fd = dup(devnull_fd); - assert(fd != -1); - assert(wrap_fds[fd].mode == UNUSED); - wrap_fds[fd].mode = COMMONBUF; - wrap_fds[fd].closein = 0; - wrap_fds[fd].closeout = 0; - wrapfd_maxfd = MAX(fd, wrapfd_maxfd); - - return fd; -} - -static void wrapfd_remove(int fd) { - TRACE(("wrapfd_remove %d", fd)) - assert(fd >= 0); - assert(fd <= IOWRAP_MAXFD); - assert(wrap_fds[fd].mode != UNUSED); - wrap_fds[fd].mode = UNUSED; - m_close(fd); -} - -int wrapfd_close(int fd) { - if (fd >= 0 && fd <= IOWRAP_MAXFD && wrap_fds[fd].mode != UNUSED) { - wrapfd_remove(fd); - return 0; - } else { - return close(fd); - } -} - -int wrapfd_read(int fd, void *out, size_t count) { - size_t maxread; - - if (!fuzz.wrapfds) { - return read(fd, out, count); - } - - if (fd < 0 || fd > IOWRAP_MAXFD || wrap_fds[fd].mode == UNUSED) { - /* XXX - assertion failure? */ - TRACE(("Bad read descriptor %d\n", fd)) - errno = EBADF; - return -1; - } - - assert(count != 0); - - if (wrap_fds[fd].closein || erand48(rand_state) < CHANCE_CLOSE) { - wrap_fds[fd].closein = 1; - errno = ECONNRESET; - return -1; - } - - if (erand48(rand_state) < CHANCE_INTR) { - errno = EINTR; - return -1; - } - - if (input_buf) { - maxread = MIN(input_buf->len - input_buf->pos, count); - /* returns 0 if buf is EOF, as intended */ - if (maxread > 0) { - maxread = nrand48(rand_state) % maxread + 1; - } - memcpy(out, buf_getptr(input_buf, maxread), maxread); - buf_incrpos(input_buf, maxread); - return maxread; - } - - maxread = MIN(MAX_RANDOM_IN, count); - maxread = nrand48(rand_state) % maxread + 1; - memset(out, 0xef, maxread); - return maxread; -} - -int wrapfd_write(int fd, const void* in, size_t count) { - unsigned const volatile char* volin = in; - unsigned int i; - - if (!fuzz.wrapfds) { - return write(fd, in, count); - } - - if (fd < 0 || fd > IOWRAP_MAXFD || wrap_fds[fd].mode == UNUSED) { - /* XXX - assertion failure? */ - TRACE(("Bad read descriptor %d\n", fd)) - errno = EBADF; - return -1; - } - - assert(count != 0); - - /* force read to exercise sanitisers */ - for (i = 0; i < count; i++) { - (void)volin[i]; - } - - if (wrap_fds[fd].closeout || erand48(rand_state) < CHANCE_CLOSE) { - wrap_fds[fd].closeout = 1; - errno = ECONNRESET; - return -1; - } - - if (erand48(rand_state) < CHANCE_INTR) { - errno = EINTR; - return -1; - } - - return nrand48(rand_state) % (count+1); -} - -int wrapfd_select(int nfds, fd_set *readfds, fd_set *writefds, - fd_set *exceptfds, struct timeval *timeout) { - int i, nset, sel; - int ret = 0; - int fdlist[IOWRAP_MAXFD+1]; - - if (!fuzz.wrapfds) { - return select(nfds, readfds, writefds, exceptfds, timeout); - } - - assert(nfds <= IOWRAP_MAXFD+1); - - if (erand48(rand_state) < CHANCE_INTR) { - errno = EINTR; - return -1; - } - - /* read */ - if (readfds != NULL && erand48(rand_state) < CHANCE_READ1) { - for (i = 0, nset = 0; i < nfds; i++) { - if (FD_ISSET(i, readfds)) { - assert(wrap_fds[i].mode != UNUSED); - fdlist[nset] = i; - nset++; - } - } - DROPBEAR_FD_ZERO(readfds); - - if (nset > 0) { - /* set one */ - sel = fdlist[nrand48(rand_state) % nset]; - FD_SET(sel, readfds); - ret++; - - if (erand48(rand_state) < CHANCE_READ2) { - sel = fdlist[nrand48(rand_state) % nset]; - if (!FD_ISSET(sel, readfds)) { - FD_SET(sel, readfds); - ret++; - } - } - } - } - - /* write */ - if (writefds != NULL && erand48(rand_state) < CHANCE_WRITE1) { - for (i = 0, nset = 0; i < nfds; i++) { - if (FD_ISSET(i, writefds)) { - assert(wrap_fds[i].mode != UNUSED); - fdlist[nset] = i; - nset++; - } - } - DROPBEAR_FD_ZERO(writefds); - - /* set one */ - if (nset > 0) { - sel = fdlist[nrand48(rand_state) % nset]; - FD_SET(sel, writefds); - ret++; - - if (erand48(rand_state) < CHANCE_WRITE2) { - sel = fdlist[nrand48(rand_state) % nset]; - if (!FD_ISSET(sel, writefds)) { - FD_SET(sel, writefds); - ret++; - } - } - } - } - return ret; -} - diff -r 064f5be2fc45 -r 4c5599435084 fuzz.h --- a/fuzz.h Sat Oct 24 18:56:45 2020 +0800 +++ b/fuzz.h Sun Oct 25 21:47:42 2020 +0800 @@ -15,6 +15,10 @@ void fuzz_svr_setup(void); void fuzz_cli_setup(void); +// constructor attribute so it runs before main(), including +// in non-fuzzing mode. +void fuzz_early_setup(void) __attribute__((constructor)); + // must be called once per fuzz iteration. // returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE int fuzz_set_input(const uint8_t *Data, size_t Size); @@ -29,7 +33,7 @@ const char* algo, unsigned int algolen, const unsigned char* keyblob, unsigned int keybloblen); extern const char * const * fuzz_signkey_names; -void fuzz_seed(void); +void fuzz_seed(const unsigned char* dat, unsigned int len); // helpers void fuzz_get_socket_address(int fd, char **local_host, char **local_port, @@ -68,10 +72,21 @@ int dumping; // the file descriptor int recv_dumpfd; + + // avoid filling fuzzing logs, this points to /dev/null + FILE *stderr; }; extern struct dropbear_fuzz_options fuzz; +/* This is a bodge but seems to work. + glibc stdio.h has the comment + "C89/C99 say they're macros. Make them happy." */ +#ifdef stderr +#undef stderr +#endif +#define stderr (fuzz.stderr) + #endif // DROPBEAR_FUZZ #endif /* DROPBEAR_FUZZ_H */ diff -r 064f5be2fc45 -r 4c5599435084 fuzz/fuzz-common.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fuzz/fuzz-common.c Sun Oct 25 21:47:42 2020 +0800 @@ -0,0 +1,332 @@ +#include "includes.h" + +#include "includes.h" +#include "fuzz.h" +#include "dbutil.h" +#include "runopts.h" +#include "crypto_desc.h" +#include "session.h" +#include "dbrandom.h" +#include "bignum.h" +#include "atomicio.h" +#include "fuzz-wrapfd.h" + +/* fuzz.h redefines stderr, we don't want that here */ +#undef stderr + +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); +static void load_fixed_client_key(void); + +// This runs automatically before main, due to contructor attribute in fuzz.h +void fuzz_early_setup(void) { + /* Set stderr to point to normal stderr by default */ + fuzz.stderr = stderr; +} + +void fuzz_common_setup(void) { + disallow_core(); + fuzz.fuzzing = 1; + fuzz.wrapfds = 1; + fuzz.do_jmp = 1; + fuzz.input = m_malloc(sizeof(buffer)); + _dropbear_log = fuzz_dropbear_log; + crypto_init(); + fuzz_seed("start", 5); + /* let any messages get flushed */ + setlinebuf(stdout); +#if DEBUG_TRACE + if (debug_trace) + { + fprintf(stderr, "Dropbear fuzzer: -v specified, not disabling stderr output\n"); + } + else +#endif + { + fprintf(stderr, "Dropbear fuzzer: Disabling stderr output\n"); + fuzz.stderr = fopen("/dev/null", "w"); + assert(fuzz.stderr); + } +} + +int fuzz_set_input(const uint8_t *Data, size_t Size) { + + fuzz.input->data = (unsigned char*)Data; + fuzz.input->size = Size; + fuzz.input->len = Size; + fuzz.input->pos = 0; + + memset(&ses, 0x0, sizeof(ses)); + memset(&svr_ses, 0x0, sizeof(svr_ses)); + memset(&cli_ses, 0x0, sizeof(cli_ses)); + wrapfd_setup(fuzz.input); + + fuzz_seed(fuzz.input->data, MIN(fuzz.input->len, 16)); + + return DROPBEAR_SUCCESS; +} + +#if DEBUG_TRACE +static void fuzz_dropbear_log(int UNUSED(priority), const char* format, va_list param) { + if (debug_trace) { + char printbuf[1024]; + vsnprintf(printbuf, sizeof(printbuf), format, param); + fprintf(stderr, "%s\n", printbuf); + } +} +#else +static void fuzz_dropbear_log(int UNUSED(priority), const char* UNUSED(format), va_list UNUSED(param)) { + /* No print */ +} +#endif /* DEBUG_TRACE */ + +void fuzz_svr_setup(void) { + fuzz_common_setup(); + + _dropbear_exit = svr_dropbear_exit; + + char *argv[] = { + "dropbear", + "-E", + }; + + int argc = sizeof(argv) / sizeof(*argv); + svr_getopts(argc, argv); + + load_fixed_hostkeys(); +} + +void fuzz_cli_setup(void) { + fuzz_common_setup(); + + _dropbear_exit = cli_dropbear_exit; + _dropbear_log = cli_dropbear_log; + + char *argv[] = { + "dbclient", + "-y", + "localhost", + "uptime" + }; + + int argc = sizeof(argv) / sizeof(*argv); + cli_getopts(argc, argv); + + load_fixed_client_key(); + /* Avoid password prompt */ + setenv(DROPBEAR_PASSWORD_ENV, "password", 1); +} + +#include "fuzz-hostkeys.c" + +static void load_fixed_client_key(void) { + + buffer *b = buf_new(3000); + sign_key *key; + enum signkey_type keytype; + + key = new_sign_key(); + keytype = DROPBEAR_SIGNKEY_ANY; + buf_putbytes(b, keyed25519, keyed25519_len); + buf_setpos(b, 0); + if (buf_get_priv_key(b, key, &keytype) == DROPBEAR_FAILURE) { + dropbear_exit("failed fixed ed25519 hostkey"); + } + list_append(cli_opts.privkeys, key); + + buf_free(b); +} + +static void load_fixed_hostkeys(void) { + + buffer *b = buf_new(3000); + enum signkey_type type; + + TRACE(("load fixed hostkeys")) + + svr_opts.hostkey = new_sign_key(); + + buf_setlen(b, 0); + buf_putbytes(b, keyr, keyr_len); + buf_setpos(b, 0); + type = DROPBEAR_SIGNKEY_RSA; + if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) { + dropbear_exit("failed fixed rsa hostkey"); + } + + buf_setlen(b, 0); + buf_putbytes(b, keyd, keyd_len); + buf_setpos(b, 0); + type = DROPBEAR_SIGNKEY_DSS; + if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) { + dropbear_exit("failed fixed dss hostkey"); + } + + buf_setlen(b, 0); + buf_putbytes(b, keye, keye_len); + buf_setpos(b, 0); + type = DROPBEAR_SIGNKEY_ECDSA_NISTP256; + if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) { + dropbear_exit("failed fixed ecdsa hostkey"); + } + + buf_setlen(b, 0); + buf_putbytes(b, keyed25519, keyed25519_len); + buf_setpos(b, 0); + type = DROPBEAR_SIGNKEY_ED25519; + if (buf_get_priv_key(b, svr_opts.hostkey, &type) == DROPBEAR_FAILURE) { + dropbear_exit("failed fixed ed25519 hostkey"); + } + + buf_free(b); +} + +void fuzz_kex_fakealgos(void) { + ses.newkeys->recv.crypt_mode = &dropbear_mode_none; +} + +void fuzz_get_socket_address(int UNUSED(fd), char **local_host, char **local_port, + char **remote_host, char **remote_port, int UNUSED(host_lookup)) { + if (local_host) { + *local_host = m_strdup("fuzzlocalhost"); + } + if (local_port) { + *local_port = m_strdup("1234"); + } + if (remote_host) { + *remote_host = m_strdup("fuzzremotehost"); + } + if (remote_port) { + *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_ul(ses.dh_K, 12345678uL); + finish_kexhashbuf(); +} + +/* fake version of spawn_command() */ +int fuzz_spawn_command(int *ret_writefd, int *ret_readfd, int *ret_errfd, pid_t *ret_pid) { + *ret_writefd = wrapfd_new(); + *ret_readfd = wrapfd_new(); + if (ret_errfd) { + *ret_errfd = wrapfd_new(); + } + *ret_pid = 999; + return DROPBEAR_SUCCESS; +} + +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, allowing for future extensibility. 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 = wrapfd_new(); + + 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; +} + +int fuzz_run_client(const uint8_t *Data, size_t Size, int skip_kexmaths) { + static int once = 0; + if (!once) { + fuzz_cli_setup(); + fuzz.skip_kexmaths = skip_kexmaths; + once = 1; + } + + if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) { + return 0; + } + + /* + get prefix, allowing for future extensibility. 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 = wrapfd_new(); + + m_malloc_set_epoch(1); + if (setjmp(fuzz.jmp) == 0) { + cli_session(fakesock, fakesock, NULL, 0); + m_malloc_free_epoch(1, 0); + } else { + m_malloc_free_epoch(1, 1); + TRACE(("dropbear_exit longjmped")) + /* dropbear_exit jumped here */ + } + + return 0; +} + +const void* fuzz_get_algo(const algo_type *algos, const char* name) { + const algo_type *t; + for (t = algos; t->name; t++) { + if (strcmp(t->name, name) == 0) { + return t->data; + } + } + assert(0); +} + +void fuzz_dump(const unsigned char* data, size_t len) { + TRACE(("dump %zu", len)) + if (fuzz.dumping) { + assert(atomicio(vwrite, fuzz.recv_dumpfd, (void*)data, len) == len); + } +} diff -r 064f5be2fc45 -r 4c5599435084 fuzz/fuzz-harness.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fuzz/fuzz-harness.c Sun Oct 25 21:47:42 2020 +0800 @@ -0,0 +1,48 @@ +#include "includes.h" +#include "buffer.h" +#include "dbutil.h" + +extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size); + +int main(int argc, char ** argv) { + int i; + buffer *input = buf_new(100000); + + for (i = 1; i < argc; i++) { +#if DEBUG_TRACE + if (strcmp(argv[i], "-v") == 0) { + debug_trace = 1; + TRACE(("debug printing on")) + } +#endif + } + + int old_fuzz_wrapfds = 0; + for (i = 1; i < argc; i++) { + if (argv[i][0] == '-') { + /* ignore arguments */ + continue; + } + + char* fn = argv[i]; + buf_setlen(input, 0); + buf_readfile(input, fn); + buf_setpos(input, 0); + + /* Run twice to catch problems with statefulness */ + fuzz.wrapfds = old_fuzz_wrapfds; + printf("Running %s once \n", fn); + LLVMFuzzerTestOneInput(input->data, input->len); + printf("Running %s twice \n", fn); + LLVMFuzzerTestOneInput(input->data, input->len); + printf("Done %s\n", fn); + + /* Disable wrapfd so it won't interfere with buf_readfile() above */ + old_fuzz_wrapfds = fuzz.wrapfds; + fuzz.wrapfds = 0; + } + + printf("Finished\n"); + + return 0; +} diff -r 064f5be2fc45 -r 4c5599435084 fuzz/fuzz-hostkeys.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fuzz/fuzz-hostkeys.c Sun Oct 25 21:47:42 2020 +0800 @@ -0,0 +1,140 @@ +/* To be included in fuzz-common.c */ + +static unsigned char keyr[] = { + 0x00, 0x00, 0x00, 0x07, 0x73, 0x73, 0x68, 0x2d, 0x72, 0x73, 0x61, 0x00, + 0x00, 0x00, 0x03, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0xb1, + 0x06, 0x95, 0xc9, 0xa8, 0x38, 0xb9, 0x99, 0x91, 0xb5, 0x17, 0x39, 0xb9, + 0xfa, 0xa4, 0x49, 0xf8, 0x2a, 0x4c, 0x14, 0xbd, 0xb6, 0x85, 0xdb, 0x38, + 0x99, 0x44, 0xfa, 0xd6, 0xaa, 0x67, 0xef, 0x00, 0x75, 0x2b, 0x6a, 0x5c, + 0x1b, 0x50, 0xa8, 0x52, 0xf9, 0xa7, 0xee, 0xe2, 0xb3, 0x80, 0x38, 0x92, + 0x20, 0x86, 0x7c, 0xe5, 0x89, 0xb3, 0x06, 0xe4, 0x3b, 0xd1, 0xe2, 0x45, + 0xea, 0xc1, 0xd5, 0x8e, 0x05, 0xfb, 0x90, 0x29, 0xd9, 0x41, 0xb3, 0x05, + 0x31, 0x1e, 0xcc, 0xeb, 0x89, 0xdc, 0xd2, 0x6a, 0x99, 0x23, 0xbd, 0x7a, + 0xbe, 0x8c, 0xe3, 0x3f, 0xa1, 0xe8, 0xf5, 0xb4, 0x51, 0x40, 0xb4, 0xb1, + 0xc1, 0x16, 0x9f, 0x07, 0xbb, 0x99, 0xaa, 0x4b, 0x8f, 0x11, 0x19, 0x3c, + 0x18, 0xbd, 0x6e, 0xce, 0x14, 0x54, 0x2c, 0x16, 0x4a, 0x5f, 0x89, 0xe4, + 0x6b, 0x9f, 0x55, 0x68, 0xcc, 0x09, 0x8e, 0x4b, 0x92, 0xc8, 0x87, 0xfe, + 0x09, 0xed, 0x53, 0x6e, 0xff, 0x5f, 0x15, 0x0d, 0x19, 0x9d, 0xa6, 0x54, + 0xd2, 0xea, 0x59, 0x4f, 0xa1, 0x7c, 0xf6, 0xf5, 0x7f, 0x32, 0x23, 0xed, + 0x72, 0xa8, 0x96, 0x17, 0x87, 0x06, 0xf2, 0xc7, 0xcd, 0xda, 0x4a, 0x10, + 0xd1, 0xfd, 0xb8, 0xf1, 0xaf, 0x25, 0x55, 0x32, 0x45, 0x39, 0x95, 0xec, + 0x0c, 0xa9, 0xf0, 0x47, 0x8b, 0x66, 0xe0, 0xb7, 0xa2, 0xf6, 0x35, 0x50, + 0x27, 0xe7, 0x2f, 0x90, 0x35, 0x5b, 0xd5, 0x62, 0x19, 0xb4, 0x41, 0xd4, + 0x52, 0xe7, 0x7f, 0x97, 0xfc, 0x5b, 0x4a, 0x5b, 0x19, 0x06, 0x65, 0x2d, + 0x23, 0x29, 0x15, 0x8b, 0x05, 0xaf, 0xbe, 0xd3, 0x4a, 0x27, 0x5b, 0xc9, + 0xc0, 0xd0, 0xd2, 0xba, 0x8b, 0x00, 0x7a, 0x2f, 0x39, 0xa0, 0x13, 0xb9, + 0xe6, 0xf5, 0x4b, 0x21, 0x54, 0x57, 0xb3, 0xf9, 0x6c, 0x6f, 0xd0, 0x17, + 0xf4, 0x50, 0x9d, 0x00, 0x00, 0x01, 0x00, 0x01, 0xf2, 0xda, 0x5f, 0xfb, + 0xe2, 0xda, 0xfc, 0xe0, 0xdf, 0x3a, 0x0e, 0x14, 0x18, 0xc1, 0xd9, 0x1f, + 0x43, 0xe3, 0x65, 0x3e, 0x07, 0xe7, 0x8d, 0xdc, 0x1d, 0x11, 0xc1, 0xd6, + 0xc0, 0xd8, 0xda, 0x53, 0xf5, 0x04, 0x73, 0x51, 0x1b, 0x26, 0xef, 0x4e, + 0xf5, 0xce, 0x3d, 0x77, 0x21, 0x94, 0xd0, 0xc7, 0xc1, 0xda, 0x19, 0x7d, + 0xf8, 0xc5, 0x4c, 0xc8, 0xee, 0x7d, 0xd1, 0xbb, 0x02, 0x90, 0x2b, 0xff, + 0x4e, 0x4d, 0xd7, 0x9d, 0x72, 0x0c, 0x60, 0x0f, 0x4b, 0x83, 0xf5, 0xc2, + 0x26, 0xd6, 0x22, 0xb8, 0x60, 0x3a, 0xf9, 0x2f, 0x92, 0x2a, 0x2e, 0x14, + 0xa7, 0x56, 0x1c, 0x56, 0x05, 0x41, 0x92, 0xac, 0xb1, 0x4e, 0x44, 0x1e, + 0x70, 0x42, 0xda, 0xc7, 0xc8, 0x9c, 0xae, 0x29, 0x2d, 0x0c, 0x3a, 0xff, + 0x9b, 0xb6, 0xad, 0xb4, 0xfb, 0x49, 0x28, 0x96, 0x74, 0xf5, 0x94, 0x74, + 0xb7, 0x40, 0x93, 0x2b, 0x34, 0x29, 0xd2, 0x8a, 0xf3, 0x99, 0xf9, 0xe9, + 0xd8, 0xcc, 0x48, 0x1d, 0x3e, 0xc1, 0x82, 0x35, 0x4f, 0xef, 0xb1, 0x81, + 0x3c, 0xe1, 0xa1, 0x03, 0x65, 0xac, 0x21, 0x21, 0x40, 0x61, 0xfb, 0xd3, + 0x54, 0xac, 0xa1, 0xf2, 0xf0, 0x61, 0xd9, 0x01, 0x4e, 0xc2, 0x28, 0xb1, + 0x7c, 0x27, 0x6e, 0x56, 0x68, 0x69, 0x8f, 0xc5, 0xfd, 0xca, 0x39, 0x6e, + 0x22, 0x09, 0xf1, 0xb4, 0xd5, 0xac, 0xb8, 0xe0, 0x1b, 0x21, 0x86, 0xf4, + 0xc8, 0x15, 0xc6, 0x1f, 0x21, 0xae, 0xcb, 0xab, 0x5a, 0x09, 0x30, 0x9e, + 0xdd, 0x6c, 0x38, 0x59, 0xec, 0x59, 0x3a, 0x08, 0xee, 0x46, 0x7b, 0x78, + 0x23, 0xbc, 0xfc, 0xe2, 0xda, 0xe8, 0x1a, 0x65, 0xe6, 0xe0, 0x78, 0xd3, + 0xb0, 0x03, 0x2e, 0xf1, 0xb8, 0xca, 0x8e, 0x90, 0x75, 0xaf, 0xf7, 0xa8, + 0x48, 0xed, 0x82, 0xc9, 0xcf, 0x44, 0x56, 0xfc, 0x05, 0xfd, 0x6b, 0x00, + 0x00, 0x00, 0x81, 0x00, 0xfc, 0x94, 0xdf, 0x42, 0xc7, 0x9a, 0xa2, 0xff, + 0x32, 0xdf, 0x06, 0xb6, 0x4d, 0x90, 0x31, 0x28, 0x28, 0xdb, 0x03, 0xf9, + 0xa6, 0xb3, 0xa2, 0x91, 0x4c, 0xdf, 0x6e, 0xf6, 0xb9, 0x44, 0x3b, 0xdd, + 0x17, 0xc1, 0xc8, 0x1d, 0xd1, 0xc0, 0xc0, 0x30, 0x22, 0xbe, 0x24, 0x2e, + 0x0e, 0xdf, 0xe0, 0x18, 0x37, 0x3e, 0xb8, 0x7f, 0xb2, 0x50, 0x34, 0xc4, + 0x08, 0x5e, 0x69, 0x1f, 0xd5, 0xc9, 0xce, 0x47, 0x7d, 0x75, 0x5e, 0x3b, + 0x87, 0xdd, 0x46, 0x35, 0x01, 0x0f, 0x17, 0x8a, 0xf1, 0xf1, 0xc4, 0xa9, + 0x94, 0xa7, 0x6e, 0xce, 0x80, 0xe3, 0x17, 0x2e, 0xb0, 0xef, 0x63, 0xa7, + 0x11, 0x86, 0x96, 0x4a, 0x63, 0x2d, 0x9e, 0x92, 0x62, 0x43, 0x43, 0x72, + 0xa5, 0xdc, 0xa0, 0xcd, 0x19, 0x93, 0xd7, 0xe0, 0x80, 0x41, 0x27, 0xea, + 0xe4, 0xe8, 0xc1, 0x91, 0x9e, 0x13, 0xb3, 0x9c, 0xd1, 0xed, 0xcb, 0xbf, + 0x00, 0x00, 0x00, 0x81, 0x00, 0xb3, 0x6b, 0xee, 0xa4, 0x70, 0x4e, 0xfb, + 0xf9, 0x7e, 0x2e, 0x74, 0x5d, 0x3e, 0x8b, 0x3f, 0xff, 0x8c, 0xde, 0x68, + 0x38, 0xda, 0xce, 0xc0, 0x66, 0x4b, 0xca, 0x35, 0xc3, 0x97, 0xa8, 0xf0, + 0x00, 0x8e, 0xb3, 0x46, 0x60, 0xd0, 0x4d, 0x7e, 0x7b, 0xdf, 0x17, 0x7b, + 0x2f, 0xc4, 0x16, 0xee, 0x45, 0xdb, 0xa5, 0x5d, 0xc0, 0x72, 0xe9, 0xc6, + 0x91, 0x0f, 0xd9, 0x30, 0x74, 0x6c, 0xde, 0x93, 0xb5, 0xb6, 0xaf, 0x52, + 0x53, 0x3c, 0x08, 0x55, 0xea, 0xb8, 0x66, 0x07, 0xbe, 0xce, 0xf9, 0x80, + 0x8d, 0xe0, 0xca, 0xdc, 0x63, 0xe8, 0x58, 0x94, 0x22, 0x4f, 0x08, 0x66, + 0x13, 0x9e, 0x63, 0x2e, 0x92, 0x7a, 0xb6, 0x66, 0x94, 0x9b, 0x71, 0x66, + 0xd3, 0x08, 0xc9, 0x89, 0xea, 0x78, 0x35, 0x0d, 0xf2, 0x25, 0x55, 0xd4, + 0xb0, 0x9b, 0xea, 0x18, 0x77, 0xf6, 0x25, 0x02, 0xb4, 0x5e, 0x71, 0xea, + 0xa3 +}; +static unsigned int keyr_len = 805; +static unsigned char keye[] = { + 0x00, 0x00, 0x00, 0x13, 0x65, 0x63, 0x64, 0x73, 0x61, 0x2d, 0x73, 0x68, + 0x61, 0x32, 0x2d, 0x6e, 0x69, 0x73, 0x74, 0x70, 0x32, 0x35, 0x36, 0x00, + 0x00, 0x00, 0x08, 0x6e, 0x69, 0x73, 0x74, 0x70, 0x32, 0x35, 0x36, 0x00, + 0x00, 0x00, 0x41, 0x04, 0x0a, 0x00, 0x6c, 0x7c, 0x1c, 0xc4, 0x03, 0x44, + 0x46, 0x70, 0xba, 0x00, 0x7c, 0x79, 0x89, 0x7b, 0xc3, 0xd6, 0x32, 0x98, + 0x34, 0xe7, 0x1c, 0x60, 0x04, 0x73, 0xd9, 0xb5, 0x7e, 0x94, 0x04, 0x04, + 0xea, 0xc8, 0xb8, 0xfb, 0xd4, 0x70, 0x9f, 0x29, 0xa7, 0x8d, 0x9a, 0x64, + 0x3a, 0x8c, 0x45, 0x23, 0x37, 0x5a, 0x2b, 0x4f, 0x54, 0x91, 0x80, 0xf1, + 0xac, 0x3a, 0xf5, 0x6d, 0xfa, 0xe8, 0x76, 0x20, 0x00, 0x00, 0x00, 0x21, + 0x00, 0xc2, 0xaf, 0xbe, 0xdc, 0x06, 0xff, 0x3d, 0x08, 0x9b, 0x73, 0xe0, + 0x3c, 0x58, 0x28, 0x70, 0x9b, 0x23, 0x39, 0x51, 0xd7, 0xbc, 0xa7, 0x1a, + 0xf5, 0xb4, 0x23, 0xd3, 0xf6, 0x17, 0xa6, 0x9c, 0x02 +}; +static unsigned int keye_len = 141; +static unsigned char keyd[] = { + 0x00, 0x00, 0x00, 0x07, 0x73, 0x73, 0x68, 0x2d, 0x64, 0x73, 0x73, 0x00, + 0x00, 0x00, 0x81, 0x00, 0xb0, 0x02, 0x19, 0x8b, 0xf3, 0x46, 0xf9, 0xc5, + 0x47, 0x78, 0x3d, 0x7f, 0x04, 0x10, 0x0a, 0x43, 0x8e, 0x00, 0x9e, 0xa4, + 0x30, 0xfd, 0x47, 0xb9, 0x05, 0x9e, 0x95, 0xaa, 0x37, 0x9a, 0x91, 0xbf, + 0xf8, 0xb9, 0xe0, 0x8d, 0x97, 0x49, 0x87, 0xe2, 0xe6, 0x90, 0xc1, 0xe4, + 0x61, 0x57, 0x77, 0xfd, 0x91, 0x1d, 0xe1, 0x4b, 0xa0, 0xb2, 0xbc, 0xa1, + 0x6a, 0x6a, 0xdd, 0x31, 0xda, 0xe7, 0x54, 0x03, 0xfd, 0x48, 0x62, 0x8a, + 0x1d, 0x1d, 0xe2, 0x26, 0x76, 0x29, 0x08, 0xab, 0x65, 0x88, 0x74, 0x02, + 0x1e, 0xa9, 0x29, 0x1b, 0x69, 0x3b, 0xb4, 0x5f, 0x62, 0x80, 0xa3, 0xa6, + 0x4b, 0xc3, 0x0e, 0x89, 0x24, 0xe4, 0x8a, 0x31, 0xae, 0x89, 0x7a, 0x7a, + 0x58, 0x44, 0x46, 0x77, 0x62, 0x33, 0xa2, 0x5d, 0x17, 0x0e, 0x0b, 0x64, + 0xee, 0x1a, 0x02, 0xbd, 0xf8, 0x27, 0x86, 0xe1, 0x87, 0x92, 0x84, 0xc7, + 0x00, 0x00, 0x00, 0x15, 0x00, 0xb3, 0x8b, 0x81, 0x39, 0x9c, 0xba, 0xe1, + 0x1d, 0x9a, 0x8b, 0x89, 0xb3, 0x08, 0x9b, 0x12, 0xa8, 0x7b, 0xea, 0x25, + 0x8d, 0x00, 0x00, 0x00, 0x80, 0x76, 0x3f, 0x72, 0xb2, 0xef, 0xc3, 0x16, + 0xd8, 0x09, 0x36, 0x23, 0x03, 0xf9, 0x5c, 0xac, 0x8b, 0x51, 0x35, 0x2e, + 0x36, 0xba, 0x39, 0xd0, 0x57, 0x19, 0x4f, 0x14, 0x8b, 0xea, 0x32, 0xfc, + 0x86, 0x41, 0xea, 0x85, 0x71, 0x4d, 0x52, 0x0c, 0xff, 0xc1, 0xd3, 0xd5, + 0xcd, 0x2e, 0x37, 0xcc, 0xe1, 0xcc, 0x22, 0x38, 0xa8, 0x47, 0x16, 0x34, + 0x3b, 0x32, 0x9c, 0x2f, 0x0f, 0xcd, 0x5f, 0x7f, 0x06, 0x64, 0x89, 0xc5, + 0x02, 0x4f, 0x9a, 0x70, 0x11, 0xf0, 0xaa, 0xe1, 0x7a, 0x75, 0x49, 0x8d, + 0x0f, 0x8d, 0x5b, 0x54, 0xe2, 0xe7, 0x10, 0x6e, 0xe5, 0xbd, 0xb7, 0x62, + 0xf7, 0x40, 0x59, 0x39, 0x31, 0xd9, 0x13, 0x7b, 0xa3, 0xdf, 0x0d, 0x31, + 0x52, 0x43, 0xe0, 0xaf, 0x19, 0x12, 0x15, 0x12, 0x34, 0x01, 0x6f, 0xcf, + 0x62, 0x21, 0xe4, 0xc8, 0x34, 0x69, 0xc9, 0x85, 0xe3, 0xde, 0xd7, 0x0c, + 0xac, 0x00, 0x00, 0x00, 0x80, 0x41, 0xa3, 0xc5, 0xa4, 0x89, 0x86, 0xc8, + 0x17, 0xf3, 0x8e, 0x68, 0x72, 0xbe, 0x13, 0x8b, 0x63, 0xe3, 0x07, 0xe3, + 0xd5, 0xa4, 0xa2, 0xd3, 0x2c, 0x2f, 0xbe, 0x16, 0x71, 0xc9, 0x79, 0x64, + 0x5a, 0x1e, 0x19, 0x82, 0x07, 0xe2, 0x93, 0xda, 0x22, 0xcf, 0x6d, 0xdd, + 0x38, 0xcb, 0x6e, 0x6b, 0x0f, 0x95, 0x8d, 0xfa, 0x3f, 0xbb, 0xb8, 0x6a, + 0x7d, 0xc3, 0x22, 0x1e, 0x49, 0xcf, 0x98, 0x73, 0x05, 0x5d, 0x97, 0xfa, + 0x4c, 0xf2, 0x82, 0x3d, 0x98, 0x61, 0x4e, 0x96, 0x80, 0x26, 0x79, 0xda, + 0x24, 0xf8, 0xa1, 0x9c, 0x71, 0x82, 0xe6, 0xc7, 0xdc, 0xc2, 0xa5, 0xd0, + 0xf4, 0x36, 0xba, 0xaa, 0xee, 0xd3, 0x43, 0x46, 0x1d, 0xaa, 0x53, 0xea, + 0x85, 0x2c, 0x1b, 0xc8, 0x7c, 0x3c, 0xe7, 0x06, 0x44, 0xab, 0x16, 0xad, + 0xc6, 0x54, 0x91, 0x9a, 0xb9, 0xc0, 0xeb, 0x93, 0x8c, 0xca, 0x39, 0xcf, + 0x6f, 0x00, 0x00, 0x00, 0x15, 0x00, 0x90, 0x26, 0x0a, 0xfc, 0x15, 0x99, + 0x7b, 0xac, 0xaa, 0x0c, 0xa2, 0xca, 0x7b, 0xa8, 0xd4, 0xdf, 0x68, 0x56, + 0xf9, 0x39 +}; +static unsigned int keyd_len = 458; +static unsigned char keyed25519[] = { + 0x00, 0x00, 0x00, 0x0b, 0x73, 0x73, 0x68, 0x2d, 0x65, 0x64, 0x32, 0x35, + 0x35, 0x31, 0x39, 0x00, 0x00, 0x00, 0x40, 0x10, 0xb3, 0x79, 0x06, 0xe5, + 0x9b, 0xe7, 0xe4, 0x6e, 0xec, 0xfe, 0xa5, 0x39, 0x21, 0x7c, 0xf6, 0x66, + 0x8c, 0x0b, 0x6a, 0x01, 0x09, 0x05, 0xc7, 0x4f, 0x64, 0xa8, 0x24, 0xd2, + 0x8d, 0xbd, 0xdd, 0xc6, 0x3c, 0x99, 0x1b, 0x2d, 0x3e, 0x33, 0x90, 0x19, + 0xa4, 0xd5, 0xe9, 0x23, 0xfe, 0x8e, 0xd6, 0xd4, 0xf9, 0xb1, 0x11, 0x69, + 0x7c, 0x57, 0x52, 0x0e, 0x41, 0xdb, 0x1b, 0x12, 0x87, 0xfa, 0xc9 +}; +static unsigned int keyed25519_len = 83; diff -r 064f5be2fc45 -r 4c5599435084 fuzz/fuzz-wrapfd.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fuzz/fuzz-wrapfd.c Sun Oct 25 21:47:42 2020 +0800 @@ -0,0 +1,241 @@ +#define FUZZ_SKIP_WRAP 1 +#include "includes.h" +#include "fuzz-wrapfd.h" + +#include "dbutil.h" + +#include "fuzz.h" + +#define IOWRAP_MAXFD (FD_SETSIZE-1) +static const int MAX_RANDOM_IN = 50000; +static const double CHANCE_CLOSE = 1.0 / 600; +static const double CHANCE_INTR = 1.0 / 900; +static const double CHANCE_READ1 = 0.96; +static const double CHANCE_READ2 = 0.5; +static const double CHANCE_WRITE1 = 0.96; +static const double CHANCE_WRITE2 = 0.5; + +struct fdwrap { + enum wrapfd_mode mode; + int closein; + int closeout; +}; + +static struct fdwrap wrap_fds[IOWRAP_MAXFD+1] = {{UNUSED, 0, 0}}; +static int wrapfd_maxfd = -1; +static unsigned short rand_state[3]; +static buffer *input_buf; +static int devnull_fd = -1; + +static void wrapfd_remove(int fd); + +void wrapfd_setup(buffer *buf) { + TRACE(("wrapfd_setup")) + + // clean old ones + int i; + for (i = 0; i <= wrapfd_maxfd; i++) { + if (wrap_fds[i].mode == COMMONBUF) { + wrapfd_remove(i); + } + } + wrapfd_maxfd = -1; + + memset(rand_state, 0x0, sizeof(rand_state)); + wrapfd_setseed(50); + input_buf = buf; +} + +void wrapfd_setseed(uint32_t seed) { + memcpy(rand_state, &seed, sizeof(seed)); + nrand48(rand_state); +} + +int wrapfd_new() { + if (devnull_fd == -1) { + devnull_fd = open("/dev/null", O_RDONLY); + assert(devnull_fd != -1); + } + + int fd = dup(devnull_fd); + assert(fd != -1); + assert(wrap_fds[fd].mode == UNUSED); + wrap_fds[fd].mode = COMMONBUF; + wrap_fds[fd].closein = 0; + wrap_fds[fd].closeout = 0; + wrapfd_maxfd = MAX(fd, wrapfd_maxfd); + + return fd; +} + +static void wrapfd_remove(int fd) { + TRACE(("wrapfd_remove %d", fd)) + assert(fd >= 0); + assert(fd <= IOWRAP_MAXFD); + assert(wrap_fds[fd].mode != UNUSED); + wrap_fds[fd].mode = UNUSED; + m_close(fd); +} + +int wrapfd_close(int fd) { + if (fd >= 0 && fd <= IOWRAP_MAXFD && wrap_fds[fd].mode != UNUSED) { + wrapfd_remove(fd); + return 0; + } else { + return close(fd); + } +} + +int wrapfd_read(int fd, void *out, size_t count) { + size_t maxread; + + if (!fuzz.wrapfds) { + return read(fd, out, count); + } + + if (fd < 0 || fd > IOWRAP_MAXFD || wrap_fds[fd].mode == UNUSED) { + /* XXX - assertion failure? */ + TRACE(("Bad read descriptor %d\n", fd)) + errno = EBADF; + return -1; + } + + assert(count != 0); + + if (wrap_fds[fd].closein || erand48(rand_state) < CHANCE_CLOSE) { + wrap_fds[fd].closein = 1; + errno = ECONNRESET; + return -1; + } + + if (erand48(rand_state) < CHANCE_INTR) { + errno = EINTR; + return -1; + } + + if (input_buf) { + maxread = MIN(input_buf->len - input_buf->pos, count); + /* returns 0 if buf is EOF, as intended */ + if (maxread > 0) { + maxread = nrand48(rand_state) % maxread + 1; + } + memcpy(out, buf_getptr(input_buf, maxread), maxread); + buf_incrpos(input_buf, maxread); + return maxread; + } + + maxread = MIN(MAX_RANDOM_IN, count); + maxread = nrand48(rand_state) % maxread + 1; + memset(out, 0xef, maxread); + return maxread; +} + +int wrapfd_write(int fd, const void* in, size_t count) { + unsigned const volatile char* volin = in; + unsigned int i; + + if (!fuzz.wrapfds) { + return write(fd, in, count); + } + + if (fd < 0 || fd > IOWRAP_MAXFD || wrap_fds[fd].mode == UNUSED) { + /* XXX - assertion failure? */ + TRACE(("Bad read descriptor %d\n", fd)) + errno = EBADF; + return -1; + } + + assert(count != 0); + + /* force read to exercise sanitisers */ + for (i = 0; i < count; i++) { + (void)volin[i]; + } + + if (wrap_fds[fd].closeout || erand48(rand_state) < CHANCE_CLOSE) { + wrap_fds[fd].closeout = 1; + errno = ECONNRESET; + return -1; + } + + if (erand48(rand_state) < CHANCE_INTR) { + errno = EINTR; + return -1; + } + + return nrand48(rand_state) % (count+1); +} + +int wrapfd_select(int nfds, fd_set *readfds, fd_set *writefds, + fd_set *exceptfds, struct timeval *timeout) { + int i, nset, sel; + int ret = 0; + int fdlist[IOWRAP_MAXFD+1]; + + if (!fuzz.wrapfds) { + return select(nfds, readfds, writefds, exceptfds, timeout); + } + + assert(nfds <= IOWRAP_MAXFD+1); + + if (erand48(rand_state) < CHANCE_INTR) { + errno = EINTR; + return -1; + } + + /* read */ + if (readfds != NULL && erand48(rand_state) < CHANCE_READ1) { + for (i = 0, nset = 0; i < nfds; i++) { + if (FD_ISSET(i, readfds)) { + assert(wrap_fds[i].mode != UNUSED); + fdlist[nset] = i; + nset++; + } + } + DROPBEAR_FD_ZERO(readfds); + + if (nset > 0) { + /* set one */ + sel = fdlist[nrand48(rand_state) % nset]; + FD_SET(sel, readfds); + ret++; + + if (erand48(rand_state) < CHANCE_READ2) { + sel = fdlist[nrand48(rand_state) % nset]; + if (!FD_ISSET(sel, readfds)) { + FD_SET(sel, readfds); + ret++; + } + } + } + } + + /* write */ + if (writefds != NULL && erand48(rand_state) < CHANCE_WRITE1) { + for (i = 0, nset = 0; i < nfds; i++) { + if (FD_ISSET(i, writefds)) { + assert(wrap_fds[i].mode != UNUSED); + fdlist[nset] = i; + nset++; + } + } + DROPBEAR_FD_ZERO(writefds); + + /* set one */ + if (nset > 0) { + sel = fdlist[nrand48(rand_state) % nset]; + FD_SET(sel, writefds); + ret++; + + if (erand48(rand_state) < CHANCE_WRITE2) { + sel = fdlist[nrand48(rand_state) % nset]; + if (!FD_ISSET(sel, writefds)) { + FD_SET(sel, writefds); + ret++; + } + } + } + } + return ret; +} + diff -r 064f5be2fc45 -r 4c5599435084 fuzz/fuzzer-client.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fuzz/fuzzer-client.c Sun Oct 25 21:47:42 2020 +0800 @@ -0,0 +1,6 @@ +#include "fuzz.h" + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + return fuzz_run_client(Data, Size, 0); +} + diff -r 064f5be2fc45 -r 4c5599435084 fuzz/fuzzer-client_nomaths.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fuzz/fuzzer-client_nomaths.c Sun Oct 25 21:47:42 2020 +0800 @@ -0,0 +1,6 @@ +#include "fuzz.h" + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + return fuzz_run_client(Data, Size, 1); +} + diff -r 064f5be2fc45 -r 4c5599435084 fuzz/fuzzer-kexcurve25519.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fuzz/fuzzer-kexcurve25519.c Sun Oct 25 21:47:42 2020 +0800 @@ -0,0 +1,72 @@ +#include "fuzz.h" +#include "session.h" +#include "fuzz-wrapfd.h" +#include "debug.h" +#include "runopts.h" +#include "algo.h" +#include "bignum.h" + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + static int once = 0; + static struct key_context* keep_newkeys = NULL; + /* number of generated parameters is limited by the timeout for the first run. + TODO move this to the libfuzzer initialiser function instead if the timeout + doesn't apply there */ + #define NUM_PARAMS 20 + static struct kex_curve25519_param *curve25519_params[NUM_PARAMS]; + + if (!once) { + fuzz_common_setup(); + fuzz_svr_setup(); + + keep_newkeys = (struct key_context*)m_malloc(sizeof(struct key_context)); + keep_newkeys->algo_kex = fuzz_get_algo(sshkex, "curve25519-sha256"); + keep_newkeys->algo_hostkey = DROPBEAR_SIGNKEY_ED25519; + ses.newkeys = keep_newkeys; + + /* Pre-generate parameters */ + int i; + for (i = 0; i < NUM_PARAMS; i++) { + curve25519_params[i] = gen_kexcurve25519_param(); + } + + once = 1; + } + + if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) { + return 0; + } + + m_malloc_set_epoch(1); + + if (setjmp(fuzz.jmp) == 0) { + /* Based on recv_msg_kexdh_init()/send_msg_kexdh_reply() + with DROPBEAR_KEX_CURVE25519 */ + ses.newkeys = keep_newkeys; + + /* Choose from the collection of curve25519 params */ + unsigned int e = buf_getint(fuzz.input); + struct kex_curve25519_param *curve25519_param = curve25519_params[e % NUM_PARAMS]; + + buffer * ecdh_qs = buf_getstringbuf(fuzz.input); + + ses.kexhashbuf = buf_new(KEXHASHBUF_MAX_INTS); + kexcurve25519_comb_key(curve25519_param, ecdh_qs, svr_opts.hostkey); + + mp_clear(ses.dh_K); + m_free(ses.dh_K); + buf_free(ecdh_qs); + + buf_free(ses.hash); + buf_free(ses.session_id); + /* kexhashbuf is freed in kexdh_comb_key */ + + 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 064f5be2fc45 -r 4c5599435084 fuzz/fuzzer-kexdh.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fuzz/fuzzer-kexdh.c Sun Oct 25 21:47:42 2020 +0800 @@ -0,0 +1,76 @@ +#include "fuzz.h" +#include "session.h" +#include "fuzz-wrapfd.h" +#include "debug.h" +#include "runopts.h" +#include "algo.h" +#include "bignum.h" + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + static int once = 0; + static struct key_context* keep_newkeys = NULL; + /* number of generated parameters is limited by the timeout for the first run. + TODO move this to the libfuzzer initialiser function instead if the timeout + doesn't apply there */ + #define NUM_PARAMS 20 + static struct kex_dh_param *dh_params[NUM_PARAMS]; + + if (!once) { + fuzz_common_setup(); + fuzz_svr_setup(); + + keep_newkeys = (struct key_context*)m_malloc(sizeof(struct key_context)); + keep_newkeys->algo_kex = fuzz_get_algo(sshkex, "diffie-hellman-group14-sha256"); + keep_newkeys->algo_hostkey = DROPBEAR_SIGNKEY_ECDSA_NISTP256; + ses.newkeys = keep_newkeys; + + /* Pre-generate parameters */ + int i; + for (i = 0; i < NUM_PARAMS; i++) { + dh_params[i] = gen_kexdh_param(); + } + + once = 1; + } + + if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) { + return 0; + } + + m_malloc_set_epoch(1); + + if (setjmp(fuzz.jmp) == 0) { + /* Based on recv_msg_kexdh_init()/send_msg_kexdh_reply() + with DROPBEAR_KEX_NORMAL_DH */ + ses.newkeys = keep_newkeys; + + /* Choose from the collection of ecdh params */ + unsigned int e = buf_getint(fuzz.input); + struct kex_dh_param * dh_param = dh_params[e % NUM_PARAMS]; + + DEF_MP_INT(dh_e); + m_mp_init(&dh_e); + if (buf_getmpint(fuzz.input, &dh_e) != DROPBEAR_SUCCESS) { + dropbear_exit("Bad kex value"); + } + + ses.kexhashbuf = buf_new(KEXHASHBUF_MAX_INTS); + kexdh_comb_key(dh_param, &dh_e, svr_opts.hostkey); + + mp_clear(ses.dh_K); + m_free(ses.dh_K); + mp_clear(&dh_e); + + buf_free(ses.hash); + buf_free(ses.session_id); + /* kexhashbuf is freed in kexdh_comb_key */ + + 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 064f5be2fc45 -r 4c5599435084 fuzz/fuzzer-kexecdh.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fuzz/fuzzer-kexecdh.c Sun Oct 25 21:47:42 2020 +0800 @@ -0,0 +1,82 @@ +#include "fuzz.h" +#include "session.h" +#include "fuzz-wrapfd.h" +#include "debug.h" +#include "runopts.h" +#include "algo.h" +#include "bignum.h" + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + static int once = 0; + static const struct dropbear_kex *ecdh[3]; /* 256, 384, 521 */ + static struct key_context* keep_newkeys = NULL; + /* number of generated parameters is limited by the timeout for the first run */ + #define NUM_PARAMS 80 + static struct kex_ecdh_param *ecdh_params[NUM_PARAMS]; + + if (!once) { + fuzz_common_setup(); + fuzz_svr_setup(); + + /* ses gets zeroed by fuzz_set_input */ + keep_newkeys = (struct key_context*)m_malloc(sizeof(struct key_context)); + ecdh[0] = fuzz_get_algo(sshkex, "ecdh-sha2-nistp256"); + ecdh[1] = fuzz_get_algo(sshkex, "ecdh-sha2-nistp384"); + ecdh[2] = fuzz_get_algo(sshkex, "ecdh-sha2-nistp521"); + assert(ecdh[0]); + assert(ecdh[1]); + assert(ecdh[2]); + keep_newkeys->algo_hostkey = DROPBEAR_SIGNKEY_ECDSA_NISTP256; + ses.newkeys = keep_newkeys; + + /* Pre-generate parameters */ + int i; + for (i = 0; i < NUM_PARAMS; i++) { + ses.newkeys->algo_kex = ecdh[i % 3]; + ecdh_params[i] = gen_kexecdh_param(); + } + + once = 1; + } + + if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) { + return 0; + } + + m_malloc_set_epoch(1); + + if (setjmp(fuzz.jmp) == 0) { + /* Based on recv_msg_kexdh_init()/send_msg_kexdh_reply() + with DROPBEAR_KEX_ECDH */ + ses.newkeys = keep_newkeys; + + /* random choice of ecdh 256, 384, 521 */ + unsigned char b = buf_getbyte(fuzz.input); + ses.newkeys->algo_kex = ecdh[b % 3]; + + /* Choose from the collection of ecdh params */ + unsigned int e = buf_getint(fuzz.input); + struct kex_ecdh_param *ecdh_param = ecdh_params[e % NUM_PARAMS]; + + buffer * ecdh_qs = buf_getstringbuf(fuzz.input); + + ses.kexhashbuf = buf_new(KEXHASHBUF_MAX_INTS); + kexecdh_comb_key(ecdh_param, ecdh_qs, svr_opts.hostkey); + + mp_clear(ses.dh_K); + m_free(ses.dh_K); + buf_free(ecdh_qs); + + buf_free(ses.hash); + buf_free(ses.session_id); + /* kexhashbuf is freed in kexdh_comb_key */ + + 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 064f5be2fc45 -r 4c5599435084 fuzz/fuzzer-preauth.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fuzz/fuzzer-preauth.c Sun Oct 25 21:47:42 2020 +0800 @@ -0,0 +1,6 @@ +#include "fuzz.h" + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + return fuzz_run_preauth(Data, Size, 0); +} + diff -r 064f5be2fc45 -r 4c5599435084 fuzz/fuzzer-preauth_nomaths.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fuzz/fuzzer-preauth_nomaths.c Sun Oct 25 21:47:42 2020 +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 064f5be2fc45 -r 4c5599435084 fuzz/fuzzer-pubkey.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fuzz/fuzzer-pubkey.c Sun Oct 25 21:47:42 2020 +0800 @@ -0,0 +1,54 @@ +#include "fuzz.h" +#include "session.h" +#include "fuzz-wrapfd.h" +#include "debug.h" + +static void setup_fuzzer(void) { + fuzz_common_setup(); +} + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + static int once = 0; + if (!once) { + setup_fuzzer(); + once = 1; + } + + if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) { + return 0; + } + + m_malloc_set_epoch(1); + + if (setjmp(fuzz.jmp) == 0) { + buffer *line = buf_getstringbuf(fuzz.input); + buffer *keyblob = buf_getstringbuf(fuzz.input); + + unsigned int algolen; + char* algoname = buf_getstring(keyblob, &algolen); + + if (signature_type_from_name(algoname, algolen) == DROPBEAR_SIGNKEY_NONE) { + dropbear_exit("fuzzer imagined a bogus algorithm"); + } + + int ret = fuzz_checkpubkey_line(line, 5, "/home/me/authorized_keys", + algoname, algolen, + keyblob->data, keyblob->len); + + if (ret == DROPBEAR_SUCCESS) { + /* fuzz_checkpubkey_line() should have cleaned up for failure */ + svr_pubkey_options_cleanup(); + } + + buf_free(line); + buf_free(keyblob); + m_free(algoname); + 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 064f5be2fc45 -r 4c5599435084 fuzz/fuzzer-verify.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fuzz/fuzzer-verify.c Sun Oct 25 21:47:42 2020 +0800 @@ -0,0 +1,79 @@ +#include "fuzz.h" +#include "session.h" +#include "fuzz-wrapfd.h" +#include "debug.h" +#include "dss.h" + +static void setup_fuzzer(void) { + fuzz_common_setup(); +} + +static buffer *verifydata; + +/* Tests reading a public key and verifying a signature */ +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + static int once = 0; + if (!once) { + setup_fuzzer(); + verifydata = buf_new(30); + buf_putstring(verifydata, "x", 1); + once = 1; + } + + if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) { + return 0; + } + + m_malloc_set_epoch(1); + + if (setjmp(fuzz.jmp) == 0) { + sign_key *key = new_sign_key(); + enum signkey_type keytype = DROPBEAR_SIGNKEY_ANY; + if (buf_get_pub_key(fuzz.input, key, &keytype) == DROPBEAR_SUCCESS) { + enum signature_type sigtype; + if (keytype == DROPBEAR_SIGNKEY_RSA) { + /* Flip a coin to decide rsa signature type */ + int flag = buf_getbyte(fuzz.input); + if (flag & 0x01) { + sigtype = DROPBEAR_SIGNATURE_RSA_SHA256; + } else { + sigtype = DROPBEAR_SIGNATURE_RSA_SHA1; + } + } else { + sigtype = signature_type_from_signkey(keytype); + } + if (buf_verify(fuzz.input, key, sigtype, verifydata) == DROPBEAR_SUCCESS) { + /* The fuzzer is capable of generating keys with a signature to match. + We don't want false positives if the key is bogus, since a client/server + wouldn't be trusting a bogus key anyway */ + int boguskey = 0; + + if (keytype == DROPBEAR_SIGNKEY_DSS) { + /* So far have seen dss keys with bad p/q/g domain parameters */ + int pprime, qprime, trials; + trials = mp_prime_rabin_miller_trials(mp_count_bits(key->dsskey->p)); + assert(mp_prime_is_prime(key->dsskey->p, trials, &pprime) == MP_OKAY); + trials = mp_prime_rabin_miller_trials(mp_count_bits(key->dsskey->q)); + assert(mp_prime_is_prime(key->dsskey->q, trials, &qprime) == MP_OKAY); + boguskey = !(pprime && qprime); + /* Could also check g**q mod p == 1 */ + } + + if (!boguskey) { + printf("Random key/signature managed to verify!\n"); + abort(); + } + + + } + } + sign_key_free(key); + 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 064f5be2fc45 -r 4c5599435084 fuzzer-client.c --- a/fuzzer-client.c Sat Oct 24 18:56:45 2020 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -#include "fuzz.h" - -int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { - return fuzz_run_client(Data, Size, 0); -} - diff -r 064f5be2fc45 -r 4c5599435084 fuzzer-client_nomaths.c --- a/fuzzer-client_nomaths.c Sat Oct 24 18:56:45 2020 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -#include "fuzz.h" - -int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { - return fuzz_run_client(Data, Size, 1); -} - diff -r 064f5be2fc45 -r 4c5599435084 fuzzer-kexcurve25519.c --- a/fuzzer-kexcurve25519.c Sat Oct 24 18:56:45 2020 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -#include "fuzz.h" -#include "session.h" -#include "fuzz-wrapfd.h" -#include "debug.h" -#include "runopts.h" -#include "algo.h" -#include "bignum.h" - -int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { - static int once = 0; - static struct key_context* keep_newkeys = NULL; - /* number of generated parameters is limited by the timeout for the first run. - TODO move this to the libfuzzer initialiser function instead if the timeout - doesn't apply there */ - #define NUM_PARAMS 20 - static struct kex_curve25519_param *curve25519_params[NUM_PARAMS]; - - if (!once) { - fuzz_common_setup(); - fuzz_svr_setup(); - - keep_newkeys = (struct key_context*)m_malloc(sizeof(struct key_context)); - keep_newkeys->algo_kex = fuzz_get_algo(sshkex, "curve25519-sha256"); - keep_newkeys->algo_hostkey = DROPBEAR_SIGNKEY_ED25519; - ses.newkeys = keep_newkeys; - - /* Pre-generate parameters */ - int i; - for (i = 0; i < NUM_PARAMS; i++) { - curve25519_params[i] = gen_kexcurve25519_param(); - } - - once = 1; - } - - if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) { - return 0; - } - - m_malloc_set_epoch(1); - - if (setjmp(fuzz.jmp) == 0) { - /* Based on recv_msg_kexdh_init()/send_msg_kexdh_reply() - with DROPBEAR_KEX_CURVE25519 */ - ses.newkeys = keep_newkeys; - - /* Choose from the collection of curve25519 params */ - unsigned int e = buf_getint(fuzz.input); - struct kex_curve25519_param *curve25519_param = curve25519_params[e % NUM_PARAMS]; - - buffer * ecdh_qs = buf_getstringbuf(fuzz.input); - - ses.kexhashbuf = buf_new(KEXHASHBUF_MAX_INTS); - kexcurve25519_comb_key(curve25519_param, ecdh_qs, svr_opts.hostkey); - - mp_clear(ses.dh_K); - m_free(ses.dh_K); - buf_free(ecdh_qs); - - buf_free(ses.hash); - buf_free(ses.session_id); - /* kexhashbuf is freed in kexdh_comb_key */ - - 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 064f5be2fc45 -r 4c5599435084 fuzzer-kexdh.c --- a/fuzzer-kexdh.c Sat Oct 24 18:56:45 2020 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -#include "fuzz.h" -#include "session.h" -#include "fuzz-wrapfd.h" -#include "debug.h" -#include "runopts.h" -#include "algo.h" -#include "bignum.h" - -int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { - static int once = 0; - static struct key_context* keep_newkeys = NULL; - /* number of generated parameters is limited by the timeout for the first run. - TODO move this to the libfuzzer initialiser function instead if the timeout - doesn't apply there */ - #define NUM_PARAMS 20 - static struct kex_dh_param *dh_params[NUM_PARAMS]; - - if (!once) { - fuzz_common_setup(); - fuzz_svr_setup(); - - keep_newkeys = (struct key_context*)m_malloc(sizeof(struct key_context)); - keep_newkeys->algo_kex = fuzz_get_algo(sshkex, "diffie-hellman-group14-sha256"); - keep_newkeys->algo_hostkey = DROPBEAR_SIGNKEY_ECDSA_NISTP256; - ses.newkeys = keep_newkeys; - - /* Pre-generate parameters */ - int i; - for (i = 0; i < NUM_PARAMS; i++) { - dh_params[i] = gen_kexdh_param(); - } - - once = 1; - } - - if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) { - return 0; - } - - m_malloc_set_epoch(1); - - if (setjmp(fuzz.jmp) == 0) { - /* Based on recv_msg_kexdh_init()/send_msg_kexdh_reply() - with DROPBEAR_KEX_NORMAL_DH */ - ses.newkeys = keep_newkeys; - - /* Choose from the collection of ecdh params */ - unsigned int e = buf_getint(fuzz.input); - struct kex_dh_param * dh_param = dh_params[e % NUM_PARAMS]; - - DEF_MP_INT(dh_e); - m_mp_init(&dh_e); - if (buf_getmpint(fuzz.input, &dh_e) != DROPBEAR_SUCCESS) { - dropbear_exit("Bad kex value"); - } - - ses.kexhashbuf = buf_new(KEXHASHBUF_MAX_INTS); - kexdh_comb_key(dh_param, &dh_e, svr_opts.hostkey); - - mp_clear(ses.dh_K); - m_free(ses.dh_K); - mp_clear(&dh_e); - - buf_free(ses.hash); - buf_free(ses.session_id); - /* kexhashbuf is freed in kexdh_comb_key */ - - 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 064f5be2fc45 -r 4c5599435084 fuzzer-kexecdh.c --- a/fuzzer-kexecdh.c Sat Oct 24 18:56:45 2020 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -#include "fuzz.h" -#include "session.h" -#include "fuzz-wrapfd.h" -#include "debug.h" -#include "runopts.h" -#include "algo.h" -#include "bignum.h" - -int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { - static int once = 0; - static const struct dropbear_kex *ecdh[3]; /* 256, 384, 521 */ - static struct key_context* keep_newkeys = NULL; - /* number of generated parameters is limited by the timeout for the first run */ - #define NUM_PARAMS 80 - static struct kex_ecdh_param *ecdh_params[NUM_PARAMS]; - - if (!once) { - fuzz_common_setup(); - fuzz_svr_setup(); - - /* ses gets zeroed by fuzz_set_input */ - keep_newkeys = (struct key_context*)m_malloc(sizeof(struct key_context)); - ecdh[0] = fuzz_get_algo(sshkex, "ecdh-sha2-nistp256"); - ecdh[1] = fuzz_get_algo(sshkex, "ecdh-sha2-nistp384"); - ecdh[2] = fuzz_get_algo(sshkex, "ecdh-sha2-nistp521"); - assert(ecdh[0]); - assert(ecdh[1]); - assert(ecdh[2]); - keep_newkeys->algo_hostkey = DROPBEAR_SIGNKEY_ECDSA_NISTP256; - ses.newkeys = keep_newkeys; - - /* Pre-generate parameters */ - int i; - for (i = 0; i < NUM_PARAMS; i++) { - ses.newkeys->algo_kex = ecdh[i % 3]; - ecdh_params[i] = gen_kexecdh_param(); - } - - once = 1; - } - - if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) { - return 0; - } - - m_malloc_set_epoch(1); - - if (setjmp(fuzz.jmp) == 0) { - /* Based on recv_msg_kexdh_init()/send_msg_kexdh_reply() - with DROPBEAR_KEX_ECDH */ - ses.newkeys = keep_newkeys; - - /* random choice of ecdh 256, 384, 521 */ - unsigned char b = buf_getbyte(fuzz.input); - ses.newkeys->algo_kex = ecdh[b % 3]; - - /* Choose from the collection of ecdh params */ - unsigned int e = buf_getint(fuzz.input); - struct kex_ecdh_param *ecdh_param = ecdh_params[e % NUM_PARAMS]; - - buffer * ecdh_qs = buf_getstringbuf(fuzz.input); - - ses.kexhashbuf = buf_new(KEXHASHBUF_MAX_INTS); - kexecdh_comb_key(ecdh_param, ecdh_qs, svr_opts.hostkey); - - mp_clear(ses.dh_K); - m_free(ses.dh_K); - buf_free(ecdh_qs); - - buf_free(ses.hash); - buf_free(ses.session_id); - /* kexhashbuf is freed in kexdh_comb_key */ - - 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 064f5be2fc45 -r 4c5599435084 fuzzer-preauth.c --- a/fuzzer-preauth.c Sat Oct 24 18:56:45 2020 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -#include "fuzz.h" - -int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { - return fuzz_run_preauth(Data, Size, 0); -} - diff -r 064f5be2fc45 -r 4c5599435084 fuzzer-preauth_nomaths.c --- a/fuzzer-preauth_nomaths.c Sat Oct 24 18:56:45 2020 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -#include "fuzz.h" - -int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { - return fuzz_run_preauth(Data, Size, 1); -} - diff -r 064f5be2fc45 -r 4c5599435084 fuzzer-pubkey.c --- a/fuzzer-pubkey.c Sat Oct 24 18:56:45 2020 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -#include "fuzz.h" -#include "session.h" -#include "fuzz-wrapfd.h" -#include "debug.h" - -static void setup_fuzzer(void) { - fuzz_common_setup(); -} - -int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { - static int once = 0; - if (!once) { - setup_fuzzer(); - once = 1; - } - - if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) { - return 0; - } - - m_malloc_set_epoch(1); - - if (setjmp(fuzz.jmp) == 0) { - buffer *line = buf_getstringbuf(fuzz.input); - buffer *keyblob = buf_getstringbuf(fuzz.input); - - unsigned int algolen; - char* algoname = buf_getstring(keyblob, &algolen); - - if (signature_type_from_name(algoname, algolen) == DROPBEAR_SIGNKEY_NONE) { - dropbear_exit("fuzzer imagined a bogus algorithm"); - } - - int ret = fuzz_checkpubkey_line(line, 5, "/home/me/authorized_keys", - algoname, algolen, - keyblob->data, keyblob->len); - - if (ret == DROPBEAR_SUCCESS) { - /* fuzz_checkpubkey_line() should have cleaned up for failure */ - svr_pubkey_options_cleanup(); - } - - buf_free(line); - buf_free(keyblob); - m_free(algoname); - 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 064f5be2fc45 -r 4c5599435084 fuzzer-verify.c --- a/fuzzer-verify.c Sat Oct 24 18:56:45 2020 +0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -#include "fuzz.h" -#include "session.h" -#include "fuzz-wrapfd.h" -#include "debug.h" -#include "dss.h" - -static void setup_fuzzer(void) { - fuzz_common_setup(); -} - -static buffer *verifydata; - -/* Tests reading a public key and verifying a signature */ -int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { - static int once = 0; - if (!once) { - setup_fuzzer(); - verifydata = buf_new(30); - buf_putstring(verifydata, "x", 1); - once = 1; - } - - if (fuzz_set_input(Data, Size) == DROPBEAR_FAILURE) { - return 0; - } - - m_malloc_set_epoch(1); - - if (setjmp(fuzz.jmp) == 0) { - sign_key *key = new_sign_key(); - enum signkey_type keytype = DROPBEAR_SIGNKEY_ANY; - if (buf_get_pub_key(fuzz.input, key, &keytype) == DROPBEAR_SUCCESS) { - enum signature_type sigtype; - if (keytype == DROPBEAR_SIGNKEY_RSA) { - /* Flip a coin to decide rsa signature type */ - int flag = buf_getbyte(fuzz.input); - if (flag & 0x01) { - sigtype = DROPBEAR_SIGNATURE_RSA_SHA256; - } else { - sigtype = DROPBEAR_SIGNATURE_RSA_SHA1; - } - } else { - sigtype = signature_type_from_signkey(keytype); - } - if (buf_verify(fuzz.input, key, sigtype, verifydata) == DROPBEAR_SUCCESS) { - /* The fuzzer is capable of generating keys with a signature to match. - We don't want false positives if the key is bogus, since a client/server - wouldn't be trusting a bogus key anyway */ - int boguskey = 0; - - if (keytype == DROPBEAR_SIGNKEY_DSS) { - /* So far have seen dss keys with bad p/q/g domain parameters */ - int pprime, qprime, trials; - trials = mp_prime_rabin_miller_trials(mp_count_bits(key->dsskey->p)); - assert(mp_prime_is_prime(key->dsskey->p, trials, &pprime) == MP_OKAY); - trials = mp_prime_rabin_miller_trials(mp_count_bits(key->dsskey->q)); - assert(mp_prime_is_prime(key->dsskey->q, trials, &qprime) == MP_OKAY); - boguskey = !(pprime && qprime); - /* Could also check g**q mod p == 1 */ - } - - if (!boguskey) { - printf("Random key/signature managed to verify!\n"); - abort(); - } - - - } - } - sign_key_free(key); - m_malloc_free_epoch(1, 0); - } else { - m_malloc_free_epoch(1, 1); - TRACE(("dropbear_exit longjmped")) - /* dropbear_exit jumped here */ - } - - return 0; -}