Skip to content

Commit

Permalink
fuzz harness
Browse files Browse the repository at this point in the history
--HG--
branch : fuzz
  • Loading branch information
mkj committed May 13, 2017
1 parent 9f24cdf commit fb719e3
Show file tree
Hide file tree
Showing 13 changed files with 191 additions and 94 deletions.
2 changes: 2 additions & 0 deletions .hgignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.*\.o
.*~
25 changes: 22 additions & 3 deletions Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ COMMONOBJS=dbutil.o buffer.o dbhelpers.o \
queue.o \
atomicio.o compat.o fake-rfc2553.o \
ltc_prng.o ecc.o ecdsa.o crypto_desc.o \
gensignkey.o gendss.o genrsa.o
gensignkey.o gendss.o genrsa.o fuzz-common.o

SVROBJS=svr-kex.o svr-auth.o sshpty.o \
svr-authpasswd.o svr-authpubkey.o svr-authpubkeyoptions.o svr-session.o svr-service.o \
Expand Down Expand Up @@ -224,8 +224,27 @@ distclean: clean tidy
tidy:
-rm -f *~ *.gcov */*~

# run this manually for fuzzing. hostkeys.c is checked in.
hostkeys:
## Fuzzing targets

# exclude svr-main.o to avoid duplicate main
svrfuzzobjs=$(subst svr-main.o, ,$(dropbearobjs))
CLANG=clang

# fuzzers that don't use libfuzzer, just a standalone harness that feeds inputs
fuzzstandalone: LIBS+=fuzz-harness.o
fuzzstandalone: fuzz-harness.o fuzzers

# build all the fuzzers. This will require fail to link unless built with
# make fuzzers LIBS=-lFuzzer.a
# or similar - the library provides main().
fuzzers: fuzzer-preauth

fuzzer-preauth: fuzzer-preauth.o $(HEADERS) $(LIBTOM_DEPS) Makefile $(svrfuzzobjs)
$(CC) $@.o $(LDFLAGS) $(svrfuzzobjs) -o $@$(EXEEXT) $(LIBTOM_LIBS) $(LIBS) @CRYPTLIB@

# run this to update hardcoded hostkeys for for fuzzing.
# hostkeys.c is checked in to hg.
fuzz-hostkeys:
dropbearkey -t rsa -f keyr
dropbearkey -t dss -f keyd
dropbearkey -t ecdsa -size 256 -f keye
Expand Down
7 changes: 4 additions & 3 deletions dbrandom.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "bignum.h"
#include "dbrandom.h"
#include "runopts.h"
#include "fuzz.h"


/* this is used to generate unique output from the same hashpool */
Expand Down Expand Up @@ -147,7 +148,7 @@ void addrandom(unsigned char * buf, unsigned int len)
hash_state hs;

#ifdef DROPBEAR_FUZZ
if (opts.fuzz.fuzzing || opts.fuzz.recordf) {
if (fuzz.fuzzing || fuzz.recordf) {
return;
}
#endif
Expand All @@ -165,7 +166,7 @@ void addrandom(unsigned char * buf, unsigned int len)
static void write_urandom()
{
#ifdef DROPBEAR_FUZZ
if (opts.fuzz.fuzzing || opts.fuzz.recordf) {
if (fuzz.fuzzing || fuzz.recordf) {
return;
}
#endif
Expand Down Expand Up @@ -203,7 +204,7 @@ void seedrandom() {
clock_t clockval;

#ifdef DROPBEAR_FUZZ
if (opts.fuzz.fuzzing || opts.fuzz.recordf) {
if (fuzz.fuzzing || fuzz.recordf) {
seedfuzz();
return;
}
Expand Down
78 changes: 78 additions & 0 deletions fuzz-common.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#include "includes.h"

#ifdef DROPBEAR_FUZZ

#include "includes.h"
#include "fuzz.h"
#include "dbutil.h"
#include "runopts.h"

struct dropbear_fuzz_options fuzz;

static void load_fixed_hostkeys(void);

static void common_setup_fuzzer(void) {
fuzz.fuzzing = 1;
}

void svr_setup_fuzzer(void) {
struct passwd *pw;

common_setup_fuzzer();

char *argv[] = {
"-E",
};

int argc = sizeof(argv) / sizeof(*argv);
svr_getopts(argc, argv);

/* user lookups might be slow, cache it */
pw = getpwuid(getuid());
dropbear_assert(pw);
fuzz.pw_name = m_strdup(pw->pw_name);
fuzz.pw_dir = m_strdup(pw->pw_dir);
fuzz.pw_shell = m_strdup(pw->pw_shell);
fuzz.pw_passwd = m_strdup("!!zzznope");

load_fixed_hostkeys();
}

static void load_fixed_hostkeys(void) {
#include "fuzz-hostkeys.c"

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_free(b);
}

#endif /* DROPBEAR_FUZZ */
8 changes: 8 additions & 0 deletions fuzz-harness.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#include "includes.h"

extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size);

int main(int argc, char ** argv) {
LLVMFuzzerTestOneInput("hello", 5);
return 0;
}
File renamed without changes.
35 changes: 35 additions & 0 deletions fuzz.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#ifndef DROPBEAR_FUZZ_H
#define DROPBEAR_FUZZ_H

#include "includes.h"
#include "buffer.h"

#ifdef DROPBEAR_FUZZ

void svr_setup_fuzzer(void);

struct dropbear_fuzz_options {
int fuzzing;

// to record an unencrypted stream
FILE* recordf;

// fuzzing input
buffer input;

// dropbear_exit() jumps back
sigjmp_buf jmp;

uid_t pw_uid;
gid_t pw_gid;
char* pw_name;
char* pw_dir;
char* pw_shell;
char* pw_passwd;
};

extern struct dropbear_fuzz_options fuzz;

#endif

#endif /* DROPBEAR_FUZZ_H */
31 changes: 31 additions & 0 deletions fuzzer-preauth.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include "fuzz.h"
#include "dbrandom.h"
#include "session.h"

static int setup_fuzzer(void) {
svr_setup_fuzzer();
return 0;
}

int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
static int once = 0;
if (!once) {
setup_fuzzer();
once = 1;
}

fuzz.input.data = (unsigned char*)Data;
fuzz.input.size = Size;
fuzz.input.len = Size;
fuzz.input.pos = 0;

seedrandom();

if (setjmp(fuzz.jmp) == 0) {
svr_session(-1, -1);
} else {
// dropbear_exit jumped here
}

return 0;
}
3 changes: 2 additions & 1 deletion packet.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "channel.h"
#include "netio.h"
#include "runopts.h"
#include "fuzz.h"

static int read_packet_init(void);
static void make_mac(unsigned int seqno, const struct key_context_directional * key_state,
Expand Down Expand Up @@ -78,7 +79,7 @@ void write_packet() {
calls write_packet() without bothering to test with select() since
it's likely to be necessary */
#ifdef DROPBEAR_FUZZ
if (opts.fuzz.fuzzing) {
if (fuzz.fuzzing) {
// pretend to write one packet at a time
// TODO(fuzz): randomise amount written based on the fuzz input
written = iov[0].iov_len;
Expand Down
23 changes: 0 additions & 23 deletions runopts.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,29 +58,6 @@ typedef struct runopts {
char *mac_list;
#endif

#ifdef DROPBEAR_FUZZ
struct {
int fuzzing;

// to record an unencrypted stream
FILE* recordf;

// fuzzing input
buffer *input;

// dropbear_exit() jumps back
sigjmp_buf jmp;

uid_t pw_uid;
gid_t pw_gid;
char* pw_name;
char* pw_dir;
char* pw_shell;
char* pw_passwd;

} fuzz;
#endif

} runopts;

extern runopts opts;
Expand Down
2 changes: 1 addition & 1 deletion svr-auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ void send_msg_userauth_failure(int partial, int incrfail) {
/* We delay for 300ms +- 50ms */
delay = 250000 + (delay % 100000);
#ifndef DROPBEAR_FUZZ
if (!opts.fuzz.fuzzing) {
if (!fuzz.fuzzing) {
usleep(delay);
}
#endif
Expand Down
58 changes: 0 additions & 58 deletions svr-runopts.c
Original file line number Diff line number Diff line change
Expand Up @@ -346,19 +346,6 @@ void svr_getopts(int argc, char ** argv) {
}
opts.idle_timeout_secs = val;
}

#ifdef DROPBEAR_FUZZ
if (opts.fuzz.fuzzing) {
struct passwd *pw;
/* user lookups might be slow, cache it */
pw = getpwuid(getuid());
dropbear_assert(pw);
opts.fuzz.pw_name = m_strdup(pw->pw_name);
opts.fuzz.pw_dir = m_strdup(pw->pw_dir);
opts.fuzz.pw_shell = m_strdup(pw->pw_shell);
opts.fuzz.pw_passwd = m_strdup("!!zzznope");
}
#endif
}

static void addportandaddress(const char* spec) {
Expand Down Expand Up @@ -488,57 +475,12 @@ static void addhostkey(const char *keyfile) {
svr_opts.num_hostkey_files++;
}

#ifdef DROPBEAR_FUZZ
static void load_fixed_hostkeys() {
#include "hostkeys.c"

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_free(b);
}
#endif // DROPBEAR_FUZZ

void load_all_hostkeys() {
int i;
int disable_unset_keys = 1;
int any_keys = 0;

#ifdef DROPBEAR_FUZZ
if (opts.fuzz.fuzzing) {
load_fixed_hostkeys();
return;
}
#endif

svr_opts.hostkey = new_sign_key();

for (i = 0; i < svr_opts.num_hostkey_files; i++) {
Expand Down
Loading

0 comments on commit fb719e3

Please sign in to comment.