diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | ad18d877ddd2a44d98fa12ccd3dbbcf4d0ac4299 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /security/nss/fuzz | |
parent | 15477ed9af4859dacb069040b5d4de600803d3bc (diff) | |
download | uxp-ad18d877ddd2a44d98fa12ccd3dbbcf4d0ac4299.tar.gz |
Add m-esr52 at 52.6.0
Diffstat (limited to 'security/nss/fuzz')
-rw-r--r-- | security/nss/fuzz/.clang-format | 4 | ||||
-rwxr-xr-x | security/nss/fuzz/clone_corpus.sh | 4 | ||||
-rwxr-xr-x | security/nss/fuzz/clone_libfuzzer.sh | 4 | ||||
-rw-r--r-- | security/nss/fuzz/fuzz.gyp | 65 | ||||
-rwxr-xr-x | security/nss/fuzz/git-copy.sh | 32 | ||||
-rw-r--r-- | security/nss/fuzz/nssfuzz.cc | 148 | ||||
-rw-r--r-- | security/nss/fuzz/pkcs8_target.cc | 37 | ||||
-rw-r--r-- | security/nss/fuzz/quickder_targets.cc | 36 | ||||
-rw-r--r-- | security/nss/fuzz/registry.h | 71 | ||||
-rw-r--r-- | security/nss/fuzz/shared.h | 18 | ||||
-rw-r--r-- | security/nss/fuzz/warning.txt | 15 |
11 files changed, 434 insertions, 0 deletions
diff --git a/security/nss/fuzz/.clang-format b/security/nss/fuzz/.clang-format new file mode 100644 index 0000000000..06e3c5115f --- /dev/null +++ b/security/nss/fuzz/.clang-format @@ -0,0 +1,4 @@ +--- +Language: Cpp +BasedOnStyle: Google +... diff --git a/security/nss/fuzz/clone_corpus.sh b/security/nss/fuzz/clone_corpus.sh new file mode 100755 index 0000000000..a41cbc0c50 --- /dev/null +++ b/security/nss/fuzz/clone_corpus.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +d=$(dirname $0) +exec $d/git-copy.sh https://github.com/mozilla/nss-fuzzing-corpus master $d/corpus diff --git a/security/nss/fuzz/clone_libfuzzer.sh b/security/nss/fuzz/clone_libfuzzer.sh new file mode 100755 index 0000000000..91c93de314 --- /dev/null +++ b/security/nss/fuzz/clone_libfuzzer.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +d=$(dirname $0) +exec $d/git-copy.sh https://chromium.googlesource.com/chromium/llvm-project/llvm/lib/Fuzzer 1b543d6e5073b56be214394890c9193979a3d7e1 $d/libFuzzer diff --git a/security/nss/fuzz/fuzz.gyp b/security/nss/fuzz/fuzz.gyp new file mode 100644 index 0000000000..4321c5cf5e --- /dev/null +++ b/security/nss/fuzz/fuzz.gyp @@ -0,0 +1,65 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +{ + 'includes': [ + '../coreconf/config.gypi', + '../cmd/platlibs.gypi' + ], + 'targets': [ + { + 'target_name': 'libFuzzer', + 'type': 'static_library', + 'sources': [ + 'libFuzzer/FuzzerCrossOver.cpp', + 'libFuzzer/FuzzerDriver.cpp', + 'libFuzzer/FuzzerExtFunctionsDlsym.cpp', + 'libFuzzer/FuzzerExtFunctionsWeak.cpp', + 'libFuzzer/FuzzerIO.cpp', + 'libFuzzer/FuzzerLoop.cpp', + 'libFuzzer/FuzzerMutate.cpp', + 'libFuzzer/FuzzerSHA1.cpp', + 'libFuzzer/FuzzerTracePC.cpp', + 'libFuzzer/FuzzerTraceState.cpp', + 'libFuzzer/FuzzerUtil.cpp', + 'libFuzzer/FuzzerUtilDarwin.cpp', + 'libFuzzer/FuzzerUtilLinux.cpp', + ], + 'cflags': [ + '-O2', + ], + 'cflags/': [ + ['exclude', '-fsanitize='], + ['exclude', '-fsanitize-'], + ], + 'xcode_settings': { + 'GCC_OPTIMIZATION_LEVEL': '2', # -O2 + 'OTHER_CFLAGS/': [ + ['exclude', '-fsanitize='], + ['exclude', '-fsanitize-'], + ], + }, + }, + { + 'target_name': 'nssfuzz', + 'type': 'executable', + 'sources': [ + 'nssfuzz.cc', + 'pkcs8_target.cc', + 'quickder_targets.cc', + ], + 'dependencies': [ + '<(DEPTH)/exports.gyp:nss_exports', + 'libFuzzer', + ] + } + ], + 'target_defaults': { + 'include_dirs': [ + 'libFuzzer', + ], + }, + 'variables': { + 'module': 'nss', + } +} diff --git a/security/nss/fuzz/git-copy.sh b/security/nss/fuzz/git-copy.sh new file mode 100755 index 0000000000..1389ddabde --- /dev/null +++ b/security/nss/fuzz/git-copy.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +set -e + +if [ $# -lt 3 ]; then + echo "Usage: $0 <repo> <branch> <directory>" 1>&2 + exit 2 +fi + +REPO=$1 +COMMIT=$2 +DIR=$3 + +echo "Copy '$COMMIT' from '$REPO' to '$DIR'" +if [ -f $DIR/.git-copy ]; then + CURRENT=$(cat $DIR/.git-copy) + if [ $(echo -n $COMMIT | wc -c) != "40" ]; then + ACTUAL=$(git ls-remote $REPO $COMMIT | cut -c 1-40 -) + else + ACTUAL=$COMMIT + fi + if [ CURRENT = ACTUAL ]; then + echo "Up to date." + fi +fi + +mkdir -p $DIR +git -C $DIR init -q +git -C $DIR fetch -q --depth=1 $REPO $COMMIT:git-copy-tmp +git -C $DIR reset --hard git-copy-tmp +git -C $DIR show-ref HEAD | cut -c 1-40 - > $DIR/.git-copy +rm -rf $DIR/.git diff --git a/security/nss/fuzz/nssfuzz.cc b/security/nss/fuzz/nssfuzz.cc new file mode 100644 index 0000000000..d9769309a4 --- /dev/null +++ b/security/nss/fuzz/nssfuzz.cc @@ -0,0 +1,148 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include <iomanip> +#include <iostream> +#include <memory> + +#include "keyhi.h" +#include "pk11pub.h" + +#include "FuzzerInternal.h" +#include "registry.h" +#include "shared.h" + +using namespace std; + +class Args { + public: + Args(int argc, char **argv) : args_(argv, argv + argc) {} + + string &operator[](const int idx) { return args_[idx]; } + + bool Has(const string &arg) { + return any_of(args_.begin(), args_.end(), + [&arg](string &a) { return a.find(arg) == 0; }); + } + + void Append(const string &arg) { args_.push_back(arg); } + + void Remove(const int index) { + assert(index < count()); + args_.erase(args_.begin() + index); + } + + vector<char *> argv() { + vector<char *> out; + out.resize(count()); + + transform(args_.begin(), args_.end(), out.begin(), + [](string &a) { return const_cast<char *>(a.c_str()); }); + + return out; + } + + size_t count() { return args_.size(); } + + private: + vector<string> args_; +}; + +void printUsage(Args &args) { + size_t sep = args[0].rfind("/") + 1; + string progName = args[0].substr(sep); + + cerr << progName << " - Various libFuzzer targets for NSS" << endl << endl; + cerr << "Usage: " << progName << " <target> <libFuzzer options>" << endl + << endl; + cerr << "Valid targets:" << endl; + + vector<string> names = Registry::Names(); + + // Find length of the longest name. + size_t name_w = + max_element(names.begin(), names.end(), [](string &a, string &b) { + return a.size() < b.size(); + })->size(); + + // Find length of the longest description. + auto max = max_element(names.begin(), names.end(), [](string &a, string &b) { + return Registry::Desc(a).size() < Registry::Desc(b).size(); + }); + size_t desc_w = Registry::Desc(*max).size(); + + // Print list of targets. + for (string name : names) { + cerr << " " << left << setw(name_w) << name << " - " << setw(desc_w) + << Registry::Desc(name) + << " [default max_len=" << Registry::MaxLen(name) << "]" << endl; + } + + // Some usage examples. + cerr << endl << "Run fuzzer with a given corpus directory:" << endl; + cerr << " " << progName << " <target> /path/to/corpus" << endl; + + cerr << endl << "Run fuzzer with a single test input:" << endl; + cerr << " " << progName + << " <target> ./crash-14d4355b971092e39572bc306a135ddf9f923e19" << endl; + + cerr << endl + << "Specify the number of cores you wish to dedicate to fuzzing:" + << endl; + cerr << " " << progName << " <target> -jobs=8 -workers=8 /path/to/corpus" + << endl; + + cerr << endl << "Override the maximum length of a test input:" << endl; + cerr << " " << progName << " <target> -max_len=2048 /path/to/corpus" << endl; + + cerr << endl + << "Minimize a given corpus and put the result into 'new_corpus':" + << endl; + cerr << " " << progName + << " <target> -merge=1 -max_len=50000 ./new_corpus /path/to/corpus" + << endl; + + cerr << endl << "Merge new test inputs into a corpus:" << endl; + cerr + << " " << progName + << " <target> -merge=1 -max_len=50000 /path/to/corpus ./inputs1 ./inputs2" + << endl; + + cerr << endl << "Print libFuzzer usage information:" << endl; + cerr << " " << progName << " <target> -help=1" << endl << endl; + + cerr << "Check out the docs at http://llvm.org/docs/LibFuzzer.html" << endl; +} + +int main(int argc, char **argv) { + Args args(argc, argv); + + if (args.count() < 2 || !Registry::Has(args[1])) { + printUsage(args); + return 1; + } + + string targetName(args[1]); + + // Remove the target argument when -workers=x or -jobs=y is NOT given. + // If both are given, libFuzzer will spawn multiple processes for the target. + if (!args.Has("-workers=") || !args.Has("-jobs=")) { + args.Remove(1); + } + + // Set default max_len arg, if none given and we're not merging. + if (!args.Has("-max_len=") && !args.Has("-merge=1")) { + uint16_t maxLen = Registry::MaxLen(targetName); + args.Append("-max_len=" + to_string(maxLen)); + } + + // Hand control to the libFuzzer driver. + vector<char *> args_new(args.argv()); + argc = args_new.size(); + argv = args_new.data(); + + return fuzzer::FuzzerDriver(&argc, &argv, Registry::Func(targetName)); +} diff --git a/security/nss/fuzz/pkcs8_target.cc b/security/nss/fuzz/pkcs8_target.cc new file mode 100644 index 0000000000..8b6ed7b57b --- /dev/null +++ b/security/nss/fuzz/pkcs8_target.cc @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include <assert.h> +#include <stdint.h> +#include <memory> + +#include "keyhi.h" +#include "pk11pub.h" + +#include "registry.h" +#include "shared.h" + +extern "C" int pkcs8_fuzzing_target(const uint8_t *Data, size_t Size) { + SECItem data = {siBuffer, (unsigned char *)Data, (unsigned int)Size}; + + static std::unique_ptr<NSSDatabase> db(new NSSDatabase()); + assert(db != nullptr); + + PK11SlotInfo *slot = PK11_GetInternalSlot(); + assert(slot != nullptr); + + SECKEYPrivateKey *key = nullptr; + if (PK11_ImportDERPrivateKeyInfoAndReturnKey(slot, &data, nullptr, nullptr, + false, false, KU_ALL, &key, + nullptr) == SECSuccess) { + SECKEY_DestroyPrivateKey(key); + } + + PK11_FreeSlot(slot); + return 0; +} + +REGISTER_FUZZING_TARGET("pkcs8", pkcs8_fuzzing_target, 2048, "PKCS#8 Import") diff --git a/security/nss/fuzz/quickder_targets.cc b/security/nss/fuzz/quickder_targets.cc new file mode 100644 index 0000000000..2517721961 --- /dev/null +++ b/security/nss/fuzz/quickder_targets.cc @@ -0,0 +1,36 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include <stdint.h> + +#include "cert.h" + +#include "registry.h" + +void QuickDERDecode(void *dst, const SEC_ASN1Template *tpl, const uint8_t *buf, + size_t len) { + PORTCheapArenaPool pool; + SECItem data = {siBuffer, const_cast<unsigned char *>(buf), + static_cast<unsigned int>(len)}; + + PORT_InitCheapArena(&pool, DER_DEFAULT_CHUNKSIZE); + (void)SEC_QuickDERDecodeItem(&pool.arena, dst, tpl, &data); + PORT_DestroyCheapArena(&pool); +} + +extern "C" int cert_fuzzing_target(const uint8_t *Data, size_t Size) { + CERTCertificate cert; + QuickDERDecode(&cert, SEC_SignedCertificateTemplate, Data, Size); + return 0; +} + +REGISTER_FUZZING_TARGET("cert", cert_fuzzing_target, 3072, "Certificate Import") + +extern "C" int spki_fuzzing_target(const uint8_t *Data, size_t Size) { + CERTSubjectPublicKeyInfo spki; + QuickDERDecode(&spki, CERT_SubjectPublicKeyInfoTemplate, Data, Size); + return 0; +} + +REGISTER_FUZZING_TARGET("spki", spki_fuzzing_target, 1024, "SPKI Import") diff --git a/security/nss/fuzz/registry.h b/security/nss/fuzz/registry.h new file mode 100644 index 0000000000..760118dec9 --- /dev/null +++ b/security/nss/fuzz/registry.h @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef registry_h__ +#define registry_h__ + +#include <map> +#include "FuzzerInternal.h" +#include "nss.h" + +class Registry { + public: + static void Add(std::string name, fuzzer::UserCallback func, uint16_t max_len, + std::string desc) { + assert(!Has(name)); + GetInstance().targets_[name] = TargetData(func, max_len, desc); + } + + static bool Has(std::string name) { + return GetInstance().targets_.count(name) > 0; + } + + static fuzzer::UserCallback Func(std::string name) { + assert(Has(name)); + return std::get<0>(Get(name)); + } + + static uint16_t MaxLen(std::string name) { + assert(Has(name)); + return std::get<1>(Get(name)); + } + + static std::string& Desc(std::string name) { + assert(Has(name)); + return std::get<2>(Get(name)); + } + + static std::vector<std::string> Names() { + std::vector<std::string> names; + for (auto& it : GetInstance().targets_) { + names.push_back(it.first); + } + return names; + } + + private: + typedef std::tuple<fuzzer::UserCallback, uint16_t, std::string> TargetData; + + static Registry& GetInstance() { + static Registry registry; + return registry; + } + + static TargetData& Get(std::string name) { + return GetInstance().targets_[name]; + } + + Registry() {} + + std::map<std::string, TargetData> targets_; +}; + +#define REGISTER_FUZZING_TARGET(name, func, max_len, desc) \ + static void __attribute__((constructor)) Register_##func() { \ + Registry::Add(name, func, max_len, desc); \ + } + +#endif // registry_h__ diff --git a/security/nss/fuzz/shared.h b/security/nss/fuzz/shared.h new file mode 100644 index 0000000000..09d805ed85 --- /dev/null +++ b/security/nss/fuzz/shared.h @@ -0,0 +1,18 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef shared_h__ +#define shared_h__ + +#include "nss.h" + +class NSSDatabase { + public: + NSSDatabase() { NSS_NoDB_Init(nullptr); } + ~NSSDatabase() { NSS_Shutdown(); } +}; + +#endif // shared_h__ diff --git a/security/nss/fuzz/warning.txt b/security/nss/fuzz/warning.txt new file mode 100644 index 0000000000..2c83d7ed2a --- /dev/null +++ b/security/nss/fuzz/warning.txt @@ -0,0 +1,15 @@ + +############################################## +## ## +## WARNING: You're building with -Dfuzz=1 ## +## ## +## This means: ## +## ## +## * Your PRNG is DETERMINISTIC. ## +## * TLS transcripts are PLAINTEXT. ## +## * TLS signature checks are DISABLED. ## +## ## +## Thank you for fuzzing! ## +## ## +############################################## + |