summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2017-09-08 12:44:13 +1000
committerDamien Miller <djm@mindrot.org>2017-09-08 12:44:13 +1000
commitec9d22cc251cc5acfe7b2bcef9cc7a1fe0e949d8 (patch)
treed6dd817fd7bf3a02bbcb14e3d536590c0fcefac1
parentde35c382894964a896a63ecd5607d3a3b93af75d (diff)
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.
-rw-r--r--.gitignore1
-rw-r--r--regress/misc/fuzz-harness/Makefile22
-rw-r--r--regress/misc/fuzz-harness/README1
-rw-r--r--regress/misc/fuzz-harness/pubkey_fuzz.cc18
-rw-r--r--regress/misc/fuzz-harness/sig_fuzz.cc50
5 files changed, 92 insertions, 0 deletions
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 <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+
+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 <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+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