From ec9d22cc251cc5acfe7b2bcef9cc7a1fe0e949d8 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Fri, 8 Sep 2017 12:44:13 +1000 Subject: Fuzzer harnesses for sig verify and pubkey parsing These are some basic clang libfuzzer harnesses for signature verification and public key parsing. Some assembly (metaphorical) required. --- .gitignore | 1 + regress/misc/fuzz-harness/Makefile | 22 ++++++++++++++ regress/misc/fuzz-harness/README | 1 + regress/misc/fuzz-harness/pubkey_fuzz.cc | 18 ++++++++++++ regress/misc/fuzz-harness/sig_fuzz.cc | 50 ++++++++++++++++++++++++++++++++ 5 files changed, 92 insertions(+) create mode 100644 regress/misc/fuzz-harness/Makefile create mode 100644 regress/misc/fuzz-harness/README create mode 100644 regress/misc/fuzz-harness/pubkey_fuzz.cc create mode 100644 regress/misc/fuzz-harness/sig_fuzz.cc diff --git a/.gitignore b/.gitignore index e25a8302..650eb3c3 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,4 @@ ssh-keyscan ssh-keysign ssh-pkcs11-helper sshd +!regress/misc/fuzz-harness/Makefile diff --git a/regress/misc/fuzz-harness/Makefile b/regress/misc/fuzz-harness/Makefile new file mode 100644 index 00000000..8fbfc20c --- /dev/null +++ b/regress/misc/fuzz-harness/Makefile @@ -0,0 +1,22 @@ +# NB. libssh and libopenbsd-compat should be built with the same sanitizer opts. +CXX=clang++-3.9 +FUZZ_FLAGS=-fsanitize=address,undefined -fsanitize-coverage=edge +FUZZ_LIBS=-lFuzzer + +CXXFLAGS=-O2 -g -Wall -Wextra -I ../../.. $(FUZZ_FLAGS) +LDFLAGS=-L ../../.. -L ../../../openbsd-compat -g $(FUZZ_FLAGS) +LIBS=-lssh -lopenbsd-compat -lcrypto $(FUZZ_LIBS) + +all: pubkey_fuzz sig_fuzz + +.cc.o: + $(CXX) $(CXXFLAGS) -c $< -o $@ + +pubkey_fuzz: pubkey_fuzz.o + $(CXX) -o $@ pubkey_fuzz.o $(LDFLAGS) $(LIBS) + +sig_fuzz: sig_fuzz.o + $(CXX) -o $@ sig_fuzz.o $(LDFLAGS) $(LIBS) + +clean: + -rm -f *.o pubkey_fuzz sig_fuzz diff --git a/regress/misc/fuzz-harness/README b/regress/misc/fuzz-harness/README new file mode 100644 index 00000000..ae6fbe75 --- /dev/null +++ b/regress/misc/fuzz-harness/README @@ -0,0 +1 @@ +This directory contains fuzzing harnesses for use with clang's libfuzzer. diff --git a/regress/misc/fuzz-harness/pubkey_fuzz.cc b/regress/misc/fuzz-harness/pubkey_fuzz.cc new file mode 100644 index 00000000..8bbc1109 --- /dev/null +++ b/regress/misc/fuzz-harness/pubkey_fuzz.cc @@ -0,0 +1,18 @@ +#include +#include +#include + +extern "C" { + +#include "sshkey.h" + +int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + struct sshkey *k = NULL; + int r = sshkey_from_blob(data, size, &k); + if (r == 0) sshkey_free(k); + return 0; +} + +} // extern + diff --git a/regress/misc/fuzz-harness/sig_fuzz.cc b/regress/misc/fuzz-harness/sig_fuzz.cc new file mode 100644 index 00000000..0e535b49 --- /dev/null +++ b/regress/misc/fuzz-harness/sig_fuzz.cc @@ -0,0 +1,50 @@ +// cc_fuzz_target test for public key parsing. + +#include +#include +#include +#include +#include + +extern "C" { + +#include "includes.h" +#include "sshkey.h" +#include "ssherr.h" + +static struct sshkey *generate_or_die(int type, unsigned bits) { + int r; + struct sshkey *ret; + if ((r = sshkey_generate(type, bits, &ret)) != 0) { + fprintf(stderr, "generate(%d, %u): %s", type, bits, ssh_err(r)); + abort(); + } + return ret; +} + +int LLVMFuzzerTestOneInput(const uint8_t* sig, size_t slen) +{ +#ifdef WITH_OPENSSL + static struct sshkey *rsa = generate_or_die(KEY_RSA, 2048); + static struct sshkey *dsa = generate_or_die(KEY_DSA, 1024); + static struct sshkey *ecdsa256 = generate_or_die(KEY_ECDSA, 256); + static struct sshkey *ecdsa384 = generate_or_die(KEY_ECDSA, 384); + static struct sshkey *ecdsa521 = generate_or_die(KEY_ECDSA, 521); +#endif + static struct sshkey *ed25519 = generate_or_die(KEY_ED25519, 0); + static const char *data = "If everyone started announcing his nose had " + "run away, I don’t know how it would all end"; + static const size_t dlen = strlen(data); + +#ifdef WITH_OPENSSL + sshkey_verify(rsa, sig, slen, (const u_char *)data, dlen, 0); + sshkey_verify(dsa, sig, slen, (const u_char *)data, dlen, 0); + sshkey_verify(ecdsa256, sig, slen, (const u_char *)data, dlen, 0); + sshkey_verify(ecdsa384, sig, slen, (const u_char *)data, dlen, 0); + sshkey_verify(ecdsa521, sig, slen, (const u_char *)data, dlen, 0); +#endif + sshkey_verify(ed25519, sig, slen, (const u_char *)data, dlen, 0); + return 0; +} + +} // extern -- cgit v1.2.3