Commit c38bb727 authored by Ben Laurie's avatar Ben Laurie
Browse files

Add fuzzing!

parent 049f5bbc
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -57,6 +57,14 @@ Makefile

# Executables
/apps/openssl
/fuzz/asn1
/fuzz/asn1parse
/fuzz/bignum
/fuzz/bndiv
/fuzz/conf
/fuzz/cms
/fuzz/server
/fuzz/x509
/test/sha256t
/test/sha512t
/test/gost2814789t
+24 −0
Original line number Diff line number Diff line
@@ -266,6 +266,7 @@ my @dtls = qw(dtls1 dtls1_2);

my @disablables = (
    "afalgeng",
    "asan",
    "asm",
    "async",
    "autoalginit",
@@ -299,6 +300,7 @@ my @disablables = (
    "engine",
    "err",
    "filenames",
    "fuzz",
    "gost",
    "heartbeats",
    "hw(-.+)?",
@@ -337,6 +339,7 @@ my @disablables = (
    "threads",
    "tls",
    "ts",
    "ubsan",
    "ui",
    "unit-test",
    "whirlpool",
@@ -357,14 +360,17 @@ my @deprecated_disablables = (
# All of the following is disabled by default (RC5 was enabled before 0.9.8):

our %disabled = ( # "what"         => "comment"
                  "asan"		=> "default",
		  "ec_nistp_64_gcc_128" => "default",
		  "egd"                 => "default",
		  "fuzz"		=> "default",
		  "md2"                 => "default",
		  "rc5"                 => "default",
		  "sctp"                => "default",
		  "ssl-trace"           => "default",
		  "ssl3"                => "default",
		  "ssl3-method"         => "default",
                  "ubsan"		=> "default",
		  "unit-test"           => "default",
		  "weak-ssl-ciphers"    => "default",
		  "zlib"                => "default",
@@ -1029,6 +1035,24 @@ if ($disabled{"dynamic-engine"}) {
        $config{dynamic_engines} = 1;
}

unless ($disabled{fuzz}) {
    push $config{dirs}, "fuzz";
    $config{cflags} .= "-fsanitize-coverage=edge,indirect-calls ";
}

unless ($disabled{asan}) {
    $config{cflags} .= "-fsanitize=address ";
}

unless ($disabled{ubsan}) {
    # -DPEDANTIC or -fnosanitize=aligmnent may also be required on some
    # platforms.
    $config{cflags} .= "-fsanitize=undefined -fno-sanitize-recover=all ";
}

unless ($disabled{fuzz} && $disabled{asan} && $disabled{ubsan}) {
    $config{cflags} .= "-fno-omit-frame-pointer -g ";
}
#
# Platform fix-ups
#

fuzz/README.md

0 → 100644
+47 −0
Original line number Diff line number Diff line
# I Can Haz Fuzz?

Or, how to fuzz OpenSSL with libfuzzer.

Starting from a vanilla+OpenSSH server Ubuntu install.

Use Chrome's handy recent build of clang. Older versions may also work.

    $ sudo apt-get install git
    $ mkdir git-work
    $ git clone https://chromium.googlesource.com/chromium/src/tools/clang
    $ clang/scripts/update.py

You may want to git pull and re-run the update from time to time.

Update your path:

    $ PATH=~/third_party/llvm-build/Release+Asserts/bin/:$PATH

Get and build libFuzzer (there is a git mirror at
https://github.com/llvm-mirror/llvm/tree/master/lib/Fuzzer if you prefer):

    $ cd
    $ sudo apt-get install subversion
    $ mkdir svn-work
    $ cd svn-work
    $ svn co http://llvm.org/svn/llvm-project/llvm/trunk/lib/Fuzzer
    $ cd Fuzzer
    $ clang++ -c -g -O2 -std=c++11 *.cpp
    $ ar r libFuzzer.a *.o
    $ ranlib libFuzzer.a

Configure for fuzzing:

    $ CC=clang ./config enable-fuzz enable-asan enable-ubsan no-shared
    $ sudo apt-get install make
    $ LDCMD=clang++ make -j
    $ fuzz/helper.py <fuzzer> <arguments>

Where `<fuzzer>` is one of the executables in `fuzz/`. Most fuzzers do not
need any command line arguments, but, for example, `asn1` needs the name of a
data type.

If you get a crash, you should find a corresponding input file in
`fuzz/corpora/<fuzzer>-crash/`. You can reproduce the crash with

    $ fuzz/<fuzzer> <crashfile>

fuzz/asn1.c

0 → 100644
+86 −0
Original line number Diff line number Diff line
/*
 * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
 *
 * Licensed under the OpenSSL licenses, (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://www.openssl.org/source/license.html
 * or in the file LICENSE in the source distribution.
 */

/*
 * Fuzz ASN.1 parsing for various data structures. Specify which on the
 * command line:
 *
 * asn1 <data structure>
 */

#include <stdio.h>
#include <string.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/ec.h>
#include <openssl/ocsp.h>
#include <openssl/pkcs12.h>
#include <openssl/ts.h>
#include <openssl/x509v3.h>
#include "fuzzer.h"

static const ASN1_ITEM *item_type;

int LLVMFuzzerInitialize(int *argc, char ***argv) {
    const char *cmd;
    OPENSSL_assert(*argc > 1);

    cmd = (*argv)[1];
    (*argv)[1] = (*argv)[0];
    ++*argv;
    --*argc;

    // TODO: make this work like d2i_test.c does, once its decided what the
    // common scheme is!
#define Y(t)  if (!strcmp(cmd, #t)) item_type = ASN1_ITEM_rptr(t)
#define X(t)  else Y(t)

    Y(ASN1_SEQUENCE);
    X(AUTHORITY_INFO_ACCESS);
    X(BIGNUM);
    X(ECPARAMETERS);
    X(ECPKPARAMETERS);
    X(GENERAL_NAME);
    X(GENERAL_SUBTREE);
    X(NAME_CONSTRAINTS);
    X(OCSP_BASICRESP);
    X(OCSP_RESPONSE);
    X(PKCS12);
    X(PKCS12_AUTHSAFES);
    X(PKCS12_SAFEBAGS);
    X(PKCS7);
    X(PKCS7_ATTR_SIGN);
    X(PKCS7_ATTR_VERIFY);
    X(PKCS7_DIGEST);
    X(PKCS7_ENC_CONTENT);
    X(PKCS7_ENCRYPT);
    X(PKCS7_ENVELOPE);
    X(PKCS7_RECIP_INFO);
    X(PKCS7_SIGN_ENVELOPE);
    X(PKCS7_SIGNED);
    X(PKCS7_SIGNER_INFO);
    X(POLICY_CONSTRAINTS);
    X(POLICY_MAPPINGS);
    X(SXNET);
    //X(TS_RESP);  want to do this, but type is hidden, however d2i exists...
    X(X509);
    X(X509_CRL);
    else
        OPENSSL_assert(!"Bad type");

    return 0;
}

int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
    const uint8_t *b = buf;
    ASN1_VALUE *o = ASN1_item_d2i(NULL, &b, len, item_type);
    ASN1_item_free(o, item_type);
    return 0;
}

fuzz/asn1parse.c

0 → 100644
+29 −0
Original line number Diff line number Diff line
/*
 * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
 *
 * Licensed under the OpenSSL licenses, (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://www.openssl.org/source/license.html
 * or in the file LICENSE in the source distribution.
 */

/*
 * Fuzz the parser used for dumping ASN.1 using "openssl asn1parse".
 */

#include <stdio.h>
#include <openssl/asn1.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include "fuzzer.h"

int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
    static BIO *bio_out;

    if (bio_out == NULL)
        bio_out = BIO_new_file("/dev/null", "w");

    (void)ASN1_parse_dump(bio_out, buf, len, 0, 0);
    return 0;
}
Loading