]> git.ipfire.org Git - thirdparty/openssh-portable.git/commitdiff
Fuzzer harnesses for sig verify and pubkey parsing
authorDamien Miller <djm@mindrot.org>
Fri, 8 Sep 2017 02:44:13 +0000 (12:44 +1000)
committerDamien Miller <djm@mindrot.org>
Fri, 8 Sep 2017 02:44:13 +0000 (12:44 +1000)
These are some basic clang libfuzzer harnesses for signature
verification and public key parsing. Some assembly (metaphorical)
required.

.gitignore
regress/misc/fuzz-harness/Makefile [new file with mode: 0644]
regress/misc/fuzz-harness/README [new file with mode: 0644]
regress/misc/fuzz-harness/pubkey_fuzz.cc [new file with mode: 0644]
regress/misc/fuzz-harness/sig_fuzz.cc [new file with mode: 0644]

index e25a83025154d57118cdac34169057f4cbdc3d9d..650eb3c3c90c3702641a6a71a5f233aea474c5c5 100644 (file)
@@ -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 (file)
index 0000000..8fbfc20
--- /dev/null
@@ -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 (file)
index 0000000..ae6fbe7
--- /dev/null
@@ -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 (file)
index 0000000..8bbc110
--- /dev/null
@@ -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 (file)
index 0000000..0e535b4
--- /dev/null
@@ -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